VirtualBox

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

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

winnt/vboxsf: Contiuing cleaning up VBoxMRxSetFileInfo; moving stuff to improve locality somewhat. bugref:9172

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