VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/SharedFolders/driver/info.cpp@ 78326

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

winnt/vboxsf: Cleaned up the vbsfhlp.cpp code, removing a few unused functions and such. bugref:9172

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