VirtualBox

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

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

winnt/vboxsf: Simplified file attribute conversion and made sure the result is never zero. bugref:9172

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