VirtualBox

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

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

winnt/vboxsf: Try keep the FCB file sizes (in FSRTL_COMMON_FCB_HEADER) up to date when we have relevant info handy. For now that means setting information, querying information and reading. bugref:9172

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette