VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/SharedFolders/driver/file.cpp@ 78321

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

winnt/vboxsf: Doxygen and related cleanups; eliminating the separate helper header. bugref:9172

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