VirtualBox

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

Last change on this file since 52560 was 51997, checked in by vboxsync, 10 years ago

include,Main,Additions: SHFLSTRING cleanup.

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