VirtualBox

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

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

Additions/SharedFolders: fixed ShflStringInitBuffer(), do really use this function for initializing the SHFLSTRING content; some cosmetcis

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