VirtualBox

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

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

VBox/shflsvc.h: Use errcore.h rather than err.h. bugref:9344

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