VirtualBox

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

Last change on this file since 61503 was 58195, checked in by vboxsync, 10 years ago

VBoxGuestR0LibSharedFolders: Prefixed functions ('vbox' wasn't a very good one). Hope I found all places these functions are called...

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

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