VirtualBox

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

Last change on this file since 42154 was 40532, checked in by vboxsync, 13 years ago

VBOXSF: update timestamps when a file handle is closed.

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