VirtualBox

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

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

winnt/vboxsf: Use g_SfClient everywhere to avoid having dangling pointers (MRX_VBOX_NETROOT_EXTENSION::phgcmClient) and copies (MRX_VBOX_DEVICE_EXTENSION::hgcmClient). This also reduces the stack space usage. ASSUMES that the module can only be instantiated once (already an assumption of the g_SfClient variable and related code in VBoxGuestLibSharedFoldersInline.h). Renamed all sources to .cpp (except the w2k hacks). bugref:9172

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 19.8 KB
Line 
1/* $Id: file.cpp 78304 2019-04-26 01:19:49Z 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_NETROOT_EXTENSION pNetRootExtension = VBoxMRxGetNetRootExtension(capFcb->pNetRoot);
229 PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);
230
231 PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
232
233 PMDL BufferMdl = LowIoContext->ParamsFor.ReadWrite.Buffer;
234 uint32_t ByteCount = LowIoContext->ParamsFor.ReadWrite.ByteCount;
235 RXVBO ByteOffset = LowIoContext->ParamsFor.ReadWrite.ByteOffset;
236
237 PVOID pbUserBuffer = RxLowIoGetBufferAddress(RxContext);
238
239 int vrc;
240
241#ifdef LOG_ENABLED
242 BOOLEAN AsyncIo = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_ASYNC_OPERATION);
243#endif
244 LONGLONG FileSize;
245
246 RxGetFileSizeWithLock((PFCB)capFcb, &FileSize);
247
248 Log(("VBOXSF: vbsfReadInternal: AsyncIo = %d, Fcb->FileSize = 0x%RX64\n",
249 AsyncIo, capFcb->Header.FileSize.QuadPart));
250 Log(("VBOXSF: vbsfReadInternal: UserBuffer %p, BufferMdl %p\n",
251 pbUserBuffer, BufferMdl));
252 Log(("VBOXSF: vbsfReadInternal: ByteCount 0x%X, ByteOffset 0x%RX64, FileSize 0x%RX64\n",
253 ByteCount, ByteOffset, FileSize));
254
255 /** @todo check if this is necessary. */
256#ifdef FCB_STATE_READCACHING_ENABLED /* Correct spelling for Vista 6001 SDK. */
257 if (!FlagOn(capFcb->FcbState, FCB_STATE_READCACHING_ENABLED))
258#else
259 if (!FlagOn(capFcb->FcbState, FCB_STATE_READCACHEING_ENABLED))
260#endif
261 {
262/** @todo r=bird: How is this file size accurate given that the file resides
263 * on the host and be grown/shrunk independently there? Why is this
264 * only done when FCB_STATE_READCACHEING_ENABLED is clear? */
265 if (ByteOffset >= FileSize)
266 {
267 Log(("VBOXSF: vbsfReadInternal: EOF\n"));
268 return STATUS_END_OF_FILE;
269 }
270
271 if (ByteCount > FileSize - ByteOffset)
272 ByteCount = (ULONG)(FileSize - ByteOffset);
273 }
274
275 /** @todo read 0 bytes == always success? */
276 if ( !BufferMdl
277 || ByteCount == 0)
278 {
279 AssertFailed();
280 return STATUS_INVALID_PARAMETER;
281 }
282
283 ctx.pClient = &g_SfClient;
284 ctx.pMap = &pNetRootExtension->map;
285 ctx.hFile = pVBoxFobx->hFile;
286 ctx.offset = (uint64_t)ByteOffset;
287 ctx.cbData = ByteCount;
288 ctx.pMdl = BufferMdl;
289 ctx.pBuffer = (uint8_t *)pbUserBuffer;
290 ctx.fLocked = true;
291 ctx.pfnTransferBuffer = vbsfTransferBufferRead;
292 ctx.pfnTransferPages = vbsfTransferPagesRead;
293
294 vrc = vbsfTransferCommon(&ctx);
295
296 ByteCount = ctx.cbData;
297
298 Status = VBoxErrorToNTStatus(vrc);
299
300 if (Status != STATUS_SUCCESS)
301 {
302 /* Nothing read. */
303 ByteCount = 0;
304 }
305
306 RxContext->InformationToReturn = ByteCount;
307
308 Log(("VBOXSF: vbsfReadInternal: Status = 0x%08X, ByteCount = 0x%X\n",
309 Status, ByteCount));
310
311 return Status;
312}
313
314
315static VOID vbsfReadWorker(VOID *pv)
316{
317 PRX_CONTEXT RxContext = (PRX_CONTEXT)pv;
318
319 Log(("VBOXSF: vbsfReadWorker: calling the worker\n"));
320
321 RxContext->IoStatusBlock.Status = vbsfReadInternal(RxContext);
322
323 Log(("VBOXSF: vbsfReadWorker: Status 0x%08X\n",
324 RxContext->IoStatusBlock.Status));
325
326 RxLowIoCompletion(RxContext);
327}
328
329NTSTATUS VBoxMRxRead(IN PRX_CONTEXT RxContext)
330{
331 NTSTATUS Status;
332
333#if 0
334 if ( IoIsOperationSynchronous(RxContext->CurrentIrp)
335 /*&& IoGetRemainingStackSize() >= 1024 - not necessary, checked by RxFsdCommonDispatch already */)
336 {
337 RxContext->IoStatusBlock.Status = Status = vbsfReadInternal(RxContext);
338 Assert(Status != STATUS_PENDING);
339
340 Log(("VBOXSF: MRxRead: vbsfReadInternal: Status %#08X\n", Status));
341 }
342 else
343#endif
344 {
345 Status = RxDispatchToWorkerThread(VBoxMRxDeviceObject, DelayedWorkQueue, vbsfReadWorker, RxContext);
346
347 Log(("VBOXSF: MRxRead: RxDispatchToWorkerThread: Status 0x%08X\n", Status));
348
349 if (Status == STATUS_SUCCESS)
350 Status = STATUS_PENDING;
351 }
352
353 return Status;
354}
355
356static NTSTATUS vbsfWriteInternal(IN PRX_CONTEXT RxContext)
357{
358 NTSTATUS Status = STATUS_SUCCESS;
359 VBSFTRANSFERCTX ctx;
360
361 RxCaptureFcb;
362 RxCaptureFobx;
363
364 PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = VBoxMRxGetNetRootExtension(capFcb->pNetRoot);
365 PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);
366
367 PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
368
369 PMDL BufferMdl = LowIoContext->ParamsFor.ReadWrite.Buffer;
370 uint32_t ByteCount = LowIoContext->ParamsFor.ReadWrite.ByteCount;
371 RXVBO ByteOffset = LowIoContext->ParamsFor.ReadWrite.ByteOffset;
372
373 PVOID pbUserBuffer = RxLowIoGetBufferAddress(RxContext);
374
375 int vrc;
376
377#ifdef LOG_ENABLED
378 BOOLEAN AsyncIo = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_ASYNC_OPERATION);
379#endif
380 LONGLONG FileSize;
381
382 RxGetFileSizeWithLock((PFCB)capFcb, &FileSize);
383
384 Log(("VBOXSF: vbsfWriteInternal: AsyncIo = %d, Fcb->FileSize = 0x%RX64\n",
385 AsyncIo, capFcb->Header.FileSize.QuadPart));
386 Log(("VBOXSF: vbsfWriteInternal: UserBuffer %p, BufferMdl %p\n",
387 pbUserBuffer, BufferMdl));
388 Log(("VBOXSF: vbsfWriteInternal: ByteCount is 0x%X, ByteOffset is 0x%RX64, FileSize 0x%RX64\n",
389 ByteCount, ByteOffset, FileSize));
390
391 /** @todo allow to write 0 bytes. */
392 if ( !BufferMdl
393 || ByteCount == 0)
394 {
395 AssertFailed();
396 return STATUS_INVALID_PARAMETER;
397 }
398
399 ctx.pClient = &g_SfClient;
400 ctx.pMap = &pNetRootExtension->map;
401 ctx.hFile = pVBoxFobx->hFile;
402 ctx.offset = (uint64_t)ByteOffset;
403 ctx.cbData = ByteCount;
404 ctx.pMdl = BufferMdl;
405 ctx.pBuffer = (uint8_t *)pbUserBuffer;
406 ctx.fLocked = true;
407 ctx.pfnTransferBuffer = vbsfTransferBufferWrite;
408 ctx.pfnTransferPages = vbsfTransferPagesWrite;
409
410 vrc = vbsfTransferCommon(&ctx);
411
412 ByteCount = ctx.cbData;
413
414 Status = VBoxErrorToNTStatus(vrc);
415
416 if (Status != STATUS_SUCCESS)
417 {
418 /* Nothing written. */
419 ByteCount = 0;
420 }
421
422 RxContext->InformationToReturn = ByteCount;
423
424 Log(("VBOXSF: vbsfWriteInternal: Status = 0x%08X, ByteCount = 0x%X\n",
425 Status, ByteCount));
426
427 return Status;
428}
429
430static VOID vbsfWriteWorker(VOID *pv)
431{
432 PRX_CONTEXT RxContext = (PRX_CONTEXT)pv;
433
434 Log(("VBOXSF: vbsfWriteWorker: calling the worker\n"));
435
436 RxContext->IoStatusBlock.Status = vbsfWriteInternal(RxContext);
437
438 Log(("VBOXSF: vbsfWriteWorker: Status 0x%08X\n",
439 RxContext->IoStatusBlock.Status));
440
441 RxLowIoCompletion(RxContext);
442}
443
444
445NTSTATUS VBoxMRxWrite(IN PRX_CONTEXT RxContext)
446{
447 NTSTATUS Status = RxDispatchToWorkerThread(VBoxMRxDeviceObject, DelayedWorkQueue,
448 vbsfWriteWorker,
449 RxContext);
450
451 Log(("VBOXSF: MRxWrite: RxDispatchToWorkerThread: Status 0x%08X\n",
452 Status));
453
454 if (Status == STATUS_SUCCESS)
455 Status = STATUS_PENDING;
456
457 return Status;
458}
459
460
461NTSTATUS VBoxMRxLocks(IN PRX_CONTEXT RxContext)
462{
463 NTSTATUS Status = STATUS_SUCCESS;
464
465 RxCaptureFcb;
466 RxCaptureFobx;
467
468 PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = VBoxMRxGetNetRootExtension(capFcb->pNetRoot);
469 PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);
470
471 PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
472 uint32_t fu32Lock = 0;
473 int vrc;
474
475 Log(("VBOXSF: MRxLocks: Operation %d\n",
476 LowIoContext->Operation));
477
478 switch (LowIoContext->Operation)
479 {
480 default:
481 AssertMsgFailed(("VBOXSF: MRxLocks: Unsupported lock/unlock type %d detected!\n",
482 LowIoContext->Operation));
483 return STATUS_NOT_IMPLEMENTED;
484
485 case LOWIO_OP_UNLOCK_MULTIPLE:
486 /** @todo Remove multiple locks listed in LowIoContext.ParamsFor.Locks.LockList. */
487 Log(("VBOXSF: MRxLocks: Unsupported LOWIO_OP_UNLOCK_MULTIPLE!\n",
488 LowIoContext->Operation));
489 return STATUS_NOT_IMPLEMENTED;
490
491 case LOWIO_OP_SHAREDLOCK:
492 fu32Lock = SHFL_LOCK_SHARED | SHFL_LOCK_PARTIAL;
493 break;
494
495 case LOWIO_OP_EXCLUSIVELOCK:
496 fu32Lock = SHFL_LOCK_EXCLUSIVE | SHFL_LOCK_PARTIAL;
497 break;
498
499 case LOWIO_OP_UNLOCK:
500 fu32Lock = SHFL_LOCK_CANCEL | SHFL_LOCK_PARTIAL;
501 break;
502 }
503
504 if (LowIoContext->ParamsFor.Locks.Flags & LOWIO_LOCKSFLAG_FAIL_IMMEDIATELY)
505 fu32Lock |= SHFL_LOCK_NOWAIT;
506 else
507 fu32Lock |= SHFL_LOCK_WAIT;
508
509 vrc = VbglR0SfLock(&g_SfClient, &pNetRootExtension->map, pVBoxFobx->hFile,
510 LowIoContext->ParamsFor.Locks.ByteOffset, LowIoContext->ParamsFor.Locks.Length, fu32Lock);
511
512 Status = VBoxErrorToNTStatus(vrc);
513
514 Log(("VBOXSF: MRxLocks: Returned 0x%08X\n", Status));
515 return Status;
516}
517
518NTSTATUS VBoxMRxCompleteBufferingStateChangeRequest(IN OUT PRX_CONTEXT RxContext, IN OUT PMRX_SRV_OPEN SrvOpen,
519 IN PVOID pvContext)
520{
521 RT_NOREF(RxContext, SrvOpen, pvContext);
522 Log(("VBOXSF: MRxCompleteBufferingStateChangeRequest: not implemented\n"));
523 return STATUS_NOT_IMPLEMENTED;
524}
525
526NTSTATUS VBoxMRxFlush (IN PRX_CONTEXT RxContext)
527{
528 NTSTATUS Status = STATUS_SUCCESS;
529
530 RxCaptureFcb;
531 RxCaptureFobx;
532
533 PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = VBoxMRxGetNetRootExtension(capFcb->pNetRoot);
534 PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);
535
536 int vrc;
537
538 Log(("VBOXSF: MRxFlush\n"));
539
540 /* Do the actual flushing of file buffers */
541 vrc = VbglR0SfFlush(&g_SfClient, &pNetRootExtension->map, pVBoxFobx->hFile);
542
543 Status = VBoxErrorToNTStatus(vrc);
544
545 Log(("VBOXSF: MRxFlush: Returned 0x%08X\n", Status));
546 return Status;
547}
548
549NTSTATUS vbsfSetEndOfFile(IN OUT struct _RX_CONTEXT * RxContext,
550 IN OUT PLARGE_INTEGER pNewFileSize,
551 OUT PLARGE_INTEGER pNewAllocationSize)
552{
553 NTSTATUS Status = STATUS_SUCCESS;
554
555 RxCaptureFcb;
556 RxCaptureFobx;
557
558 PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = VBoxMRxGetNetRootExtension(capFcb->pNetRoot);
559 PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx);
560
561 PSHFLFSOBJINFO pObjInfo;
562 uint32_t cbBuffer;
563 int vrc;
564
565 Log(("VBOXSF: vbsfSetEndOfFile: New size = %RX64 (%p), pNewAllocationSize = %p\n",
566 pNewFileSize->QuadPart, pNewFileSize, pNewAllocationSize));
567
568 Assert(pVBoxFobx && pNetRootExtension);
569
570 cbBuffer = sizeof(SHFLFSOBJINFO);
571 pObjInfo = (SHFLFSOBJINFO *)vbsfAllocNonPagedMem(cbBuffer);
572 if (!pObjInfo)
573 {
574 AssertFailed();
575 return STATUS_INSUFFICIENT_RESOURCES;
576 }
577
578 RtlZeroMemory(pObjInfo, cbBuffer);
579 pObjInfo->cbObject = pNewFileSize->QuadPart;
580
581 vrc = VbglR0SfFsInfo(&g_SfClient, &pNetRootExtension->map, pVBoxFobx->hFile,
582 SHFL_INFO_SET | SHFL_INFO_SIZE, &cbBuffer, (PSHFLDIRINFO)pObjInfo);
583
584 Log(("VBOXSF: vbsfSetEndOfFile: VbglR0SfFsInfo returned %Rrc\n", vrc));
585
586 Status = VBoxErrorToNTStatus(vrc);
587 if (Status == STATUS_SUCCESS)
588 {
589 Log(("VBOXSF: vbsfSetEndOfFile: VbglR0SfFsInfo new allocation size = %RX64\n",
590 pObjInfo->cbAllocated));
591
592 /* Return new allocation size */
593 pNewAllocationSize->QuadPart = pObjInfo->cbAllocated;
594 }
595
596 if (pObjInfo)
597 vbsfFreeNonPagedMem(pObjInfo);
598
599 Log(("VBOXSF: vbsfSetEndOfFile: Returned 0x%08X\n", Status));
600 return Status;
601}
602
603/** See PMRX_EXTENDFILE_CALLDOWN in ddk/mrx.h
604 *
605 * Documentation says it returns STATUS_SUCCESS on success and an error
606 * status on failure, so the ULONG return type is probably just a typo that
607 * stuck.
608 */
609ULONG NTAPI VBoxMRxExtendStub(IN OUT struct _RX_CONTEXT * RxContext, IN OUT PLARGE_INTEGER pNewFileSize,
610 OUT PLARGE_INTEGER pNewAllocationSize)
611{
612 RT_NOREF(RxContext);
613
614 /* Note: On Windows hosts vbsfSetEndOfFile returns ACCESS_DENIED if the file has been
615 * opened in APPEND mode. Writes to a file will extend it anyway, therefore it is
616 * better to not call the host at all and tell the caller that the file was extended.
617 */
618 Log(("VBOXSF: MRxExtendStub: new size = %RX64\n",
619 pNewFileSize->QuadPart));
620
621 pNewAllocationSize->QuadPart = pNewFileSize->QuadPart;
622
623 return STATUS_SUCCESS;
624}
625
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