VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/SharedFolders/driver/path.c@ 78285

Last change on this file since 78285 was 78285, checked in by vboxsync, 6 years ago

winnt/vboxsf: Fixed status code some DeleteFile & RemoveDir corner cases that made FsPerf unhappy. Problem was in RDBSS, so had to get a little inventive to work around it. bugref:9172

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 35.0 KB
Line 
1/* $Id: path.c 78285 2019-04-25 00:30:32Z vboxsync $ */
2/** @file
3 * VirtualBox Windows Guest Shared Folders - Path related routines.
4 */
5
6/*
7 * Copyright (C) 2012-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#include "vbsf.h"
19#include <iprt/err.h>
20
21
22static UNICODE_STRING g_UnicodeBackslash = { 2, 4, L"\\" };
23
24static NTSTATUS vbsfProcessCreate(PRX_CONTEXT RxContext,
25 PUNICODE_STRING RemainingName,
26 FILE_BASIC_INFORMATION *pFileBasicInfo,
27 FILE_STANDARD_INFORMATION *pFileStandardInfo,
28 PVOID EaBuffer,
29 ULONG EaLength,
30 ULONG *pulCreateAction,
31 SHFLHANDLE *pHandle)
32{
33 NTSTATUS Status = STATUS_SUCCESS;
34
35 RxCaptureFcb;
36
37 PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext);
38 PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = VBoxMRxGetNetRootExtension(capFcb->pNetRoot);
39
40 int vrc = VINF_SUCCESS;
41
42 /* Various boolean flags. */
43 struct
44 {
45 ULONG CreateDirectory :1;
46 ULONG OpenDirectory :1;
47 ULONG DirectoryFile :1;
48 ULONG NonDirectoryFile :1;
49 ULONG DeleteOnClose :1;
50 ULONG TemporaryFile :1;
51 ULONG SlashHack :1;
52 } bf;
53
54 ACCESS_MASK DesiredAccess;
55 ULONG Options;
56 UCHAR FileAttributes;
57 ULONG ShareAccess;
58 ULONG CreateDisposition;
59 SHFLCREATEPARMS *pCreateParms = NULL;
60
61 RT_NOREF(EaBuffer);
62
63 if (EaLength)
64 {
65 Log(("VBOXSF: vbsfProcessCreate: Unsupported: extended attributes!\n"));
66 Status = STATUS_NOT_SUPPORTED; /// @todo STATUS_EAS_NOT_SUPPORTED ?
67 goto failure;
68 }
69
70 if (BooleanFlagOn(capFcb->FcbState, FCB_STATE_PAGING_FILE))
71 {
72 Log(("VBOXSF: vbsfProcessCreate: Unsupported: paging file!\n"));
73 Status = STATUS_NOT_IMPLEMENTED;
74 goto failure;
75 }
76
77 Log(("VBOXSF: vbsfProcessCreate: FileAttributes = 0x%08x\n",
78 RxContext->Create.NtCreateParameters.FileAttributes));
79 Log(("VBOXSF: vbsfProcessCreate: CreateOptions = 0x%08x\n",
80 RxContext->Create.NtCreateParameters.CreateOptions));
81
82 RtlZeroMemory (&bf, sizeof (bf));
83
84 DesiredAccess = RxContext->Create.NtCreateParameters.DesiredAccess;
85 Options = RxContext->Create.NtCreateParameters.CreateOptions & FILE_VALID_OPTION_FLAGS;
86 FileAttributes = (UCHAR)(RxContext->Create.NtCreateParameters.FileAttributes & ~FILE_ATTRIBUTE_NORMAL);
87 ShareAccess = RxContext->Create.NtCreateParameters.ShareAccess;
88
89 /* We do not support opens by file ids. */
90 if (FlagOn(Options, FILE_OPEN_BY_FILE_ID))
91 {
92 Log(("VBOXSF: vbsfProcessCreate: Unsupported: file open by id!\n"));
93 Status = STATUS_NOT_IMPLEMENTED;
94 goto failure;
95 }
96
97 /* Mask out unsupported attribute bits. */
98 FileAttributes &= (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_ARCHIVE);
99
100 bf.DirectoryFile = BooleanFlagOn(Options, FILE_DIRECTORY_FILE);
101 bf.NonDirectoryFile = BooleanFlagOn(Options, FILE_NON_DIRECTORY_FILE);
102 bf.DeleteOnClose = BooleanFlagOn(Options, FILE_DELETE_ON_CLOSE);
103 if (bf.DeleteOnClose)
104 Log(("VBOXSF: vbsfProcessCreate: Delete on close!\n"));
105
106 CreateDisposition = RxContext->Create.NtCreateParameters.Disposition;
107
108 bf.CreateDirectory = (bf.DirectoryFile && ((CreateDisposition == FILE_CREATE) || (CreateDisposition == FILE_OPEN_IF)));
109 bf.OpenDirectory = (bf.DirectoryFile && ((CreateDisposition == FILE_OPEN) || (CreateDisposition == FILE_OPEN_IF)));
110 bf.TemporaryFile = BooleanFlagOn(RxContext->Create.NtCreateParameters.FileAttributes, FILE_ATTRIBUTE_TEMPORARY);
111
112 if (FlagOn(capFcb->FcbState, FCB_STATE_TEMPORARY))
113 bf.TemporaryFile = TRUE;
114
115 bf.SlashHack = RxContext->CurrentIrpSp
116 && (RxContext->CurrentIrpSp->Parameters.Create.ShareAccess & VBOX_MJ_CREATE_SLASH_HACK);
117
118 Log(("VBOXSF: vbsfProcessCreate: bf.TemporaryFile %d, bf.CreateDirectory %d, bf.DirectoryFile = %d, bf.SlashHack = %d\n",
119 bf.TemporaryFile, bf.CreateDirectory, bf.DirectoryFile, bf.SlashHack));
120
121 /* Check consistency in specified flags. */
122 if (bf.TemporaryFile && bf.CreateDirectory) /* Directories with temporary flag set are not allowed! */
123 {
124 Log(("VBOXSF: vbsfProcessCreate: Not allowed: Temporary directories!\n"));
125 Status = STATUS_INVALID_PARAMETER;
126 goto failure;
127 }
128
129 if (bf.DirectoryFile && bf.NonDirectoryFile)
130 {
131 /** @todo r=bird: Check if FILE_DIRECTORY_FILE+FILE_NON_DIRECTORY_FILE really is illegal in all combinations... */
132 Log(("VBOXSF: vbsfProcessCreate: Unsupported combination: dir && !dir\n"));
133 Status = STATUS_INVALID_PARAMETER;
134 goto failure;
135 }
136
137 /* Initialize create parameters. */
138 pCreateParms = (SHFLCREATEPARMS *)vbsfAllocNonPagedMem(sizeof(SHFLCREATEPARMS));
139 if (!pCreateParms)
140 {
141 Status = STATUS_INSUFFICIENT_RESOURCES;
142 goto failure;
143 }
144
145 RtlZeroMemory(pCreateParms, sizeof (SHFLCREATEPARMS));
146
147 pCreateParms->Handle = SHFL_HANDLE_NIL;
148 pCreateParms->Result = SHFL_NO_RESULT;
149
150 if (bf.DirectoryFile)
151 {
152 if (CreateDisposition != FILE_CREATE && CreateDisposition != FILE_OPEN && CreateDisposition != FILE_OPEN_IF)
153 {
154 Log(("VBOXSF: vbsfProcessCreate: Invalid disposition 0x%08X for directory!\n",
155 CreateDisposition));
156 Status = STATUS_INVALID_PARAMETER;
157 goto failure;
158 }
159
160 pCreateParms->CreateFlags |= SHFL_CF_DIRECTORY;
161 }
162
163 Log(("VBOXSF: vbsfProcessCreate: CreateDisposition = 0x%08X\n",
164 CreateDisposition));
165
166 switch (CreateDisposition)
167 {
168 case FILE_SUPERSEDE:
169 pCreateParms->CreateFlags |= SHFL_CF_ACT_REPLACE_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW;
170 Log(("VBOXSF: vbsfProcessCreate: CreateFlags |= SHFL_CF_ACT_REPLACE_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW\n"));
171 break;
172
173 case FILE_OPEN:
174 pCreateParms->CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW;
175 Log(("VBOXSF: vbsfProcessCreate: CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW\n"));
176 break;
177
178 case FILE_CREATE:
179 pCreateParms->CreateFlags |= SHFL_CF_ACT_FAIL_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW;
180 Log(("VBOXSF: vbsfProcessCreate: CreateFlags |= SHFL_CF_ACT_FAIL_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW\n"));
181 break;
182
183 case FILE_OPEN_IF:
184 pCreateParms->CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW;
185 Log(("VBOXSF: vbsfProcessCreate: CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW\n"));
186 break;
187
188 case FILE_OVERWRITE:
189 pCreateParms->CreateFlags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW;
190 Log(("VBOXSF: vbsfProcessCreate: CreateFlags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW\n"));
191 break;
192
193 case FILE_OVERWRITE_IF:
194 pCreateParms->CreateFlags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW;
195 Log(("VBOXSF: vbsfProcessCreate: CreateFlags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW\n"));
196 break;
197
198 default:
199 Log(("VBOXSF: vbsfProcessCreate: Unexpected create disposition: 0x%08X\n",
200 CreateDisposition));
201 Status = STATUS_INVALID_PARAMETER;
202 goto failure;
203 }
204
205 Log(("VBOXSF: vbsfProcessCreate: DesiredAccess = 0x%08X\n",
206 DesiredAccess));
207 Log(("VBOXSF: vbsfProcessCreate: ShareAccess = 0x%08X\n",
208 ShareAccess));
209
210 if (DesiredAccess & FILE_READ_DATA)
211 {
212 Log(("VBOXSF: vbsfProcessCreate: FILE_READ_DATA\n"));
213 pCreateParms->CreateFlags |= SHFL_CF_ACCESS_READ;
214 }
215
216 if (DesiredAccess & FILE_WRITE_DATA)
217 {
218 Log(("VBOXSF: vbsfProcessCreate: FILE_WRITE_DATA\n"));
219 /* FILE_WRITE_DATA means write access regardless of FILE_APPEND_DATA bit.
220 */
221 pCreateParms->CreateFlags |= SHFL_CF_ACCESS_WRITE;
222 }
223 else if (DesiredAccess & FILE_APPEND_DATA)
224 {
225 Log(("VBOXSF: vbsfProcessCreate: FILE_APPEND_DATA\n"));
226 /* FILE_APPEND_DATA without FILE_WRITE_DATA means append only mode.
227 *
228 * Both write and append access flags are required for shared folders,
229 * as on Windows FILE_APPEND_DATA implies write access.
230 */
231 pCreateParms->CreateFlags |= SHFL_CF_ACCESS_WRITE | SHFL_CF_ACCESS_APPEND;
232 }
233
234 if (DesiredAccess & FILE_READ_ATTRIBUTES)
235 pCreateParms->CreateFlags |= SHFL_CF_ACCESS_ATTR_READ;
236 if (DesiredAccess & FILE_WRITE_ATTRIBUTES)
237 pCreateParms->CreateFlags |= SHFL_CF_ACCESS_ATTR_WRITE;
238
239 if (ShareAccess & (FILE_SHARE_READ | FILE_SHARE_WRITE))
240 pCreateParms->CreateFlags |= SHFL_CF_ACCESS_DENYNONE;
241 else if (ShareAccess & FILE_SHARE_READ)
242 pCreateParms->CreateFlags |= SHFL_CF_ACCESS_DENYWRITE;
243 else if (ShareAccess & FILE_SHARE_WRITE)
244 pCreateParms->CreateFlags |= SHFL_CF_ACCESS_DENYREAD;
245 else pCreateParms->CreateFlags |= SHFL_CF_ACCESS_DENYALL;
246
247 /* Set initial allocation size. */
248 pCreateParms->Info.cbObject = RxContext->Create.NtCreateParameters.AllocationSize.QuadPart;
249
250 if (FileAttributes == 0)
251 FileAttributes = FILE_ATTRIBUTE_NORMAL;
252
253 pCreateParms->Info.Attr.fMode = NTToVBoxFileAttributes(FileAttributes);
254
255 {
256 PSHFLSTRING ParsedPath;
257 Log(("VBOXSF: vbsfProcessCreate: RemainingName->Length = %d\n", RemainingName->Length));
258
259
260 if (!bf.SlashHack)
261 {
262 Status = vbsfShflStringFromUnicodeAlloc(&ParsedPath, RemainingName->Buffer, RemainingName->Length);
263 if (Status != STATUS_SUCCESS)
264 goto failure;
265 }
266 else
267 {
268 /* Add back the slash we had to hide from RDBSS. */
269 Status = vbsfShflStringFromUnicodeAlloc(&ParsedPath, NULL, RemainingName->Length + sizeof(RTUTF16));
270 if (Status != STATUS_SUCCESS)
271 goto failure;
272 memcpy(ParsedPath->String.utf16, RemainingName->Buffer, RemainingName->Length);
273 ParsedPath->String.utf16[RemainingName->Length / sizeof(RTUTF16)] = '\\';
274 ParsedPath->String.utf16[RemainingName->Length / sizeof(RTUTF16) + 1] = '\0';
275 ParsedPath->u16Length = RemainingName->Length + sizeof(RTUTF16);
276 }
277
278 Log(("VBOXSF: ParsedPath: %.*ls\n",
279 ParsedPath->u16Length / sizeof(WCHAR), ParsedPath->String.ucs2));
280
281 /* Call host. */
282 Log(("VBOXSF: vbsfProcessCreate: VbglR0SfCreate called.\n"));
283 vrc = VbglR0SfCreate(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, ParsedPath, pCreateParms);
284
285 vbsfFreeNonPagedMem(ParsedPath);
286 }
287
288 Log(("VBOXSF: vbsfProcessCreate: VbglR0SfCreate returns vrc = %Rrc, Result = 0x%x\n",
289 vrc, pCreateParms->Result));
290
291 if (RT_FAILURE(vrc))
292 {
293 /* Map some VBoxRC to STATUS codes expected by the system. */
294 switch (vrc)
295 {
296 case VERR_ALREADY_EXISTS:
297 {
298 *pulCreateAction = FILE_EXISTS;
299 Status = STATUS_OBJECT_NAME_COLLISION;
300 goto failure;
301 }
302
303 /* On POSIX systems, the "mkdir" command returns VERR_FILE_NOT_FOUND when
304 doing a recursive directory create. Handle this case.
305
306 bird: We end up here on windows systems too if opening a dir that doesn't
307 exists. Thus, I've changed the SHFL_PATH_NOT_FOUND to SHFL_FILE_NOT_FOUND
308 so that FsPerf is happy. */
309 case VERR_FILE_NOT_FOUND: /** @todo r=bird: this is a host bug, isn't it? */
310 {
311 pCreateParms->Result = SHFL_FILE_NOT_FOUND;
312 break;
313 }
314
315 default:
316 {
317 *pulCreateAction = FILE_DOES_NOT_EXIST;
318 Status = VBoxErrorToNTStatus(vrc);
319 goto failure;
320 }
321 }
322 }
323
324 /*
325 * The request succeeded. Analyze host response,
326 */
327 switch (pCreateParms->Result)
328 {
329 case SHFL_PATH_NOT_FOUND:
330 {
331 /* Path to the object does not exist. */
332 Log(("VBOXSF: vbsfProcessCreate: Path not found\n"));
333 *pulCreateAction = FILE_DOES_NOT_EXIST;
334 Status = STATUS_OBJECT_PATH_NOT_FOUND;
335 goto failure;
336 }
337
338 case SHFL_FILE_NOT_FOUND:
339 {
340 Log(("VBOXSF: vbsfProcessCreate: File not found\n"));
341 *pulCreateAction = FILE_DOES_NOT_EXIST;
342 if (pCreateParms->Handle == SHFL_HANDLE_NIL)
343 {
344 Status = STATUS_OBJECT_NAME_NOT_FOUND;
345 goto failure;
346 }
347
348 Log(("VBOXSF: vbsfProcessCreate: File not found but have a handle!\n"));
349 Status = STATUS_UNSUCCESSFUL;
350 goto failure;
351 }
352
353 case SHFL_FILE_EXISTS:
354 {
355 Log(("VBOXSF: vbsfProcessCreate: File exists, Handle = 0x%RX64\n",
356 pCreateParms->Handle));
357 if (pCreateParms->Handle == SHFL_HANDLE_NIL)
358 {
359 *pulCreateAction = FILE_EXISTS;
360 if (CreateDisposition == FILE_CREATE)
361 {
362 /* File was not opened because we requested a create. */
363 Status = STATUS_OBJECT_NAME_COLLISION;
364 goto failure;
365 }
366
367 /* Actually we should not go here, unless we have no rights to open the object. */
368 Log(("VBOXSF: vbsfProcessCreate: Existing file was not opened!\n"));
369 Status = STATUS_ACCESS_DENIED;
370 goto failure;
371 }
372
373 *pulCreateAction = FILE_OPENED;
374
375 /* Existing file was opened. Go check flags and create FCB. */
376 break;
377 }
378
379 case SHFL_FILE_CREATED:
380 {
381 /* A new file was created. */
382 Assert(pCreateParms->Handle != SHFL_HANDLE_NIL);
383
384 *pulCreateAction = FILE_CREATED;
385
386 /* Go check flags and create FCB. */
387 break;
388 }
389
390 case SHFL_FILE_REPLACED:
391 {
392 /* Existing file was replaced or overwriting. */
393 Assert(pCreateParms->Handle != SHFL_HANDLE_NIL);
394
395 if (CreateDisposition == FILE_SUPERSEDE)
396 *pulCreateAction = FILE_SUPERSEDED;
397 else
398 *pulCreateAction = FILE_OVERWRITTEN;
399 /* Go check flags and create FCB. */
400 break;
401 }
402
403 default:
404 {
405 Log(("VBOXSF: vbsfProcessCreate: Invalid CreateResult from host (0x%08X)\n",
406 pCreateParms->Result));
407 *pulCreateAction = FILE_DOES_NOT_EXIST;
408 Status = STATUS_OBJECT_PATH_NOT_FOUND;
409 goto failure;
410 }
411 }
412
413 /* Check flags. */
414 if (bf.NonDirectoryFile && FlagOn(pCreateParms->Info.Attr.fMode, RTFS_DOS_DIRECTORY))
415 {
416 /* Caller wanted only a file, but the object is a directory. */
417 Log(("VBOXSF: vbsfProcessCreate: File is a directory!\n"));
418 Status = STATUS_FILE_IS_A_DIRECTORY;
419 goto failure;
420 }
421
422 if (bf.DirectoryFile && !FlagOn(pCreateParms->Info.Attr.fMode, RTFS_DOS_DIRECTORY))
423 {
424 /* Caller wanted only a directory, but the object is not a directory. */
425 Log(("VBOXSF: vbsfProcessCreate: File is not a directory!\n"));
426 Status = STATUS_NOT_A_DIRECTORY;
427 goto failure;
428 }
429
430 *pHandle = pCreateParms->Handle;
431
432 /* Translate attributes */
433 pFileBasicInfo->FileAttributes = VBoxToNTFileAttributes(pCreateParms->Info.Attr.fMode);
434
435 /* Translate file times */
436 pFileBasicInfo->CreationTime.QuadPart = RTTimeSpecGetNtTime(&pCreateParms->Info.BirthTime); /* ridiculous name */
437 pFileBasicInfo->LastAccessTime.QuadPart = RTTimeSpecGetNtTime(&pCreateParms->Info.AccessTime);
438 pFileBasicInfo->LastWriteTime.QuadPart = RTTimeSpecGetNtTime(&pCreateParms->Info.ModificationTime);
439 pFileBasicInfo->ChangeTime.QuadPart = RTTimeSpecGetNtTime(&pCreateParms->Info.ChangeTime);
440
441 if (!FlagOn(pCreateParms->Info.Attr.fMode, RTFS_DOS_DIRECTORY))
442 {
443 pFileStandardInfo->AllocationSize.QuadPart = pCreateParms->Info.cbAllocated;
444 pFileStandardInfo->EndOfFile.QuadPart = pCreateParms->Info.cbObject;
445 pFileStandardInfo->Directory = FALSE;
446
447 Log(("VBOXSF: vbsfProcessCreate: AllocationSize = 0x%RX64, EndOfFile = 0x%RX64\n",
448 pCreateParms->Info.cbAllocated, pCreateParms->Info.cbObject));
449 }
450 else
451 {
452 pFileStandardInfo->AllocationSize.QuadPart = 0;
453 pFileStandardInfo->EndOfFile.QuadPart = 0;
454 pFileStandardInfo->Directory = TRUE;
455 }
456 pFileStandardInfo->NumberOfLinks = 0;
457 pFileStandardInfo->DeletePending = FALSE;
458
459 vbsfFreeNonPagedMem(pCreateParms);
460
461 return Status;
462
463failure:
464
465 Log(("VBOXSF: vbsfProcessCreate: Returned with status = 0x%08X\n",
466 Status));
467
468 if (pCreateParms && pCreateParms->Handle != SHFL_HANDLE_NIL)
469 {
470 VbglR0SfClose(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pCreateParms->Handle);
471 *pHandle = SHFL_HANDLE_NIL;
472 }
473
474 if (pCreateParms)
475 vbsfFreeNonPagedMem(pCreateParms);
476
477 return Status;
478}
479
480NTSTATUS VBoxMRxCreate(IN OUT PRX_CONTEXT RxContext)
481{
482 NTSTATUS Status = STATUS_SUCCESS;
483
484 RxCaptureFcb;
485 RxCaptureFobx;
486
487 PMRX_NET_ROOT pNetRoot = capFcb->pNetRoot;
488 PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
489 PUNICODE_STRING RemainingName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
490
491 FILE_BASIC_INFORMATION FileBasicInfo;
492 FILE_STANDARD_INFORMATION FileStandardInfo;
493
494 ULONG CreateAction = FILE_CREATED;
495 SHFLHANDLE Handle = SHFL_HANDLE_NIL;
496 PMRX_VBOX_FOBX pVBoxFobx;
497
498 RT_NOREF(__C_Fobx); /* RxCaptureFobx */
499
500 Log(("VBOXSF: MRxCreate: name ptr %p length=%d, SrvOpen->Flags 0x%08X\n",
501 RemainingName, RemainingName->Length, SrvOpen->Flags));
502
503 /* Disable FastIO. It causes a verifier bugcheck. */
504#ifdef SRVOPEN_FLAG_DONTUSE_READ_CACHING
505 SetFlag(SrvOpen->Flags, SRVOPEN_FLAG_DONTUSE_READ_CACHING | SRVOPEN_FLAG_DONTUSE_WRITE_CACHING);
506#else
507 SetFlag(SrvOpen->Flags, SRVOPEN_FLAG_DONTUSE_READ_CACHEING | SRVOPEN_FLAG_DONTUSE_WRITE_CACHEING);
508#endif
509
510 if (RemainingName->Length)
511 {
512 Log(("VBOXSF: MRxCreate: Attempt to open %.*ls\n",
513 RemainingName->Length/sizeof(WCHAR), RemainingName->Buffer));
514 }
515 else
516 {
517 if (FlagOn(RxContext->Create.Flags, RX_CONTEXT_CREATE_FLAG_STRIPPED_TRAILING_BACKSLASH))
518 {
519 Log(("VBOXSF: MRxCreate: Empty name -> Only backslash used\n"));
520 RemainingName = &g_UnicodeBackslash;
521 }
522 }
523
524 if ( pNetRoot->Type != NET_ROOT_WILD
525 && pNetRoot->Type != NET_ROOT_DISK)
526 {
527 Log(("VBOXSF: MRxCreate: netroot type %d not supported\n",
528 pNetRoot->Type));
529 Status = STATUS_NOT_IMPLEMENTED;
530 goto Exit;
531 }
532
533 FileBasicInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
534
535 Status = vbsfProcessCreate(RxContext,
536 RemainingName,
537 &FileBasicInfo,
538 &FileStandardInfo,
539 RxContext->Create.EaBuffer,
540 RxContext->Create.EaLength,
541 &CreateAction,
542 &Handle);
543
544 if (Status != STATUS_SUCCESS)
545 {
546 Log(("VBOXSF: MRxCreate: vbsfProcessCreate failed 0x%08X\n",
547 Status));
548 goto Exit;
549 }
550
551 Log(("VBOXSF: MRxCreate: EOF is 0x%RX64 AllocSize is 0x%RX64\n",
552 FileStandardInfo.EndOfFile.QuadPart, FileStandardInfo.AllocationSize.QuadPart));
553
554 RxContext->pFobx = RxCreateNetFobx(RxContext, SrvOpen);
555 if (!RxContext->pFobx)
556 {
557 Log(("VBOXSF: MRxCreate: RxCreateNetFobx failed\n"));
558 Status = STATUS_INSUFFICIENT_RESOURCES;
559 goto Exit;
560 }
561
562 Log(("VBOXSF: MRxCreate: CreateAction = 0x%08X\n",
563 CreateAction));
564
565 RxContext->Create.ReturnedCreateInformation = CreateAction;
566
567 if (capFcb->OpenCount == 0)
568 {
569 FCB_INIT_PACKET InitPacket;
570 RxFormInitPacket(InitPacket,
571 &FileBasicInfo.FileAttributes,
572 &FileStandardInfo.NumberOfLinks,
573 &FileBasicInfo.CreationTime,
574 &FileBasicInfo.LastAccessTime,
575 &FileBasicInfo.LastWriteTime,
576 &FileBasicInfo.ChangeTime,
577 &FileStandardInfo.AllocationSize,
578 &FileStandardInfo.EndOfFile,
579 &FileStandardInfo.EndOfFile);
580 RxFinishFcbInitialization(capFcb, RDBSS_STORAGE_NTC(FileTypeFile), &InitPacket);
581 }
582
583 SrvOpen->BufferingFlags = 0;
584
585 RxContext->pFobx->OffsetOfNextEaToReturn = 1;
586
587 pVBoxFobx = VBoxMRxGetFileObjectExtension(RxContext->pFobx);
588
589 Log(("VBOXSF: MRxCreate: VBoxFobx = %p\n",
590 pVBoxFobx));
591
592 if (!pVBoxFobx)
593 {
594 Log(("VBOXSF: MRxCreate: no VBoxFobx!\n"));
595 AssertFailed();
596 Status = STATUS_INSUFFICIENT_RESOURCES;
597 goto Exit;
598 }
599
600 Log(("VBOXSF: MRxCreate: FileBasicInformation: CreationTime %RX64\n", FileBasicInfo.CreationTime.QuadPart));
601 Log(("VBOXSF: MRxCreate: FileBasicInformation: LastAccessTime %RX64\n", FileBasicInfo.LastAccessTime.QuadPart));
602 Log(("VBOXSF: MRxCreate: FileBasicInformation: LastWriteTime %RX64\n", FileBasicInfo.LastWriteTime.QuadPart));
603 Log(("VBOXSF: MRxCreate: FileBasicInformation: ChangeTime %RX64\n", FileBasicInfo.ChangeTime.QuadPart));
604 Log(("VBOXSF: MRxCreate: FileBasicInformation: FileAttributes %RX32\n", FileBasicInfo.FileAttributes));
605
606 pVBoxFobx->hFile = Handle;
607 pVBoxFobx->pSrvCall = RxContext->Create.pSrvCall;
608 pVBoxFobx->FileStandardInfo = FileStandardInfo;
609 pVBoxFobx->FileBasicInfo = FileBasicInfo;
610 pVBoxFobx->fKeepCreationTime = FALSE;
611 pVBoxFobx->fKeepLastAccessTime = FALSE;
612 pVBoxFobx->fKeepLastWriteTime = FALSE;
613 pVBoxFobx->fKeepChangeTime = FALSE;
614 pVBoxFobx->SetFileInfoOnCloseFlags = 0;
615
616 if (!RxIsFcbAcquiredExclusive(capFcb))
617 {
618 RxAcquireExclusiveFcbResourceInMRx(capFcb);
619 }
620
621 Log(("VBOXSF: MRxCreate: NetRoot is %p, Fcb is %p, SrvOpen is %p, Fobx is %p\n",
622 pNetRoot, capFcb, SrvOpen, RxContext->pFobx));
623 Log(("VBOXSF: MRxCreate: return 0x%08X\n",
624 Status));
625
626Exit:
627 return Status;
628}
629
630NTSTATUS VBoxMRxComputeNewBufferingState(IN OUT PMRX_SRV_OPEN pMRxSrvOpen, IN PVOID pMRxContext, OUT PULONG pNewBufferingState)
631{
632 RT_NOREF(pMRxSrvOpen, pMRxContext, pNewBufferingState);
633 Log(("VBOXSF: MRxComputeNewBufferingState\n"));
634 return STATUS_NOT_SUPPORTED;
635}
636
637NTSTATUS VBoxMRxDeallocateForFcb(IN OUT PMRX_FCB pFcb)
638{
639 RT_NOREF(pFcb);
640 Log(("VBOXSF: MRxDeallocateForFcb\n"));
641 return STATUS_SUCCESS;
642}
643
644NTSTATUS VBoxMRxDeallocateForFobx(IN OUT PMRX_FOBX pFobx)
645{
646 RT_NOREF(pFobx);
647 Log(("VBOXSF: MRxDeallocateForFobx\n"));
648 return STATUS_SUCCESS;
649}
650
651NTSTATUS VBoxMRxTruncate(IN PRX_CONTEXT RxContext)
652{
653 RT_NOREF(RxContext);
654 Log(("VBOXSF: MRxTruncate\n"));
655 return STATUS_NOT_IMPLEMENTED;
656}
657
658NTSTATUS VBoxMRxCleanupFobx(IN PRX_CONTEXT RxContext)
659{
660 PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(RxContext->pFobx);
661
662 Log(("VBOXSF: MRxCleanupFobx: pVBoxFobx = %p, Handle = 0x%RX64\n", pVBoxFobx, pVBoxFobx? pVBoxFobx->hFile: 0));
663
664 if (!pVBoxFobx)
665 return STATUS_INVALID_PARAMETER;
666
667 return STATUS_SUCCESS;
668}
669
670NTSTATUS VBoxMRxForceClosed(IN PMRX_SRV_OPEN pSrvOpen)
671{
672 RT_NOREF(pSrvOpen);
673 Log(("VBOXSF: MRxForceClosed\n"));
674 return STATUS_NOT_IMPLEMENTED;
675}
676
677NTSTATUS vbsfSetFileInfo(PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension,
678 PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension,
679 PMRX_VBOX_FOBX pVBoxFobx,
680 PFILE_BASIC_INFORMATION pInfo,
681 BYTE SetAttrFlags)
682{
683 NTSTATUS Status = STATUS_SUCCESS;
684
685 int vrc;
686 PSHFLFSOBJINFO pSHFLFileInfo;
687
688 uint8_t *pHGCMBuffer = NULL;
689 uint32_t cbBuffer = 0;
690
691 Log(("VBOXSF: vbsfSetFileInfo: SetAttrFlags 0x%02X\n", SetAttrFlags));
692 Log(("VBOXSF: vbsfSetFileInfo: FileBasicInformation: CreationTime %RX64\n", pInfo->CreationTime.QuadPart));
693 Log(("VBOXSF: vbsfSetFileInfo: FileBasicInformation: LastAccessTime %RX64\n", pInfo->LastAccessTime.QuadPart));
694 Log(("VBOXSF: vbsfSetFileInfo: FileBasicInformation: LastWriteTime %RX64\n", pInfo->LastWriteTime.QuadPart));
695 Log(("VBOXSF: vbsfSetFileInfo: FileBasicInformation: ChangeTime %RX64\n", pInfo->ChangeTime.QuadPart));
696 Log(("VBOXSF: vbsfSetFileInfo: FileBasicInformation: FileAttributes %RX32\n", pInfo->FileAttributes));
697
698 if (SetAttrFlags == 0)
699 {
700 Log(("VBOXSF: vbsfSetFileInfo: nothing to set\n"));
701 return STATUS_SUCCESS;
702 }
703
704 cbBuffer = sizeof(SHFLFSOBJINFO);
705 pHGCMBuffer = (uint8_t *)vbsfAllocNonPagedMem(cbBuffer);
706 if (!pHGCMBuffer)
707 {
708 AssertFailed();
709 return STATUS_INSUFFICIENT_RESOURCES;
710 }
711 RtlZeroMemory(pHGCMBuffer, cbBuffer);
712 pSHFLFileInfo = (PSHFLFSOBJINFO)pHGCMBuffer;
713
714 /* The properties, that need to be changed, are set to something other than zero */
715 if (pInfo->CreationTime.QuadPart && (SetAttrFlags & VBOX_FOBX_F_INFO_CREATION_TIME) != 0)
716 RTTimeSpecSetNtTime(&pSHFLFileInfo->BirthTime, pInfo->CreationTime.QuadPart);
717 if (pInfo->LastAccessTime.QuadPart && (SetAttrFlags & VBOX_FOBX_F_INFO_LASTACCESS_TIME) != 0)
718 RTTimeSpecSetNtTime(&pSHFLFileInfo->AccessTime, pInfo->LastAccessTime.QuadPart);
719 if (pInfo->LastWriteTime.QuadPart && (SetAttrFlags & VBOX_FOBX_F_INFO_LASTWRITE_TIME) != 0)
720 RTTimeSpecSetNtTime(&pSHFLFileInfo->ModificationTime, pInfo->LastWriteTime.QuadPart);
721 if (pInfo->ChangeTime.QuadPart && (SetAttrFlags & VBOX_FOBX_F_INFO_CHANGE_TIME) != 0)
722 RTTimeSpecSetNtTime(&pSHFLFileInfo->ChangeTime, pInfo->ChangeTime.QuadPart);
723 if (pInfo->FileAttributes && (SetAttrFlags & VBOX_FOBX_F_INFO_ATTRIBUTES) != 0)
724 pSHFLFileInfo->Attr.fMode = NTToVBoxFileAttributes(pInfo->FileAttributes);
725
726 vrc = VbglR0SfFsInfo(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile,
727 SHFL_INFO_SET | SHFL_INFO_FILE, &cbBuffer, (PSHFLDIRINFO)pSHFLFileInfo);
728
729 if (vrc != VINF_SUCCESS)
730 Status = VBoxErrorToNTStatus(vrc);
731
732 if (pHGCMBuffer)
733 vbsfFreeNonPagedMem(pHGCMBuffer);
734
735 Log(("VBOXSF: vbsfSetFileInfo: Returned 0x%08X\n", Status));
736 return Status;
737}
738
739/*
740 * Closes an opened file handle of a MRX_VBOX_FOBX.
741 * Updates file attributes if necessary.
742 */
743NTSTATUS vbsfCloseFileHandle(PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension,
744 PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension,
745 PMRX_VBOX_FOBX pVBoxFobx)
746{
747 NTSTATUS Status = STATUS_SUCCESS;
748
749 int vrc;
750
751 if (pVBoxFobx->hFile == SHFL_HANDLE_NIL)
752 {
753 Log(("VBOXSF: vbsfCloseFileHandle: SHFL_HANDLE_NIL\n"));
754 return STATUS_SUCCESS;
755 }
756
757 Log(("VBOXSF: vbsfCloseFileHandle: 0x%RX64, on close info 0x%02X\n",
758 pVBoxFobx->hFile, pVBoxFobx->SetFileInfoOnCloseFlags));
759
760 if (pVBoxFobx->SetFileInfoOnCloseFlags)
761 {
762 /* If the file timestamps were set by the user, then update them before closing the handle,
763 * to cancel any effect of the file read/write operations on the host.
764 */
765 Status = vbsfSetFileInfo(pDeviceExtension,
766 pNetRootExtension,
767 pVBoxFobx,
768 &pVBoxFobx->FileBasicInfo,
769 pVBoxFobx->SetFileInfoOnCloseFlags);
770 }
771
772 vrc = VbglR0SfClose(&pDeviceExtension->hgcmClient,
773 &pNetRootExtension->map,
774 pVBoxFobx->hFile);
775
776 pVBoxFobx->hFile = SHFL_HANDLE_NIL;
777
778 if (vrc != VINF_SUCCESS)
779 Status = VBoxErrorToNTStatus(vrc);
780
781 Log(("VBOXSF: vbsfCloseFileHandle: Returned 0x%08X\n", Status));
782 return Status;
783}
784
785NTSTATUS VBoxMRxCloseSrvOpen(IN PRX_CONTEXT RxContext)
786{
787 NTSTATUS Status = STATUS_SUCCESS;
788
789 RxCaptureFcb;
790 RxCaptureFobx;
791
792 PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext);
793 PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = VBoxMRxGetNetRootExtension(capFcb->pNetRoot);
794 PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);
795 PMRX_SRV_OPEN pSrvOpen = capFobx->pSrvOpen;
796
797 PUNICODE_STRING RemainingName = NULL;
798
799 Log(("VBOXSF: MRxCloseSrvOpen: capFcb = %p, capFobx = %p, pVBoxFobx = %p, pSrvOpen = %p\n",
800 capFcb, capFobx, pVBoxFobx, pSrvOpen));
801
802 RemainingName = pSrvOpen->pAlreadyPrefixedName;
803
804 Log(("VBOXSF: MRxCloseSrvOpen: Remaining name = %.*ls, Len = %d\n",
805 RemainingName->Length / sizeof(WCHAR), RemainingName->Buffer, RemainingName->Length));
806
807 if (!pVBoxFobx)
808 return STATUS_INVALID_PARAMETER;
809
810 if (FlagOn(pSrvOpen->Flags, (SRVOPEN_FLAG_FILE_RENAMED | SRVOPEN_FLAG_FILE_DELETED)))
811 {
812 /* If we renamed or delete the file/dir, then it's already closed */
813 Assert(pVBoxFobx->hFile == SHFL_HANDLE_NIL);
814 Log(("VBOXSF: MRxCloseSrvOpen: File was renamed, handle 0x%RX64 ignore close.\n",
815 pVBoxFobx->hFile));
816 return STATUS_SUCCESS;
817 }
818
819 /* Close file */
820 if (pVBoxFobx->hFile != SHFL_HANDLE_NIL)
821 vbsfCloseFileHandle(pDeviceExtension, pNetRootExtension, pVBoxFobx);
822
823 if (capFcb->FcbState & FCB_STATE_DELETE_ON_CLOSE)
824 {
825 Log(("VBOXSF: MRxCloseSrvOpen: Delete on close. Open count = %d\n",
826 capFcb->OpenCount));
827
828 /* Remove file or directory if delete action is pending. */
829 if (capFcb->OpenCount == 0)
830 Status = vbsfRemove(RxContext);
831 }
832
833 return Status;
834}
835
836NTSTATUS vbsfRemove(IN PRX_CONTEXT RxContext)
837{
838 NTSTATUS Status = STATUS_SUCCESS;
839
840 RxCaptureFcb;
841 RxCaptureFobx;
842
843 PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext);
844 PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = VBoxMRxGetNetRootExtension(capFcb->pNetRoot);
845 PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);
846
847 PUNICODE_STRING RemainingName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
848
849 int vrc;
850 PSHFLSTRING ParsedPath = NULL;
851
852 Log(("VBOXSF: vbsfRemove: Delete %.*ls. open count = %d\n",
853 RemainingName->Length / sizeof(WCHAR), RemainingName->Buffer, capFcb->OpenCount));
854
855 /* Close file first if not already done. */
856 if (pVBoxFobx->hFile != SHFL_HANDLE_NIL)
857 vbsfCloseFileHandle(pDeviceExtension, pNetRootExtension, pVBoxFobx);
858
859 Log(("VBOXSF: vbsfRemove: RemainingName->Length %d\n", RemainingName->Length));
860 Status = vbsfShflStringFromUnicodeAlloc(&ParsedPath, RemainingName->Buffer, RemainingName->Length);
861 if (Status != STATUS_SUCCESS)
862 return Status;
863
864 /* Call host. */
865 vrc = VbglR0SfRemove(&pDeviceExtension->hgcmClient, &pNetRootExtension->map,
866 ParsedPath,
867 (pVBoxFobx->FileStandardInfo.Directory) ? SHFL_REMOVE_DIR : SHFL_REMOVE_FILE);
868
869 if (ParsedPath)
870 vbsfFreeNonPagedMem(ParsedPath);
871
872 if (vrc == VINF_SUCCESS)
873 SetFlag(capFobx->pSrvOpen->Flags, SRVOPEN_FLAG_FILE_DELETED);
874
875 Status = VBoxErrorToNTStatus(vrc);
876 if (vrc != VINF_SUCCESS)
877 Log(("VBOXSF: vbsfRemove: VbglR0SfRemove failed with %Rrc\n", vrc));
878
879 Log(("VBOXSF: vbsfRemove: Returned 0x%08X\n", Status));
880 return Status;
881}
882
883NTSTATUS vbsfRename(IN PRX_CONTEXT RxContext,
884 IN FILE_INFORMATION_CLASS FileInformationClass,
885 IN PVOID pBuffer,
886 IN ULONG BufferLength)
887{
888 NTSTATUS Status = STATUS_SUCCESS;
889
890 RxCaptureFcb;
891 RxCaptureFobx;
892
893 PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext);
894 PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = VBoxMRxGetNetRootExtension(capFcb->pNetRoot);
895 PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);
896 PMRX_SRV_OPEN pSrvOpen = capFobx->pSrvOpen;
897
898 PFILE_RENAME_INFORMATION RenameInformation = (PFILE_RENAME_INFORMATION)RxContext->Info.Buffer;
899 PUNICODE_STRING RemainingName = GET_ALREADY_PREFIXED_NAME(pSrvOpen, capFcb);
900
901 int vrc;
902 PSHFLSTRING SrcPath = 0, DestPath = 0;
903 ULONG flags;
904
905 RT_NOREF(FileInformationClass, pBuffer, BufferLength);
906
907 Assert(FileInformationClass == FileRenameInformation);
908
909 Log(("VBOXSF: vbsfRename: FileName = %.*ls\n",
910 RenameInformation->FileNameLength / sizeof(WCHAR), &RenameInformation->FileName[0]));
911
912 /* Must close the file before renaming it! */
913 if (pVBoxFobx->hFile != SHFL_HANDLE_NIL)
914 vbsfCloseFileHandle(pDeviceExtension, pNetRootExtension, pVBoxFobx);
915
916 /* Mark it as renamed, so we do nothing during close */
917 SetFlag(pSrvOpen->Flags, SRVOPEN_FLAG_FILE_RENAMED);
918
919 Log(("VBOXSF: vbsfRename: RenameInformation->FileNameLength = %d\n", RenameInformation->FileNameLength));
920 Status = vbsfShflStringFromUnicodeAlloc(&DestPath, RenameInformation->FileName, (uint16_t)RenameInformation->FileNameLength);
921 if (Status != STATUS_SUCCESS)
922 return Status;
923
924 Log(("VBOXSF: vbsfRename: Destination path = %.*ls\n",
925 DestPath->u16Length / sizeof(WCHAR), &DestPath->String.ucs2[0]));
926
927 Log(("VBOXSF: vbsfRename: RemainingName->Length = %d\n", RemainingName->Length));
928 Status = vbsfShflStringFromUnicodeAlloc(&SrcPath, RemainingName->Buffer, RemainingName->Length);
929 if (Status != STATUS_SUCCESS)
930 {
931 vbsfFreeNonPagedMem(DestPath);
932 return Status;
933 }
934
935 Log(("VBOXSF: vbsfRename: Source path = %.*ls\n",
936 SrcPath->u16Length / sizeof(WCHAR), &SrcPath->String.ucs2[0]));
937
938 /* Call host. */
939 flags = pVBoxFobx->FileStandardInfo.Directory? SHFL_RENAME_DIR : SHFL_RENAME_FILE;
940 if (RenameInformation->ReplaceIfExists)
941 flags |= SHFL_RENAME_REPLACE_IF_EXISTS;
942
943 Log(("VBOXSF: vbsfRename: Calling VbglR0SfRename\n"));
944 vrc = VbglR0SfRename(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, SrcPath, DestPath, flags);
945
946 vbsfFreeNonPagedMem(SrcPath);
947 vbsfFreeNonPagedMem(DestPath);
948
949 Status = VBoxErrorToNTStatus(vrc);
950 if (vrc != VINF_SUCCESS)
951 Log(("VBOXSF: vbsfRename: VbglR0SfRename failed with %Rrc\n", vrc));
952
953 Log(("VBOXSF: vbsfRename: Returned 0x%08X\n", Status));
954 return Status;
955}
956
957NTSTATUS VBoxMRxShouldTryToCollapseThisOpen(IN PRX_CONTEXT RxContext)
958{
959 RT_NOREF(RxContext);
960 Log(("VBOXSF: MRxShouldTryToCollapseThisOpen\n"));
961 return STATUS_MORE_PROCESSING_REQUIRED;
962}
963
964NTSTATUS VBoxMRxCollapseOpen(IN OUT PRX_CONTEXT RxContext)
965{
966 RT_NOREF(RxContext);
967 Log(("VBOXSF: MRxCollapseOpen\n"));
968 return STATUS_MORE_PROCESSING_REQUIRED;
969}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette