Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

991 lines
23 KiB

  1. /*++
  2. Module Name:
  3. mca.c
  4. Abstract:
  5. Sample device driver to register itself with the HAL and log Machine Check
  6. Errors on a Intel Architecture Platform
  7. Author:
  8. Environment:
  9. Kernel mode
  10. Notes:
  11. Revision History:
  12. --*/
  13. #include <stdarg.h>
  14. #include <string.h>
  15. #include <stdio.h>
  16. #include <ntddk.h>
  17. #include "imca.h"
  18. //
  19. // Device names for the MCA driver
  20. //
  21. #define MCA_DEVICE_NAME "\\Device\\imca" // ANSI Name
  22. #define MCA_DEVICE_NAME_U L"\\Device\\imca" // Unicode Name
  23. #define MCA_DEVICE_NAME_DOS "\\DosDevices\\imca" // Device Name for Win32 App
  24. NTSTATUS
  25. DriverEntry(
  26. IN PDRIVER_OBJECT DriverObject,
  27. IN PUNICODE_STRING RegistryPath
  28. );
  29. NTSTATUS
  30. MCAOpen(
  31. IN PDEVICE_OBJECT DeviceObject,
  32. IN PIRP Irp
  33. );
  34. NTSTATUS
  35. MCAClose(
  36. IN PDEVICE_OBJECT DeviceObject,
  37. IN PIRP Irp
  38. );
  39. VOID
  40. MCAStartIo(
  41. IN PDEVICE_OBJECT DeviceObject,
  42. IN PIRP Irp
  43. );
  44. #if defined(_AMD64_)
  45. ERROR_SEVERITY
  46. MCADriverExceptionCallback(
  47. IN PDEVICE_OBJECT DeviceObject,
  48. IN PKTRAP_FRAME TrapFrame,
  49. IN PKEXCEPTION_FRAME ExceptionFrame,
  50. IN PMCA_EXCEPTION InException
  51. );
  52. #else
  53. ERROR_SEVERITY
  54. MCADriverExceptionCallback(
  55. IN PDEVICE_OBJECT DeviceObject,
  56. IN PMCA_EXCEPTION InException
  57. );
  58. #endif
  59. VOID
  60. MCADriverDpcCallback(
  61. IN PKDPC Dpc,
  62. IN PVOID DeferredContext,
  63. IN PVOID SystemContext1,
  64. IN PVOID SystemContext2
  65. );
  66. NTSTATUS
  67. MCACleanup(
  68. IN PDEVICE_OBJECT DeviceObject,
  69. IN PIRP Irp
  70. );
  71. VOID
  72. McaCancelIrp(
  73. IN PDEVICE_OBJECT DeviceObject,
  74. IN PIRP Irp
  75. );
  76. NTSTATUS
  77. MCADeviceControl(
  78. IN PDEVICE_OBJECT DeviceObject,
  79. IN PIRP Irp
  80. );
  81. VOID
  82. MCAUnload(
  83. IN PDRIVER_OBJECT DriverObject
  84. );
  85. NTSTATUS
  86. MCACreateSymbolicLinkObject(
  87. VOID
  88. );
  89. VOID
  90. MCAProcessWorkItem(
  91. PVOID Context
  92. );
  93. //
  94. // This temporary buffer holds the data between the Machine Check error
  95. // notification from HAL and the asynchronous IOCTL completion to the
  96. // application
  97. //
  98. typedef struct _MCA_DEVICE_EXTENSION {
  99. PDEVICE_OBJECT DeviceObject;
  100. PIRP SavedIrp;
  101. BOOLEAN WorkItemQueued;
  102. WORK_QUEUE_ITEM WorkItem;
  103. // Place to log the exceptions. Whenever the exception callback
  104. // routine is called by the HAL MCA component, record the exception here.
  105. // This can potentially be a link list.
  106. MCA_EXCEPTION McaException;
  107. } MCA_DEVICE_EXTENSION, *PMCA_DEVICE_EXTENSION;
  108. #ifdef ALLOC_PRAGMA
  109. #pragma alloc_text(INIT, DriverEntry)
  110. #pragma alloc_text(INIT, MCACreateSymbolicLinkObject)
  111. #endif // ALLOC_PRAGMA
  112. NTSTATUS
  113. DriverEntry(
  114. IN PDRIVER_OBJECT DriverObject,
  115. IN PUNICODE_STRING RegistryPath
  116. )
  117. /*++
  118. Routine Description:
  119. This routine does the driver specific initialization at entry time
  120. Arguments:
  121. DriverObject: Pointer to the driver object
  122. RegistryPath: Path to driver's registry key
  123. Return Value:
  124. Success or failure
  125. --*/
  126. {
  127. UNICODE_STRING UnicodeString;
  128. NTSTATUS Status = STATUS_SUCCESS;
  129. PMCA_DEVICE_EXTENSION Extension;
  130. PDEVICE_OBJECT McaDeviceObject;
  131. MCA_DRIVER_INFO McaDriverInfo;
  132. //
  133. // Create device object for MCA device.
  134. //
  135. RtlInitUnicodeString(&UnicodeString, MCA_DEVICE_NAME_U);
  136. //
  137. // Device is created as exclusive since only a single thread can send
  138. // I/O requests to this device
  139. //
  140. Status = IoCreateDevice(
  141. DriverObject,
  142. sizeof(MCA_DEVICE_EXTENSION),
  143. &UnicodeString,
  144. FILE_DEVICE_UNKNOWN,
  145. 0,
  146. TRUE,
  147. &McaDeviceObject
  148. );
  149. if (!NT_SUCCESS( Status )) {
  150. DbgPrint("Mca DriverEntry: IoCreateDevice failed\n");
  151. return Status;
  152. }
  153. McaDeviceObject->Flags |= DO_BUFFERED_IO;
  154. Extension = McaDeviceObject->DeviceExtension;
  155. RtlZeroMemory(Extension, sizeof(MCA_DEVICE_EXTENSION));
  156. Extension->DeviceObject = McaDeviceObject;
  157. //
  158. // Make the device visible to Win32 subsystem
  159. //
  160. Status = MCACreateSymbolicLinkObject ();
  161. if (!NT_SUCCESS( Status )) {
  162. DbgPrint("Mca DriverEntry: McaCreateSymbolicLinkObject failed\n");
  163. return Status;
  164. }
  165. //
  166. // Set up the device driver entry points.
  167. //
  168. DriverObject->MajorFunction[IRP_MJ_CREATE] = MCAOpen;
  169. DriverObject->MajorFunction[IRP_MJ_CLOSE] = MCAClose;
  170. DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = MCADeviceControl;
  171. DriverObject->MajorFunction[IRP_MJ_CLEANUP] = MCACleanup;
  172. DriverObject->DriverUnload = MCAUnload;
  173. DriverObject->DriverStartIo = MCAStartIo;
  174. //
  175. // Register the driver with the HAL
  176. //
  177. McaDriverInfo.ExceptionCallback = MCADriverExceptionCallback;
  178. McaDriverInfo.DpcCallback = MCADriverDpcCallback;
  179. McaDriverInfo.DeviceContext = McaDeviceObject;
  180. Status = HalSetSystemInformation(
  181. HalMcaRegisterDriver,
  182. sizeof(MCA_DRIVER_INFO),
  183. (PVOID)&McaDriverInfo
  184. );
  185. if (!NT_SUCCESS( Status )) {
  186. DbgPrint("Mca DriverEntry: HalMcaRegisterDriver failed\n");
  187. //
  188. // Clean up whatever we have done so far
  189. //
  190. MCAUnload(DriverObject);
  191. return(STATUS_UNSUCCESSFUL);
  192. }
  193. //
  194. // This is the place where you would check non-volatile area (if any) for
  195. // any Machine Check errros logged and process them.
  196. // ...
  197. //
  198. return STATUS_SUCCESS;
  199. }
  200. NTSTATUS
  201. MCACreateSymbolicLinkObject(
  202. VOID
  203. )
  204. /*++
  205. Routine Description:
  206. Makes MCA device visible to Win32 subsystem
  207. Arguments:
  208. None
  209. Return Value:
  210. Success or failure
  211. --*/
  212. {
  213. NTSTATUS Status;
  214. STRING DosString;
  215. STRING NtString;
  216. UNICODE_STRING DosUnicodeString;
  217. UNICODE_STRING NtUnicodeString;
  218. //
  219. // Create a symbolic link for sharing.
  220. //
  221. RtlInitAnsiString( &DosString, MCA_DEVICE_NAME_DOS );
  222. Status = RtlAnsiStringToUnicodeString(
  223. &DosUnicodeString,
  224. &DosString,
  225. TRUE
  226. );
  227. if ( !NT_SUCCESS( Status )) {
  228. return Status;
  229. }
  230. RtlInitAnsiString( &NtString, MCA_DEVICE_NAME );
  231. Status = RtlAnsiStringToUnicodeString(
  232. &NtUnicodeString,
  233. &NtString,
  234. TRUE
  235. );
  236. if ( !NT_SUCCESS( Status )) {
  237. return Status;
  238. }
  239. Status = IoCreateSymbolicLink(
  240. &DosUnicodeString,
  241. &NtUnicodeString
  242. );
  243. RtlFreeUnicodeString( &DosUnicodeString );
  244. RtlFreeUnicodeString( &NtUnicodeString );
  245. return (Status);
  246. }
  247. //
  248. // Dispatch routine for close requests
  249. //
  250. NTSTATUS
  251. MCAClose(
  252. IN PDEVICE_OBJECT DeviceObject,
  253. IN PIRP Irp
  254. )
  255. /*++
  256. Routine Description:
  257. Close dispatch routine
  258. Arguments:
  259. DeviceObject: Pointer to the device object
  260. Irp: Incoming Irp
  261. Return Value:
  262. Success or failure
  263. --*/
  264. {
  265. NTSTATUS Status = STATUS_SUCCESS;
  266. //
  267. // Complete the request and return status.
  268. //
  269. Irp->IoStatus.Status = Status;
  270. Irp->IoStatus.Information = 0;
  271. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  272. return (Status);
  273. }
  274. NTSTATUS
  275. MCAOpen(
  276. IN PDEVICE_OBJECT DeviceObject,
  277. IN PIRP Irp
  278. )
  279. /*++
  280. Routine Description:
  281. This routine is the dispatch routine for create/open requests.
  282. Arguments:
  283. DeviceObject: Pointer to the device object
  284. Irp: Incoming Irp
  285. Return Value:
  286. Success or failure
  287. --*/
  288. {
  289. //
  290. // Complete the request and return status.
  291. //
  292. Irp->IoStatus.Status = STATUS_SUCCESS;
  293. Irp->IoStatus.Information = FILE_OPENED;
  294. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  295. return (STATUS_SUCCESS);
  296. }
  297. ERROR_SEVERITY
  298. MCADriverExceptionCallback(
  299. IN PDEVICE_OBJECT DeviceObject,
  300. #if defined(_AMD64_)
  301. IN PKTRAP_FRAME TrapFrame,
  302. IN PKEXCEPTION_FRAME ExceptionFrame,
  303. #endif
  304. IN PMCA_EXCEPTION InException
  305. )
  306. /*++
  307. Routine Description:
  308. This is the callback routine for MCA exception. It was registered
  309. by this driver at INIT time with the HAL as a callback when a
  310. non-restartable error occurs. This routine simply copies the
  311. information to a platform specific area
  312. NOTE: If the information needs to be saved in NVRAM, this is the place
  313. to do it.
  314. Once you return from this callback, the system is going to bugcheck.
  315. Arguments:
  316. DeviceObject: Pointer to the device object
  317. InException: Exception information record
  318. Return Value:
  319. None
  320. --*/
  321. {
  322. PMCA_DEVICE_EXTENSION Extension = DeviceObject->DeviceExtension;
  323. PCHAR Destination, Source;
  324. UCHAR Bytes;
  325. //
  326. // An exception has occured on a processor.
  327. // Perform any vendor specific action here like saving stuff in NVRAM
  328. // NOTE : No system services of any kind can be used here.
  329. //
  330. //
  331. // Save the exception from HAL. May want to use link list for these
  332. // exceptions.
  333. //
  334. Destination = (PCHAR)&(Extension->McaException); // Put your platform
  335. // specific destination
  336. Source = (PCHAR)InException;
  337. //
  338. // Copy from source to destination here
  339. //
  340. #if defined(_IA64_)
  341. //
  342. // Return information to the generic HAL MCA handler.
  343. //
  344. // Update it accordingly here, the default value being the ERROR_SEVERITY value
  345. // in the MCA exception.
  346. //
  347. return( InException->ErrorSeverity );
  348. #endif // defined(_IA64_)
  349. #if defined(_AMD64_)
  350. //
  351. // Return the error severity information to the HAL MCA handler.
  352. //
  353. // Chose from:
  354. //
  355. // ErrorRecoverable
  356. // ErrorFatal
  357. // ErrorCorrected
  358. //
  359. return ErrorRecoverable;
  360. #endif
  361. }
  362. //
  363. // DPC routine for IRP completion
  364. //
  365. VOID
  366. MCADriverDpcCallback(
  367. IN PKDPC Dpc,
  368. IN PVOID DeferredContext,
  369. IN PVOID SystemContext1,
  370. IN PVOID SystemContext2
  371. )
  372. /*++
  373. Routine Description:
  374. This is the DPC - callback routine for MCA exception. It was registered
  375. by this driver at INIT time with the HAL as a DPC callback when a
  376. restartable error occurs (which causes Machine Check exception)
  377. Arguments:
  378. Dpc: The DPC Object itself
  379. DefferedContext: Pointer to the device object
  380. SystemContext1: Not used
  381. SystemContext2: Not used
  382. Return Value:
  383. None
  384. --*/
  385. {
  386. PMCA_DEVICE_EXTENSION Extension;
  387. Extension = ((PDEVICE_OBJECT)DeferredContext)->DeviceExtension;
  388. if (Extension->SavedIrp == NULL) {
  389. //
  390. // We got an MCA exception but no app was asking for anything.
  391. //
  392. return;
  393. }
  394. //
  395. // If we have reached this point, it means that the exception was
  396. // restartable. Since we cannot read the log at Dispatch level,
  397. // queue a work item to read the Machine Check log at Passive level
  398. //
  399. if (Extension->WorkItemQueued == FALSE) {
  400. //
  401. // Set a boolean to indicate that we have already queued a work item
  402. //
  403. Extension->WorkItemQueued = TRUE;
  404. //
  405. // Initialize the work item
  406. //
  407. ExInitializeWorkItem(&Extension->WorkItem,
  408. (PWORKER_THREAD_ROUTINE)MCAProcessWorkItem,
  409. (PVOID)DeferredContext
  410. );
  411. //
  412. // Queue the work item for processing at PASSIVE level
  413. //
  414. ExQueueWorkItem(&Extension->WorkItem, CriticalWorkQueue);
  415. }
  416. }
  417. VOID
  418. MCAProcessWorkItem(
  419. PVOID Context
  420. )
  421. /*++
  422. Routine Description:
  423. This routine gets invoked when a work item is queued from the DPC
  424. callback routine for a restartable machine check error.
  425. Its job is to read the machine check registers and copy the log
  426. to complete the asynchronous IRP
  427. Arguments:
  428. Context : Pointer to the device object
  429. Return Value:
  430. None
  431. --*/
  432. {
  433. PMCA_DEVICE_EXTENSION Extension;
  434. KIRQL CancelIrql;
  435. ULONG ReturnedLength;
  436. NTSTATUS Status;
  437. Extension = ((PDEVICE_OBJECT)Context)->DeviceExtension;
  438. //
  439. // Mark this IRP as non-cancellable
  440. //
  441. IoAcquireCancelSpinLock(&CancelIrql);
  442. if (Extension->SavedIrp->Cancel == TRUE) {
  443. IoReleaseCancelSpinLock(CancelIrql);
  444. } else {
  445. IoSetCancelRoutine(Extension->SavedIrp, NULL);
  446. IoReleaseCancelSpinLock(CancelIrql);
  447. //
  448. // Call HalQuerySystemInformation() to obtain MCA log.
  449. //
  450. Status = HalQuerySystemInformation(
  451. HalMcaLogInformation,
  452. sizeof(MCA_EXCEPTION),
  453. Extension->SavedIrp->AssociatedIrp.SystemBuffer,
  454. &ReturnedLength
  455. );
  456. ASSERT(Status != STATUS_NO_SUCH_DEVICE);
  457. ASSERT(Status != STATUS_NOT_FOUND);
  458. IoStartPacket(((PDEVICE_OBJECT)Context), Extension->SavedIrp, 0, NULL);
  459. Extension->SavedIrp = NULL;
  460. Extension->WorkItemQueued = FALSE;
  461. }
  462. }
  463. VOID
  464. MCAStartIo(
  465. IN PDEVICE_OBJECT DeviceObject,
  466. IN PIRP Irp
  467. )
  468. /*++
  469. Routine Description:
  470. This routine completes the async call from the app
  471. Arguments:
  472. DeviceObject: Pointer to the device object
  473. Irp: Incoming Irp
  474. Return Value:
  475. None
  476. --*/
  477. {
  478. //
  479. // The system Buffer has already been setup
  480. //
  481. Irp->IoStatus.Information = sizeof(MCA_EXCEPTION);
  482. Irp->IoStatus.Status = STATUS_SUCCESS;
  483. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  484. IoStartNextPacket(DeviceObject, TRUE);
  485. }
  486. VOID
  487. McaCancelIrp(
  488. IN PDEVICE_OBJECT DeviceObject,
  489. IN PIRP Irp
  490. )
  491. /*++
  492. Routine Description:
  493. This function gets called when the IRP is cancelled. When this routine
  494. is called, we hold the cancel spin lock and we are at DISPATCH level
  495. Arguments:
  496. DeviceObject and the Irp to be cancelled.
  497. Return Value:
  498. None.
  499. --*/
  500. {
  501. ((PMCA_DEVICE_EXTENSION)(DeviceObject->DeviceExtension))->SavedIrp = NULL;
  502. Irp->IoStatus.Status = STATUS_CANCELLED;
  503. Irp->IoStatus.Information = 0;
  504. IoReleaseCancelSpinLock(Irp->CancelIrql);
  505. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  506. }
  507. NTSTATUS
  508. MCADeviceControl(
  509. IN PDEVICE_OBJECT DeviceObject,
  510. IN PIRP Irp
  511. )
  512. /*++
  513. Routine Description:
  514. This routine is the dispatch routine for the IOCTL requests to driver.
  515. It accepts an I/O Request Packet, performs the request, and then
  516. returns with the appropriate status.
  517. Arguments:
  518. DeviceObject: Pointer to the device object
  519. Irp: Incoming Irp
  520. Return Value:
  521. Success or failure
  522. --*/
  523. {
  524. NTSTATUS Status;
  525. PIO_STACK_LOCATION IrpSp;
  526. PMCA_DEVICE_EXTENSION Extension = DeviceObject->DeviceExtension;
  527. KIRQL CancelIrql;
  528. ULONG ReturnedLength;
  529. ULONG PhysicalAddress;
  530. KIRQL OldIrql;
  531. //
  532. // Get a pointer to the current stack location in the IRP. This is
  533. // where the function codes and parameters are stored.
  534. //
  535. IrpSp = IoGetCurrentIrpStackLocation( Irp );
  536. //
  537. // The individual IOCTLs will return errors if HAL MCA is not installed
  538. //
  539. //
  540. // Switch on the IOCTL code that is being requested by the user. If the
  541. // operation is a valid one for this device do the needful.
  542. //
  543. switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
  544. case IOCTL_READ_BANKS:
  545. //
  546. // we need a user buffer for this call to complete
  547. // Our user buffer is in SystemBuffer
  548. //
  549. if (Irp->AssociatedIrp.SystemBuffer == NULL) {
  550. Status = STATUS_UNSUCCESSFUL;
  551. break;
  552. }
  553. if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength !=
  554. sizeof(MCA_EXCEPTION)) {
  555. Status = STATUS_UNSUCCESSFUL;
  556. break;
  557. }
  558. //
  559. // Call HalQuerySystemInformation() to obtain MCA log.
  560. // This call can also fail if the processor does not support
  561. // Intel Machine Check Architecture
  562. //
  563. Status = HalQuerySystemInformation(
  564. HalMcaLogInformation,
  565. sizeof(MCA_EXCEPTION),
  566. Irp->AssociatedIrp.SystemBuffer,
  567. &ReturnedLength
  568. );
  569. if (NT_SUCCESS(Status)) {
  570. Irp->IoStatus.Information = ReturnedLength;
  571. } else {
  572. if (Status == STATUS_NO_SUCH_DEVICE) {
  573. //
  574. // MCA support not available\n");
  575. //
  576. NOTHING;
  577. }
  578. if (Status == STATUS_NOT_FOUND) {
  579. //
  580. // No machine check errors present\n");
  581. //
  582. NOTHING;
  583. }
  584. Irp->IoStatus.Information = 0;
  585. }
  586. break;
  587. case IOCTL_READ_BANKS_ASYNC:
  588. if (Irp->AssociatedIrp.SystemBuffer == NULL) {
  589. Status = STATUS_UNSUCCESSFUL;
  590. break;
  591. }
  592. if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength !=
  593. sizeof(MCA_EXCEPTION)) {
  594. Status = STATUS_UNSUCCESSFUL;
  595. break;
  596. }
  597. //
  598. // Implementation Note:
  599. //
  600. // Our Async model is such that the next DeviceIoControl
  601. // does not start from the app until the previous one
  602. // completes (asynchronously). Since there is no inherent
  603. // parallelism that is needed here, we do not have to worry
  604. // about protecting data integrity in the face of more than
  605. // one app level ioctls active at the same time.
  606. //
  607. //
  608. // asynchronous reads provide a mechanism for the
  609. // app to asynchronously get input from the HAL on an
  610. // exception. This request is marked as pending at this time
  611. // but it will be completed when an MCA exception occurs.
  612. //
  613. IoMarkIrpPending(Irp);
  614. //
  615. // Complete the processing in StartIo Dispatch routine
  616. // ASSERT: at any given time there is only 1 async call pending
  617. // So just save the pointer
  618. //
  619. if (Extension->SavedIrp == NULL) {
  620. Extension->SavedIrp = Irp;
  621. } else {
  622. //
  623. // We can have ONLY one outstanding ASYNC request
  624. //
  625. Status = STATUS_DEVICE_BUSY;
  626. break;
  627. }
  628. //
  629. // Set the IRP to cancellable state
  630. //
  631. IoAcquireCancelSpinLock(&CancelIrql);
  632. IoSetCancelRoutine(Irp, McaCancelIrp);
  633. IoReleaseCancelSpinLock(CancelIrql);
  634. return(STATUS_PENDING);
  635. break;
  636. default:
  637. //
  638. // This should not happen
  639. //
  640. DbgPrint("MCA driver: Bad ioctl\n");
  641. Status = STATUS_NOT_IMPLEMENTED;
  642. break;
  643. }
  644. //
  645. // Copy the final status into the return status, complete the request and
  646. // get out of here.
  647. //
  648. if (Status != STATUS_PENDING) {
  649. //
  650. // Complete the Io Request
  651. //
  652. Irp->IoStatus.Status = Status;
  653. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  654. }
  655. return (Status);
  656. }
  657. NTSTATUS
  658. MCACleanup(
  659. IN PDEVICE_OBJECT DeviceObject,
  660. IN PIRP Irp
  661. )
  662. /*++
  663. Routine Description:
  664. This is the dispatch routine for cleanup requests.
  665. All queued IRPs are completed with STATUS_CANCELLED.
  666. Arguments:
  667. DeviceObject: Pointer to the device object
  668. Irp: Incoming Irp
  669. Return Value:
  670. Success or failure
  671. --*/
  672. {
  673. PIRP CurrentIrp;
  674. PMCA_DEVICE_EXTENSION Extension = DeviceObject->DeviceExtension;
  675. //
  676. // Complete all queued requests with STATUS_CANCELLED.
  677. //
  678. if (Extension->SavedIrp != NULL) {
  679. CurrentIrp = Extension->SavedIrp;
  680. //
  681. // Acquire the Cancel Spinlock
  682. //
  683. IoAcquireCancelSpinLock(&CurrentIrp->CancelIrql);
  684. Extension->SavedIrp = NULL;
  685. if (CurrentIrp->Cancel == TRUE) {
  686. //
  687. // Cancel routine got called for this one.
  688. // No need to do anything else
  689. //
  690. IoReleaseCancelSpinLock(CurrentIrp->CancelIrql);
  691. } else {
  692. if (CurrentIrp->CancelRoutine == NULL) {
  693. //
  694. // Release the Cancel Spinlock
  695. //
  696. IoReleaseCancelSpinLock(CurrentIrp->CancelIrql);
  697. } else {
  698. (CurrentIrp->CancelRoutine)(DeviceObject, CurrentIrp );
  699. }
  700. }
  701. }
  702. //
  703. // Complete the Cleanup Dispatch with STATUS_SUCCESS
  704. //
  705. Irp->IoStatus.Status = STATUS_SUCCESS;
  706. Irp->IoStatus.Information = 0;
  707. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  708. return(STATUS_SUCCESS);
  709. }
  710. VOID
  711. MCAUnload(
  712. IN PDRIVER_OBJECT DriverObject
  713. )
  714. /*++
  715. Routine Description:
  716. Dispatch routine for unloads
  717. Arguments:
  718. DeviceObject: Pointer to the device object
  719. Return Value:
  720. None
  721. --*/
  722. {
  723. NTSTATUS Status;
  724. STRING DosString;
  725. UNICODE_STRING DosUnicodeString;
  726. //
  727. // Delete the user visible device name.
  728. //
  729. RtlInitAnsiString( &DosString, MCA_DEVICE_NAME_DOS );
  730. Status = RtlAnsiStringToUnicodeString(
  731. &DosUnicodeString,
  732. &DosString,
  733. TRUE
  734. );
  735. if ( !NT_SUCCESS( Status )) {
  736. DbgPrint("MCAUnload: Error in RtlAnsiStringToUnicodeString\n");
  737. return;
  738. }
  739. Status = IoDeleteSymbolicLink(
  740. &DosUnicodeString
  741. );
  742. RtlFreeUnicodeString( &DosUnicodeString );
  743. //
  744. // Delete the device object
  745. //
  746. IoDeleteDevice(DriverObject->DeviceObject);
  747. return;
  748. }