Changeset 78577 in vbox
- Timestamp:
- May 18, 2019 10:53:11 AM (6 years ago)
- Location:
- trunk/src/VBox/Additions
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/WINNT/SharedFolders/driver/file.cpp
r78575 r78577 31 31 #define VBSF_MAX_IO_PAGES RT_MIN(_16K / sizeof(RTGCPHYS64) /* => 8MB buffer */, VMMDEV_MAX_HGCM_DATA_SIZE >> PAGE_SHIFT) 32 32 33 /* How much data to transfer in one HGCM request. */34 #define VBSF_MAX_READ_WRITE_PAGES 25635 36 37 typedef int FNVBSFTRANSFERBUFFER(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, SHFLHANDLE hFile,38 uint64_t offset, uint32_t *pcbBuffer,39 uint8_t *pBuffer, bool fLocked);40 typedef FNVBSFTRANSFERBUFFER *PFNVBSFTRANSFERBUFFER;41 42 typedef int FNVBSFTRANSFERPAGES(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, SHFLHANDLE hFile,43 uint64_t offset, uint32_t *pcbBuffer,44 uint16_t offFirstPage, uint16_t cPages, RTGCPHYS64 *paPages);45 typedef FNVBSFTRANSFERPAGES *PFNVBSFTRANSFERPAGES;46 47 48 static int vbsfTransferBufferWrite(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, SHFLHANDLE hFile,49 uint64_t offset, uint32_t *pcbBuffer,50 uint8_t *pBuffer, bool fLocked)51 {52 return VbglR0SfWrite(pClient, pMap, hFile, offset, pcbBuffer, pBuffer, fLocked);53 }54 55 static int vbsfTransferPagesWrite(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, SHFLHANDLE hFile,56 uint64_t offset, uint32_t *pcbBuffer,57 uint16_t offFirstPage, uint16_t cPages, RTGCPHYS64 *paPages)58 {59 return VbglR0SfWritePageList(pClient, pMap, hFile, offset, pcbBuffer, offFirstPage, cPages, paPages);60 }61 62 63 typedef struct VBSFTRANSFERCTX64 {65 PVBGLSFCLIENT pClient;66 PVBGLSFMAP pMap;67 SHFLHANDLE hFile;68 uint64_t offset;69 uint32_t cbData;70 71 PMDL pMdl;72 uint8_t *pBuffer;73 bool fLocked;74 75 PFNVBSFTRANSFERBUFFER pfnTransferBuffer;76 PFNVBSFTRANSFERPAGES pfnTransferPages;77 } VBSFTRANSFERCTX;78 79 80 static int vbsfTransferCommon(VBSFTRANSFERCTX *pCtx)81 {82 int rc = VINF_SUCCESS;83 BOOLEAN fProcessed = FALSE;84 85 uint32_t cbTransferred = 0;86 87 uint32_t cbToTransfer;88 uint32_t cbIO;89 90 /** @todo Remove the test and the fall-back path. VbglR0CanUsePhysPageList()91 * returns true for any host version after 3.0, i.e. further back than92 * we support. */93 if (VbglR0CanUsePhysPageList())94 {95 ULONG offFirstPage = MmGetMdlByteOffset(pCtx->pMdl);96 ULONG cPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(pCtx->pMdl), pCtx->cbData);97 ULONG cPagesToTransfer = RT_MIN(cPages, VBSF_MAX_READ_WRITE_PAGES);98 RTGCPHYS64 *paPages = (RTGCPHYS64 *)RTMemTmpAlloc(cPagesToTransfer * sizeof(RTGCPHYS64));99 100 Log(("VBOXSF: vbsfTransferCommon: using page list: %d pages, offset 0x%03X\n", cPages, offFirstPage));101 102 if (paPages)103 {104 PPFN_NUMBER paPfns = MmGetMdlPfnArray(pCtx->pMdl);105 ULONG cPagesTransferred = 0;106 cbTransferred = 0;107 108 while (cPagesToTransfer != 0)109 {110 ULONG iPage;111 cbToTransfer = cPagesToTransfer * PAGE_SIZE - offFirstPage;112 113 if (cbToTransfer > pCtx->cbData - cbTransferred)114 cbToTransfer = pCtx->cbData - cbTransferred;115 116 if (cbToTransfer == 0)117 {118 /* Nothing to transfer. */119 break;120 }121 122 cbIO = cbToTransfer;123 124 Log(("VBOXSF: vbsfTransferCommon: transferring %d pages at %d; %d bytes at %d\n",125 cPagesToTransfer, cPagesTransferred, cbToTransfer, cbTransferred));126 127 for (iPage = 0; iPage < cPagesToTransfer; iPage++)128 paPages[iPage] = (RTGCPHYS64)paPfns[iPage + cPagesTransferred] << PAGE_SHIFT;129 130 rc = pCtx->pfnTransferPages(pCtx->pClient, pCtx->pMap, pCtx->hFile,131 pCtx->offset + cbTransferred, &cbIO,132 (uint16_t)offFirstPage, (uint16_t)cPagesToTransfer, paPages);133 if (RT_FAILURE(rc))134 {135 Log(("VBOXSF: vbsfTransferCommon: pfnTransferPages %Rrc, cbTransferred %d\n", rc, cbTransferred));136 137 /* If some data was transferred, then it is no error. */138 if (cbTransferred > 0)139 rc = VINF_SUCCESS;140 141 break;142 }143 144 cbTransferred += cbIO;145 146 if (cbToTransfer < cbIO)147 {148 /* Transferred less than requested, do not continue with the possibly remaining data. */149 break;150 }151 152 cPagesTransferred += cPagesToTransfer;153 offFirstPage = 0;154 155 cPagesToTransfer = cPages - cPagesTransferred;156 if (cPagesToTransfer > VBSF_MAX_READ_WRITE_PAGES)157 cPagesToTransfer = VBSF_MAX_READ_WRITE_PAGES;158 }159 160 RTMemTmpFree(paPages);161 162 fProcessed = TRUE;163 }164 }165 166 if (fProcessed != TRUE)167 {168 /* Split large transfers. */169 cbTransferred = 0;170 cbToTransfer = RT_MIN(pCtx->cbData, VBSF_MAX_READ_WRITE_PAGES * PAGE_SIZE);171 172 /* Page list not supported or a fallback. */173 Log(("VBOXSF: vbsfTransferCommon: using linear address\n"));174 175 while (cbToTransfer != 0)176 {177 cbIO = cbToTransfer;178 179 Log(("VBOXSF: vbsfTransferCommon: transferring %d bytes at %d\n",180 cbToTransfer, cbTransferred));181 182 rc = pCtx->pfnTransferBuffer(pCtx->pClient, pCtx->pMap, pCtx->hFile,183 pCtx->offset + cbTransferred, &cbIO,184 pCtx->pBuffer + cbTransferred, true /* locked */);185 186 if (RT_FAILURE(rc))187 {188 Log(("VBOXSF: vbsfTransferCommon: pfnTransferBuffer %Rrc, cbTransferred %d\n", rc, cbTransferred));189 190 /* If some data was transferred, then it is no error. */191 if (cbTransferred > 0)192 rc = VINF_SUCCESS;193 194 break;195 }196 197 cbTransferred += cbIO;198 199 if (cbToTransfer < cbIO)200 {201 /* Transferred less than requested, do not continue with the possibly remaining data. */202 break;203 }204 205 cbToTransfer = pCtx->cbData - cbTransferred;206 if (cbToTransfer > VBSF_MAX_READ_WRITE_PAGES * PAGE_SIZE)207 cbToTransfer = VBSF_MAX_READ_WRITE_PAGES * PAGE_SIZE;208 }209 }210 211 pCtx->cbData = cbTransferred;212 213 return rc;214 }215 33 216 34 /** 217 35 * Performs a read. 36 * 37 * @note Almost identical to vbsfNtWriteWorker. 218 38 */ 219 39 static NTSTATUS vbsfNtReadWorker(PRX_CONTEXT RxContext) … … 228 48 LogFlow(("vbsfNtReadWorker: hFile=%#RX64 offFile=%#RX64 cbToRead=%#x %s\n", pVBoxFobX->hFile, 229 49 RxContext->LowIoContext.ParamsFor.ReadWrite.ByteOffset, RxContext->LowIoContext.ParamsFor.ReadWrite.ByteCount, 230 RxContext->Flags ,RX_CONTEXT_FLAG_ASYNC_OPERATION ? " async" : "sync"));50 RxContext->Flags & RX_CONTEXT_FLAG_ASYNC_OPERATION ? " async" : "sync")); 231 51 232 52 AssertReturn(pBufferMdl, STATUS_INTERNAL_ERROR); … … 398 218 * Wrapper for RxDispatchToWorkerThread(). 399 219 */ 400 static VOID vbsf ReadWorker(VOID *pv)220 static VOID vbsfNtReadThreadWorker(VOID *pv) 401 221 { 402 222 PRX_CONTEXT RxContext = (PRX_CONTEXT)pv; 403 223 404 Log(("VBOXSF: vbsf ReadWorker: calling the worker\n"));224 Log(("VBOXSF: vbsfNtReadThreadWorker: calling the worker\n")); 405 225 406 226 RxContext->IoStatusBlock.Status = vbsfNtReadWorker(RxContext); 407 227 408 Log(("VBOXSF: vbsf ReadWorker: Status 0x%08X\n",228 Log(("VBOXSF: vbsfNtReadThreadWorker: Status 0x%08X\n", 409 229 RxContext->IoStatusBlock.Status)); 410 230 … … 439 259 Assert(Status != STATUS_PENDING); 440 260 441 Log(("VBOXSF: MRxRead: vbsfReadInternal: Status %#08X\n", Status));261 Log(("VBOXSF: VBoxMRxRead: vbsfNtReadWorker: Status %#08X\n", Status)); 442 262 } 443 263 else 444 264 { 445 Status = RxDispatchToWorkerThread(VBoxMRxDeviceObject, DelayedWorkQueue, vbsf ReadWorker, RxContext);446 447 Log(("VBOXSF: MRxRead: RxDispatchToWorkerThread: Status 0x%08X\n", Status));265 Status = RxDispatchToWorkerThread(VBoxMRxDeviceObject, DelayedWorkQueue, vbsfNtReadThreadWorker, RxContext); 266 267 Log(("VBOXSF: VBoxMRxRead: RxDispatchToWorkerThread: Status 0x%08X\n", Status)); 448 268 449 269 if (Status == STATUS_SUCCESS) … … 454 274 } 455 275 456 static NTSTATUS vbsfWriteInternal(IN PRX_CONTEXT RxContext) 457 { 458 NTSTATUS Status = STATUS_SUCCESS; 459 VBSFTRANSFERCTX ctx; 460 276 /** 277 * Performs a write. 278 * 279 * @note Almost identical to vbsfNtReadWorker. 280 */ 281 static NTSTATUS vbsfNtWriteWorker(PRX_CONTEXT RxContext) 282 { 461 283 RxCaptureFcb; 462 284 RxCaptureFobx; 463 464 PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = VBoxMRxGetNetRootExtension(capFcb->pNetRoot); 465 PVBSFNTFCBEXT pVBoxFcbx = VBoxMRxGetFcbExtension(capFcb); 466 PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx); 467 468 PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext; 469 470 PMDL BufferMdl = LowIoContext->ParamsFor.ReadWrite.Buffer; 471 uint32_t ByteCount = LowIoContext->ParamsFor.ReadWrite.ByteCount; 472 RXVBO ByteOffset = LowIoContext->ParamsFor.ReadWrite.ByteOffset; 473 474 PVOID pbUserBuffer = RxLowIoGetBufferAddress(RxContext); 475 476 int vrc; 477 478 #ifdef LOG_ENABLED 479 BOOLEAN AsyncIo = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_ASYNC_OPERATION); 480 #endif 481 LONGLONG FileSize; 482 483 RxGetFileSizeWithLock((PFCB)capFcb, &FileSize); 484 485 Log(("VBOXSF: vbsfWriteInternal: AsyncIo = %d, Fcb->FileSize = 0x%RX64\n", 486 AsyncIo, capFcb->Header.FileSize.QuadPart)); 487 Log(("VBOXSF: vbsfWriteInternal: UserBuffer %p, BufferMdl %p\n", 488 pbUserBuffer, BufferMdl)); 489 Log(("VBOXSF: vbsfWriteInternal: ByteCount is 0x%X, ByteOffset is 0x%RX64, FileSize 0x%RX64\n", 490 ByteCount, ByteOffset, FileSize)); 491 492 /** @todo allow to write 0 bytes. */ 493 if ( !BufferMdl 494 || ByteCount == 0) 495 { 496 AssertFailed(); 497 return STATUS_INVALID_PARAMETER; 498 } 499 500 ctx.pClient = &g_SfClient; 501 ctx.pMap = &pNetRootExtension->map; 502 ctx.hFile = pVBoxFobx->hFile; 503 ctx.offset = (uint64_t)ByteOffset; 504 ctx.cbData = ByteCount; 505 ctx.pMdl = BufferMdl; 506 ctx.pBuffer = (uint8_t *)pbUserBuffer; 507 ctx.fLocked = true; 508 ctx.pfnTransferBuffer = vbsfTransferBufferWrite; 509 ctx.pfnTransferPages = vbsfTransferPagesWrite; 510 511 vrc = vbsfTransferCommon(&ctx); 512 513 ByteCount = ctx.cbData; 514 515 Status = vbsfNtVBoxStatusToNt(vrc); 516 517 if (Status == STATUS_SUCCESS) 518 { 519 pVBoxFobx->fTimestampsImplicitlyUpdated |= VBOX_FOBX_F_INFO_LASTWRITE_TIME; 520 if (pVBoxFcbx->pFobxLastWriteTime != pVBoxFobx) 521 pVBoxFcbx->pFobxLastWriteTime = NULL; 522 523 /* Make sure our cached file size value is up to date: */ 524 if (ctx.cbData > 0) 285 PMRX_VBOX_NETROOT_EXTENSION pNetRootX = VBoxMRxGetNetRootExtension(capFcb->pNetRoot); 286 PVBSFNTFCBEXT pVBoxFcbX = VBoxMRxGetFcbExtension(capFcb); 287 PMRX_VBOX_FOBX pVBoxFobX = VBoxMRxGetFileObjectExtension(capFobx); 288 PMDL pBufferMdl = RxContext->LowIoContext.ParamsFor.ReadWrite.Buffer; 289 290 LogFlow(("vbsfNtWriteWorker: hFile=%#RX64 offFile=%#RX64 cbToWrite=%#x %s\n", pVBoxFobX->hFile, 291 RxContext->LowIoContext.ParamsFor.ReadWrite.ByteOffset, RxContext->LowIoContext.ParamsFor.ReadWrite.ByteCount, 292 RxContext->Flags & RX_CONTEXT_FLAG_ASYNC_OPERATION ? " async" : "sync")); 293 294 AssertReturn(pBufferMdl, STATUS_INTERNAL_ERROR); 295 296 297 /* 298 * We should never get a zero byte request (RDBSS checks), but in case we 299 * do, it should succeed. 300 */ 301 uint32_t cbRet = 0; 302 uint32_t cbLeft = RxContext->LowIoContext.ParamsFor.ReadWrite.ByteCount; 303 AssertReturnStmt(cbLeft > 0, RxContext->InformationToReturn = 0, STATUS_SUCCESS); 304 305 Assert(cbLeft <= MmGetMdlByteCount(pBufferMdl)); 306 307 /* 308 * Allocate a request buffer. 309 */ 310 uint32_t cPagesLeft = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(pBufferMdl), cbLeft); 311 uint32_t cMaxPages = RT_MIN(cPagesLeft, VBSF_MAX_IO_PAGES); 312 VBOXSFWRITEPGLSTREQ *pReq = (VBOXSFWRITEPGLSTREQ *)VbglR0PhysHeapAlloc(RT_UOFFSETOF_DYN(VBOXSFWRITEPGLSTREQ, 313 PgLst.aPages[cMaxPages])); 314 while (!pReq && cMaxPages > 4) 315 { 316 cMaxPages /= 2; 317 pReq = (VBOXSFWRITEPGLSTREQ *)VbglR0PhysHeapAlloc(RT_UOFFSETOF_DYN(VBOXSFWRITEPGLSTREQ, PgLst.aPages[cMaxPages])); 318 } 319 NTSTATUS rcNt = STATUS_SUCCESS; 320 if (pReq) 321 { 322 /* 323 * The write loop. 324 */ 325 RTFOFF offFile = RxContext->LowIoContext.ParamsFor.ReadWrite.ByteOffset; 326 PPFN_NUMBER paPfns = MmGetMdlPfnArray(pBufferMdl); 327 uint32_t offPage = MmGetMdlByteOffset(pBufferMdl); 328 if (offPage < PAGE_SIZE) 329 { /* likely */ } 330 else 525 331 { 526 RTFOFF offEndOfWrite = LowIoContext->ParamsFor.ReadWrite.ByteOffset + ctx.cbData; 527 if (pVBoxFobx->Info.cbObject < offEndOfWrite) 528 pVBoxFobx->Info.cbObject = offEndOfWrite; 529 530 if (pVBoxFobx->Info.cbAllocated < offEndOfWrite) 531 { 532 pVBoxFobx->Info.cbAllocated = offEndOfWrite; 533 pVBoxFobx->nsUpToDate = 0; 534 } 332 paPfns += offPage >> PAGE_SHIFT; 333 offPage &= PAGE_OFFSET_MASK; 535 334 } 335 336 for (;;) 337 { 338 /* 339 * Figure out how much to process now and set up the page list for it. 340 */ 341 uint32_t cPagesInChunk; 342 uint32_t cbChunk; 343 if (cPagesLeft <= cMaxPages) 344 { 345 cPagesInChunk = cPagesLeft; 346 cbChunk = cbLeft; 347 } 348 else 349 { 350 cPagesInChunk = cMaxPages; 351 cbChunk = (cMaxPages << PAGE_SHIFT) - offPage; 352 } 353 354 size_t iPage = cPagesInChunk; 355 while (iPage-- > 0) 356 pReq->PgLst.aPages[iPage] = (RTGCPHYS)paPfns[iPage] << PAGE_SHIFT; 357 pReq->PgLst.offFirstPage = offPage; 358 359 /* 360 * Issue the request and unlock the pages. 361 */ 362 int vrc = VbglR0SfHostReqWritePgLst(pNetRootX->map.root, pReq, pVBoxFobX->hFile, offFile, cbChunk, cPagesInChunk); 363 if (RT_SUCCESS(vrc)) 364 { 365 /* 366 * Success, advance position and buffer. 367 */ 368 uint32_t cbActual = pReq->Parms.cb32Write.u.value32; 369 AssertStmt(cbActual <= cbChunk, cbActual = cbChunk); 370 cbRet += cbActual; 371 offFile += cbActual; 372 cbLeft -= cbActual; 373 374 /* 375 * Update timestamp state (FCB is shared). 376 */ 377 pVBoxFobX->fTimestampsImplicitlyUpdated |= VBOX_FOBX_F_INFO_LASTWRITE_TIME; 378 if (pVBoxFcbX->pFobxLastWriteTime != pVBoxFobX) 379 pVBoxFcbX->pFobxLastWriteTime = NULL; 380 381 /* 382 * Are we done already? 383 */ 384 if (!cbLeft || cbActual < cbChunk) 385 { 386 /* 387 * Make sure our cached file size value is up to date (RDBSS takes care 388 * of the ones in the FCB as well as the cache manager). 389 */ 390 if (cbRet > 0) 391 { 392 if (pVBoxFobX->Info.cbObject < offFile) 393 pVBoxFobX->Info.cbObject = offFile; 394 395 if (pVBoxFobX->Info.cbAllocated < offFile) 396 { 397 pVBoxFobX->Info.cbAllocated = offFile; 398 pVBoxFobX->nsUpToDate = 0; 399 } 400 } 401 break; 402 } 403 404 /* 405 * More to write, advance page related variables and loop. 406 */ 407 paPfns += cPagesInChunk; 408 cPagesLeft -= cPagesInChunk; 409 offPage = 0; 410 } 411 else if (vrc == VERR_NO_MEMORY && cMaxPages > 4) 412 { 413 /* 414 * The host probably doesn't have enough heap to handle the 415 * request, reduce the page count and retry. 416 */ 417 cMaxPages /= 4; 418 Assert(cMaxPages > 0); 419 } 420 else 421 { 422 /* 423 * If we've successfully written stuff, return it rather than 424 * the error. (Not sure if this is such a great idea...) 425 */ 426 if (cbRet > 0) 427 Log(("vbsfNtWriteWorker: write at %#RX64 -> %Rrc; got cbRet=%#zx already\n", offFile, vrc, cbRet)); 428 else 429 { 430 rcNt = vbsfNtVBoxStatusToNt(vrc); 431 Log(("vbsfNtWriteWorker: write at %#RX64 -> %Rrc (rcNt=%#x)\n", offFile, vrc, rcNt)); 432 } 433 break; 434 } 435 436 } 437 438 VbglR0PhysHeapFree(pReq); 536 439 } 537 440 else 538 ByteCount = 0; /* Nothing written. */539 540 RxContext->InformationToReturn = ByteCount;541 542 Log(("VBOXSF: vbsfWriteInternal: Status = 0x%08X, ByteCount = 0x%X\n",543 Status, ByteCount)); 544 545 return Status; 546 } 547 548 static VOID vbsf WriteWorker(VOID *pv)441 rcNt = STATUS_INSUFFICIENT_RESOURCES; 442 RxContext->InformationToReturn = cbRet; 443 LogFlow(("vbsfNtWriteWorker: returns %#x cbRet=%#x @ %#RX64\n", 444 rcNt, cbRet, RxContext->LowIoContext.ParamsFor.ReadWrite.ByteOffset)); 445 return rcNt; 446 } 447 448 /** 449 * Wrapper for RxDispatchToWorkerThread(). 450 */ 451 static VOID vbsfNtWriteThreadWorker(VOID *pv) 549 452 { 550 453 PRX_CONTEXT RxContext = (PRX_CONTEXT)pv; 551 454 552 Log(("VBOXSF: vbsf WriteWorker: calling the worker\n"));553 554 RxContext->IoStatusBlock.Status = vbsf WriteInternal(RxContext);555 556 Log(("VBOXSF: vbsf WriteWorker: Status 0x%08X\n",455 Log(("VBOXSF: vbsfNtWriteThreadWorker: calling the worker\n")); 456 457 RxContext->IoStatusBlock.Status = vbsfNtWriteWorker(RxContext); 458 459 Log(("VBOXSF: vbsfNtWriteThreadWorker: Status 0x%08X\n", 557 460 RxContext->IoStatusBlock.Status)); 558 461 … … 560 463 } 561 464 562 563 465 NTSTATUS VBoxMRxWrite(IN PRX_CONTEXT RxContext) 564 466 { 565 NTSTATUS Status = RxDispatchToWorkerThread(VBoxMRxDeviceObject, DelayedWorkQueue, 566 vbsfWriteWorker, 567 RxContext); 568 569 Log(("VBOXSF: MRxWrite: RxDispatchToWorkerThread: Status 0x%08X\n", 570 Status)); 571 572 if (Status == STATUS_SUCCESS) 573 Status = STATUS_PENDING; 467 NTSTATUS Status; 468 469 /* If synchronous operation, keep it on this thread (RDBSS already checked 470 if we've got enough stack before calling us). */ 471 if (!(RxContext->Flags & RX_CONTEXT_FLAG_ASYNC_OPERATION)) 472 { 473 RxContext->IoStatusBlock.Status = Status = vbsfNtWriteWorker(RxContext); 474 Assert(Status != STATUS_PENDING); 475 476 Log(("VBOXSF: VBoxMRxWrite: vbsfNtWriteWorker: Status %#08X\n", Status)); 477 } 478 else 479 { 480 Status = RxDispatchToWorkerThread(VBoxMRxDeviceObject, DelayedWorkQueue, vbsfNtWriteThreadWorker, RxContext); 481 482 Log(("VBOXSF: VBoxMRxWrite: RxDispatchToWorkerThread: Status 0x%08X\n", Status)); 483 484 if (Status == STATUS_SUCCESS) 485 Status = STATUS_PENDING; 486 } 574 487 575 488 return Status; -
trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR0LibSharedFolders.c
r78576 r78577 393 393 } 394 394 395 # endif /* !RT_OS_WINDOWS */396 397 395 DECLVBGL(int) VbglR0SfWrite(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, SHFLHANDLE hFile, 398 396 uint64_t offset, uint32_t *pcbBuffer, uint8_t *pBuffer, bool fLocked) … … 520 518 return rc; 521 519 } 520 521 # endif /* !RT_OS_WINDOWS */ 522 522 523 523 DECLVBGL(int) VbglR0SfFlush(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, SHFLHANDLE hFile)
Note:
See TracChangeset
for help on using the changeset viewer.