VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/SharedFolders/driver/path.cpp@ 78321

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

winnt/vboxsf: Doxygen and related cleanups; eliminating the separate helper header. bugref:9172

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