Changeset 51229 in vbox
- Timestamp:
- May 9, 2014 7:34:42 PM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/Support/win/SUPDrv-win.cpp
r49855 r51229 65 65 /** Win Symlink name for user access. */ 66 66 #define DEVICE_NAME_DOS_USR L"\\DosDevices\\VBoxDrvU" 67 68 /** Enables the fast I/O control code path. */ 69 #define VBOXDRV_WITH_FAST_IO 67 70 68 71 … … 109 112 static NTSTATUS _stdcall VBoxDrvNtCleanup(PDEVICE_OBJECT pDevObj, PIRP pIrp); 110 113 static NTSTATUS _stdcall VBoxDrvNtClose(PDEVICE_OBJECT pDevObj, PIRP pIrp); 114 #ifdef VBOXDRV_WITH_FAST_IO 115 static BOOLEAN _stdcall VBoxDrvNtFastIoDeviceControl(PFILE_OBJECT pFileObj, BOOLEAN fWait, PVOID pvInput, ULONG cbInput, 116 PVOID pvOutput, ULONG cbOutput, ULONG uCmd, 117 PIO_STATUS_BLOCK pIoStatus, PDEVICE_OBJECT pDevObj); 118 #endif 111 119 static NTSTATUS _stdcall VBoxDrvNtDeviceControl(PDEVICE_OBJECT pDevObj, PIRP pIrp); 112 120 static int VBoxDrvNtDeviceControlSlow(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PIRP pIrp, PIO_STACK_LOCATION pStack); … … 132 140 /** Pointer to the user device instance. */ 133 141 static PDEVICE_OBJECT g_pDevObjUsr = NULL; 142 #ifdef VBOXDRV_WITH_FAST_IO 143 /** Fast I/O dispatch table. */ 144 static FAST_IO_DISPATCH const g_VBoxDrvFastIoDispatch = 145 { 146 /* .SizeOfFastIoDispatch = */ sizeof(g_VBoxDrvFastIoDispatch), 147 /* .FastIoCheckIfPossible = */ NULL, 148 /* .FastIoRead = */ NULL, 149 /* .FastIoWrite = */ NULL, 150 /* .FastIoQueryBasicInfo = */ NULL, 151 /* .FastIoQueryStandardInfo = */ NULL, 152 /* .FastIoLock = */ NULL, 153 /* .FastIoUnlockSingle = */ NULL, 154 /* .FastIoUnlockAll = */ NULL, 155 /* .FastIoUnlockAllByKey = */ NULL, 156 /* .FastIoDeviceControl = */ VBoxDrvNtFastIoDeviceControl, 157 /* .AcquireFileForNtCreateSection = */ NULL, 158 /* .ReleaseFileForNtCreateSection = */ NULL, 159 /* .FastIoDetachDevice = */ NULL, 160 /* .FastIoQueryNetworkOpenInfo = */ NULL, 161 /* .AcquireForModWrite = */ NULL, 162 /* .MdlRead = */ NULL, 163 /* .MdlReadComplete = */ NULL, 164 /* .PrepareMdlWrite = */ NULL, 165 /* .MdlWriteComplete = */ NULL, 166 /* .FastIoReadCompressed = */ NULL, 167 /* .FastIoWriteCompressed = */ NULL, 168 /* .MdlReadCompleteCompressed = */ NULL, 169 /* .MdlWriteCompleteCompressed = */ NULL, 170 /* .FastIoQueryOpen = */ NULL, 171 /* .ReleaseForModWrite = */ NULL, 172 /* .AcquireForCcFlush = */ NULL, 173 /* .ReleaseForCcFlush = */ NULL, 174 }; 175 #endif /* VBOXDRV_WITH_FAST_IO */ 134 176 135 177 … … 219 261 { 220 262 /* 263 * Sanity checks. 264 */ 265 #ifdef VBOXDRV_WITH_FAST_IO 266 if (g_VBoxDrvFastIoDispatch.FastIoDeviceControl != VBoxDrvNtFastIoDeviceControl) 267 { 268 DbgPrint("VBoxDrv: FastIoDeviceControl=%p instead of %p\n", 269 g_VBoxDrvFastIoDispatch.FastIoDeviceControl, VBoxDrvNtFastIoDeviceControl); 270 return STATUS_INTERNAL_ERROR; 271 } 272 #endif 273 274 /* 221 275 * Create device. 222 276 * (That means creating a device object and a symbolic link so the DOS … … 254 308 /* more? */ 255 309 310 #ifdef VBOXDRV_WITH_FAST_IO 311 /* Fast I/O to speed up guest execution roundtrips. */ 312 pDrvObj->FastIoDispatch = (PFAST_IO_DISPATCH)&g_VBoxDrvFastIoDispatch; 313 #endif 314 256 315 /* Register ourselves for power state changes. */ 257 316 UNICODE_STRING CallbackName; … … 428 487 429 488 489 #ifdef VBOXDRV_WITH_FAST_IO 490 /** 491 * Fast I/O device control callback. 492 * 493 * This performs no buffering, neither on the way in or out. 494 * 495 * @returns TRUE if handled, FALSE if the normal I/O control routine should be 496 * called. 497 * @param pFileObj The file object. 498 * @param fWait Whether it's a blocking call 499 * @param pvInput The input buffer as specified by the user. 500 * @param cbInput The size of the input buffer. 501 * @param pvOutput The output buffer as specfied by the user. 502 * @param cbOutput The size of the output buffer. 503 * @param uFunction The function. 504 * @param pIoStatus Where to return the status of the operation. 505 * @param pDevObj The device object.. 506 */ 507 static BOOLEAN _stdcall VBoxDrvNtFastIoDeviceControl(PFILE_OBJECT pFileObj, BOOLEAN fWait, PVOID pvInput, ULONG cbInput, 508 PVOID pvOutput, ULONG cbOutput, ULONG uCmd, 509 PIO_STATUS_BLOCK pIoStatus, PDEVICE_OBJECT pDevObj) 510 { 511 PSUPDRVDEVEXT pDevExt = SUPDRVNT_GET_DEVEXT(pDevObj); 512 PSUPDRVSESSION pSession = (PSUPDRVSESSION)pFileObj->FsContext; 513 514 /* 515 * Check the input a little bit. 516 */ 517 if (!pSession) 518 { 519 pIoStatus->Status = STATUS_INVALID_PARAMETER; 520 pIoStatus->Information = 0; 521 return TRUE; 522 } 523 524 /* 525 * Deal with the 2-3 high-speed IOCtl that takes their arguments from 526 * the session and iCmd, and does not return anything. 527 */ 528 if ( ( uCmd == SUP_IOCTL_FAST_DO_RAW_RUN 529 || uCmd == SUP_IOCTL_FAST_DO_HM_RUN 530 || uCmd == SUP_IOCTL_FAST_DO_NOP) 531 && pSession->fUnrestricted == true) 532 { 533 int rc = supdrvIOCtlFast(uCmd, (unsigned)(uintptr_t)pvInput/* VMCPU id */, pDevExt, pSession); 534 pIoStatus->Status = RT_SUCCESS(rc) ? STATUS_SUCCESS : STATUS_INVALID_PARAMETER; 535 pIoStatus->Information = 0; /* Could be used to pass rc if we liked. */ 536 return TRUE; 537 } 538 539 /* 540 * The normal path. 541 */ 542 NTSTATUS rcNt; 543 unsigned cbOut = 0; 544 int rc = 0; 545 Log2(("VBoxDrvNtFastIoDeviceControl(%p): ioctl=%#x pvIn=%p cbIn=%#x pvOut=%p cbOut=%#x pSession=%p\n", 546 pDevExt, uCmd, pvInput, cbInput, pvOutput, cbOutput, pSession)); 547 548 #ifdef RT_ARCH_AMD64 549 /* Don't allow 32-bit processes to do any I/O controls. */ 550 if (!IoIs32bitProcess(NULL)) 551 #endif 552 { 553 /* 554 * In this fast I/O device control path we have to do our own buffering. 555 */ 556 /* Verify that the I/O control function matches our pattern. */ 557 if ((uCmd & 0x3) == METHOD_BUFFERED) 558 { 559 /* Get the header so we can validate it a little bit against the 560 parameters before allocating any memory kernel for the reqest. */ 561 SUPREQHDR Hdr; 562 if (cbInput >= sizeof(Hdr) && cbOutput >= sizeof(Hdr)) 563 { 564 __try 565 { 566 RtlCopyMemory(&Hdr, pvInput, sizeof(Hdr)); 567 rcNt = STATUS_SUCCESS; 568 } 569 __except(EXCEPTION_EXECUTE_HANDLER) 570 { 571 rcNt = GetExceptionCode(); 572 } 573 } 574 else 575 rcNt = STATUS_INVALID_PARAMETER; 576 if (NT_SUCCESS(rcNt)) 577 { 578 /* Verify that the sizes in the request header are correct. */ 579 ULONG cbBuf = RT_MAX(cbInput, cbOutput); 580 if ( cbInput == Hdr.cbIn 581 && cbOutput == Hdr.cbOut 582 && cbBuf < _1M*16) 583 { 584 /* Allocate a buffer and copy all the input into it. */ 585 PSUPREQHDR pHdr = (PSUPREQHDR)ExAllocatePoolWithTag(NonPagedPool, cbBuf, 'VBox'); 586 if (pHdr) 587 { 588 __try 589 { 590 RtlCopyMemory(pHdr, pvInput, cbInput); 591 if (cbInput < cbBuf) 592 RtlZeroMemory((uint8_t *)pHdr + cbInput, cbBuf - cbInput); 593 rcNt = STATUS_SUCCESS; 594 } 595 __except(EXCEPTION_EXECUTE_HANDLER) 596 { 597 rcNt = GetExceptionCode(); 598 } 599 } 600 else 601 rcNt = STATUS_NO_MEMORY; 602 if (NT_SUCCESS(rcNt)) 603 { 604 /* 605 * Now call the common code to do the real work. 606 */ 607 rc = supdrvIOCtl(uCmd, pDevExt, pSession, pHdr); 608 if (RT_SUCCESS(rc)) 609 { 610 /* 611 * Copy back the result. 612 */ 613 cbOut = pHdr->cbOut; 614 if (cbOut > cbOutput) 615 { 616 cbOut = cbOutput; 617 OSDBGPRINT(("VBoxDrvNtFastIoDeviceControl: too much output! %#x > %#x; uCmd=%#x!\n", 618 pHdr->cbOut, cbOut, uCmd)); 619 } 620 if (cbOut) 621 { 622 __try 623 { 624 RtlCopyMemory(pvOutput, pHdr, cbOut); 625 rcNt = STATUS_SUCCESS; 626 } 627 __except(EXCEPTION_EXECUTE_HANDLER) 628 { 629 rcNt = GetExceptionCode(); 630 } 631 } 632 else 633 rcNt = STATUS_SUCCESS; 634 } 635 else if (rc == VERR_INVALID_PARAMETER) 636 rcNt = STATUS_INVALID_PARAMETER; 637 else 638 rcNt = STATUS_NOT_SUPPORTED; 639 Log2(("VBoxDrvNtFastIoDeviceControl: returns %#x cbOut=%d rc=%#x\n", rcNt, cbOut, rc)); 640 } 641 ExFreePoolWithTag(pHdr, 'VBox'); 642 } 643 else 644 { 645 Log(("VBoxDrvNtFastIoDeviceControl: Mismatching sizes (%#x) - Hdr=%#lx/%#lx Irp=%#lx/%#lx!\n", 646 uCmd, Hdr.cbIn, Hdr.cbOut, cbInput, cbOutput)); 647 rcNt = STATUS_INVALID_PARAMETER; 648 } 649 } 650 } 651 else 652 { 653 Log(("VBoxDrvNtFastIoDeviceControl: not buffered request (%#x) - not supported\n", uCmd)); 654 rcNt = STATUS_NOT_SUPPORTED; 655 } 656 } 657 #ifdef RT_ARCH_AMD64 658 else 659 { 660 Log(("VBoxDrvNtFastIoDeviceControl: WOW64 req - not supported\n")); 661 rcNt = STATUS_NOT_SUPPORTED; 662 } 663 #endif 664 665 /* complete the request. */ 666 pIoStatus->Status = rcNt; 667 pIoStatus->Information = cbOut; 668 return TRUE; /* handled. */ 669 } 670 #endif /* VBOXDRV_WITH_FAST_IO */ 671 672 430 673 /** 431 674 * Device I/O Control entry point. … … 441 684 442 685 /* 443 * Deal with the two high-speed IOCtl that takes it's arguments from 444 * the session and iCmd, and only returns a VBox status code. 445 * 446 * Note: The previous method of returning the rc prior to IOC version 447 * 7.4 has been abandond, we're no longer compatible with that 448 * interface. 686 * Deal with the 2-3 high-speed IOCtl that takes their arguments from 687 * the session and iCmd, and does not return anything. 449 688 */ 450 689 ULONG ulCmd = pStack->Parameters.DeviceIoControl.IoControlCode; … … 455 694 { 456 695 int rc = supdrvIOCtlFast(ulCmd, (unsigned)(uintptr_t)pIrp->UserBuffer /* VMCPU id */, pDevExt, pSession); 457 458 #if 0 /* When preemption was not used i.e. !VBOX_WITH_VMMR0_DISABLE_PREEMPTION. That's no longer required. */459 /* Raise the IRQL to DISPATCH_LEVEL to prevent Windows from rescheduling us to another CPU/core. */460 Assert(KeGetCurrentIrql() <= DISPATCH_LEVEL);461 KIRQL oldIrql;462 KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);463 int rc = supdrvIOCtlFast(ulCmd, (unsigned)(uintptr_t)pIrp->UserBuffer /* VMCPU id */, pDevExt, pSession);464 KeLowerIrql(oldIrql);465 #endif466 696 467 697 /* Complete the I/O request. */
Note:
See TracChangeset
for help on using the changeset viewer.

