Changeset 70279 in vbox for trunk/src/VBox
- Timestamp:
- Dec 21, 2017 1:55:51 PM (7 years ago)
- svn:sync-xref-src-repo-rev:
- 119875
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest-win.cpp
r70276 r70279 177 177 *********************************************************************************************************************************/ 178 178 RT_C_DECLS_BEGIN 179 #ifdef TARGET_NT4180 static NTSTATUS vgdrvNt4CreateDevice(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath);181 static NTSTATUS vgdrvNt4FindPciDevice(PULONG puluBusNumber, PPCI_SLOT_NUMBER puSlotNumber);182 #endif183 179 static NTSTATUS NTAPI vgdrvNtNt5PlusAddDevice(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj); 184 180 static NTSTATUS NTAPI vgdrvNtNt5PlusPnP(PDEVICE_OBJECT pDevObj, PIRP pIrp); 185 181 static NTSTATUS NTAPI vgdrvNtNt5PlusPower(PDEVICE_OBJECT pDevObj, PIRP pIrp); 186 182 static NTSTATUS NTAPI vgdrvNtNt5PlusSystemControl(PDEVICE_OBJECT pDevObj, PIRP pIrp); 187 static void vgdrvNtUnmapVMMDevMemory(PVBOXGUESTDEVEXTWIN pDevExt);188 183 static void NTAPI vgdrvNtUnload(PDRIVER_OBJECT pDrvObj); 189 184 static NTSTATUS NTAPI vgdrvNtCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp); … … 197 192 static NTSTATUS NTAPI vgdrvNtNotSupportedStub(PDEVICE_OBJECT pDevObj, PIRP pIrp); 198 193 static VOID NTAPI vgdrvNtBugCheckCallback(PVOID pvBuffer, ULONG cbBuffer); 194 static VOID NTAPI vgdrvNtDpcHandler(PKDPC pDPC, PDEVICE_OBJECT pDevObj, PIRP pIrp, PVOID pContext); 195 static BOOLEAN NTAPI vgdrvNtIsrHandler(PKINTERRUPT interrupt, PVOID serviceContext); 199 196 #ifdef VBOX_STRICT 200 197 static void vgdrvNtDoTests(void); 201 198 #endif 202 static VOID NTAPI vgdrvNtDpcHandler(PKDPC pDPC, PDEVICE_OBJECT pDevObj, PIRP pIrp, PVOID pContext); 203 static BOOLEAN NTAPI vgdrvNtIsrHandler(PKINTERRUPT interrupt, PVOID serviceContext); 204 static NTSTATUS vgdrvNtScanPCIResourceList(PVBOXGUESTDEVEXTWIN pDevExt, PCM_RESOURCE_LIST pResList, bool fTranslated); 205 static NTSTATUS vgdrvNtMapVMMDevMemory(PVBOXGUESTDEVEXTWIN pDevExt, PHYSICAL_ADDRESS PhysAddr, ULONG cbToMap, 206 void **ppvMMIOBase, uint32_t *pcbMMIO); 207 RT_C_DECLS_END 208 209 210 /********************************************************************************************************************************* 211 * Exported Functions * 212 *********************************************************************************************************************************/ 213 RT_C_DECLS_BEGIN 199 200 /* 201 * We only do INIT allocations. PAGE is too much work and risk for little gain. 202 */ 203 #ifdef ALLOC_PRAGMA 214 204 NTSTATUS DriverEntry(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath); 215 RT_C_DECLS_END216 217 #ifdef ALLOC_PRAGMA218 /* We only do INIT allocations. PAGE is too much work and risk for little gain. */219 205 # pragma alloc_text(INIT, DriverEntry) 220 206 # ifdef TARGET_NT4 207 static NTSTATUS vgdrvNt4CreateDevice(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath); 221 208 # pragma alloc_text(INIT, vgdrvNt4CreateDevice) 209 static NTSTATUS vgdrvNt4FindPciDevice(PULONG puluBusNumber, PPCI_SLOT_NUMBER puSlotNumber); 222 210 # pragma alloc_text(INIT, vgdrvNt4FindPciDevice) 223 211 # endif 224 212 #endif 213 RT_C_DECLS_END 225 214 226 215 … … 536 525 } 537 526 #endif /* LOG_ENABLED */ 527 528 529 /** 530 * Helper to scan the PCI resource list and remember stuff. 531 * 532 * @param pDevExt The device extension. 533 * @param pResList Resource list 534 * @param fTranslated Whether the addresses are translated or not. 535 */ 536 static NTSTATUS vgdrvNtScanPCIResourceList(PVBOXGUESTDEVEXTWIN pDevExt, PCM_RESOURCE_LIST pResList, bool fTranslated) 537 { 538 /* Enumerate the resource list. */ 539 LogFlowFunc(("Found %d resources\n", 540 pResList->List->PartialResourceList.Count)); 541 542 NTSTATUS rc = STATUS_SUCCESS; 543 PCM_PARTIAL_RESOURCE_DESCRIPTOR pPartialData = NULL; 544 PVBOXGUESTWINBASEADDRESS pBaseAddress = pDevExt->aPciBaseAddresses; 545 uint32_t cBaseAddresses = 0; 546 bool fGotIrq = false; 547 bool fGotMmio = false; 548 bool fGotIoPorts = false; 549 for (ULONG i = 0; i < pResList->List->PartialResourceList.Count; i++) 550 { 551 pPartialData = &pResList->List->PartialResourceList.PartialDescriptors[i]; 552 switch (pPartialData->Type) 553 { 554 case CmResourceTypePort: 555 { 556 LogFlowFunc(("I/O range: Base=%#RX64, length=%08x\n", 557 pPartialData->u.Port.Start.QuadPart, pPartialData->u.Port.Length)); 558 559 /* Overflow protection. */ 560 if (cBaseAddresses < PCI_TYPE0_ADDRESSES) 561 { 562 /* Save the first I/O port base. */ 563 if (!fGotIoPorts) 564 { 565 pDevExt->Core.IOPortBase = (RTIOPORT)pPartialData->u.Port.Start.LowPart; 566 fGotIoPorts = true; 567 } 568 else 569 LogRelFunc(("More than one I/O port range?!?\n")); 570 571 /* Save resource information. */ 572 pBaseAddress->RangeStart = pPartialData->u.Port.Start; 573 pBaseAddress->RangeLength = pPartialData->u.Port.Length; 574 pBaseAddress->RangeInMemory = FALSE; 575 pBaseAddress->ResourceMapped = FALSE; 576 577 LogFunc(("I/O range for VMMDev found! Base=%#RX64, length=%08x\n", 578 pPartialData->u.Port.Start.QuadPart, pPartialData->u.Port.Length)); 579 580 /* Next item ... */ 581 pBaseAddress++; 582 cBaseAddresses++; 583 } 584 else 585 LogFunc(("Too many PCI addresses!\n")); 586 break; 587 } 588 589 case CmResourceTypeInterrupt: 590 { 591 LogFunc(("Interrupt: Level=%x, vector=%x, mode=%x\n", 592 pPartialData->u.Interrupt.Level, pPartialData->u.Interrupt.Vector, pPartialData->Flags)); 593 594 if (!fGotIrq) 595 { 596 /* Save information. */ 597 pDevExt->uInterruptLevel = pPartialData->u.Interrupt.Level; 598 pDevExt->uInterruptVector = pPartialData->u.Interrupt.Vector; 599 pDevExt->fInterruptAffinity = pPartialData->u.Interrupt.Affinity; 600 601 /* Check interrupt mode. */ 602 if (pPartialData->Flags & CM_RESOURCE_INTERRUPT_LATCHED) 603 pDevExt->enmInterruptMode = Latched; 604 else 605 pDevExt->enmInterruptMode = LevelSensitive; 606 fGotIrq = true; 607 } 608 else 609 LogFunc(("More than one IRQ resource!\n")); 610 break; 611 } 612 613 case CmResourceTypeMemory: 614 { 615 LogFlowFunc(("Memory range: Base=%#RX64, length=%08x\n", 616 pPartialData->u.Memory.Start.QuadPart, pPartialData->u.Memory.Length)); 617 618 /* Overflow protection. */ 619 if (cBaseAddresses < PCI_TYPE0_ADDRESSES) 620 { 621 /* We only care about the first read/write memory range. */ 622 if ( !fGotMmio 623 && (pPartialData->Flags & CM_RESOURCE_MEMORY_WRITEABILITY_MASK) == CM_RESOURCE_MEMORY_READ_WRITE) 624 { 625 /* Save physical MMIO base + length for VMMDev. */ 626 pDevExt->uVmmDevMemoryPhysAddr = pPartialData->u.Memory.Start; 627 pDevExt->cbVmmDevMemory = (ULONG)pPartialData->u.Memory.Length; 628 629 if (!fTranslated) 630 { 631 /* Technically we need to make the HAL translate the address. since we 632 didn't used to do this and it probably just returns the input address, 633 we allow ourselves to ignore failures. */ 634 ULONG uAddressSpace = 0; 635 PHYSICAL_ADDRESS PhysAddr = pPartialData->u.Memory.Start; 636 if (HalTranslateBusAddress(pResList->List->InterfaceType, pResList->List->BusNumber, PhysAddr, 637 &uAddressSpace, &PhysAddr)) 638 { 639 Log(("HalTranslateBusAddress(%#RX64) -> %RX64, type %#x\n", 640 pPartialData->u.Memory.Start.QuadPart, PhysAddr.QuadPart, uAddressSpace)); 641 if (pPartialData->u.Memory.Start.QuadPart != PhysAddr.QuadPart) 642 pDevExt->uVmmDevMemoryPhysAddr = PhysAddr; 643 } 644 else 645 Log(("HalTranslateBusAddress(%#RX64) -> failed!\n", pPartialData->u.Memory.Start.QuadPart)); 646 } 647 648 /* Save resource information. */ 649 pBaseAddress->RangeStart = pPartialData->u.Memory.Start; 650 pBaseAddress->RangeLength = pPartialData->u.Memory.Length; 651 pBaseAddress->RangeInMemory = TRUE; 652 pBaseAddress->ResourceMapped = FALSE; 653 654 LogFunc(("Found memory range for VMMDev! Base = %#RX64, Length = %08x\n", 655 pPartialData->u.Memory.Start.QuadPart, pPartialData->u.Memory.Length)); 656 657 /* Next item ... */ 658 cBaseAddresses++; 659 pBaseAddress++; 660 fGotMmio = true; 661 } 662 else 663 LogFunc(("Ignoring memory: Flags=%08x Base=%#RX64\n", 664 pPartialData->Flags, pPartialData->u.Memory.Start.QuadPart)); 665 } 666 else 667 LogFunc(("Too many PCI addresses!\n")); 668 break; 669 } 670 671 default: 672 { 673 LogFunc(("Unhandled resource found, type=%d\n", pPartialData->Type)); 674 break; 675 } 676 } 677 } 678 679 /* Memorize the number of resources found. */ 680 pDevExt->cPciAddresses = cBaseAddresses; 681 return rc; 682 } 683 684 685 /** 686 * Unmaps the VMMDev I/O range from kernel space. 687 * 688 * @param pDevExt The device extension. 689 */ 690 static void vgdrvNtUnmapVMMDevMemory(PVBOXGUESTDEVEXTWIN pDevExt) 691 { 692 LogFlowFunc(("pVMMDevMemory = %#x\n", pDevExt->Core.pVMMDevMemory)); 693 if (pDevExt->Core.pVMMDevMemory) 694 { 695 MmUnmapIoSpace((void*)pDevExt->Core.pVMMDevMemory, pDevExt->cbVmmDevMemory); 696 pDevExt->Core.pVMMDevMemory = NULL; 697 } 698 699 pDevExt->uVmmDevMemoryPhysAddr.QuadPart = 0; 700 pDevExt->cbVmmDevMemory = 0; 701 } 702 703 704 /** 705 * Maps the I/O space from VMMDev to virtual kernel address space. 706 * 707 * @return NTSTATUS 708 * 709 * @param pDevExt The device extension. 710 * @param PhysAddr Physical address to map. 711 * @param cbToMap Number of bytes to map. 712 * @param ppvMMIOBase Pointer of mapped I/O base. 713 * @param pcbMMIO Length of mapped I/O base. 714 */ 715 static NTSTATUS vgdrvNtMapVMMDevMemory(PVBOXGUESTDEVEXTWIN pDevExt, PHYSICAL_ADDRESS PhysAddr, ULONG cbToMap, 716 void **ppvMMIOBase, uint32_t *pcbMMIO) 717 { 718 AssertPtrReturn(pDevExt, VERR_INVALID_POINTER); 719 AssertPtrReturn(ppvMMIOBase, VERR_INVALID_POINTER); 720 /* pcbMMIO is optional. */ 721 722 NTSTATUS rc = STATUS_SUCCESS; 723 if (PhysAddr.LowPart > 0) /* We're mapping below 4GB. */ 724 { 725 VMMDevMemory *pVMMDevMemory = (VMMDevMemory *)MmMapIoSpace(PhysAddr, cbToMap, MmNonCached); 726 LogFlowFunc(("pVMMDevMemory = %#x\n", pVMMDevMemory)); 727 if (pVMMDevMemory) 728 { 729 LogFunc(("VMMDevMemory: Version = %#x, Size = %d\n", pVMMDevMemory->u32Version, pVMMDevMemory->u32Size)); 730 731 /* Check version of the structure; do we have the right memory version? */ 732 if (pVMMDevMemory->u32Version == VMMDEV_MEMORY_VERSION) 733 { 734 /* Save results. */ 735 *ppvMMIOBase = pVMMDevMemory; 736 if (pcbMMIO) /* Optional. */ 737 *pcbMMIO = pVMMDevMemory->u32Size; 738 739 LogFlowFunc(("VMMDevMemory found and mapped! pvMMIOBase = 0x%p\n", *ppvMMIOBase)); 740 } 741 else 742 { 743 /* Not our version, refuse operation and unmap the memory. */ 744 LogFunc(("Wrong version (%u), refusing operation!\n", pVMMDevMemory->u32Version)); 745 746 vgdrvNtUnmapVMMDevMemory(pDevExt); 747 rc = STATUS_UNSUCCESSFUL; 748 } 749 } 750 else 751 rc = STATUS_UNSUCCESSFUL; 752 } 753 return rc; 754 } 538 755 539 756 … … 1567 1784 1568 1785 return IoCallDriver(pDevExt->pNextLowerDriver, pIrp); 1569 }1570 1571 1572 1573 /**1574 * Unmaps the VMMDev I/O range from kernel space.1575 *1576 * @param pDevExt The device extension.1577 */1578 static void vgdrvNtUnmapVMMDevMemory(PVBOXGUESTDEVEXTWIN pDevExt)1579 {1580 LogFlowFunc(("pVMMDevMemory = %#x\n", pDevExt->Core.pVMMDevMemory));1581 if (pDevExt->Core.pVMMDevMemory)1582 {1583 MmUnmapIoSpace((void*)pDevExt->Core.pVMMDevMemory, pDevExt->cbVmmDevMemory);1584 pDevExt->Core.pVMMDevMemory = NULL;1585 }1586 1587 pDevExt->uVmmDevMemoryPhysAddr.QuadPart = 0;1588 pDevExt->cbVmmDevMemory = 0;1589 1786 } 1590 1787 … … 2246 2443 } 2247 2444 2248 2249 /**2250 * Helper to scan the PCI resource list and remember stuff.2251 *2252 * @param pDevExt The device extension.2253 * @param pResList Resource list2254 * @param fTranslated Whether the addresses are translated or not.2255 */2256 static NTSTATUS vgdrvNtScanPCIResourceList(PVBOXGUESTDEVEXTWIN pDevExt, PCM_RESOURCE_LIST pResList, bool fTranslated)2257 {2258 /* Enumerate the resource list. */2259 LogFlowFunc(("Found %d resources\n",2260 pResList->List->PartialResourceList.Count));2261 2262 NTSTATUS rc = STATUS_SUCCESS;2263 PCM_PARTIAL_RESOURCE_DESCRIPTOR pPartialData = NULL;2264 PVBOXGUESTWINBASEADDRESS pBaseAddress = pDevExt->aPciBaseAddresses;2265 uint32_t cBaseAddresses = 0;2266 bool fGotIrq = false;2267 bool fGotMmio = false;2268 bool fGotIoPorts = false;2269 for (ULONG i = 0; i < pResList->List->PartialResourceList.Count; i++)2270 {2271 pPartialData = &pResList->List->PartialResourceList.PartialDescriptors[i];2272 switch (pPartialData->Type)2273 {2274 case CmResourceTypePort:2275 {2276 LogFlowFunc(("I/O range: Base=%#RX64, length=%08x\n",2277 pPartialData->u.Port.Start.QuadPart, pPartialData->u.Port.Length));2278 2279 /* Overflow protection. */2280 if (cBaseAddresses < PCI_TYPE0_ADDRESSES)2281 {2282 /* Save the first I/O port base. */2283 if (!fGotIoPorts)2284 {2285 pDevExt->Core.IOPortBase = (RTIOPORT)pPartialData->u.Port.Start.LowPart;2286 fGotIoPorts = true;2287 }2288 else2289 LogRelFunc(("More than one I/O port range?!?\n"));2290 2291 /* Save resource information. */2292 pBaseAddress->RangeStart = pPartialData->u.Port.Start;2293 pBaseAddress->RangeLength = pPartialData->u.Port.Length;2294 pBaseAddress->RangeInMemory = FALSE;2295 pBaseAddress->ResourceMapped = FALSE;2296 2297 LogFunc(("I/O range for VMMDev found! Base=%#RX64, length=%08x\n",2298 pPartialData->u.Port.Start.QuadPart, pPartialData->u.Port.Length));2299 2300 /* Next item ... */2301 pBaseAddress++;2302 cBaseAddresses++;2303 }2304 else2305 LogFunc(("Too many PCI addresses!\n"));2306 break;2307 }2308 2309 case CmResourceTypeInterrupt:2310 {2311 LogFunc(("Interrupt: Level=%x, vector=%x, mode=%x\n",2312 pPartialData->u.Interrupt.Level, pPartialData->u.Interrupt.Vector, pPartialData->Flags));2313 2314 if (!fGotIrq)2315 {2316 /* Save information. */2317 pDevExt->uInterruptLevel = pPartialData->u.Interrupt.Level;2318 pDevExt->uInterruptVector = pPartialData->u.Interrupt.Vector;2319 pDevExt->fInterruptAffinity = pPartialData->u.Interrupt.Affinity;2320 2321 /* Check interrupt mode. */2322 if (pPartialData->Flags & CM_RESOURCE_INTERRUPT_LATCHED)2323 pDevExt->enmInterruptMode = Latched;2324 else2325 pDevExt->enmInterruptMode = LevelSensitive;2326 fGotIrq = true;2327 }2328 else2329 LogFunc(("More than one IRQ resource!\n"));2330 break;2331 }2332 2333 case CmResourceTypeMemory:2334 {2335 LogFlowFunc(("Memory range: Base=%#RX64, length=%08x\n",2336 pPartialData->u.Memory.Start.QuadPart, pPartialData->u.Memory.Length));2337 2338 /* Overflow protection. */2339 if (cBaseAddresses < PCI_TYPE0_ADDRESSES)2340 {2341 /* We only care about the first read/write memory range. */2342 if ( !fGotMmio2343 && (pPartialData->Flags & CM_RESOURCE_MEMORY_WRITEABILITY_MASK) == CM_RESOURCE_MEMORY_READ_WRITE)2344 {2345 /* Save physical MMIO base + length for VMMDev. */2346 pDevExt->uVmmDevMemoryPhysAddr = pPartialData->u.Memory.Start;2347 pDevExt->cbVmmDevMemory = (ULONG)pPartialData->u.Memory.Length;2348 2349 if (!fTranslated)2350 {2351 /* Technically we need to make the HAL translate the address. since we2352 didn't used to do this and it probably just returns the input address,2353 we allow ourselves to ignore failures. */2354 ULONG uAddressSpace = 0;2355 PHYSICAL_ADDRESS PhysAddr = pPartialData->u.Memory.Start;2356 if (HalTranslateBusAddress(pResList->List->InterfaceType, pResList->List->BusNumber, PhysAddr,2357 &uAddressSpace, &PhysAddr))2358 {2359 Log(("HalTranslateBusAddress(%#RX64) -> %RX64, type %#x\n",2360 pPartialData->u.Memory.Start.QuadPart, PhysAddr.QuadPart, uAddressSpace));2361 if (pPartialData->u.Memory.Start.QuadPart != PhysAddr.QuadPart)2362 pDevExt->uVmmDevMemoryPhysAddr = PhysAddr;2363 }2364 else2365 Log(("HalTranslateBusAddress(%#RX64) -> failed!\n", pPartialData->u.Memory.Start.QuadPart));2366 }2367 2368 /* Save resource information. */2369 pBaseAddress->RangeStart = pPartialData->u.Memory.Start;2370 pBaseAddress->RangeLength = pPartialData->u.Memory.Length;2371 pBaseAddress->RangeInMemory = TRUE;2372 pBaseAddress->ResourceMapped = FALSE;2373 2374 LogFunc(("Found memory range for VMMDev! Base = %#RX64, Length = %08x\n",2375 pPartialData->u.Memory.Start.QuadPart, pPartialData->u.Memory.Length));2376 2377 /* Next item ... */2378 cBaseAddresses++;2379 pBaseAddress++;2380 fGotMmio = true;2381 }2382 else2383 LogFunc(("Ignoring memory: Flags=%08x Base=%#RX64\n",2384 pPartialData->Flags, pPartialData->u.Memory.Start.QuadPart));2385 }2386 else2387 LogFunc(("Too many PCI addresses!\n"));2388 break;2389 }2390 2391 default:2392 {2393 LogFunc(("Unhandled resource found, type=%d\n", pPartialData->Type));2394 break;2395 }2396 }2397 }2398 2399 /* Memorize the number of resources found. */2400 pDevExt->cPciAddresses = cBaseAddresses;2401 return rc;2402 }2403 2404 2405 /**2406 * Maps the I/O space from VMMDev to virtual kernel address space.2407 *2408 * @return NTSTATUS2409 *2410 * @param pDevExt The device extension.2411 * @param PhysAddr Physical address to map.2412 * @param cbToMap Number of bytes to map.2413 * @param ppvMMIOBase Pointer of mapped I/O base.2414 * @param pcbMMIO Length of mapped I/O base.2415 */2416 static NTSTATUS vgdrvNtMapVMMDevMemory(PVBOXGUESTDEVEXTWIN pDevExt, PHYSICAL_ADDRESS PhysAddr, ULONG cbToMap,2417 void **ppvMMIOBase, uint32_t *pcbMMIO)2418 {2419 AssertPtrReturn(pDevExt, VERR_INVALID_POINTER);2420 AssertPtrReturn(ppvMMIOBase, VERR_INVALID_POINTER);2421 /* pcbMMIO is optional. */2422 2423 NTSTATUS rc = STATUS_SUCCESS;2424 if (PhysAddr.LowPart > 0) /* We're mapping below 4GB. */2425 {2426 VMMDevMemory *pVMMDevMemory = (VMMDevMemory *)MmMapIoSpace(PhysAddr, cbToMap, MmNonCached);2427 LogFlowFunc(("pVMMDevMemory = %#x\n", pVMMDevMemory));2428 if (pVMMDevMemory)2429 {2430 LogFunc(("VMMDevMemory: Version = %#x, Size = %d\n", pVMMDevMemory->u32Version, pVMMDevMemory->u32Size));2431 2432 /* Check version of the structure; do we have the right memory version? */2433 if (pVMMDevMemory->u32Version == VMMDEV_MEMORY_VERSION)2434 {2435 /* Save results. */2436 *ppvMMIOBase = pVMMDevMemory;2437 if (pcbMMIO) /* Optional. */2438 *pcbMMIO = pVMMDevMemory->u32Size;2439 2440 LogFlowFunc(("VMMDevMemory found and mapped! pvMMIOBase = 0x%p\n", *ppvMMIOBase));2441 }2442 else2443 {2444 /* Not our version, refuse operation and unmap the memory. */2445 LogFunc(("Wrong version (%u), refusing operation!\n", pVMMDevMemory->u32Version));2446 2447 vgdrvNtUnmapVMMDevMemory(pDevExt);2448 rc = STATUS_UNSUCCESSFUL;2449 }2450 }2451 else2452 rc = STATUS_UNSUCCESSFUL;2453 }2454 return rc;2455 }2456 2457 2445 #ifdef VBOX_STRICT 2458 2446
Note:
See TracChangeset
for help on using the changeset viewer.