VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/SharedFolders/driver/info.c@ 75761

Last change on this file since 75761 was 75654, checked in by vboxsync, 7 years ago

win/VBoxSF: Implement restarting directory listing (RxContext->QueryDirectory.RestartScan == TRUE).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 60.9 KB
Line 
1/* $Id: info.c 75654 2018-11-21 21:02:14Z vboxsync $ */
2/** @file
3 *
4 * VirtualBox Windows Guest Shared Folders
5 *
6 * File System Driver query and set information routines
7 */
8
9/*
10 * Copyright (C) 2012-2017 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
23/** Macro for copying a SHFLSTRING file name into a FILE_DIRECTORY_INFORMATION structure. */
24#define INIT_FILE_NAME(obj, str) \
25 do { \
26 ULONG cbLength = (str).u16Length; \
27 (obj)->FileNameLength = cbLength; \
28 RtlCopyMemory((obj)->FileName, &(str).String.ucs2[0], cbLength + 2); \
29 } while (0)
30
31NTSTATUS VBoxMRxQueryDirectory(IN OUT PRX_CONTEXT RxContext)
32{
33 NTSTATUS Status = STATUS_SUCCESS;
34
35 RxCaptureFobx;
36 RxCaptureFcb;
37
38 PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext);
39 PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = VBoxMRxGetNetRootExtension(capFcb->pNetRoot);
40 PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);
41
42 PUNICODE_STRING DirectoryName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
43 PUNICODE_STRING Template = &capFobx->UnicodeQueryTemplate;
44 FILE_INFORMATION_CLASS FileInformationClass = RxContext->Info.FileInformationClass;
45 PCHAR pInfoBuffer = (PCHAR)RxContext->Info.Buffer;
46 LONG cbMaxSize = RxContext->Info.Length;
47 LONG *pLengthRemaining = (LONG *)&RxContext->Info.LengthRemaining;
48
49 LONG cbToCopy;
50 int vboxRC;
51 uint8_t *pHGCMBuffer;
52 uint32_t index, fSFFlags, cFiles, u32BufSize;
53 LONG cbHGCMBuffer;
54 PSHFLDIRINFO pDirEntry;
55
56 ULONG *pNextOffset = 0;
57 PSHFLSTRING ParsedPath = NULL;
58
59 Log(("VBOXSF: MrxQueryDirectory: FileInformationClass %d, pVBoxFobx %p, hFile %RX64, pInfoBuffer %p\n",
60 FileInformationClass, pVBoxFobx, pVBoxFobx->hFile, pInfoBuffer));
61
62 if (!pVBoxFobx)
63 {
64 Log(("VBOXSF: MrxQueryDirectory: pVBoxFobx is invalid!\n"));
65 return STATUS_INVALID_PARAMETER;
66 }
67
68 if (!DirectoryName)
69 return STATUS_INVALID_PARAMETER;
70
71 if (DirectoryName->Length == 0)
72 Log(("VBOXSF: MrxQueryDirectory: DirectoryName = \\ (null string)\n"));
73 else
74 Log(("VBOXSF: MrxQueryDirectory: DirectoryName = %.*ls\n",
75 DirectoryName->Length / sizeof(WCHAR), DirectoryName->Buffer));
76
77 if (!Template)
78 return STATUS_INVALID_PARAMETER;
79
80 if (Template->Length == 0)
81 Log(("VBOXSF: MrxQueryDirectory: Template = \\ (null string)\n"));
82 else
83 Log(("VBOXSF: MrxQueryDirectory: Template = %.*ls\n",
84 Template->Length / sizeof(WCHAR), Template->Buffer));
85
86 cbHGCMBuffer = RT_MAX(cbMaxSize, PAGE_SIZE);
87
88 Log(("VBOXSF: MrxQueryDirectory: Allocating cbHGCMBuffer = %d\n",
89 cbHGCMBuffer));
90
91 pHGCMBuffer = (uint8_t *)vbsfAllocNonPagedMem(cbHGCMBuffer);
92 if (!pHGCMBuffer)
93 {
94 AssertFailed();
95 return STATUS_INSUFFICIENT_RESOURCES;
96 }
97
98 /* Assume start from the beginning. */
99 index = 0;
100 if (RxContext->QueryDirectory.IndexSpecified == TRUE)
101 {
102 Log(("VBOXSF: MrxQueryDirectory: Index specified %d\n",
103 index));
104 index = RxContext->QueryDirectory.FileIndex;
105 }
106
107 fSFFlags = SHFL_LIST_NONE;
108 if (RxContext->QueryDirectory.ReturnSingleEntry == TRUE)
109 {
110 Log(("VBOXSF: MrxQueryDirectory: Query single entry\n"));
111 fSFFlags |= SHFL_LIST_RETURN_ONE;
112 }
113 if ( RxContext->QueryDirectory.RestartScan == TRUE
114 && RxContext->QueryDirectory.InitialQuery == FALSE)
115 {
116 Log(("VBOXSF: MrxQueryDirectory: Restart scan\n"));
117 fSFFlags |= SHFL_LIST_RESTART;
118 }
119
120 if (Template->Length)
121 {
122 ULONG ParsedPathSize, cch;
123
124 /* Calculate size required for parsed path: dir + \ + template + 0. */
125 ParsedPathSize = SHFLSTRING_HEADER_SIZE + Template->Length + sizeof(WCHAR);
126 if (DirectoryName->Length)
127 ParsedPathSize += DirectoryName->Length + sizeof(WCHAR);
128 Log(("VBOXSF: MrxQueryDirectory: ParsedPathSize = %d\n", ParsedPathSize));
129
130 ParsedPath = (PSHFLSTRING)vbsfAllocNonPagedMem(ParsedPathSize);
131 if (!ParsedPath)
132 {
133 Status = STATUS_INSUFFICIENT_RESOURCES;
134 goto end;
135 }
136
137 if (!ShflStringInitBuffer(ParsedPath, ParsedPathSize))
138 {
139 Status = STATUS_INSUFFICIENT_RESOURCES;
140 goto end;
141 }
142
143 cch = 0;
144 if (DirectoryName->Length)
145 {
146 /* Copy directory name into ParsedPath. */
147 RtlCopyMemory(ParsedPath->String.ucs2, DirectoryName->Buffer, DirectoryName->Length);
148 cch += DirectoryName->Length / sizeof(WCHAR);
149
150 /* Add terminating backslash. */
151 ParsedPath->String.ucs2[cch] = L'\\';
152 cch++;
153 }
154
155 RtlCopyMemory (&ParsedPath->String.ucs2[cch], Template->Buffer, Template->Length);
156 cch += Template->Length / sizeof(WCHAR);
157
158 /* Add terminating nul. */
159 ParsedPath->String.ucs2[cch] = 0;
160
161 /* cch is the number of chars without trailing nul. */
162 ParsedPath->u16Length = (uint16_t)(cch * sizeof(WCHAR));
163
164 AssertMsg(ParsedPath->u16Length + sizeof(WCHAR) == ParsedPath->u16Size,
165 ("u16Length %d, u16Size %d\n", ParsedPath->u16Length, ParsedPath->u16Size));
166
167 Log(("VBOXSF: MrxQueryDirectory: ParsedPath = %.*ls\n",
168 ParsedPath->u16Length / sizeof(WCHAR), ParsedPath->String.ucs2));
169 }
170
171 cFiles = 0;
172
173 /* VbglR0SfDirInfo requires a pointer to uint32_t. */
174 u32BufSize = cbHGCMBuffer;
175
176 Log(("VBOXSF: MrxQueryDirectory: CallDirInfo: File = 0x%08x, Flags = 0x%08x, Index = %d, u32BufSize = %d\n",
177 pVBoxFobx->hFile, fSFFlags, index, u32BufSize));
178 vboxRC = VbglR0SfDirInfo(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile,
179 ParsedPath, fSFFlags, index, &u32BufSize, (PSHFLDIRINFO)pHGCMBuffer, &cFiles);
180 Log(("VBOXSF: MrxQueryDirectory: u32BufSize after CallDirInfo = %d, rc = %Rrc\n",
181 u32BufSize, vboxRC));
182
183 switch (vboxRC)
184 {
185 case VINF_SUCCESS:
186 /* Nothing to do here. */
187 break;
188
189 case VERR_NO_TRANSLATION:
190 Log(("VBOXSF: MrxQueryDirectory: Host could not translate entry!\n"));
191 break;
192
193 case VERR_NO_MORE_FILES:
194 if (cFiles <= 0) /* VERR_NO_MORE_FILES appears at the first lookup when just returning the current dir ".".
195 * So we also have to check for the cFiles counter. */
196 {
197 /* Not an error, but we have to handle the return value. */
198 Log(("VBOXSF: MrxQueryDirectory: Host reported no more files!\n"));
199
200 if (RxContext->QueryDirectory.InitialQuery)
201 {
202 /* First call. MSDN on FindFirstFile: "If the function fails because no matching files
203 * can be found, the GetLastError function returns ERROR_FILE_NOT_FOUND."
204 * So map this rc to file not found.
205 */
206 Status = STATUS_NO_SUCH_FILE;
207 }
208 else
209 {
210 /* Search continued. */
211 Status = STATUS_NO_MORE_FILES;
212 }
213 }
214 break;
215
216 case VERR_FILE_NOT_FOUND:
217 Status = STATUS_NO_SUCH_FILE;
218 Log(("VBOXSF: MrxQueryDirectory: no such file!\n"));
219 break;
220
221 default:
222 Status = VBoxErrorToNTStatus(vboxRC);
223 Log(("VBOXSF: MrxQueryDirectory: Error %Rrc from CallDirInfo (cFiles=%d)!\n",
224 vboxRC, cFiles));
225 break;
226 }
227
228 if (Status != STATUS_SUCCESS)
229 goto end;
230
231 /* Verify that the returned buffer length is not greater than the original one. */
232 if (u32BufSize > (uint32_t)cbHGCMBuffer)
233 {
234 Log(("VBOXSF: MrxQueryDirectory: returned buffer size (%u) is invalid!!!\n",
235 u32BufSize));
236 Status = STATUS_INVALID_NETWORK_RESPONSE;
237 goto end;
238 }
239
240 /* How many bytes remain in the buffer. */
241 cbHGCMBuffer = u32BufSize;
242
243 pDirEntry = (PSHFLDIRINFO)pHGCMBuffer;
244 Status = STATUS_SUCCESS;
245
246 Log(("VBOXSF: MrxQueryDirectory: cFiles=%d, Length=%d\n",
247 cFiles, cbHGCMBuffer));
248
249 while ((*pLengthRemaining) && (cFiles > 0) && (pDirEntry != NULL))
250 {
251 int cbEntry = RT_UOFFSETOF(SHFLDIRINFO, name.String) + pDirEntry->name.u16Size;
252
253 if (cbEntry > cbHGCMBuffer)
254 {
255 Log(("VBOXSF: MrxQueryDirectory: Entry size (%d) exceeds the buffer size (%d)!!!\n",
256 cbEntry, cbHGCMBuffer));
257 Status = STATUS_INVALID_NETWORK_RESPONSE;
258 goto end;
259 }
260
261 switch (FileInformationClass)
262 {
263 case FileDirectoryInformation:
264 {
265 PFILE_DIRECTORY_INFORMATION pInfo = (PFILE_DIRECTORY_INFORMATION)pInfoBuffer;
266 Log(("VBOXSF: MrxQueryDirectory: FileDirectoryInformation\n"));
267
268 cbToCopy = sizeof(FILE_DIRECTORY_INFORMATION);
269 /* Struct already contains one char for null terminator. */
270 cbToCopy += pDirEntry->name.u16Size;
271
272 if (*pLengthRemaining >= cbToCopy)
273 {
274 RtlZeroMemory(pInfo, cbToCopy);
275
276 pInfo->CreationTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.BirthTime); /* ridiculous name */
277 pInfo->LastAccessTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.AccessTime);
278 pInfo->LastWriteTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.ModificationTime);
279 pInfo->ChangeTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.ChangeTime);
280 pInfo->AllocationSize.QuadPart = pDirEntry->Info.cbAllocated;
281 pInfo->EndOfFile.QuadPart = pDirEntry->Info.cbObject;
282 pInfo->FileIndex = index;
283 pInfo->FileAttributes = VBoxToNTFileAttributes(pDirEntry->Info.Attr.fMode);
284
285 INIT_FILE_NAME(pInfo, pDirEntry->name);
286
287 /* Align to 8 byte boundary */
288 cbToCopy = RT_ALIGN(cbToCopy, sizeof(LONGLONG));
289 pInfo->NextEntryOffset = cbToCopy;
290 pNextOffset = &pInfo->NextEntryOffset;
291 }
292 else
293 {
294 pInfo->NextEntryOffset = 0; /* last item */
295 Status = STATUS_BUFFER_OVERFLOW;
296 }
297 break;
298 }
299
300 case FileFullDirectoryInformation:
301 {
302 PFILE_FULL_DIR_INFORMATION pInfo = (PFILE_FULL_DIR_INFORMATION)pInfoBuffer;
303 Log(("VBOXSF: MrxQueryDirectory: FileFullDirectoryInformation\n"));
304
305 cbToCopy = sizeof(FILE_FULL_DIR_INFORMATION);
306 /* Struct already contains one char for null terminator. */
307 cbToCopy += pDirEntry->name.u16Size;
308
309 if (*pLengthRemaining >= cbToCopy)
310 {
311 RtlZeroMemory(pInfo, cbToCopy);
312
313 pInfo->CreationTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.BirthTime); /* ridiculous name */
314 pInfo->LastAccessTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.AccessTime);
315 pInfo->LastWriteTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.ModificationTime);
316 pInfo->ChangeTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.ChangeTime);
317 pInfo->AllocationSize.QuadPart = pDirEntry->Info.cbAllocated;
318 pInfo->EndOfFile.QuadPart = pDirEntry->Info.cbObject;
319 pInfo->EaSize = 0;
320 pInfo->FileIndex = index;
321 pInfo->FileAttributes = VBoxToNTFileAttributes(pDirEntry->Info.Attr.fMode);
322
323 INIT_FILE_NAME(pInfo, pDirEntry->name);
324
325 /* Align to 8 byte boundary */
326 cbToCopy = RT_ALIGN(cbToCopy, sizeof(LONGLONG));
327 pInfo->NextEntryOffset = cbToCopy;
328 pNextOffset = &pInfo->NextEntryOffset;
329 }
330 else
331 {
332 pInfo->NextEntryOffset = 0; /* last item */
333 Status = STATUS_BUFFER_OVERFLOW;
334 }
335 break;
336 }
337
338 case FileBothDirectoryInformation:
339 {
340 PFILE_BOTH_DIR_INFORMATION pInfo = (PFILE_BOTH_DIR_INFORMATION)pInfoBuffer;
341 Log(("VBOXSF: MrxQueryDirectory: FileBothDirectoryInformation\n"));
342
343 cbToCopy = sizeof(FILE_BOTH_DIR_INFORMATION);
344 /* struct already contains one char for null terminator */
345 cbToCopy += pDirEntry->name.u16Size;
346
347 if (*pLengthRemaining >= cbToCopy)
348 {
349 RtlZeroMemory(pInfo, cbToCopy);
350
351 pInfo->CreationTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.BirthTime); /* ridiculous name */
352 pInfo->LastAccessTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.AccessTime);
353 pInfo->LastWriteTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.ModificationTime);
354 pInfo->ChangeTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.ChangeTime);
355 pInfo->AllocationSize.QuadPart = pDirEntry->Info.cbAllocated;
356 pInfo->EndOfFile.QuadPart = pDirEntry->Info.cbObject;
357 pInfo->EaSize = 0;
358 pInfo->ShortNameLength = 0; /** @todo ? */
359 pInfo->FileIndex = index;
360 pInfo->FileAttributes = VBoxToNTFileAttributes(pDirEntry->Info.Attr.fMode);
361
362 INIT_FILE_NAME(pInfo, pDirEntry->name);
363
364 Log(("VBOXSF: MrxQueryDirectory: FileBothDirectoryInformation cbAlloc = %x cbObject = %x\n",
365 pDirEntry->Info.cbAllocated, pDirEntry->Info.cbObject));
366 Log(("VBOXSF: MrxQueryDirectory: FileBothDirectoryInformation cbToCopy = %d, name size=%d name len=%d\n",
367 cbToCopy, pDirEntry->name.u16Size, pDirEntry->name.u16Length));
368 Log(("VBOXSF: MrxQueryDirectory: FileBothDirectoryInformation File name %.*ls (DirInfo)\n",
369 pInfo->FileNameLength / sizeof(WCHAR), pInfo->FileName));
370 Log(("VBOXSF: MrxQueryDirectory: FileBothDirectoryInformation File name %.*ls (DirEntry)\n",
371 pDirEntry->name.u16Size / sizeof(WCHAR), pDirEntry->name.String.ucs2));
372
373 /* Align to 8 byte boundary. */
374 cbToCopy = RT_ALIGN(cbToCopy, sizeof(LONGLONG));
375 pInfo->NextEntryOffset = cbToCopy;
376 pNextOffset = &pInfo->NextEntryOffset;
377 }
378 else
379 {
380 pInfo->NextEntryOffset = 0; /* Last item. */
381 Status = STATUS_BUFFER_OVERFLOW;
382 }
383 break;
384 }
385
386 case FileIdBothDirectoryInformation:
387 {
388 PFILE_ID_BOTH_DIR_INFORMATION pInfo = (PFILE_ID_BOTH_DIR_INFORMATION)pInfoBuffer;
389 Log(("VBOXSF: MrxQueryDirectory: FileIdBothDirectoryInformation\n"));
390
391 cbToCopy = sizeof(FILE_ID_BOTH_DIR_INFORMATION);
392 /* struct already contains one char for null terminator */
393 cbToCopy += pDirEntry->name.u16Size;
394
395 if (*pLengthRemaining >= cbToCopy)
396 {
397 RtlZeroMemory(pInfo, cbToCopy);
398
399 pInfo->CreationTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.BirthTime); /* ridiculous name */
400 pInfo->LastAccessTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.AccessTime);
401 pInfo->LastWriteTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.ModificationTime);
402 pInfo->ChangeTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.ChangeTime);
403 pInfo->AllocationSize.QuadPart = pDirEntry->Info.cbAllocated;
404 pInfo->EndOfFile.QuadPart = pDirEntry->Info.cbObject;
405 pInfo->EaSize = 0;
406 pInfo->ShortNameLength = 0; /** @todo ? */
407 pInfo->EaSize = 0;
408 pInfo->FileId.QuadPart = 0;
409 pInfo->FileAttributes = VBoxToNTFileAttributes(pDirEntry->Info.Attr.fMode);
410
411 INIT_FILE_NAME(pInfo, pDirEntry->name);
412
413 Log(("VBOXSF: MrxQueryDirectory: FileIdBothDirectoryInformation cbAlloc = 0x%RX64 cbObject = 0x%RX64\n",
414 pDirEntry->Info.cbAllocated, pDirEntry->Info.cbObject));
415 Log(("VBOXSF: MrxQueryDirectory: FileIdBothDirectoryInformation cbToCopy = %d, name size=%d name len=%d\n",
416 cbToCopy, pDirEntry->name.u16Size, pDirEntry->name.u16Length));
417 Log(("VBOXSF: MrxQueryDirectory: FileIdBothDirectoryInformation File name %.*ls (DirInfo)\n",
418 pInfo->FileNameLength / sizeof(WCHAR), pInfo->FileName));
419 Log(("VBOXSF: MrxQueryDirectory: FileIdBothDirectoryInformation File name %.*ls (DirEntry)\n",
420 pDirEntry->name.u16Size / sizeof(WCHAR), pDirEntry->name.String.ucs2));
421
422 /* Align to 8 byte boundary. */
423 cbToCopy = RT_ALIGN(cbToCopy, sizeof(LONGLONG));
424 pInfo->NextEntryOffset = cbToCopy;
425 pNextOffset = &pInfo->NextEntryOffset;
426 }
427 else
428 {
429 pInfo->NextEntryOffset = 0; /* Last item. */
430 Status = STATUS_BUFFER_OVERFLOW;
431 }
432 break;
433 }
434
435 case FileNamesInformation:
436 {
437 PFILE_NAMES_INFORMATION pInfo = (PFILE_NAMES_INFORMATION)pInfoBuffer;
438 Log(("VBOXSF: MrxQueryDirectory: FileNamesInformation\n"));
439
440 cbToCopy = sizeof(FILE_NAMES_INFORMATION);
441 /* Struct already contains one char for null terminator. */
442 cbToCopy += pDirEntry->name.u16Size;
443
444 if (*pLengthRemaining >= cbToCopy)
445 {
446 RtlZeroMemory(pInfo, cbToCopy);
447
448 pInfo->FileIndex = index;
449
450 INIT_FILE_NAME(pInfo, pDirEntry->name);
451
452 Log(("VBOXSF: MrxQueryDirectory: FileNamesInformation: File name [%.*ls]\n",
453 pInfo->FileNameLength / sizeof(WCHAR), pInfo->FileName));
454
455 /* Align to 8 byte boundary. */
456 cbToCopy = RT_ALIGN(cbToCopy, sizeof(LONGLONG));
457 pInfo->NextEntryOffset = cbToCopy;
458 pNextOffset = &pInfo->NextEntryOffset;
459 }
460 else
461 {
462 pInfo->NextEntryOffset = 0; /* Last item. */
463 Status = STATUS_BUFFER_OVERFLOW;
464 }
465 break;
466 }
467
468 default:
469 Log(("VBOXSF: MrxQueryDirectory: Not supported FileInformationClass %d!\n",
470 FileInformationClass));
471 Status = STATUS_INVALID_PARAMETER;
472 goto end;
473 }
474
475 cbHGCMBuffer -= cbEntry;
476 pDirEntry = (PSHFLDIRINFO)((uintptr_t)pDirEntry + cbEntry);
477
478 Log(("VBOXSF: MrxQueryDirectory: %d bytes left in HGCM buffer\n",
479 cbHGCMBuffer));
480
481 if (*pLengthRemaining >= cbToCopy)
482 {
483 pInfoBuffer += cbToCopy;
484 *pLengthRemaining -= cbToCopy;
485 }
486 else
487 break;
488
489 if (RxContext->QueryDirectory.ReturnSingleEntry)
490 break;
491
492 /* More left? */
493 if (cbHGCMBuffer <= 0)
494 break;
495
496 index++; /* File Index. */
497
498 cFiles--;
499 }
500
501 if (pNextOffset)
502 *pNextOffset = 0; /* Last pInfo->NextEntryOffset should be set to zero! */
503
504end:
505 if (pHGCMBuffer)
506 vbsfFreeNonPagedMem(pHGCMBuffer);
507
508 if (ParsedPath)
509 vbsfFreeNonPagedMem(ParsedPath);
510
511 Log(("VBOXSF: MrxQueryDirectory: Returned 0x%08X\n",
512 Status));
513 return Status;
514}
515
516NTSTATUS VBoxMRxQueryVolumeInfo(IN OUT PRX_CONTEXT RxContext)
517{
518 NTSTATUS Status;
519
520 RxCaptureFcb;
521 RxCaptureFobx;
522
523 PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext);
524 PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = VBoxMRxGetNetRootExtension(capFcb->pNetRoot);
525 PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);
526
527 FS_INFORMATION_CLASS FsInformationClass = RxContext->Info.FsInformationClass;
528 PVOID pInfoBuffer = RxContext->Info.Buffer;
529 ULONG cbInfoBuffer = RxContext->Info.LengthRemaining;
530 ULONG cbToCopy = 0;
531 ULONG cbString = 0;
532
533 Log(("VBOXSF: MrxQueryVolumeInfo: pInfoBuffer = %p, cbInfoBuffer = %d\n",
534 RxContext->Info.Buffer, RxContext->Info.LengthRemaining));
535 Log(("VBOXSF: MrxQueryVolumeInfo: vboxFobx = %p, Handle = 0x%RX64\n",
536 pVBoxFobx, pVBoxFobx? pVBoxFobx->hFile: 0));
537
538 Status = STATUS_INVALID_PARAMETER;
539
540 switch (FsInformationClass)
541 {
542 case FileFsVolumeInformation:
543 {
544 PFILE_FS_VOLUME_INFORMATION pInfo = (PFILE_FS_VOLUME_INFORMATION)pInfoBuffer;
545
546 PMRX_NET_ROOT pNetRoot = capFcb->pNetRoot;
547 PMRX_SRV_CALL pSrvCall = pNetRoot->pSrvCall;
548
549 PWCHAR pRootName;
550 ULONG cbRootName;
551
552 PSHFLVOLINFO pShflVolInfo;
553 uint32_t cbHGCMBuffer;
554 uint8_t *pHGCMBuffer;
555 int vboxRC;
556
557 Log(("VBOXSF: MrxQueryVolumeInfo: FileFsVolumeInformation\n"));
558
559 if (!pVBoxFobx)
560 {
561 Log(("VBOXSF: MrxQueryVolumeInfo: pVBoxFobx is NULL!\n"));
562 Status = STATUS_INVALID_PARAMETER;
563 break;
564 }
565
566 cbRootName = pNetRoot->pNetRootName->Length - pSrvCall->pSrvCallName->Length;
567 cbRootName -= sizeof(WCHAR); /* Remove the leading backslash. */
568 pRootName = pNetRoot->pNetRootName->Buffer + (pSrvCall->pSrvCallName->Length / sizeof(WCHAR));
569 pRootName++; /* Remove the leading backslash. */
570
571 Log(("VBOXSF: MrxQueryVolumeInfo: FileFsVolumeInformation: Root name = %.*ls, %d bytes\n",
572 cbRootName / sizeof(WCHAR), pRootName, cbRootName));
573
574 cbToCopy = FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel);
575
576 cbString = VBOX_VOLNAME_PREFIX_SIZE;
577 cbString += cbRootName;
578 cbString += sizeof(WCHAR);
579
580 Log(("VBOXSF: MrxQueryVolumeInfo: FileFsVolumeInformation: cbToCopy %d, cbString %d\n",
581 cbToCopy, cbString));
582
583 if (cbInfoBuffer < cbToCopy)
584 {
585 Status = STATUS_BUFFER_TOO_SMALL;
586 break;
587 }
588
589 RtlZeroMemory(pInfo, cbToCopy);
590
591 /* Query serial number. */
592 cbHGCMBuffer = sizeof(SHFLVOLINFO);
593 pHGCMBuffer = (uint8_t *)vbsfAllocNonPagedMem(cbHGCMBuffer);
594 if (!pHGCMBuffer)
595 {
596 Status = STATUS_INSUFFICIENT_RESOURCES;
597 break;
598 }
599
600 vboxRC = VbglR0SfFsInfo(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile,
601 SHFL_INFO_GET | SHFL_INFO_VOLUME, &cbHGCMBuffer, (PSHFLDIRINFO)pHGCMBuffer);
602
603 if (vboxRC != VINF_SUCCESS)
604 {
605 Status = VBoxErrorToNTStatus(vboxRC);
606 vbsfFreeNonPagedMem(pHGCMBuffer);
607 break;
608 }
609
610 pShflVolInfo = (PSHFLVOLINFO)pHGCMBuffer;
611 pInfo->VolumeSerialNumber = pShflVolInfo->ulSerial;
612 vbsfFreeNonPagedMem(pHGCMBuffer);
613
614 pInfo->VolumeCreationTime.QuadPart = 0;
615 pInfo->SupportsObjects = FALSE;
616
617 if (cbInfoBuffer >= cbToCopy + cbString)
618 {
619 RtlCopyMemory(&pInfo->VolumeLabel[0],
620 VBOX_VOLNAME_PREFIX,
621 VBOX_VOLNAME_PREFIX_SIZE);
622 RtlCopyMemory(&pInfo->VolumeLabel[VBOX_VOLNAME_PREFIX_SIZE / sizeof(WCHAR)],
623 pRootName,
624 cbRootName);
625 pInfo->VolumeLabel[cbString / sizeof(WCHAR) - 1] = 0;
626 }
627 else
628 {
629 cbString = cbInfoBuffer - cbToCopy;
630
631 RtlCopyMemory(&pInfo->VolumeLabel[0],
632 VBOX_VOLNAME_PREFIX,
633 RT_MIN(cbString, VBOX_VOLNAME_PREFIX_SIZE));
634 if (cbString > VBOX_VOLNAME_PREFIX_SIZE)
635 {
636 RtlCopyMemory(&pInfo->VolumeLabel[VBOX_VOLNAME_PREFIX_SIZE / sizeof(WCHAR)],
637 pRootName,
638 cbString - VBOX_VOLNAME_PREFIX_SIZE);
639 }
640 }
641
642 pInfo->VolumeLabelLength = cbString;
643
644 cbToCopy += cbString;
645
646 Log(("VBOXSF: MrxQueryVolumeInfo: FileFsVolumeInformation: VolumeLabelLength %d\n",
647 pInfo->VolumeLabelLength));
648
649 Status = STATUS_SUCCESS;
650 break;
651 }
652
653 case FileFsLabelInformation:
654 {
655 PFILE_FS_LABEL_INFORMATION pInfo = (PFILE_FS_LABEL_INFORMATION)pInfoBuffer;
656
657 PMRX_NET_ROOT pNetRoot = capFcb->pNetRoot;
658 PMRX_SRV_CALL pSrvCall = pNetRoot->pSrvCall;
659
660 PWCHAR pRootName;
661 ULONG cbRootName;
662
663 Log(("VBOXSF: MrxQueryVolumeInfo: FileFsLabelInformation\n"));
664
665 cbRootName = pNetRoot->pNetRootName->Length - pSrvCall->pSrvCallName->Length;
666 cbRootName -= sizeof(WCHAR); /* Remove the leading backslash. */
667 pRootName = pNetRoot->pNetRootName->Buffer + (pSrvCall->pSrvCallName->Length / sizeof(WCHAR));
668 pRootName++; /* Remove the leading backslash. */
669
670 Log(("VBOXSF: MrxQueryVolumeInfo: FileFsLabelInformation: Root name = %.*ls, %d bytes\n",
671 cbRootName / sizeof(WCHAR), pRootName, cbRootName));
672
673 cbToCopy = FIELD_OFFSET(FILE_FS_LABEL_INFORMATION, VolumeLabel);
674
675 cbString = VBOX_VOLNAME_PREFIX_SIZE;
676 cbString += cbRootName;
677 cbString += sizeof(WCHAR);
678
679 if (cbInfoBuffer < cbToCopy)
680 {
681 Status = STATUS_BUFFER_TOO_SMALL;
682 break;
683 }
684
685 RtlZeroMemory(pInfo, cbToCopy);
686
687 if (cbInfoBuffer >= cbToCopy + cbString)
688 {
689 RtlCopyMemory(&pInfo->VolumeLabel[0],
690 VBOX_VOLNAME_PREFIX,
691 VBOX_VOLNAME_PREFIX_SIZE);
692 RtlCopyMemory(&pInfo->VolumeLabel[VBOX_VOLNAME_PREFIX_SIZE / sizeof(WCHAR)],
693 pRootName,
694 cbRootName);
695 pInfo->VolumeLabel[cbString / sizeof(WCHAR) - 1] = 0;
696 }
697 else
698 {
699 cbString = cbInfoBuffer - cbToCopy;
700
701 RtlCopyMemory(&pInfo->VolumeLabel[0],
702 VBOX_VOLNAME_PREFIX,
703 RT_MIN(cbString, VBOX_VOLNAME_PREFIX_SIZE));
704 if (cbString > VBOX_VOLNAME_PREFIX_SIZE)
705 {
706 RtlCopyMemory(&pInfo->VolumeLabel[VBOX_VOLNAME_PREFIX_SIZE / sizeof(WCHAR)],
707 pRootName,
708 cbString - VBOX_VOLNAME_PREFIX_SIZE);
709 }
710 }
711
712 pInfo->VolumeLabelLength = cbString;
713
714 cbToCopy += cbString;
715
716 Log(("VBOXSF: MrxQueryVolumeInfo: FileFsLabelInformation: VolumeLabelLength %d\n",
717 pInfo->VolumeLabelLength));
718
719 Status = STATUS_SUCCESS;
720 break;
721 }
722
723 case FileFsFullSizeInformation:
724 case FileFsSizeInformation:
725 {
726 PFILE_FS_FULL_SIZE_INFORMATION pFullSizeInfo = (PFILE_FS_FULL_SIZE_INFORMATION)pInfoBuffer;
727 PFILE_FS_SIZE_INFORMATION pSizeInfo = (PFILE_FS_SIZE_INFORMATION)pInfoBuffer;
728
729 uint32_t cbHGCMBuffer;
730 uint8_t *pHGCMBuffer;
731 int vboxRC;
732 PSHFLVOLINFO pShflVolInfo;
733
734 LARGE_INTEGER TotalAllocationUnits;
735 LARGE_INTEGER AvailableAllocationUnits;
736 ULONG SectorsPerAllocationUnit;
737 ULONG BytesPerSector;
738
739 if (FsInformationClass == FileFsFullSizeInformation)
740 {
741 Log(("VBOXSF: MrxQueryVolumeInfo: FileFsFullSizeInformation\n"));
742 cbToCopy = sizeof(FILE_FS_FULL_SIZE_INFORMATION);
743 }
744 else
745 {
746 Log(("VBOXSF: MrxQueryVolumeInfo: FileFsSizeInformation\n"));
747 cbToCopy = sizeof(FILE_FS_SIZE_INFORMATION);
748 }
749
750 if (!pVBoxFobx)
751 {
752 Log(("VBOXSF: MrxQueryVolumeInfo: pVBoxFobx is NULL!\n"));
753 Status = STATUS_INVALID_PARAMETER;
754 break;
755 }
756
757 if (cbInfoBuffer < cbToCopy)
758 {
759 Status = STATUS_BUFFER_TOO_SMALL;
760 break;
761 }
762
763 RtlZeroMemory(pInfoBuffer, cbToCopy);
764
765 cbHGCMBuffer = sizeof(SHFLVOLINFO);
766 pHGCMBuffer = (uint8_t *)vbsfAllocNonPagedMem(cbHGCMBuffer);
767 if (!pHGCMBuffer)
768 {
769 Status = STATUS_INSUFFICIENT_RESOURCES;
770 break;
771 }
772
773 vboxRC = VbglR0SfFsInfo(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile,
774 SHFL_INFO_GET | SHFL_INFO_VOLUME, &cbHGCMBuffer, (PSHFLDIRINFO)pHGCMBuffer);
775
776 if (vboxRC != VINF_SUCCESS)
777 {
778 Status = VBoxErrorToNTStatus(vboxRC);
779 vbsfFreeNonPagedMem(pHGCMBuffer);
780 break;
781 }
782
783 pShflVolInfo = (PSHFLVOLINFO)pHGCMBuffer;
784
785 TotalAllocationUnits.QuadPart = pShflVolInfo->ullTotalAllocationBytes / pShflVolInfo->ulBytesPerAllocationUnit;
786 AvailableAllocationUnits.QuadPart = pShflVolInfo->ullAvailableAllocationBytes / pShflVolInfo->ulBytesPerAllocationUnit;
787 SectorsPerAllocationUnit = pShflVolInfo->ulBytesPerAllocationUnit / pShflVolInfo->ulBytesPerSector;
788 BytesPerSector = pShflVolInfo->ulBytesPerSector;
789
790 Log(("VBOXSF: MrxQueryVolumeInfo: TotalAllocationUnits 0x%RX64\n", TotalAllocationUnits.QuadPart));
791 Log(("VBOXSF: MrxQueryVolumeInfo: AvailableAllocationUnits 0x%RX64\n", AvailableAllocationUnits.QuadPart));
792 Log(("VBOXSF: MrxQueryVolumeInfo: SectorsPerAllocationUnit 0x%X\n", SectorsPerAllocationUnit));
793 Log(("VBOXSF: MrxQueryVolumeInfo: BytesPerSector 0x%X\n", BytesPerSector));
794
795 if (FsInformationClass == FileFsFullSizeInformation)
796 {
797 pFullSizeInfo->TotalAllocationUnits = TotalAllocationUnits;
798 pFullSizeInfo->CallerAvailableAllocationUnits = AvailableAllocationUnits;
799 pFullSizeInfo->ActualAvailableAllocationUnits = AvailableAllocationUnits;
800 pFullSizeInfo->SectorsPerAllocationUnit = SectorsPerAllocationUnit;
801 pFullSizeInfo->BytesPerSector = BytesPerSector;
802 }
803 else
804 {
805 pSizeInfo->TotalAllocationUnits = TotalAllocationUnits;
806 pSizeInfo->AvailableAllocationUnits = AvailableAllocationUnits;
807 pSizeInfo->SectorsPerAllocationUnit = SectorsPerAllocationUnit;
808 pSizeInfo->BytesPerSector = BytesPerSector;
809 }
810
811 vbsfFreeNonPagedMem(pHGCMBuffer);
812
813 Status = STATUS_SUCCESS;
814 break;
815 }
816
817 case FileFsDeviceInformation:
818 {
819 PFILE_FS_DEVICE_INFORMATION pInfo = (PFILE_FS_DEVICE_INFORMATION)pInfoBuffer;
820 PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
821
822 Log(("VBOXSF: MrxQueryVolumeInfo: FileFsDeviceInformation: Type = %d\n",
823 NetRoot->DeviceType));
824
825 cbToCopy = sizeof(FILE_FS_DEVICE_INFORMATION);
826
827 if (cbInfoBuffer < cbToCopy)
828 {
829 Status = STATUS_BUFFER_TOO_SMALL;
830 break;
831 }
832
833 pInfo->DeviceType = NetRoot->DeviceType;
834 pInfo->Characteristics = FILE_REMOTE_DEVICE;
835
836 Status = STATUS_SUCCESS;
837 break;
838 }
839
840 case FileFsAttributeInformation:
841 {
842 PFILE_FS_ATTRIBUTE_INFORMATION pInfo = (PFILE_FS_ATTRIBUTE_INFORMATION)pInfoBuffer;
843
844 Log(("VBOXSF: MrxQueryVolumeInfo: FileFsAttributeInformation\n"));
845
846 cbToCopy = FIELD_OFFSET(FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName);
847
848 cbString = sizeof(MRX_VBOX_FILESYS_NAME_U);
849
850 if (cbInfoBuffer < cbToCopy)
851 {
852 Status = STATUS_BUFFER_TOO_SMALL;
853 break;
854 }
855
856 pInfo->FileSystemAttributes = 0; /** @todo set unicode, case sensitive etc? */
857 pInfo->MaximumComponentNameLength = 255; /** @todo should query from the host */
858
859 if (cbInfoBuffer >= cbToCopy + cbString)
860 {
861 RtlCopyMemory(pInfo->FileSystemName,
862 MRX_VBOX_FILESYS_NAME_U,
863 sizeof(MRX_VBOX_FILESYS_NAME_U));
864 }
865 else
866 {
867 cbString = cbInfoBuffer - cbToCopy;
868
869 RtlCopyMemory(pInfo->FileSystemName,
870 MRX_VBOX_FILESYS_NAME_U,
871 RT_MIN(cbString, sizeof(MRX_VBOX_FILESYS_NAME_U)));
872 }
873
874 pInfo->FileSystemNameLength = cbString;
875
876 cbToCopy += cbString;
877
878 Log(("VBOXSF: MrxQueryVolumeInfo: FileFsAttributeInformation: FileSystemNameLength %d\n",
879 pInfo->FileSystemNameLength));
880
881 Status = STATUS_SUCCESS;
882 break;
883 }
884
885 case FileFsControlInformation:
886 Log(("VBOXSF: MrxQueryVolumeInfo: FileFsControlInformation: not supported\n"));
887 Status = STATUS_INVALID_PARAMETER;
888 break;
889
890 case FileFsObjectIdInformation:
891 Log(("VBOXSF: MrxQueryVolumeInfo: FileFsObjectIdInformation: not supported\n"));
892 Status = STATUS_INVALID_PARAMETER;
893 break;
894
895 case FileFsMaximumInformation:
896 Log(("VBOXSF: MrxQueryVolumeInfo: FileFsMaximumInformation: not supported\n"));
897 Status = STATUS_INVALID_PARAMETER;
898 break;
899
900 default:
901 Log(("VBOXSF: MrxQueryVolumeInfo: Not supported FsInformationClass %d!\n",
902 FsInformationClass));
903 Status = STATUS_INVALID_PARAMETER;
904 break;
905 }
906
907 if (Status == STATUS_SUCCESS)
908 RxContext->Info.LengthRemaining = cbInfoBuffer - cbToCopy;
909 else if (Status == STATUS_BUFFER_TOO_SMALL)
910 {
911 Log(("VBOXSF: MrxQueryVolumeInfo: Insufficient buffer size %d, required %d\n",
912 cbInfoBuffer, cbToCopy));
913 RxContext->InformationToReturn = cbToCopy;
914 }
915
916 Log(("VBOXSF: MrxQueryVolumeInfo: cbToCopy = %d, LengthRemaining = %d, Status = 0x%08X\n",
917 cbToCopy, RxContext->Info.LengthRemaining, Status));
918
919 return Status;
920}
921
922NTSTATUS VBoxMRxQueryFileInfo(IN PRX_CONTEXT RxContext)
923{
924 NTSTATUS Status = STATUS_SUCCESS;
925
926 RxCaptureFcb;
927 RxCaptureFobx;
928
929 PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext);
930 PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = VBoxMRxGetNetRootExtension(capFcb->pNetRoot);
931 PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);
932
933 PUNICODE_STRING FileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
934 FILE_INFORMATION_CLASS FunctionalityRequested = RxContext->Info.FileInformationClass;
935 PCHAR pInfoBuffer = (PCHAR)RxContext->Info.Buffer;
936 uint32_t cbInfoBuffer = RxContext->Info.Length;
937 ULONG *pLengthRemaining = (PULONG) & RxContext->Info.LengthRemaining;
938
939 int vboxRC = 0;
940
941 ULONG cbToCopy = 0;
942 uint8_t *pHGCMBuffer = 0;
943 uint32_t cbHGCMBuffer;
944 PSHFLFSOBJINFO pFileEntry = NULL;
945
946 if (!pLengthRemaining)
947 {
948 Log(("VBOXSF: MrxQueryFileInfo: length pointer is NULL!\n"));
949 return STATUS_INVALID_PARAMETER;
950 }
951
952 Log(("VBOXSF: MrxQueryFileInfo: InfoBuffer = %p, Size = %d bytes, LenRemain = %d bytes\n",
953 pInfoBuffer, cbInfoBuffer, *pLengthRemaining));
954
955 if (!pVBoxFobx)
956 {
957 Log(("VBOXSF: MrxQueryFileInfo: pVBoxFobx is NULL!\n"));
958 return STATUS_INVALID_PARAMETER;
959 }
960
961 if (!pInfoBuffer)
962 {
963 Log(("VBOXSF: MrxQueryFileInfo: pInfoBuffer is NULL!\n"));
964 return STATUS_INVALID_PARAMETER;
965 }
966
967 if (pVBoxFobx->FileStandardInfo.Directory == TRUE)
968 {
969 Log(("VBOXSF: MrxQueryFileInfo: Directory -> Copy info retrieved during the create call\n"));
970 Status = STATUS_SUCCESS;
971
972 switch (FunctionalityRequested)
973 {
974 case FileBasicInformation:
975 {
976 PFILE_BASIC_INFORMATION pInfo = (PFILE_BASIC_INFORMATION)pInfoBuffer;
977 Log(("VBOXSF: MrxQueryFileInfo: FileBasicInformation\n"));
978
979 cbToCopy = sizeof(FILE_BASIC_INFORMATION);
980
981 if (*pLengthRemaining >= cbToCopy)
982 {
983 *pInfo = pVBoxFobx->FileBasicInfo;
984 Log(("VBOXSF: MrxQueryFileInfo: FileBasicInformation: File attributes: 0x%x\n",
985 pInfo->FileAttributes));
986 }
987 else
988 {
989 Status = STATUS_BUFFER_TOO_SMALL;
990 }
991 break;
992 }
993
994 case FileStandardInformation:
995 {
996 PFILE_STANDARD_INFORMATION pInfo = (PFILE_STANDARD_INFORMATION)pInfoBuffer;
997 Log(("VBOXSF: MrxQueryFileInfo: FileStandardInformation\n"));
998
999 cbToCopy = sizeof(FILE_STANDARD_INFORMATION);
1000
1001 if (*pLengthRemaining >= cbToCopy)
1002 *pInfo = pVBoxFobx->FileStandardInfo;
1003 else
1004 Status = STATUS_BUFFER_TOO_SMALL;
1005 break;
1006 }
1007
1008 case FileNamesInformation:
1009 {
1010 PFILE_NAMES_INFORMATION pInfo = (PFILE_NAMES_INFORMATION)pInfoBuffer;
1011 Log(("VBOXSF: MrxQueryFileInfo: FileNamesInformation\n"));
1012
1013 cbToCopy = sizeof(FILE_NAMES_INFORMATION);
1014 /* And size in bytes of the WCHAR name. */
1015 cbToCopy += FileName->Length;
1016
1017 if (*pLengthRemaining >= cbToCopy)
1018 {
1019 RtlZeroMemory(pInfo, cbToCopy);
1020
1021 pInfo->FileNameLength = FileName->Length;
1022
1023 RtlCopyMemory(pInfo->FileName, FileName->Buffer, FileName->Length);
1024 pInfo->FileName[FileName->Length] = 0; /* FILE_NAMES_INFORMATION had space for the nul. */
1025 }
1026 else
1027 Status = STATUS_BUFFER_TOO_SMALL;
1028 break;
1029 }
1030
1031 case FileInternalInformation:
1032 {
1033 PFILE_INTERNAL_INFORMATION pInfo = (PFILE_INTERNAL_INFORMATION)pInfoBuffer;
1034 Log(("VBOXSF: MrxQueryFileInfo: FileInternalInformation\n"));
1035
1036 cbToCopy = sizeof(FILE_INTERNAL_INFORMATION);
1037
1038 if (*pLengthRemaining >= cbToCopy)
1039 {
1040 /* A 8-byte file reference number for the file. */
1041 pInfo->IndexNumber.QuadPart = (ULONG_PTR)capFcb;
1042 }
1043 else
1044 Status = STATUS_BUFFER_TOO_SMALL;
1045 break;
1046 }
1047 case FileEaInformation:
1048 {
1049 PFILE_EA_INFORMATION pInfo = (PFILE_EA_INFORMATION)pInfoBuffer;
1050 Log(("VBOXSF: MrxQueryFileInfo: FileEaInformation\n"));
1051
1052 cbToCopy = sizeof(FILE_EA_INFORMATION);
1053
1054 if (*pLengthRemaining >= cbToCopy)
1055 {
1056 pInfo->EaSize = 0;
1057 }
1058 else
1059 Status = STATUS_BUFFER_TOO_SMALL;
1060 break;
1061 }
1062
1063 case FileNetworkOpenInformation:
1064 {
1065 PFILE_NETWORK_OPEN_INFORMATION pInfo = (PFILE_NETWORK_OPEN_INFORMATION)pInfoBuffer;
1066 Log(("VBOXSF: MrxQueryFileInfo: FileNetworkOpenInformation\n"));
1067
1068 cbToCopy = sizeof(FILE_NETWORK_OPEN_INFORMATION);
1069
1070 if (*pLengthRemaining >= cbToCopy)
1071 {
1072 pInfo->CreationTime = pVBoxFobx->FileBasicInfo.CreationTime;
1073 pInfo->LastAccessTime = pVBoxFobx->FileBasicInfo.LastAccessTime;
1074 pInfo->LastWriteTime = pVBoxFobx->FileBasicInfo.LastWriteTime;
1075 pInfo->ChangeTime = pVBoxFobx->FileBasicInfo.ChangeTime;
1076 pInfo->AllocationSize.QuadPart = 0;
1077 pInfo->EndOfFile.QuadPart = 0;
1078 pInfo->FileAttributes = pVBoxFobx->FileBasicInfo.FileAttributes;
1079 }
1080 else
1081 Status = STATUS_BUFFER_TOO_SMALL;
1082 break;
1083 }
1084
1085 case FileStreamInformation:
1086 Log(("VBOXSF: MrxQueryFileInfo: FileStreamInformation: not supported\n"));
1087 Status = STATUS_INVALID_PARAMETER;
1088 goto end;
1089
1090 default:
1091 Log(("VBOXSF: MrxQueryFileInfo: Not supported FunctionalityRequested %d!\n",
1092 FunctionalityRequested));
1093 Status = STATUS_INVALID_PARAMETER;
1094 goto end;
1095 }
1096 }
1097 else /* Entry is a file. */
1098 {
1099 cbHGCMBuffer = RT_MAX(cbInfoBuffer, PAGE_SIZE);
1100 pHGCMBuffer = (uint8_t *)vbsfAllocNonPagedMem(cbHGCMBuffer);
1101
1102 if (!pHGCMBuffer)
1103 return STATUS_INSUFFICIENT_RESOURCES;
1104
1105 Assert(pVBoxFobx && pNetRootExtension && pDeviceExtension);
1106 vboxRC = VbglR0SfFsInfo(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile,
1107 SHFL_INFO_GET | SHFL_INFO_FILE, &cbHGCMBuffer, (PSHFLDIRINFO)pHGCMBuffer);
1108
1109 if (vboxRC != VINF_SUCCESS)
1110 {
1111 Status = VBoxErrorToNTStatus(vboxRC);
1112 goto end;
1113 }
1114
1115 pFileEntry = (PSHFLFSOBJINFO)pHGCMBuffer;
1116 Status = STATUS_SUCCESS;
1117
1118 switch (FunctionalityRequested)
1119 {
1120 case FileBasicInformation:
1121 {
1122 PFILE_BASIC_INFORMATION pInfo = (PFILE_BASIC_INFORMATION)pInfoBuffer;
1123 Log(("VBOXSF: MrxQueryFileInfo: FileBasicInformation\n"));
1124
1125 cbToCopy = sizeof(FILE_BASIC_INFORMATION);
1126
1127 if (*pLengthRemaining >= cbToCopy)
1128 {
1129 pInfo->CreationTime.QuadPart = RTTimeSpecGetNtTime(&pFileEntry->BirthTime); /* Ridiculous name. */
1130 pInfo->LastAccessTime.QuadPart = RTTimeSpecGetNtTime(&pFileEntry->AccessTime);
1131 pInfo->LastWriteTime.QuadPart = RTTimeSpecGetNtTime(&pFileEntry->ModificationTime);
1132 pInfo->ChangeTime.QuadPart = RTTimeSpecGetNtTime(&pFileEntry->ChangeTime);
1133 pInfo->FileAttributes = VBoxToNTFileAttributes(pFileEntry->Attr.fMode);
1134
1135 Log(("VBOXSF: MrxQueryFileInfo: FileBasicInformation: File attributes = 0x%x\n",
1136 pInfo->FileAttributes));
1137 }
1138 else
1139 Status = STATUS_BUFFER_TOO_SMALL;
1140 break;
1141 }
1142
1143 case FileStandardInformation:
1144 {
1145 PFILE_STANDARD_INFORMATION pInfo = (PFILE_STANDARD_INFORMATION)pInfoBuffer;
1146 Log(("VBOXSF: MrxQueryFileInfo: FileStandardInformation\n"));
1147
1148 cbToCopy = sizeof(FILE_STANDARD_INFORMATION);
1149
1150 if (*pLengthRemaining >= cbToCopy)
1151 {
1152 pInfo->AllocationSize.QuadPart = pFileEntry->cbAllocated;
1153 pInfo->EndOfFile.QuadPart = pFileEntry->cbObject;
1154 pInfo->NumberOfLinks = 1; /** @todo 0? */
1155 pInfo->DeletePending = FALSE;
1156
1157 if (pFileEntry->Attr.fMode & RTFS_DOS_DIRECTORY)
1158 pInfo->Directory = TRUE;
1159 else
1160 pInfo->Directory = FALSE;
1161 }
1162 else
1163 Status = STATUS_BUFFER_TOO_SMALL;
1164 break;
1165 }
1166
1167 case FileNamesInformation:
1168 {
1169 PFILE_NAMES_INFORMATION pInfo = (PFILE_NAMES_INFORMATION)pInfoBuffer;
1170 Log(("VBOXSF: MrxQueryFileInfo: FileNamesInformation\n"));
1171
1172 cbToCopy = sizeof(FILE_NAMES_INFORMATION);
1173 /* And size in bytes of the WCHAR name. */
1174 cbToCopy += FileName->Length;
1175
1176 if (*pLengthRemaining >= cbToCopy)
1177 {
1178 RtlZeroMemory(pInfo, cbToCopy);
1179
1180 pInfo->FileNameLength = FileName->Length;
1181
1182 RtlCopyMemory(pInfo->FileName, FileName->Buffer, FileName->Length);
1183 pInfo->FileName[FileName->Length] = 0; /* FILE_NAMES_INFORMATION had space for the nul. */
1184 }
1185 else
1186 Status = STATUS_BUFFER_TOO_SMALL;
1187 break;
1188 }
1189
1190 case FileInternalInformation:
1191 {
1192 PFILE_INTERNAL_INFORMATION pInfo = (PFILE_INTERNAL_INFORMATION)pInfoBuffer;
1193 Log(("VBOXSF: MrxQueryFileInfo: FileInternalInformation\n"));
1194
1195 cbToCopy = sizeof(FILE_INTERNAL_INFORMATION);
1196
1197 if (*pLengthRemaining >= cbToCopy)
1198 {
1199 /* A 8-byte file reference number for the file. */
1200 pInfo->IndexNumber.QuadPart = (ULONG_PTR)capFcb;
1201 }
1202 else
1203 Status = STATUS_BUFFER_TOO_SMALL;
1204 break;
1205 }
1206
1207 case FileEaInformation:
1208 {
1209 PFILE_EA_INFORMATION pInfo = (PFILE_EA_INFORMATION)pInfoBuffer;
1210 Log(("VBOXSF: MrxQueryFileInfo: FileEaInformation\n"));
1211
1212 cbToCopy = sizeof(FILE_EA_INFORMATION);
1213
1214 if (*pLengthRemaining >= cbToCopy)
1215 pInfo->EaSize = 0;
1216 else
1217 Status = STATUS_BUFFER_TOO_SMALL;
1218 break;
1219 }
1220
1221 case FileAttributeTagInformation:
1222 {
1223 PFILE_ATTRIBUTE_TAG_INFORMATION pInfo = (PFILE_ATTRIBUTE_TAG_INFORMATION)pInfoBuffer;
1224 Log(("VBOXSF: MrxQueryFileInfo: FileAttributeTagInformation\n"));
1225
1226 cbToCopy = sizeof(FILE_ATTRIBUTE_TAG_INFORMATION);
1227
1228 if (*pLengthRemaining >= cbToCopy)
1229 {
1230 pInfo->FileAttributes = VBoxToNTFileAttributes(pFileEntry->Attr.fMode);
1231 pInfo->ReparseTag = 0;
1232 }
1233 else
1234 Status = STATUS_BUFFER_TOO_SMALL;
1235 break;
1236 }
1237
1238 case FileEndOfFileInformation:
1239 {
1240 PFILE_END_OF_FILE_INFORMATION pInfo = (PFILE_END_OF_FILE_INFORMATION)pInfoBuffer;
1241 Log(("VBOXSF: MrxQueryFileInfo: FileEndOfFileInformation\n"));
1242
1243 cbToCopy = sizeof(FILE_END_OF_FILE_INFORMATION);
1244
1245 if (*pLengthRemaining >= cbToCopy)
1246 pInfo->EndOfFile.QuadPart = pFileEntry->cbObject;
1247 else
1248 Status = STATUS_BUFFER_TOO_SMALL;
1249 break;
1250 }
1251
1252 case FileAllocationInformation:
1253 {
1254 PFILE_ALLOCATION_INFORMATION pInfo = (PFILE_ALLOCATION_INFORMATION)pInfoBuffer;
1255 Log(("VBOXSF: MrxQueryFileInfo: FileAllocationInformation\n"));
1256
1257 cbToCopy = sizeof(FILE_ALLOCATION_INFORMATION);
1258
1259 if (*pLengthRemaining >= cbToCopy)
1260 pInfo->AllocationSize.QuadPart = pFileEntry->cbAllocated;
1261 else
1262 Status = STATUS_BUFFER_TOO_SMALL;
1263 break;
1264 }
1265
1266 case FileNetworkOpenInformation:
1267 {
1268 PFILE_NETWORK_OPEN_INFORMATION pInfo = (PFILE_NETWORK_OPEN_INFORMATION)pInfoBuffer;
1269 Log(("VBOXSF: MrxQueryFileInfo: FileNetworkOpenInformation\n"));
1270
1271 cbToCopy = sizeof(FILE_NETWORK_OPEN_INFORMATION);
1272
1273 if (*pLengthRemaining >= cbToCopy)
1274 {
1275 pInfo->CreationTime.QuadPart = RTTimeSpecGetNtTime(&pFileEntry->BirthTime); /* Ridiculous name. */
1276 pInfo->LastAccessTime.QuadPart = RTTimeSpecGetNtTime(&pFileEntry->AccessTime);
1277 pInfo->LastWriteTime.QuadPart = RTTimeSpecGetNtTime(&pFileEntry->ModificationTime);
1278 pInfo->ChangeTime.QuadPart = RTTimeSpecGetNtTime(&pFileEntry->ChangeTime);
1279 pInfo->AllocationSize.QuadPart = pFileEntry->cbAllocated;
1280 pInfo->EndOfFile.QuadPart = pFileEntry->cbObject;
1281 pInfo->FileAttributes = VBoxToNTFileAttributes(pFileEntry->Attr.fMode);
1282 }
1283 else
1284 Status = STATUS_BUFFER_TOO_SMALL;
1285 break;
1286 }
1287
1288 case FileStreamInformation:
1289 Log(("VBOXSF: MrxQueryFileInfo: FileStreamInformation: not supported\n"));
1290 Status = STATUS_INVALID_PARAMETER;
1291 goto end;
1292
1293 default:
1294 Log(("VBOXSF: MrxQueryFileInfo: Not supported FunctionalityRequested %d!\n",
1295 FunctionalityRequested));
1296 Status = STATUS_INVALID_PARAMETER;
1297 goto end;
1298 }
1299 }
1300
1301 if (Status == STATUS_SUCCESS)
1302 {
1303 if (*pLengthRemaining < cbToCopy)
1304 {
1305 /* This situation must be already taken into account by the above code. */
1306 AssertMsgFailed(("VBOXSF: MrxQueryFileInfo: Length remaining is below 0! (%d - %d)!\n",
1307 *pLengthRemaining, cbToCopy));
1308 Status = STATUS_BUFFER_TOO_SMALL;
1309 }
1310 else
1311 {
1312 pInfoBuffer += cbToCopy;
1313 *pLengthRemaining -= cbToCopy;
1314 }
1315 }
1316
1317end:
1318 if (Status == STATUS_BUFFER_TOO_SMALL)
1319 {
1320 Log(("VBOXSF: MrxQueryFileInfo: Buffer too small %d, required %d!\n",
1321 *pLengthRemaining, cbToCopy));
1322 RxContext->InformationToReturn = cbToCopy;
1323 }
1324
1325 if (pHGCMBuffer)
1326 vbsfFreeNonPagedMem(pHGCMBuffer);
1327
1328 if (Status == STATUS_SUCCESS)
1329 {
1330 Log(("VBOXSF: MrxQueryFileInfo: Remaining length = %d\n",
1331 *pLengthRemaining));
1332 }
1333
1334 Log(("VBOXSF: MrxQueryFileInfo: Returned 0x%08X\n", Status));
1335 return Status;
1336}
1337
1338NTSTATUS VBoxMRxSetFileInfo(IN PRX_CONTEXT RxContext)
1339{
1340 NTSTATUS Status = STATUS_SUCCESS;
1341
1342 RxCaptureFcb;
1343 RxCaptureFobx;
1344
1345 PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext);
1346 PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = VBoxMRxGetNetRootExtension(capFcb->pNetRoot);
1347 PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);
1348
1349 FILE_INFORMATION_CLASS FunctionalityRequested = RxContext->Info.FileInformationClass;
1350 PVOID pInfoBuffer = (PVOID)RxContext->Info.Buffer;
1351
1352 int vboxRC;
1353
1354 uint8_t *pHGCMBuffer = NULL;
1355 uint32_t cbBuffer = 0;
1356
1357 Log(("VBOXSF: MrxSetFileInfo: pInfoBuffer %p\n",
1358 pInfoBuffer));
1359
1360 switch (FunctionalityRequested)
1361 {
1362 case FileBasicInformation:
1363 {
1364 PFILE_BASIC_INFORMATION pInfo = (PFILE_BASIC_INFORMATION)pInfoBuffer;
1365 PSHFLFSOBJINFO pSHFLFileInfo;
1366
1367 Log(("VBOXSF: MRxSetFileInfo: FileBasicInformation: CreationTime %RX64\n", pInfo->CreationTime.QuadPart));
1368 Log(("VBOXSF: MRxSetFileInfo: FileBasicInformation: LastAccessTime %RX64\n", pInfo->LastAccessTime.QuadPart));
1369 Log(("VBOXSF: MRxSetFileInfo: FileBasicInformation: LastWriteTime %RX64\n", pInfo->LastWriteTime.QuadPart));
1370 Log(("VBOXSF: MRxSetFileInfo: FileBasicInformation: ChangeTime %RX64\n", pInfo->ChangeTime.QuadPart));
1371 Log(("VBOXSF: MRxSetFileInfo: FileBasicInformation: FileAttributes %RX32\n", pInfo->FileAttributes));
1372
1373 /* When setting file attributes, a value of -1 indicates to the server that it MUST NOT change this attribute
1374 * for all subsequent operations on the same file handle.
1375 */
1376 if (pInfo->CreationTime.QuadPart == -1)
1377 {
1378 pVBoxFobx->fKeepCreationTime = TRUE;
1379 pVBoxFobx->SetFileInfoOnCloseFlags |= VBOX_FOBX_F_INFO_CREATION_TIME;
1380 }
1381 if (pInfo->LastAccessTime.QuadPart == -1)
1382 {
1383 pVBoxFobx->fKeepLastAccessTime = TRUE;
1384 pVBoxFobx->SetFileInfoOnCloseFlags |= VBOX_FOBX_F_INFO_LASTACCESS_TIME;
1385 }
1386 if (pInfo->LastWriteTime.QuadPart == -1)
1387 {
1388 pVBoxFobx->fKeepLastWriteTime = TRUE;
1389 pVBoxFobx->SetFileInfoOnCloseFlags |= VBOX_FOBX_F_INFO_LASTWRITE_TIME;
1390 }
1391 if (pInfo->ChangeTime.QuadPart == -1)
1392 {
1393 pVBoxFobx->fKeepChangeTime = TRUE;
1394 pVBoxFobx->SetFileInfoOnCloseFlags |= VBOX_FOBX_F_INFO_CHANGE_TIME;
1395 }
1396
1397 cbBuffer = sizeof(SHFLFSOBJINFO);
1398 pHGCMBuffer = (uint8_t *)vbsfAllocNonPagedMem(cbBuffer);
1399 if (!pHGCMBuffer)
1400 {
1401 AssertFailed();
1402 return STATUS_INSUFFICIENT_RESOURCES;
1403 }
1404 RtlZeroMemory(pHGCMBuffer, cbBuffer);
1405 pSHFLFileInfo = (PSHFLFSOBJINFO)pHGCMBuffer;
1406
1407 Log(("VBOXSF: MrxSetFileInfo: FileBasicInformation: keeps %d %d %d %d\n",
1408 pVBoxFobx->fKeepCreationTime, pVBoxFobx->fKeepLastAccessTime, pVBoxFobx->fKeepLastWriteTime, pVBoxFobx->fKeepChangeTime));
1409
1410 /* The properties, that need to be changed, are set to something other than zero */
1411 if (pInfo->CreationTime.QuadPart && !pVBoxFobx->fKeepCreationTime)
1412 {
1413 RTTimeSpecSetNtTime(&pSHFLFileInfo->BirthTime, pInfo->CreationTime.QuadPart);
1414 pVBoxFobx->SetFileInfoOnCloseFlags |= VBOX_FOBX_F_INFO_CREATION_TIME;
1415 }
1416 if (pInfo->LastAccessTime.QuadPart && !pVBoxFobx->fKeepLastAccessTime)
1417 {
1418 RTTimeSpecSetNtTime(&pSHFLFileInfo->AccessTime, pInfo->LastAccessTime.QuadPart);
1419 pVBoxFobx->SetFileInfoOnCloseFlags |= VBOX_FOBX_F_INFO_LASTACCESS_TIME;
1420 }
1421 if (pInfo->LastWriteTime.QuadPart && !pVBoxFobx->fKeepLastWriteTime)
1422 {
1423 RTTimeSpecSetNtTime(&pSHFLFileInfo->ModificationTime, pInfo->LastWriteTime.QuadPart);
1424 pVBoxFobx->SetFileInfoOnCloseFlags |= VBOX_FOBX_F_INFO_LASTWRITE_TIME;
1425 }
1426 if (pInfo->ChangeTime.QuadPart && !pVBoxFobx->fKeepChangeTime)
1427 {
1428 RTTimeSpecSetNtTime(&pSHFLFileInfo->ChangeTime, pInfo->ChangeTime.QuadPart);
1429 pVBoxFobx->SetFileInfoOnCloseFlags |= VBOX_FOBX_F_INFO_CHANGE_TIME;
1430 }
1431 if (pInfo->FileAttributes)
1432 {
1433 pSHFLFileInfo->Attr.fMode = NTToVBoxFileAttributes(pInfo->FileAttributes);
1434 }
1435
1436 Assert(pVBoxFobx && pNetRootExtension && pDeviceExtension);
1437 vboxRC = VbglR0SfFsInfo(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile,
1438 SHFL_INFO_SET | SHFL_INFO_FILE, &cbBuffer, (PSHFLDIRINFO)pSHFLFileInfo);
1439
1440 if (vboxRC != VINF_SUCCESS)
1441 {
1442 Status = VBoxErrorToNTStatus(vboxRC);
1443 goto end;
1444 }
1445 else
1446 {
1447 /* Update our internal copy. Ignore zero fields! */
1448 if (pInfo->CreationTime.QuadPart && !pVBoxFobx->fKeepCreationTime)
1449 pVBoxFobx->FileBasicInfo.CreationTime = pInfo->CreationTime;
1450 if (pInfo->LastAccessTime.QuadPart && !pVBoxFobx->fKeepLastAccessTime)
1451 pVBoxFobx->FileBasicInfo.LastAccessTime = pInfo->LastAccessTime;
1452 if (pInfo->LastWriteTime.QuadPart && !pVBoxFobx->fKeepLastWriteTime)
1453 pVBoxFobx->FileBasicInfo.LastWriteTime = pInfo->LastWriteTime;
1454 if (pInfo->ChangeTime.QuadPart && !pVBoxFobx->fKeepChangeTime)
1455 pVBoxFobx->FileBasicInfo.ChangeTime = pInfo->ChangeTime;
1456 if (pInfo->FileAttributes)
1457 pVBoxFobx->FileBasicInfo.FileAttributes = pInfo->FileAttributes;
1458 }
1459
1460 break;
1461 }
1462
1463 case FileDispositionInformation:
1464 {
1465 PFILE_DISPOSITION_INFORMATION pInfo = (PFILE_DISPOSITION_INFORMATION)pInfoBuffer;
1466
1467 Log(("VBOXSF: MrxSetFileInfo: FileDispositionInformation: Delete = %d\n",
1468 pInfo->DeleteFile));
1469
1470 if (pInfo->DeleteFile && capFcb->OpenCount == 1)
1471 Status = vbsfRemove(RxContext);
1472 else
1473 Status = STATUS_SUCCESS;
1474 break;
1475 }
1476
1477 case FilePositionInformation:
1478 {
1479#ifdef LOG_ENABLED
1480 PFILE_POSITION_INFORMATION pInfo = (PFILE_POSITION_INFORMATION)pInfoBuffer;
1481 Log(("VBOXSF: MrxSetFileInfo: FilePositionInformation: CurrentByteOffset = 0x%RX64. Unsupported!\n",
1482 pInfo->CurrentByteOffset.QuadPart));
1483#endif
1484
1485 Status = STATUS_INVALID_PARAMETER;
1486 break;
1487 }
1488
1489 case FileAllocationInformation:
1490 {
1491 PFILE_ALLOCATION_INFORMATION pInfo = (PFILE_ALLOCATION_INFORMATION)pInfoBuffer;
1492
1493 Log(("VBOXSF: MrxSetFileInfo: FileAllocationInformation: new AllocSize = 0x%RX64, FileSize = 0x%RX64\n",
1494 pInfo->AllocationSize.QuadPart, capFcb->Header.FileSize.QuadPart));
1495
1496 /* Check if the new allocation size changes the file size. */
1497 if (pInfo->AllocationSize.QuadPart > capFcb->Header.FileSize.QuadPart)
1498 {
1499 /* Ignore this request and return success. Shared folders do not distinguish between
1500 * AllocationSize and FileSize.
1501 */
1502 Status = STATUS_SUCCESS;
1503 }
1504 else
1505 {
1506 /* Treat the request as a EndOfFile update. */
1507 LARGE_INTEGER NewAllocationSize;
1508 Status = vbsfSetEndOfFile(RxContext, &pInfo->AllocationSize, &NewAllocationSize);
1509 }
1510
1511 break;
1512 }
1513
1514 case FileEndOfFileInformation:
1515 {
1516 PFILE_END_OF_FILE_INFORMATION pInfo = (PFILE_END_OF_FILE_INFORMATION)pInfoBuffer;
1517 LARGE_INTEGER NewAllocationSize;
1518
1519 Log(("VBOXSF: MrxSetFileInfo: FileEndOfFileInformation: new EndOfFile 0x%RX64, FileSize = 0x%RX64\n",
1520 pInfo->EndOfFile.QuadPart, capFcb->Header.FileSize.QuadPart));
1521
1522 Status = vbsfSetEndOfFile(RxContext, &pInfo->EndOfFile, &NewAllocationSize);
1523
1524 Log(("VBOXSF: MrxSetFileInfo: FileEndOfFileInformation: AllocSize = 0x%RX64, Status 0x%08X\n",
1525 NewAllocationSize.QuadPart, Status));
1526
1527 break;
1528 }
1529
1530 case FileLinkInformation:
1531 {
1532#ifdef LOG_ENABLED
1533 PFILE_LINK_INFORMATION pInfo = (PFILE_LINK_INFORMATION )pInfoBuffer;
1534 Log(("VBOXSF: MrxSetFileInfo: FileLinkInformation: ReplaceIfExists = %d, RootDirectory = 0x%x = [%.*ls]. Not implemented!\n",
1535 pInfo->ReplaceIfExists, pInfo->RootDirectory, pInfo->FileNameLength / sizeof(WCHAR), pInfo->FileName));
1536#endif
1537
1538 Status = STATUS_NOT_IMPLEMENTED;
1539 break;
1540 }
1541
1542 case FileRenameInformation:
1543 {
1544#ifdef LOG_ENABLED
1545 PFILE_RENAME_INFORMATION pInfo = (PFILE_RENAME_INFORMATION)pInfoBuffer;
1546 Log(("VBOXSF: MrxSetFileInfo: FileRenameInformation: ReplaceIfExists = %d, RootDirectory = 0x%x = [%.*ls]\n",
1547 pInfo->ReplaceIfExists, pInfo->RootDirectory, pInfo->FileNameLength / sizeof(WCHAR), pInfo->FileName));
1548#endif
1549
1550 Status = vbsfRename(RxContext, FileRenameInformation, pInfoBuffer, RxContext->Info.Length);
1551 break;
1552 }
1553
1554 default:
1555 Log(("VBOXSF: MrxSetFileInfo: Not supported FunctionalityRequested %d!\n",
1556 FunctionalityRequested));
1557 Status = STATUS_INVALID_PARAMETER;
1558 break;
1559 }
1560
1561end:
1562 if (pHGCMBuffer)
1563 vbsfFreeNonPagedMem(pHGCMBuffer);
1564
1565 Log(("VBOXSF: MrxSetFileInfo: Returned 0x%08X\n", Status));
1566 return Status;
1567}
1568
1569NTSTATUS VBoxMRxSetFileInfoAtCleanup(IN PRX_CONTEXT RxContext)
1570{
1571 RT_NOREF(RxContext);
1572 Log(("VBOXSF: MRxSetFileInfoAtCleanup\n"));
1573 return STATUS_SUCCESS;
1574}
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