VirtualBox

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

Last change on this file since 54647 was 51997, checked in by vboxsync, 11 years ago

include,Main,Additions: SHFLSTRING cleanup.

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