VirtualBox

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

Last change on this file since 69498 was 69498, checked in by vboxsync, 7 years ago

backed out r118835 as it incorrectly updated the 'This file is based on' file headers.

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