VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/SharedFolders/driver/file.c@ 78279

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

winnt/vboxsf: Simplified file attribute conversion and made sure the result is never zero. bugref:9172

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.1 KB
Line 
1/* $Id: file.c 78279 2019-04-24 16:19:10Z vboxsync $ */
2/** @file
3 * VirtualBox Windows Guest Shared Folders - File System Driver file 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#include "vbsf.h"
19#include <iprt/fs.h>
20#include <iprt/mem.h>
21
22
23/* How much data to transfer in one HGCM request. */
24#define VBSF_MAX_READ_WRITE_PAGES 256
25
26
27typedef int FNVBSFTRANSFERBUFFER(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, SHFLHANDLE hFile,
28 uint64_t offset, uint32_t *pcbBuffer,
29 uint8_t *pBuffer, bool fLocked);
30typedef FNVBSFTRANSFERBUFFER *PFNVBSFTRANSFERBUFFER;
31
32typedef int FNVBSFTRANSFERPAGES(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, SHFLHANDLE hFile,
33 uint64_t offset, uint32_t *pcbBuffer,
34 uint16_t offFirstPage, uint16_t cPages, RTGCPHYS64 *paPages);
35typedef FNVBSFTRANSFERPAGES *PFNVBSFTRANSFERPAGES;
36
37
38static int vbsfTransferBufferRead(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, SHFLHANDLE hFile,
39 uint64_t offset, uint32_t *pcbBuffer,
40 uint8_t *pBuffer, bool fLocked)
41{
42 return VbglR0SfRead(pClient, pMap, hFile, offset, pcbBuffer, pBuffer, fLocked);
43}
44
45static int vbsfTransferBufferWrite(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, SHFLHANDLE hFile,
46 uint64_t offset, uint32_t *pcbBuffer,
47 uint8_t *pBuffer, bool fLocked)
48{
49 return VbglR0SfWrite(pClient, pMap, hFile, offset, pcbBuffer, pBuffer, fLocked);
50}
51
52static int vbsfTransferPagesRead(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, SHFLHANDLE hFile,
53 uint64_t offset, uint32_t *pcbBuffer,
54 uint16_t offFirstPage, uint16_t cPages, RTGCPHYS64 *paPages)
55{
56 return VbglR0SfReadPageList(pClient, pMap, hFile, offset, pcbBuffer, offFirstPage, cPages, paPages);
57}
58
59static int vbsfTransferPagesWrite(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, SHFLHANDLE hFile,
60 uint64_t offset, uint32_t *pcbBuffer,
61 uint16_t offFirstPage, uint16_t cPages, RTGCPHYS64 *paPages)
62{
63 return VbglR0SfWritePageList(pClient, pMap, hFile, offset, pcbBuffer, offFirstPage, cPages, paPages);
64}
65
66
67typedef struct VBSFTRANSFERCTX
68{
69 PVBGLSFCLIENT pClient;
70 PVBGLSFMAP pMap;
71 SHFLHANDLE hFile;
72 uint64_t offset;
73 uint32_t cbData;
74
75 PMDL pMdl;
76 uint8_t *pBuffer;
77 bool fLocked;
78
79 PFNVBSFTRANSFERBUFFER pfnTransferBuffer;
80 PFNVBSFTRANSFERPAGES pfnTransferPages;
81} VBSFTRANSFERCTX;
82
83
84static int vbsfTransferCommon(VBSFTRANSFERCTX *pCtx)
85{
86 int rc = VINF_SUCCESS;
87 BOOLEAN fProcessed = FALSE;
88
89 uint32_t cbTransferred = 0;
90
91 uint32_t cbToTransfer;
92 uint32_t cbIO;
93
94 /** @todo Remove the test and the fall-back path. VbglR0CanUsePhysPageList()
95 * returns true for any host version after 3.0, i.e. further back than
96 * we support. */
97 if (VbglR0CanUsePhysPageList())
98 {
99 ULONG offFirstPage = MmGetMdlByteOffset(pCtx->pMdl);
100 ULONG cPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(pCtx->pMdl), pCtx->cbData);
101 ULONG cPagesToTransfer = RT_MIN(cPages, VBSF_MAX_READ_WRITE_PAGES);
102 RTGCPHYS64 *paPages = (RTGCPHYS64 *)RTMemTmpAlloc(cPagesToTransfer * sizeof(RTGCPHYS64));
103
104 Log(("VBOXSF: vbsfTransferCommon: using page list: %d pages, offset 0x%03X\n", cPages, offFirstPage));
105
106 if (paPages)
107 {
108 PPFN_NUMBER paPfns = MmGetMdlPfnArray(pCtx->pMdl);
109 ULONG cPagesTransferred = 0;
110 cbTransferred = 0;
111
112 while (cPagesToTransfer != 0)
113 {
114 ULONG iPage;
115 cbToTransfer = cPagesToTransfer * PAGE_SIZE - offFirstPage;
116
117 if (cbToTransfer > pCtx->cbData - cbTransferred)
118 cbToTransfer = pCtx->cbData - cbTransferred;
119
120 if (cbToTransfer == 0)
121 {
122 /* Nothing to transfer. */
123 break;
124 }
125
126 cbIO = cbToTransfer;
127
128 Log(("VBOXSF: vbsfTransferCommon: transferring %d pages at %d; %d bytes at %d\n",
129 cPagesToTransfer, cPagesTransferred, cbToTransfer, cbTransferred));
130
131 for (iPage = 0; iPage < cPagesToTransfer; iPage++)
132 paPages[iPage] = (RTGCPHYS64)paPfns[iPage + cPagesTransferred] << PAGE_SHIFT;
133
134 rc = pCtx->pfnTransferPages(pCtx->pClient, pCtx->pMap, pCtx->hFile,
135 pCtx->offset + cbTransferred, &cbIO,
136 (uint16_t)offFirstPage, (uint16_t)cPagesToTransfer, paPages);
137 if (RT_FAILURE(rc))
138 {
139 Log(("VBOXSF: vbsfTransferCommon: pfnTransferPages %Rrc, cbTransferred %d\n", rc, cbTransferred));
140
141 /* If some data was transferred, then it is no error. */
142 if (cbTransferred > 0)
143 rc = VINF_SUCCESS;
144
145 break;
146 }
147
148 cbTransferred += cbIO;
149
150 if (cbToTransfer < cbIO)
151 {
152 /* Transferred less than requested, do not continue with the possibly remaining data. */
153 break;
154 }
155
156 cPagesTransferred += cPagesToTransfer;
157 offFirstPage = 0;
158
159 cPagesToTransfer = cPages - cPagesTransferred;
160 if (cPagesToTransfer > VBSF_MAX_READ_WRITE_PAGES)
161 cPagesToTransfer = VBSF_MAX_READ_WRITE_PAGES;
162 }
163
164 RTMemTmpFree(paPages);
165
166 fProcessed = TRUE;
167 }
168 }
169
170 if (fProcessed != TRUE)
171 {
172 /* Split large transfers. */
173 cbTransferred = 0;
174 cbToTransfer = RT_MIN(pCtx->cbData, VBSF_MAX_READ_WRITE_PAGES * PAGE_SIZE);
175
176 /* Page list not supported or a fallback. */
177 Log(("VBOXSF: vbsfTransferCommon: using linear address\n"));
178
179 while (cbToTransfer != 0)
180 {
181 cbIO = cbToTransfer;
182
183 Log(("VBOXSF: vbsfTransferCommon: transferring %d bytes at %d\n",
184 cbToTransfer, cbTransferred));
185
186 rc = pCtx->pfnTransferBuffer(pCtx->pClient, pCtx->pMap, pCtx->hFile,
187 pCtx->offset + cbTransferred, &cbIO,
188 pCtx->pBuffer + cbTransferred, true /* locked */);
189
190 if (RT_FAILURE(rc))
191 {
192 Log(("VBOXSF: vbsfTransferCommon: pfnTransferBuffer %Rrc, cbTransferred %d\n", rc, cbTransferred));
193
194 /* If some data was transferred, then it is no error. */
195 if (cbTransferred > 0)
196 rc = VINF_SUCCESS;
197
198 break;
199 }
200
201 cbTransferred += cbIO;
202
203 if (cbToTransfer < cbIO)
204 {
205 /* Transferred less than requested, do not continue with the possibly remaining data. */
206 break;
207 }
208
209 cbToTransfer = pCtx->cbData - cbTransferred;
210 if (cbToTransfer > VBSF_MAX_READ_WRITE_PAGES * PAGE_SIZE)
211 cbToTransfer = VBSF_MAX_READ_WRITE_PAGES * PAGE_SIZE;
212 }
213 }
214
215 pCtx->cbData = cbTransferred;
216
217 return rc;
218}
219
220static NTSTATUS vbsfReadInternal(IN PRX_CONTEXT RxContext)
221{
222 NTSTATUS Status = STATUS_SUCCESS;
223 VBSFTRANSFERCTX ctx;
224
225 RxCaptureFcb;
226 RxCaptureFobx;
227
228 PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext);
229 PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = VBoxMRxGetNetRootExtension(capFcb->pNetRoot);
230 PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);
231
232 PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
233
234 PMDL BufferMdl = LowIoContext->ParamsFor.ReadWrite.Buffer;
235 uint32_t ByteCount = LowIoContext->ParamsFor.ReadWrite.ByteCount;
236 RXVBO ByteOffset = LowIoContext->ParamsFor.ReadWrite.ByteOffset;
237
238 PVOID pbUserBuffer = RxLowIoGetBufferAddress(RxContext);
239
240 int vboxRC;
241
242#ifdef LOG_ENABLED
243 BOOLEAN AsyncIo = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_ASYNC_OPERATION);
244#endif
245 LONGLONG FileSize;
246
247 RxGetFileSizeWithLock((PFCB)capFcb, &FileSize);
248
249 Log(("VBOXSF: vbsfReadInternal: AsyncIo = %d, Fcb->FileSize = 0x%RX64\n",
250 AsyncIo, capFcb->Header.FileSize.QuadPart));
251 Log(("VBOXSF: vbsfReadInternal: UserBuffer %p, BufferMdl %p\n",
252 pbUserBuffer, BufferMdl));
253 Log(("VBOXSF: vbsfReadInternal: ByteCount 0x%X, ByteOffset 0x%RX64, FileSize 0x%RX64\n",
254 ByteCount, ByteOffset, FileSize));
255
256 /** @todo check if this is necessary. */
257#ifdef FCB_STATE_READCACHING_ENABLED /* Correct spelling for Vista 6001 SDK. */
258 if (!FlagOn(capFcb->FcbState, FCB_STATE_READCACHING_ENABLED))
259#else
260 if (!FlagOn(capFcb->FcbState, FCB_STATE_READCACHEING_ENABLED))
261#endif
262 {
263/** @todo r=bird: How is this file size accurate given that the file resides
264 * on the host and be grown/shrunk independently there? Why is this
265 * only done when FCB_STATE_READCACHEING_ENABLED is clear? */
266 if (ByteOffset >= FileSize)
267 {
268 Log(("VBOXSF: vbsfReadInternal: EOF\n"));
269 return STATUS_END_OF_FILE;
270 }
271
272 if (ByteCount > FileSize - ByteOffset)
273 ByteCount = (ULONG)(FileSize - ByteOffset);
274 }
275
276 /** @todo read 0 bytes == always success? */
277 if ( !BufferMdl
278 || ByteCount == 0)
279 {
280 AssertFailed();
281 return STATUS_INVALID_PARAMETER;
282 }
283
284 ctx.pClient = &pDeviceExtension->hgcmClient;
285 ctx.pMap = &pNetRootExtension->map;
286 ctx.hFile = pVBoxFobx->hFile;
287 ctx.offset = (uint64_t)ByteOffset;
288 ctx.cbData = ByteCount;
289 ctx.pMdl = BufferMdl;
290 ctx.pBuffer = (uint8_t *)pbUserBuffer;
291 ctx.fLocked = true;
292 ctx.pfnTransferBuffer = vbsfTransferBufferRead;
293 ctx.pfnTransferPages = vbsfTransferPagesRead;
294
295 vboxRC = vbsfTransferCommon(&ctx);
296
297 ByteCount = ctx.cbData;
298
299 Status = VBoxErrorToNTStatus(vboxRC);
300
301 if (Status != STATUS_SUCCESS)
302 {
303 /* Nothing read. */
304 ByteCount = 0;
305 }
306
307 RxContext->InformationToReturn = ByteCount;
308
309 Log(("VBOXSF: vbsfReadInternal: Status = 0x%08X, ByteCount = 0x%X\n",
310 Status, ByteCount));
311
312 return Status;
313}
314
315
316static VOID vbsfReadWorker(VOID *pv)
317{
318 PRX_CONTEXT RxContext = (PRX_CONTEXT)pv;
319
320 Log(("VBOXSF: vbsfReadWorker: calling the worker\n"));
321
322 RxContext->IoStatusBlock.Status = vbsfReadInternal(RxContext);
323
324 Log(("VBOXSF: vbsfReadWorker: Status 0x%08X\n",
325 RxContext->IoStatusBlock.Status));
326
327 RxLowIoCompletion(RxContext);
328}
329
330
331NTSTATUS VBoxMRxRead(IN PRX_CONTEXT RxContext)
332{
333 NTSTATUS Status = RxDispatchToWorkerThread(VBoxMRxDeviceObject, DelayedWorkQueue,
334 vbsfReadWorker,
335 RxContext);
336
337 Log(("VBOXSF: MRxRead: RxDispatchToWorkerThread: Status 0x%08X\n", Status));
338
339 if (Status == STATUS_SUCCESS)
340 Status = STATUS_PENDING;
341
342 return Status;
343}
344
345static NTSTATUS vbsfWriteInternal(IN PRX_CONTEXT RxContext)
346{
347 NTSTATUS Status = STATUS_SUCCESS;
348 VBSFTRANSFERCTX ctx;
349
350 RxCaptureFcb;
351 RxCaptureFobx;
352
353 PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext);
354 PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = VBoxMRxGetNetRootExtension(capFcb->pNetRoot);
355 PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);
356
357 PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
358
359 PMDL BufferMdl = LowIoContext->ParamsFor.ReadWrite.Buffer;
360 uint32_t ByteCount = LowIoContext->ParamsFor.ReadWrite.ByteCount;
361 RXVBO ByteOffset = LowIoContext->ParamsFor.ReadWrite.ByteOffset;
362
363 PVOID pbUserBuffer = RxLowIoGetBufferAddress(RxContext);
364
365 int vboxRC;
366
367#ifdef LOG_ENABLED
368 BOOLEAN AsyncIo = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_ASYNC_OPERATION);
369#endif
370 LONGLONG FileSize;
371
372 RxGetFileSizeWithLock((PFCB)capFcb, &FileSize);
373
374 Log(("VBOXSF: vbsfWriteInternal: AsyncIo = %d, Fcb->FileSize = 0x%RX64\n",
375 AsyncIo, capFcb->Header.FileSize.QuadPart));
376 Log(("VBOXSF: vbsfWriteInternal: UserBuffer %p, BufferMdl %p\n",
377 pbUserBuffer, BufferMdl));
378 Log(("VBOXSF: vbsfWriteInternal: ByteCount is 0x%X, ByteOffset is 0x%RX64, FileSize 0x%RX64\n",
379 ByteCount, ByteOffset, FileSize));
380
381 /** @todo allow to write 0 bytes. */
382 if ( !BufferMdl
383 || ByteCount == 0)
384 {
385 AssertFailed();
386 return STATUS_INVALID_PARAMETER;
387 }
388
389 ctx.pClient = &pDeviceExtension->hgcmClient;
390 ctx.pMap = &pNetRootExtension->map;
391 ctx.hFile = pVBoxFobx->hFile;
392 ctx.offset = (uint64_t)ByteOffset;
393 ctx.cbData = ByteCount;
394 ctx.pMdl = BufferMdl;
395 ctx.pBuffer = (uint8_t *)pbUserBuffer;
396 ctx.fLocked = true;
397 ctx.pfnTransferBuffer = vbsfTransferBufferWrite;
398 ctx.pfnTransferPages = vbsfTransferPagesWrite;
399
400 vboxRC = vbsfTransferCommon(&ctx);
401
402 ByteCount = ctx.cbData;
403
404 Status = VBoxErrorToNTStatus(vboxRC);
405
406 if (Status != STATUS_SUCCESS)
407 {
408 /* Nothing written. */
409 ByteCount = 0;
410 }
411
412 RxContext->InformationToReturn = ByteCount;
413
414 Log(("VBOXSF: vbsfWriteInternal: Status = 0x%08X, ByteCount = 0x%X\n",
415 Status, ByteCount));
416
417 return Status;
418}
419
420static VOID vbsfWriteWorker(VOID *pv)
421{
422 PRX_CONTEXT RxContext = (PRX_CONTEXT)pv;
423
424 Log(("VBOXSF: vbsfWriteWorker: calling the worker\n"));
425
426 RxContext->IoStatusBlock.Status = vbsfWriteInternal(RxContext);
427
428 Log(("VBOXSF: vbsfWriteWorker: Status 0x%08X\n",
429 RxContext->IoStatusBlock.Status));
430
431 RxLowIoCompletion(RxContext);
432}
433
434
435NTSTATUS VBoxMRxWrite(IN PRX_CONTEXT RxContext)
436{
437 NTSTATUS Status = RxDispatchToWorkerThread(VBoxMRxDeviceObject, DelayedWorkQueue,
438 vbsfWriteWorker,
439 RxContext);
440
441 Log(("VBOXSF: MRxWrite: RxDispatchToWorkerThread: Status 0x%08X\n",
442 Status));
443
444 if (Status == STATUS_SUCCESS)
445 Status = STATUS_PENDING;
446
447 return Status;
448}
449
450
451NTSTATUS VBoxMRxLocks(IN PRX_CONTEXT RxContext)
452{
453 NTSTATUS Status = STATUS_SUCCESS;
454
455 RxCaptureFcb;
456 RxCaptureFobx;
457
458 PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext);
459 PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = VBoxMRxGetNetRootExtension(capFcb->pNetRoot);
460 PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);
461
462 PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
463 uint32_t fu32Lock = 0;
464 int vboxRC;
465
466 Log(("VBOXSF: MRxLocks: Operation %d\n",
467 LowIoContext->Operation));
468
469 switch (LowIoContext->Operation)
470 {
471 default:
472 AssertMsgFailed(("VBOXSF: MRxLocks: Unsupported lock/unlock type %d detected!\n",
473 LowIoContext->Operation));
474 return STATUS_NOT_IMPLEMENTED;
475
476 case LOWIO_OP_UNLOCK_MULTIPLE:
477 /** @todo Remove multiple locks listed in LowIoContext.ParamsFor.Locks.LockList. */
478 Log(("VBOXSF: MRxLocks: Unsupported LOWIO_OP_UNLOCK_MULTIPLE!\n",
479 LowIoContext->Operation));
480 return STATUS_NOT_IMPLEMENTED;
481
482 case LOWIO_OP_SHAREDLOCK:
483 fu32Lock = SHFL_LOCK_SHARED | SHFL_LOCK_PARTIAL;
484 break;
485
486 case LOWIO_OP_EXCLUSIVELOCK:
487 fu32Lock = SHFL_LOCK_EXCLUSIVE | SHFL_LOCK_PARTIAL;
488 break;
489
490 case LOWIO_OP_UNLOCK:
491 fu32Lock = SHFL_LOCK_CANCEL | SHFL_LOCK_PARTIAL;
492 break;
493 }
494
495 if (LowIoContext->ParamsFor.Locks.Flags & LOWIO_LOCKSFLAG_FAIL_IMMEDIATELY)
496 fu32Lock |= SHFL_LOCK_NOWAIT;
497 else
498 fu32Lock |= SHFL_LOCK_WAIT;
499
500 vboxRC = VbglR0SfLock(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile,
501 LowIoContext->ParamsFor.Locks.ByteOffset, LowIoContext->ParamsFor.Locks.Length, fu32Lock);
502
503 Status = VBoxErrorToNTStatus(vboxRC);
504
505 Log(("VBOXSF: MRxLocks: Returned 0x%08X\n", Status));
506 return Status;
507}
508
509NTSTATUS VBoxMRxCompleteBufferingStateChangeRequest(IN OUT PRX_CONTEXT RxContext, IN OUT PMRX_SRV_OPEN SrvOpen,
510 IN PVOID pvContext)
511{
512 RT_NOREF(RxContext, SrvOpen, pvContext);
513 Log(("VBOXSF: MRxCompleteBufferingStateChangeRequest: not implemented\n"));
514 return STATUS_NOT_IMPLEMENTED;
515}
516
517NTSTATUS VBoxMRxFlush (IN PRX_CONTEXT RxContext)
518{
519 NTSTATUS Status = STATUS_SUCCESS;
520
521 RxCaptureFcb;
522 RxCaptureFobx;
523
524 PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext);
525 PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = VBoxMRxGetNetRootExtension(capFcb->pNetRoot);
526 PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);
527
528 int vboxRC;
529
530 Log(("VBOXSF: MRxFlush\n"));
531
532 /* Do the actual flushing of file buffers */
533 vboxRC = VbglR0SfFlush(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile);
534
535 Status = VBoxErrorToNTStatus(vboxRC);
536
537 Log(("VBOXSF: MRxFlush: Returned 0x%08X\n", Status));
538 return Status;
539}
540
541NTSTATUS vbsfSetEndOfFile(IN OUT struct _RX_CONTEXT * RxContext,
542 IN OUT PLARGE_INTEGER pNewFileSize,
543 OUT PLARGE_INTEGER pNewAllocationSize)
544{
545 NTSTATUS Status = STATUS_SUCCESS;
546
547 RxCaptureFcb;
548 RxCaptureFobx;
549
550 PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = VBoxMRxGetDeviceExtension(RxContext);
551 PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = VBoxMRxGetNetRootExtension(capFcb->pNetRoot);
552 PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);
553
554 PSHFLFSOBJINFO pObjInfo;
555 uint32_t cbBuffer;
556 int vboxRC;
557
558 Log(("VBOXSF: vbsfSetEndOfFile: New size = %RX64 (%p), pNewAllocationSize = %p\n",
559 pNewFileSize->QuadPart, pNewFileSize, pNewAllocationSize));
560
561 Assert(pVBoxFobx && pNetRootExtension && pDeviceExtension);
562
563 cbBuffer = sizeof(SHFLFSOBJINFO);
564 pObjInfo = (SHFLFSOBJINFO *)vbsfAllocNonPagedMem(cbBuffer);
565 if (!pObjInfo)
566 {
567 AssertFailed();
568 return STATUS_INSUFFICIENT_RESOURCES;
569 }
570
571 RtlZeroMemory(pObjInfo, cbBuffer);
572 pObjInfo->cbObject = pNewFileSize->QuadPart;
573
574 vboxRC = VbglR0SfFsInfo(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile,
575 SHFL_INFO_SET | SHFL_INFO_SIZE, &cbBuffer, (PSHFLDIRINFO)pObjInfo);
576
577 Log(("VBOXSF: vbsfSetEndOfFile: VbglR0SfFsInfo returned %Rrc\n", vboxRC));
578
579 Status = VBoxErrorToNTStatus(vboxRC);
580 if (Status == STATUS_SUCCESS)
581 {
582 Log(("VBOXSF: vbsfSetEndOfFile: VbglR0SfFsInfo new allocation size = %RX64\n",
583 pObjInfo->cbAllocated));
584
585 /* Return new allocation size */
586 pNewAllocationSize->QuadPart = pObjInfo->cbAllocated;
587 }
588
589 if (pObjInfo)
590 vbsfFreeNonPagedMem(pObjInfo);
591
592 Log(("VBOXSF: vbsfSetEndOfFile: Returned 0x%08X\n", Status));
593 return Status;
594}
595
596/** See PMRX_EXTENDFILE_CALLDOWN in ddk/mrx.h
597 *
598 * Documentation says it returns STATUS_SUCCESS on success and an error
599 * status on failure, so the ULONG return type is probably just a typo that
600 * stuck.
601 */
602ULONG NTAPI VBoxMRxExtendStub(IN OUT struct _RX_CONTEXT * RxContext, IN OUT PLARGE_INTEGER pNewFileSize,
603 OUT PLARGE_INTEGER pNewAllocationSize)
604{
605 RT_NOREF(RxContext);
606
607 /* Note: On Windows hosts vbsfSetEndOfFile returns ACCESS_DENIED if the file has been
608 * opened in APPEND mode. Writes to a file will extend it anyway, therefore it is
609 * better to not call the host at all and tell the caller that the file was extended.
610 */
611 Log(("VBOXSF: MRxExtendStub: new size = %RX64\n",
612 pNewFileSize->QuadPart));
613
614 pNewAllocationSize->QuadPart = pNewFileSize->QuadPart;
615
616 return STATUS_SUCCESS;
617}
618
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