VirtualBox

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

Last change on this file since 55401 was 55401, checked in by vboxsync, 10 years ago

added a couple of missing Id headers

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