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.

2852 lines
82 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. scsiscan.c
  5. Abstract:
  6. The scsi scanner class driver translates IRPs to SRBs with embedded CDBs
  7. and sends them to its devices through the port driver.
  8. Author:
  9. Ray Patrick (raypat)
  10. Environment:
  11. kernel mode only
  12. Notes:
  13. Revision History:
  14. --*/
  15. //
  16. // Include
  17. //
  18. #define INITGUID
  19. #include <stdio.h>
  20. #include "stddef.h"
  21. #include "wdm.h"
  22. #include "scsi.h"
  23. #include "ntddstor.h"
  24. #include "ntddscsi.h"
  25. #include "scsiscan.h"
  26. #include "private.h"
  27. #include <wiaintfc.h>
  28. #include "debug.h"
  29. #include <initguid.h>
  30. #include <devguid.h>
  31. #ifdef ALLOC_PRAGMA
  32. #pragma alloc_text(PAGE, DriverEntry)
  33. #pragma alloc_text(PAGE, SSPnp)
  34. #pragma alloc_text(PAGE, SSPnpAddDevice)
  35. #pragma alloc_text(PAGE, SSOpen)
  36. #pragma alloc_text(PAGE, SSClose)
  37. #pragma alloc_text(PAGE, SSReadWrite)
  38. #pragma alloc_text(PAGE, SSDeviceControl)
  39. #pragma alloc_text(PAGE, SSAdjustTransferSize)
  40. #pragma alloc_text(PAGE, SSBuildTransferContext)
  41. #pragma alloc_text(PAGE, SSCreateSymbolicLink)
  42. #pragma alloc_text(PAGE, SSDestroySymbolicLink)
  43. #pragma alloc_text(PAGE, SSUnload)
  44. #endif
  45. DEFINE_GUID(GUID_STI_DEVICE, 0xF6CBF4C0L, 0xCC61, 0x11D0, 0x84, 0xE5, 0x00, 0xA0, 0xC9, 0x27, 0x65, 0x27);
  46. //
  47. // Globals
  48. //
  49. ULONG NextDeviceInstance = 0;
  50. #if DBG
  51. ULONG SCSISCAN_DebugTraceLevel = MAX_TRACE;
  52. #endif
  53. #define DBG_DEVIOCTL 1
  54. #ifdef _WIN64
  55. BOOLEAN
  56. IoIs32bitProcess(
  57. IN PIRP Irp
  58. );
  59. #endif // _WIN64
  60. //
  61. // Function
  62. //
  63. NTSTATUS
  64. DriverEntry(
  65. IN PDRIVER_OBJECT DriverObject,
  66. IN PUNICODE_STRING RegistryPath
  67. )
  68. /*++
  69. Routine Description:
  70. This routine initializes the scanner class driver. The driver
  71. opens the port driver by name and then receives configuration
  72. information used to attach to the scanner devices.
  73. Arguments:
  74. DriverObject
  75. Return Value:
  76. NT Status
  77. --*/
  78. {
  79. PAGED_CODE();
  80. DebugTrace(TRACE_PROC_ENTER,("DriverEntry: Enter...\n"));
  81. MyDebugInit(RegistryPath);
  82. //
  83. // Set up the device driver entry points.
  84. //
  85. DriverObject->MajorFunction[IRP_MJ_READ] = SSReadWrite;
  86. DriverObject->MajorFunction[IRP_MJ_WRITE] = SSReadWrite;
  87. DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = SSDeviceControl;
  88. DriverObject->MajorFunction[IRP_MJ_CREATE] = SSOpen;
  89. DriverObject->MajorFunction[IRP_MJ_CLOSE] = SSClose;
  90. DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = SSPnp;
  91. DriverObject->MajorFunction[IRP_MJ_PNP] = SSPnp;
  92. DriverObject->MajorFunction[IRP_MJ_POWER] = SSPower;
  93. DriverObject->DriverUnload = SSUnload;
  94. DriverObject->DriverExtension->AddDevice = SSPnpAddDevice;
  95. DebugTrace(TRACE_PROC_LEAVE,("DriverEntry: Leaving... Status=STATUS_SUCCESS\n"));
  96. return STATUS_SUCCESS;
  97. } // end DriverEntry
  98. NTSTATUS
  99. SSPnpAddDevice(
  100. IN PDRIVER_OBJECT pDriverObject,
  101. IN PDEVICE_OBJECT pPhysicalDeviceObject
  102. )
  103. /*++
  104. Routine Description:
  105. This routine is called to create a new instance of the device.
  106. Arguments:
  107. pDriverObject - pointer to the driver object for this instance of SS
  108. pPhysicalDeviceObject - pointer to the device object that represents the scanner
  109. on the scsi bus.
  110. Return Value:
  111. STATUS_SUCCESS if successful,
  112. STATUS_UNSUCCESSFUL otherwise
  113. --*/
  114. {
  115. UCHAR aName[64];
  116. ANSI_STRING ansiName;
  117. UNICODE_STRING uName;
  118. PDEVICE_OBJECT pDeviceObject = NULL;
  119. NTSTATUS Status;
  120. PSCSISCAN_DEVICE_EXTENSION pde;
  121. PAGED_CODE();
  122. DebugTrace(TRACE_PROC_ENTER,("SSPnpAddDevice: Enter...\n"));
  123. //
  124. // Check arguments.
  125. //
  126. if( (NULL == pDriverObject)
  127. || (NULL == pPhysicalDeviceObject) )
  128. {
  129. DebugTrace(TRACE_ERROR,("SSPnpAddDevice: ERROR!! Invalid parameter passed.\n"));
  130. Status = STATUS_INVALID_PARAMETER;
  131. DebugTrace(TRACE_PROC_LEAVE,("SSPnpAddDevice: Leaving.. Status = 0x%x.\n", Status));
  132. return Status;
  133. }
  134. //
  135. // Create the Functional Device Object (FDO) for this device.
  136. //
  137. _snprintf(aName, sizeof(aName), "\\Device\\Scanner%d",NextDeviceInstance);
  138. aName[ARRAYSIZE(aName)-1] = '\0';
  139. RtlInitAnsiString(&ansiName, aName);
  140. DebugTrace(TRACE_STATUS,("SSPnpAddDevice: Create device object %s\n", aName));
  141. RtlAnsiStringToUnicodeString(&uName, &ansiName, TRUE);
  142. //
  143. // Create device object for this scanner.
  144. //
  145. Status = IoCreateDevice(pDriverObject,
  146. sizeof(SCSISCAN_DEVICE_EXTENSION),
  147. &uName,
  148. FILE_DEVICE_SCANNER,
  149. 0,
  150. FALSE,
  151. &pDeviceObject);
  152. RtlFreeUnicodeString(&uName);
  153. if (!NT_SUCCESS(Status)) {
  154. DebugTrace(TRACE_ERROR,("SSPnpAddDevice: ERROR!! Can't create device object\n"));
  155. DEBUG_BREAKPOINT();
  156. return Status;
  157. }
  158. //
  159. // Indicate that IRPs should include MDLs and it's pawer pagable.
  160. //
  161. pDeviceObject->Flags |= DO_DIRECT_IO;
  162. pDeviceObject->Flags |= DO_POWER_PAGABLE;
  163. //
  164. // Initialize Device Extention
  165. //
  166. pde = (PSCSISCAN_DEVICE_EXTENSION)(pDeviceObject -> DeviceExtension);
  167. RtlZeroMemory(pde, sizeof(SCSISCAN_DEVICE_EXTENSION));
  168. //
  169. // Attach our new FDO to the PDO (Physical Device Object).
  170. //
  171. pde -> pStackDeviceObject = IoAttachDeviceToDeviceStack(pDeviceObject,
  172. pPhysicalDeviceObject);
  173. if (NULL == pde -> pStackDeviceObject) {
  174. DebugTrace(MIN_TRACE,("Cannot attach FDO to PDO.\n"));
  175. DEBUG_BREAKPOINT();
  176. IoDeleteDevice( pDeviceObject );
  177. return STATUS_NOT_SUPPORTED;
  178. }
  179. //
  180. // Remember the PDO in our device extension.
  181. //
  182. pde -> pPhysicalDeviceObject = pPhysicalDeviceObject;
  183. //
  184. // Remember the DeviceInstance number.
  185. //
  186. pde -> DeviceInstance = NextDeviceInstance;
  187. //
  188. // Reset SRB error status
  189. //
  190. pde->LastSrbError = 0L;
  191. //
  192. // Disable synchronous transfer for scanner requests.
  193. // Disable QueueFreeze in case of any error.
  194. //
  195. pde -> SrbFlags = SRB_FLAGS_DISABLE_SYNCH_TRANSFER | SRB_FLAGS_NO_QUEUE_FREEZE ;
  196. //
  197. // Set timeout value in seconds.
  198. //
  199. pde -> TimeOutValue = SCSISCAN_TIMEOUT;
  200. //
  201. // Handle exporting interface
  202. //
  203. Status = ScsiScanHandleInterface(
  204. pPhysicalDeviceObject,
  205. &pde->InterfaceNameString,
  206. TRUE
  207. );
  208. //
  209. // Each time AddDevice gets called, we advance the global DeviceInstance variable.
  210. //
  211. NextDeviceInstance++;
  212. //
  213. // Finishing initialize.
  214. //
  215. pDeviceObject -> Flags &= ~DO_DEVICE_INITIALIZING;
  216. DebugTrace(TRACE_PROC_LEAVE,("SSPnpAddDevice: Leaving... Status=STATUS_SUCCESS\n"));
  217. return STATUS_SUCCESS;
  218. } // end SSPnpAddDevice()
  219. NTSTATUS SSPnp (
  220. IN PDEVICE_OBJECT pDeviceObject,
  221. IN PIRP pIrp
  222. )
  223. /*++
  224. Routine Description:
  225. This routine handles all PNP irps.
  226. Arguments:
  227. pDevciceObject - represents a scsi scanner device
  228. pIrp - PNP irp
  229. Return Value:
  230. STATUS_SUCCESS if successful,
  231. STATUS_UNSUCCESSFUL otherwise
  232. --*/
  233. {
  234. NTSTATUS Status;
  235. PSCSISCAN_DEVICE_EXTENSION pde;
  236. PIO_STACK_LOCATION pIrpStack;
  237. STORAGE_PROPERTY_ID PropertyId;
  238. KEVENT event;
  239. PDEVICE_CAPABILITIES pCaps;
  240. PAGED_CODE();
  241. DebugTrace(TRACE_PROC_ENTER,("SSPnp: Enter...\n"));
  242. Status = STATUS_SUCCESS;
  243. //
  244. // Check arguments.
  245. //
  246. if( (NULL == pDeviceObject)
  247. || (NULL == pDeviceObject->DeviceExtension)
  248. || (NULL == pIrp) )
  249. {
  250. DebugTrace(TRACE_ERROR,("SSPnp: ERROR!! Invalid parameter passed.\n"));
  251. Status = STATUS_INVALID_PARAMETER;
  252. DebugTrace(TRACE_PROC_LEAVE,("SSPnp: Leaving.. Status = 0x%x.\n", Status));
  253. return Status;
  254. }
  255. pde = (PSCSISCAN_DEVICE_EXTENSION)pDeviceObject -> DeviceExtension;
  256. pIrpStack = IoGetCurrentIrpStackLocation( pIrp );
  257. switch (pIrpStack -> MajorFunction) {
  258. case IRP_MJ_SYSTEM_CONTROL:
  259. DebugTrace(TRACE_STATUS,("SSPnp: IRP_MJ_SYSTEM_CONTROL\n"));
  260. //
  261. // Just passing down IRP to the next layer.
  262. //
  263. IoCopyCurrentIrpStackLocationToNext( pIrp );
  264. Status = IoCallDriver(pde -> pStackDeviceObject, pIrp);
  265. return Status;
  266. break;
  267. case IRP_MJ_PNP:
  268. DebugTrace(TRACE_STATUS,("SSPnp: IRP_MJ_PNP\n"));
  269. switch (pIrpStack->MinorFunction) {
  270. case IRP_MN_QUERY_CAPABILITIES:
  271. DebugTrace(TRACE_STATUS,("SSPnp: IRP_MN_QUERY_CAPABILITIES\n"));
  272. pCaps = pIrpStack -> Parameters.DeviceCapabilities.Capabilities;
  273. //
  274. // fill in the structure with non-controversial values
  275. //
  276. pCaps -> D1Latency = 10;
  277. pCaps -> D2Latency = 10;
  278. pCaps -> D3Latency = 10;
  279. //
  280. // Set SurpriseRemoval OK for SBP2 devices.
  281. //
  282. pCaps->SurpriseRemovalOK = TRUE;
  283. pCaps->Removable = TRUE;
  284. //
  285. // Call down synchronously.
  286. //
  287. pIrp -> IoStatus.Status = STATUS_SUCCESS;
  288. Status = SSCallNextDriverSynch(pde, pIrp);
  289. if(!NT_SUCCESS(Status)){
  290. DebugTrace(TRACE_ERROR,("SSPnp: ERROR!! Call down failed\n Status=0x%x", Status));
  291. }
  292. //
  293. // Complete IRP.
  294. //
  295. IoCompleteRequest( pIrp, IO_NO_INCREMENT );
  296. return Status;
  297. case IRP_MN_START_DEVICE:
  298. DebugTrace(TRACE_STATUS,("SSPnp: IRP_MN_START_DEVICE\n"));
  299. //
  300. // Initialize PendingIoEvent. Set the number of pending i/o requests for this device to 1.
  301. // When this number falls to zero, it is okay to remove, or stop the device.
  302. //
  303. pde -> PendingIoCount = 0;
  304. KeInitializeEvent(&pde -> PendingIoEvent, NotificationEvent, FALSE);
  305. SSIncrementIoCount(pDeviceObject);
  306. //
  307. // First, let the port driver start the device. Simply passing down IRP.
  308. //
  309. Status = SSCallNextDriverSynch(pde, pIrp);
  310. if(!NT_SUCCESS(Status)){
  311. DebugTrace(TRACE_ERROR,("SSPnp: ERROR!! Call down failed\n Status=0x%x", Status));
  312. break;
  313. }
  314. //
  315. // The port driver has started the device. It is time for
  316. // us to do some initialization and create symbolic links
  317. // for the device.
  318. //
  319. //
  320. // Call port driver to get adapter capabilities.
  321. //
  322. PropertyId = StorageAdapterProperty;
  323. pde -> pAdapterDescriptor = NULL;
  324. Status = ClassGetDescriptor(pde -> pStackDeviceObject,
  325. &PropertyId,
  326. &(pde -> pAdapterDescriptor));
  327. if(!NT_SUCCESS(Status)) {
  328. DebugTrace(TRACE_ERROR, ("SSPnp: ERROR!! unable to retrieve adapter descriptor.\n"
  329. "[%#08lx]\n", Status));
  330. DEBUG_BREAKPOINT();
  331. if (NULL != pde -> pAdapterDescriptor) {
  332. MyFreePool( pde -> pAdapterDescriptor);
  333. pde -> pAdapterDescriptor = NULL;
  334. }
  335. break;
  336. }
  337. //
  338. // Create the symbolic link for this device.
  339. //
  340. Status = SSCreateSymbolicLink( pde );
  341. if (!NT_SUCCESS(Status)) {
  342. DebugTrace(TRACE_ERROR, ("SSPnp: ERROR!! Can't create symbolic link.\n"));
  343. DEBUG_BREAKPOINT();
  344. if (NULL != pde -> pAdapterDescriptor) {
  345. MyFreePool( pde -> pAdapterDescriptor);
  346. pde -> pAdapterDescriptor = NULL;
  347. }
  348. break;
  349. }
  350. //
  351. // Indicate device is now ready.
  352. //
  353. pde -> DeviceLock = 0;
  354. pde -> OpenInstanceCount = 0;
  355. pde -> AcceptingRequests = TRUE;
  356. pIrp -> IoStatus.Status = Status;
  357. pIrp -> IoStatus.Information = 0;
  358. pde -> LastSrbError = 0L;
  359. IoCompleteRequest( pIrp, IO_NO_INCREMENT );
  360. return Status;
  361. break;
  362. case IRP_MN_REMOVE_DEVICE:
  363. DebugTrace(TRACE_STATUS,("SSPnp: IRP_MN_REMOVE_DEVICE\n"));
  364. //
  365. // Forward remove message to lower driver.
  366. //
  367. IoCopyCurrentIrpStackLocationToNext(pIrp);
  368. pIrp -> IoStatus.Status = STATUS_SUCCESS;
  369. Status = SSCallNextDriverSynch(pde, pIrp);
  370. if(!NT_SUCCESS(Status)){
  371. DebugTrace(TRACE_ERROR,("SSPnp: ERROR!! Call down failed\n Status=0x%x", Status));
  372. }
  373. if (pde -> AcceptingRequests) {
  374. pde -> AcceptingRequests = FALSE;
  375. SSDestroySymbolicLink( pde );
  376. }
  377. ScsiScanHandleInterface(pde-> pPhysicalDeviceObject,
  378. &pde->InterfaceNameString,
  379. FALSE);
  380. #ifndef _CHICAGO_
  381. if (pde->InterfaceNameString.Buffer != NULL) {
  382. IoSetDeviceInterfaceState(&pde->InterfaceNameString,FALSE);
  383. }
  384. #endif // !_CHICAGO_
  385. //
  386. // wait for any io requests pending in our driver to
  387. // complete before finishing the remove
  388. //
  389. SSDecrementIoCount(pDeviceObject);
  390. KeWaitForSingleObject(&pde -> PendingIoEvent, Suspended, KernelMode,
  391. FALSE,NULL);
  392. if (pde -> pAdapterDescriptor) {
  393. MyFreePool(pde -> pAdapterDescriptor);
  394. pde -> pAdapterDescriptor = NULL;
  395. }
  396. IoDetachDevice(pde -> pStackDeviceObject);
  397. IoDeleteDevice (pDeviceObject);
  398. Status = STATUS_SUCCESS;
  399. pIrp -> IoStatus.Status = Status;
  400. pIrp -> IoStatus.Information = 0;
  401. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  402. return Status;
  403. break;
  404. case IRP_MN_STOP_DEVICE:
  405. DebugTrace(TRACE_STATUS,("SSPnp: IRP_MN_STOP_DEVICE\n"));
  406. //
  407. // Indicate device is not ready.
  408. //
  409. ASSERT(pde -> AcceptingRequests);
  410. pde -> AcceptingRequests = FALSE;
  411. //
  412. // Remove symbolic link.
  413. //
  414. SSDestroySymbolicLink( pde );
  415. #ifndef _CHICAGO_
  416. if (pde->InterfaceNameString.Buffer != NULL) {
  417. IoSetDeviceInterfaceState(&pde->InterfaceNameString,FALSE);
  418. }
  419. #endif // !_CHICAGO_
  420. //
  421. // Let the port driver stop the device.
  422. //
  423. pIrp -> IoStatus.Status = STATUS_SUCCESS;
  424. Status = SSCallNextDriverSynch(pde, pIrp);
  425. if(!NT_SUCCESS(Status)){
  426. DebugTrace(TRACE_ERROR,("SSPnp: ERROR!! Call down failed\n Status=0x%x", Status));
  427. }
  428. //
  429. // wait for any io requests pending in our driver to
  430. // complete before finishing the remove
  431. //
  432. SSDecrementIoCount(pDeviceObject);
  433. KeWaitForSingleObject(&pde -> PendingIoEvent, Suspended, KernelMode,
  434. FALSE,NULL);
  435. //
  436. // Free Adapter Descriptor
  437. //
  438. if(pde -> pAdapterDescriptor){
  439. MyFreePool(pde -> pAdapterDescriptor);
  440. pde -> pAdapterDescriptor = NULL;
  441. } else {
  442. DebugTrace(TRACE_ERROR,("SSPnp: ERROR!! AdapterDescriptor doesn't exist.\n"));
  443. DEBUG_BREAKPOINT();
  444. }
  445. Status = STATUS_SUCCESS;
  446. pIrp -> IoStatus.Status = Status;
  447. pIrp -> IoStatus.Information = 0;
  448. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  449. return Status;
  450. break;
  451. case IRP_MN_QUERY_STOP_DEVICE:
  452. DebugTrace(TRACE_STATUS,("SSPnp: IRP_MN_QUERY_STOP_DEVICE\n"));
  453. pIrp->IoStatus.Status = STATUS_SUCCESS;
  454. break;
  455. case IRP_MN_QUERY_REMOVE_DEVICE:
  456. DebugTrace(TRACE_STATUS,("SSPnp: IRP_MN_QUERY_REMOVE_DEVICE\n"));
  457. pIrp->IoStatus.Status = STATUS_SUCCESS;
  458. break;
  459. case IRP_MN_CANCEL_STOP_DEVICE:
  460. DebugTrace(TRACE_STATUS,("SSPnp: IRP_MN_CANCEL_STOP_DEVICE\n"));
  461. pIrp->IoStatus.Status = STATUS_SUCCESS;
  462. break;
  463. case IRP_MN_CANCEL_REMOVE_DEVICE:
  464. DebugTrace(TRACE_STATUS,("SSPnp: IRP_MN_CANCEL_REMOVE_DEVICE\n"));
  465. pIrp->IoStatus.Status = STATUS_SUCCESS;
  466. break;
  467. case IRP_MN_SURPRISE_REMOVAL:
  468. DebugTrace(TRACE_STATUS,("SSPnp: IRP_MN_SURPRISE_REMOVAL\n"));
  469. pIrp->IoStatus.Status = STATUS_SUCCESS;
  470. break;
  471. default:
  472. DebugTrace(TRACE_STATUS,("SSPnp: Minor PNP message received, MinFunction = %x\n",
  473. pIrpStack->MinorFunction));
  474. break;
  475. } /* case MinorFunction, MajorFunction == IRP_MJ_PNP_POWER */
  476. ASSERT(Status == STATUS_SUCCESS);
  477. if (!NT_SUCCESS(Status)) {
  478. pIrp -> IoStatus.Status = Status;
  479. IoCompleteRequest( pIrp, IO_NO_INCREMENT );
  480. DebugTrace(TRACE_PROC_LEAVE,("SSPnp: Leaving(w/ Error)... Status=%x\n", Status));
  481. return Status;
  482. }
  483. //
  484. // Passing down IRP
  485. //
  486. IoCopyCurrentIrpStackLocationToNext(pIrp);
  487. Status = IoCallDriver(pde -> pStackDeviceObject, pIrp);
  488. DebugTrace(TRACE_PROC_LEAVE,("SSPnp: Leaving... Status=%x\n", Status));
  489. return Status;
  490. break; // IRP_MJ_PNP
  491. default:
  492. DebugTrace(TRACE_WARNING,("SSPnp: WARNING!! Not handled Major PNP IOCTL.\n"));
  493. pIrp -> IoStatus.Status = STATUS_INVALID_PARAMETER;
  494. IoCompleteRequest( pIrp, IO_NO_INCREMENT );
  495. DebugTrace(TRACE_PROC_LEAVE,("SSPnp: Leaving... Status=STATUS_INVALID_PARAMETER\n", Status));
  496. return Status;
  497. } /* case MajorFunction */
  498. } // end SSPnp()
  499. NTSTATUS
  500. SSOpen(
  501. IN PDEVICE_OBJECT pDeviceObject,
  502. IN PIRP pIrp
  503. )
  504. /*++
  505. Routine Description:
  506. This routine is called to establish a connection to the device
  507. class driver. It does no more than return STATUS_SUCCESS.
  508. Arguments:
  509. pDeviceObject - Device object for a device.
  510. pIrp - Open request packet
  511. Return Value:
  512. NT Status - STATUS_SUCCESS
  513. --*/
  514. {
  515. NTSTATUS Status;
  516. PSCSISCAN_DEVICE_EXTENSION pde;
  517. PIO_STACK_LOCATION pIrpStack;
  518. PAGED_CODE();
  519. DebugTrace(TRACE_PROC_ENTER,("SSOpen: Enter...\n"));
  520. Status = STATUS_SUCCESS;
  521. //
  522. // Check arguments.
  523. //
  524. if( (NULL == pDeviceObject)
  525. || (NULL == pDeviceObject->DeviceExtension)
  526. || (NULL == pIrp) )
  527. {
  528. DebugTrace(TRACE_ERROR,("SSOpen: ERROR!! Invalid parameter passed.\n"));
  529. Status = STATUS_INVALID_PARAMETER;
  530. DebugTrace(TRACE_PROC_LEAVE,("SSOpen: Leaving.. Status = 0x%x.\n", Status));
  531. return Status;
  532. }
  533. pde = (PSCSISCAN_DEVICE_EXTENSION)pDeviceObject -> DeviceExtension;
  534. pIrpStack = IoGetCurrentIrpStackLocation( pIrp );
  535. //
  536. // Increment pending IO count
  537. //
  538. SSIncrementIoCount( pDeviceObject );
  539. //
  540. // Initialize IoStatus
  541. //
  542. Status = STATUS_SUCCESS;
  543. pIrp -> IoStatus.Information = 0;
  544. pIrp -> IoStatus.Status = Status;
  545. //
  546. // Save instance-count to the context in file object.
  547. //
  548. (ULONG)(UINT_PTR)(pIrpStack -> FileObject -> FsContext) = InterlockedIncrement(&pde -> OpenInstanceCount);
  549. //
  550. // Check if device is not going away, in which case fail open request.
  551. //
  552. if (pde -> AcceptingRequests == FALSE) {
  553. DebugTrace(TRACE_STATUS,("SSOpen: Device doesn't exist.\n"));
  554. Status = STATUS_DELETE_PENDING;
  555. pIrp -> IoStatus.Information = 0;
  556. pIrp -> IoStatus.Status = Status;
  557. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  558. SSDecrementIoCount(pDeviceObject);
  559. DebugTrace(TRACE_PROC_LEAVE,("SSOpen: Leaving... Status=STATUS_DELETE_PENDING\n"));
  560. return Status;
  561. }
  562. //
  563. // Decrement pending IO count
  564. //
  565. SSDecrementIoCount(pDeviceObject);
  566. //
  567. // Passing down IRP.
  568. //
  569. IoSkipCurrentIrpStackLocation( pIrp );
  570. Status = IoCallDriver(pde -> pStackDeviceObject, pIrp);
  571. DebugTrace(TRACE_PROC_LEAVE,("SSOpen: Leaving... Status=%x\n", Status));
  572. return Status;
  573. } // end SSOpen()
  574. NTSTATUS
  575. SSClose(
  576. IN PDEVICE_OBJECT pDeviceObject,
  577. IN PIRP pIrp
  578. )
  579. /*++
  580. Routine Description:
  581. Arguments:
  582. pDeviceObject - Device object for a device.
  583. pIrp - Open request packet
  584. Return Value:
  585. NT Status - STATUS_SUCCESS
  586. --*/
  587. {
  588. NTSTATUS Status;
  589. PSCSISCAN_DEVICE_EXTENSION pde;
  590. PIO_STACK_LOCATION pIrpStack;
  591. PAGED_CODE();
  592. DebugTrace(TRACE_PROC_ENTER,("SSClose: Enter...\n"));
  593. Status = STATUS_SUCCESS;
  594. //
  595. // Check arguments.
  596. //
  597. if( (NULL == pDeviceObject)
  598. || (NULL == pDeviceObject->DeviceExtension)
  599. || (NULL == pIrp) )
  600. {
  601. DebugTrace(TRACE_ERROR,("SSClose: ERROR!! Invalid parameter passed.\n"));
  602. Status = STATUS_INVALID_PARAMETER;
  603. DebugTrace(TRACE_PROC_LEAVE,("SSClose: Leaving.. Status = 0x%x.\n", Status));
  604. return Status;
  605. }
  606. pde = (PSCSISCAN_DEVICE_EXTENSION)pDeviceObject -> DeviceExtension;
  607. //
  608. // Increment pending IO count
  609. //
  610. SSIncrementIoCount( pDeviceObject );
  611. //
  612. // Clear instance-count in context
  613. //
  614. pIrpStack = IoGetCurrentIrpStackLocation( pIrp );
  615. pIrpStack -> FileObject -> FsContext = 0;
  616. //
  617. // Initialize IoStatus
  618. //
  619. pIrp -> IoStatus.Information = 0;
  620. pIrp -> IoStatus.Status = Status;
  621. //
  622. // Decrement pending IO count
  623. //
  624. SSDecrementIoCount(pDeviceObject);
  625. //
  626. // Passing down IRP
  627. //
  628. IoSkipCurrentIrpStackLocation( pIrp );
  629. Status = IoCallDriver(pde -> pStackDeviceObject, pIrp);
  630. DebugTrace(TRACE_PROC_LEAVE,("SSClose: Leaving... Status=%x\n", Status));
  631. return Status;
  632. } // end SSClose()
  633. NTSTATUS
  634. SSDeviceControl(
  635. IN PDEVICE_OBJECT pDeviceObject,
  636. IN PIRP pIrp
  637. )
  638. /*++
  639. Routine Description:
  640. This function allows a user mode client to send CDBs to the device.
  641. Arguments:
  642. pDeviceObject - Device object for a device.
  643. pIrp - Open request packet
  644. Return Value:
  645. NT Status - STATUS_SUCCESS
  646. --*/
  647. {
  648. PIO_STACK_LOCATION pIrpStack;
  649. PIO_STACK_LOCATION pNextIrpStack;
  650. ULONG IoControlCode;
  651. ULONG OldTimeout;
  652. PSCSISCAN_DEVICE_EXTENSION pde;
  653. PTRANSFER_CONTEXT pTransferContext = NULL;
  654. PMDL pMdl = NULL;
  655. NTSTATUS Status;
  656. PVOID Owner;
  657. PULONG pTimeOut;
  658. PCDB pCdb;
  659. PVOID pUserBuffer;
  660. BOOLEAN fLockedSenseBuffer, fLockedSRBStatus;
  661. PAGED_CODE();
  662. DebugTrace(TRACE_PROC_ENTER,("SSDeviceControl: Enter...\n"));
  663. Status = STATUS_SUCCESS;
  664. //
  665. // Check arguments.
  666. //
  667. if( (NULL == pDeviceObject)
  668. || (NULL == pDeviceObject->DeviceExtension)
  669. || (NULL == pIrp) )
  670. {
  671. DebugTrace(TRACE_ERROR,("SSDeviceControl: ERROR!! Invalid parameter passed.\n"));
  672. Status = STATUS_INVALID_PARAMETER;
  673. DebugTrace(TRACE_PROC_LEAVE,("SSDeviceControl: Leaving.. Status = 0x%x.\n", Status));
  674. return Status;
  675. }
  676. SSIncrementIoCount( pDeviceObject );
  677. pde = (PSCSISCAN_DEVICE_EXTENSION)pDeviceObject -> DeviceExtension;
  678. //
  679. // Validate state of the device
  680. //
  681. if (pde -> AcceptingRequests == FALSE) {
  682. DebugTrace(TRACE_WARNING,("SSDeviceControl: WARNING!! Device's been stopped/removed!\n"));
  683. Status = STATUS_DELETE_PENDING;
  684. pIrp -> IoStatus.Information = 0;
  685. goto SSDeviceControl_Complete;
  686. }
  687. //
  688. // Indicate that MDLs are not locked yet
  689. //
  690. fLockedSenseBuffer = fLockedSRBStatus = FALSE;
  691. //
  692. // Get context pointers
  693. //
  694. pIrpStack = IoGetCurrentIrpStackLocation( pIrp );
  695. pNextIrpStack = IoGetNextIrpStackLocation( pIrp );
  696. IoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
  697. //
  698. // Get owner of device (0 = locked, >0 if someone has it locked)
  699. //
  700. Owner = InterlockedCompareExchangePointer(&pde -> DeviceLock,
  701. NULL,
  702. NULL);
  703. if (Owner != NULL) {
  704. if (Owner != pIrpStack -> FileObject -> FsContext) {
  705. DebugTrace(TRACE_WARNING,("SSDeviceControl: WARNING!! Device is already locked\n"));
  706. Status = STATUS_DEVICE_BUSY;
  707. pIrp -> IoStatus.Information = 0;
  708. goto SSDeviceControl_Complete;
  709. }
  710. }
  711. switch (IoControlCode) {
  712. case IOCTL_SCSISCAN_SET_TIMEOUT:
  713. DebugTrace(TRACE_STATUS,("SSDeviceControl: SCSISCAN_SET_TIMEOUT\n"));
  714. //
  715. // Get pointer of timeout buffer.
  716. //
  717. pTimeOut = pIrp -> AssociatedIrp.SystemBuffer;
  718. //
  719. // Validate size of the input parameter
  720. //
  721. if (pIrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(pde -> TimeOutValue) ) {
  722. DebugTrace(TRACE_WARNING,("SSDeviceControl: WARNING!! Buffer too small\n"));
  723. Status = STATUS_INVALID_PARAMETER;
  724. goto SSDeviceControl_Complete;
  725. }
  726. OldTimeout = *pTimeOut;
  727. OldTimeout = InterlockedExchange(&pde -> TimeOutValue, *pTimeOut );
  728. DebugTrace(TRACE_STATUS,("SSDeviceControl: Timeout %d->%d\n",OldTimeout, *pTimeOut));
  729. pIrp -> IoStatus.Information = 0;
  730. //
  731. // If caller wanted to get old timeout value back - give it to him.
  732. // Ideally we should've require nonNULL value for output buffer, but it had not been speced
  733. // and now we can't change compatibility.
  734. //
  735. if (pIrpStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(OldTimeout) ) {
  736. *pTimeOut = OldTimeout;
  737. pIrp -> IoStatus.Information = sizeof(OldTimeout) ;
  738. }
  739. Status = STATUS_SUCCESS;
  740. goto SSDeviceControl_Complete;
  741. case IOCTL_SCSISCAN_LOCKDEVICE:
  742. DebugTrace(TRACE_STATUS,("SSDeviceControl: IOCTL_SCSISCAN_LOCKDEVICE\n"));
  743. //
  744. // Lock device
  745. //
  746. Status = STATUS_DEVICE_BUSY;
  747. if (NULL == InterlockedCompareExchangePointer(&pde -> DeviceLock,
  748. pIrpStack -> FileObject -> FsContext,
  749. NULL)) {
  750. Status = STATUS_SUCCESS;
  751. }
  752. goto SSDeviceControl_Complete;
  753. case IOCTL_SCSISCAN_UNLOCKDEVICE:
  754. DebugTrace(TRACE_STATUS,("SSDeviceControl: IOCTL_SCSISCAN_UNLOCKDEVICE\n"));
  755. //
  756. // Unlock device
  757. //
  758. Status = STATUS_DEVICE_BUSY;
  759. if (pIrpStack -> FileObject -> FsContext ==
  760. InterlockedCompareExchangePointer(&pde -> DeviceLock,
  761. NULL,
  762. pIrpStack -> FileObject -> FsContext)) {
  763. Status = STATUS_SUCCESS;
  764. }
  765. goto SSDeviceControl_Complete;
  766. case IOCTL_SCSISCAN_CMD:
  767. {
  768. SCSISCAN_CMD LocalScsiscanCmd;
  769. PSCSISCAN_CMD pCmd;
  770. DebugTrace(TRACE_STATUS,("SSDeviceControl: IOCTL_SCSISCAN_CMD\n"));
  771. //
  772. // Check input buffer size.
  773. //
  774. #ifdef _WIN64
  775. if(IoIs32bitProcess(pIrp)){
  776. PSCSISCAN_CMD_32 pScsiscanCmd32;
  777. if (pIrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SCSISCAN_CMD_32) ) {
  778. DebugTrace(TRACE_WARNING,("SSDeviceControl: WARNING!! Buffer too small\n"));
  779. Status = STATUS_INVALID_PARAMETER;
  780. goto SSDeviceControl_Complete;
  781. }
  782. //
  783. // Copy parameters from 32bit IOCTL buffer.
  784. //
  785. pCmd = &LocalScsiscanCmd;
  786. RtlZeroMemory(pCmd, sizeof(SCSISCAN_CMD));
  787. pScsiscanCmd32 = pIrp -> AssociatedIrp.SystemBuffer;
  788. pCmd -> Size = pScsiscanCmd32 -> Size;
  789. pCmd -> SrbFlags = pScsiscanCmd32 -> SrbFlags;
  790. pCmd -> CdbLength = pScsiscanCmd32 -> CdbLength;
  791. pCmd -> SenseLength = pScsiscanCmd32 -> SenseLength;
  792. pCmd -> TransferLength = pScsiscanCmd32 -> TransferLength;
  793. pCmd -> pSrbStatus = (PUCHAR)pScsiscanCmd32 -> pSrbStatus;
  794. pCmd -> pSenseBuffer = (PUCHAR)pScsiscanCmd32 -> pSenseBuffer;
  795. RtlCopyMemory(pCmd -> Cdb, pScsiscanCmd32 -> Cdb, 16); // 16 = CDB buffer size.
  796. } else { // if(IoIs32bitProcess(pIrp))
  797. #endif // _WIN64
  798. if (pIrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SCSISCAN_CMD) ) {
  799. DebugTrace(TRACE_WARNING,("SSDeviceControl: WARNING!! Buffer too small\n"));
  800. Status = STATUS_INVALID_PARAMETER;
  801. goto SSDeviceControl_Complete;
  802. }
  803. pCmd = pIrp -> AssociatedIrp.SystemBuffer;
  804. #ifdef _WIN64
  805. } // if(IoIs32bitProcess(pIrp))
  806. #endif // _WIN64
  807. //
  808. // Issue SCSI command
  809. //
  810. #if DBG_DEVIOCTL
  811. {
  812. PCDB pCdb;
  813. pCdb = (PCDB)pCmd -> Cdb;
  814. DebugTrace(TRACE_STATUS,("SSDeviceControl: CDB->ControlCode = %d \n",pCdb->CDB6GENERIC.OperationCode));
  815. }
  816. #endif
  817. pTransferContext = SSBuildTransferContext(pde,
  818. pIrp,
  819. pCmd,
  820. pIrpStack -> Parameters.DeviceIoControl.InputBufferLength,
  821. pIrp -> MdlAddress,
  822. TRUE
  823. );
  824. if (NULL == pTransferContext) {
  825. DebugTrace(TRACE_ERROR,("SSDeviceControl: ERROR!! Can't create transfer context!\n"));
  826. DEBUG_BREAKPOINT();
  827. Status = STATUS_INVALID_PARAMETER;
  828. goto SSDeviceControl_Complete;
  829. }
  830. //
  831. // Fill in transfer length in the CDB.
  832. //
  833. if(10 == pCmd -> CdbLength){
  834. //
  835. // Currently Scsiscan only supports flagmentation of 10bytes CDB.
  836. //
  837. SSSetTransferLengthToCdb((PCDB)pCmd -> Cdb, pTransferContext -> TransferLength);
  838. } else if (6 != pCmd -> CdbLength){
  839. //
  840. // If CdbLength is not 6 or 10 and transfer size exceeds adapter limit, SCSISCAN cannot handle it.
  841. //
  842. if(pTransferContext -> TransferLength != pCmd -> TransferLength){
  843. DebugTrace(TRACE_WARNING,("SSDeviceControl: WARNING!! TransferLength (CDB !=6 or 10) exceeds limits!\n"));
  844. Status = STATUS_INVALID_PARAMETER;
  845. goto SSDeviceControl_Complete;
  846. }
  847. }
  848. //
  849. // Create system address for the user's sense buffer (if any).
  850. //
  851. if (pCmd -> SenseLength) {
  852. pTransferContext -> pSenseMdl = MmCreateMdl(NULL,
  853. pCmd -> pSenseBuffer,
  854. pCmd -> SenseLength);
  855. if (NULL == pTransferContext -> pSenseMdl) {
  856. DebugTrace(TRACE_ERROR,("SSDeviceControl: ERROR!! Can't create MDL for sense buffer!\n"));
  857. DEBUG_BREAKPOINT();
  858. Status = STATUS_INSUFFICIENT_RESOURCES;
  859. goto SSDeviceControl_Error_With_Status;
  860. }
  861. //
  862. // Probe and lock the pages associated with the
  863. // caller's buffer for write access , using processor mode of the requestor
  864. // Nb: Probing may cause an exception
  865. //
  866. try{
  867. MmProbeAndLockPages(pTransferContext -> pSenseMdl,
  868. pIrp -> RequestorMode,
  869. IoModifyAccess
  870. );
  871. } except(EXCEPTION_EXECUTE_HANDLER) {
  872. //
  873. // Invalid sense buffer pointer.
  874. //
  875. DebugTrace(TRACE_WARNING,("SSDeviceControl: WARNING!! Sense Buffer validation failed\n"));
  876. Status = GetExceptionCode();
  877. pIrp -> IoStatus.Information = 0;
  878. goto SSDeviceControl_Error_With_Status;
  879. } // except
  880. //
  881. // Indicate we succesfully locked sense buffer
  882. //
  883. fLockedSenseBuffer = TRUE;
  884. //
  885. // Get system address of sense buffer
  886. //
  887. pTransferContext -> pSenseMdl -> MdlFlags |= MDL_MAPPING_CAN_FAIL;
  888. pTransferContext -> pSenseBuffer =
  889. MmGetSystemAddressForMdl(pTransferContext -> pSenseMdl);
  890. if (NULL == pTransferContext -> pSenseBuffer) {
  891. //
  892. // Error with MmGetSystemAddressForMdl
  893. //
  894. DebugTrace(TRACE_ERROR,("SSDeviceControl: ERROR!! Can't get system address for sense buffer!\n"));
  895. DEBUG_BREAKPOINT();
  896. Status = STATUS_INSUFFICIENT_RESOURCES;
  897. goto SSDeviceControl_Error_With_Status;
  898. }
  899. }
  900. //
  901. // Create system address for the user's srb status byte.
  902. //
  903. pMdl = MmCreateMdl(NULL,
  904. pCmd -> pSrbStatus,
  905. sizeof(UCHAR)
  906. );
  907. if (NULL == pMdl) {
  908. DebugTrace(TRACE_ERROR,("SSDeviceControl: ERROR!! Can't create MDL for pSrbStatus!\n"));
  909. DEBUG_BREAKPOINT();
  910. Status = STATUS_INSUFFICIENT_RESOURCES;
  911. goto SSDeviceControl_Error_With_Status;
  912. }
  913. //
  914. // Probe and lock the pages associated with the caller's
  915. // buffer for write access , using processor mode of the requestor
  916. // Nb: Probing may cause an exception
  917. //
  918. try{
  919. MmProbeAndLockPages(pMdl,
  920. pIrp -> RequestorMode,
  921. IoModifyAccess);
  922. } except(EXCEPTION_EXECUTE_HANDLER) {
  923. //
  924. // Invalid SRB status buffer pointer.
  925. //
  926. DebugTrace(TRACE_WARNING,("SSDeviceControl: WARNING!! SRB Status Buffer validation failed\n"));
  927. Status = GetExceptionCode();
  928. pIrp -> IoStatus.Information = 0;
  929. goto SSDeviceControl_Error_With_Status;
  930. } // except
  931. //
  932. // Indicate we successfully locked SRB status
  933. //
  934. fLockedSRBStatus = TRUE;
  935. //
  936. // Replace pSrbStatus with the address gotten from MmGetSystemAddressForMdl.
  937. //
  938. pMdl -> MdlFlags |= MDL_MAPPING_CAN_FAIL;
  939. pCmd -> pSrbStatus = MmGetSystemAddressForMdl(pMdl);
  940. if (NULL == pCmd -> pSrbStatus) {
  941. //
  942. // Error with MmGetSystemAddressForMdl
  943. //
  944. DebugTrace(TRACE_ERROR,("SSDeviceControl: ERROR!! Can't get system address for pSrbStatus!\n"));
  945. DEBUG_BREAKPOINT();
  946. Status = STATUS_INSUFFICIENT_RESOURCES;
  947. goto SSDeviceControl_Error_With_Status;
  948. }
  949. //
  950. // Save Mdl for pSrbStatus
  951. //
  952. pTransferContext -> pSrbStatusMdl = pMdl;
  953. break;
  954. } // case IOCTL_SCSISCAN_CMD:
  955. case IOCTL_SCSISCAN_GET_INFO:
  956. DebugTrace(TRACE_STATUS,("SSDeviceControl: IOCTL_SCSISCAN_GET_INFO\n"));
  957. //
  958. // Get and return SCSI information block for the scanner device
  959. //
  960. if (sizeof(SCSISCAN_INFO) != pIrpStack->Parameters.DeviceIoControl.OutputBufferLength) {
  961. //
  962. // Incorrect output buffer size
  963. //
  964. DebugTrace(TRACE_WARNING,("SSDeviceControl: WARNING!! Output buffer size is wrong!\n"));
  965. Status = STATUS_INVALID_PARAMETER;
  966. goto SSDeviceControl_Error_With_Status;
  967. }
  968. if (sizeof(SCSISCAN_INFO) > MmGetMdlByteCount(pIrp->MdlAddress)) {
  969. //
  970. // buffer size is short
  971. //
  972. DebugTrace(TRACE_WARNING,("SSDeviceControl: WARNING!! Output buffer size is wrong!\n"));
  973. Status = STATUS_INVALID_PARAMETER;
  974. goto SSDeviceControl_Error_With_Status;
  975. }
  976. pIrp->MdlAddress->MdlFlags |= MDL_MAPPING_CAN_FAIL;
  977. pUserBuffer = MmGetSystemAddressForMdl(pIrp->MdlAddress);
  978. if(NULL == pUserBuffer){
  979. DebugTrace(TRACE_ERROR,("SSDeviceControl: ERROR!! MmGetSystemAddressForMdl failed!\n"));
  980. Status = STATUS_INSUFFICIENT_RESOURCES;
  981. goto SSDeviceControl_Complete;
  982. }
  983. Status = ClassGetInfo(pde -> pStackDeviceObject, pUserBuffer);
  984. goto SSDeviceControl_Complete;
  985. default:
  986. //
  987. // Unsupported IOCTL code - pass down.
  988. //
  989. DebugTrace(TRACE_STATUS,("SSDeviceControl: Passing down unsupported IOCTL(0x%x)!\n", IoControlCode));
  990. IoSkipCurrentIrpStackLocation(pIrp);
  991. Status = IoCallDriver(pde -> pStackDeviceObject, pIrp);
  992. return Status;
  993. }
  994. //
  995. // Pass request down and mark as pending
  996. //
  997. IoMarkIrpPending(pIrp);
  998. IoSetCompletionRoutine(pIrp, SSIoctlIoComplete, pTransferContext, TRUE, TRUE, FALSE);
  999. SSSendScannerRequest(pDeviceObject, pIrp, pTransferContext, FALSE);
  1000. DebugTrace(TRACE_PROC_LEAVE,("SSDeviceControl: Leaving... Status=STATUS_PENDING\n"));
  1001. return STATUS_PENDING;
  1002. //
  1003. // Cleanup
  1004. //
  1005. SSDeviceControl_Error_With_Status:
  1006. //
  1007. // Clean up if something went wrong when allocating resources
  1008. //
  1009. if (pMdl) {
  1010. if (fLockedSRBStatus) {
  1011. MmUnlockPages(pMdl);
  1012. }
  1013. IoFreeMdl(pMdl);
  1014. if (pTransferContext) {
  1015. pTransferContext -> pSrbStatusMdl = NULL;
  1016. }
  1017. }
  1018. if (pTransferContext) {
  1019. if (pTransferContext -> pSenseMdl) {
  1020. if ( fLockedSenseBuffer ) {
  1021. MmUnlockPages(pTransferContext -> pSenseMdl);
  1022. }
  1023. IoFreeMdl(pTransferContext -> pSenseMdl);
  1024. pTransferContext -> pSenseMdl = NULL;
  1025. pTransferContext -> pSenseBuffer = NULL;
  1026. }
  1027. }
  1028. SSDeviceControl_Complete:
  1029. //
  1030. // Everything seems to be OK - complet I/O request
  1031. //
  1032. pIrp -> IoStatus.Status = Status;
  1033. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  1034. SSDecrementIoCount(pDeviceObject);
  1035. DebugTrace(TRACE_PROC_LEAVE,("SSDeviceControl: Leaving... Status=%x\n",Status));
  1036. return Status;
  1037. } // end SSDeviceControl()
  1038. NTSTATUS
  1039. SSReadWrite(
  1040. IN PDEVICE_OBJECT pDeviceObject,
  1041. IN PIRP pIrp
  1042. )
  1043. /*++
  1044. Routine Description:
  1045. This is the entry called by the I/O system for scanner IO.
  1046. Arguments:
  1047. DeviceObject - the system object for the device.
  1048. Irp - IRP involved.
  1049. Return Value:
  1050. NT Status
  1051. --*/
  1052. {
  1053. NTSTATUS Status;
  1054. PIO_STACK_LOCATION pIrpStack;
  1055. PSCSISCAN_DEVICE_EXTENSION pde;
  1056. PTRANSFER_CONTEXT pTransferContext;
  1057. PMDL pMdl;
  1058. PSCSISCAN_CMD pCmd;
  1059. PCDB pCdb;
  1060. PVOID Owner;
  1061. PAGED_CODE();
  1062. DebugTrace(TRACE_PROC_ENTER,("SSReadWrite: Enter...\n"));
  1063. Status = STATUS_SUCCESS;
  1064. pCmd = NULL;
  1065. //
  1066. // Check arguments.
  1067. //
  1068. if( (NULL == pDeviceObject)
  1069. || (NULL == pDeviceObject->DeviceExtension)
  1070. || (NULL == pIrp) )
  1071. {
  1072. DebugTrace(TRACE_ERROR,("SSReadWrite: ERROR!! Invalid parameter passed.\n"));
  1073. Status = STATUS_INVALID_PARAMETER;
  1074. DebugTrace(TRACE_PROC_LEAVE,("SSReadWrite: Leaving.. Status = 0x%x.\n", Status));
  1075. return Status;
  1076. }
  1077. pde = (PSCSISCAN_DEVICE_EXTENSION)pDeviceObject -> DeviceExtension;
  1078. pIrpStack = IoGetCurrentIrpStackLocation( pIrp );
  1079. //
  1080. // Incremet pending IO count.
  1081. //
  1082. SSIncrementIoCount( pDeviceObject );
  1083. //
  1084. // Validate state of the device
  1085. //
  1086. if (pde -> AcceptingRequests == FALSE) {
  1087. DebugTrace(TRACE_WARNING,("SSReadWrite: WARNING!! Device is already stopped/removed!\n"));
  1088. Status = STATUS_DELETE_PENDING;
  1089. pIrp -> IoStatus.Information = 0;
  1090. goto SSReadWrite_Complete;
  1091. }
  1092. #if DBG
  1093. if (pIrpStack -> MajorFunction == IRP_MJ_READ) {
  1094. DebugTrace(TRACE_STATUS,("SSReadWrite: Read request received\n"));
  1095. } else {
  1096. DebugTrace(TRACE_STATUS,("SSReadWrite: Write request received\n"));
  1097. }
  1098. #endif
  1099. //
  1100. // Check if device is locked.
  1101. //
  1102. Owner = InterlockedCompareExchangePointer(&pde -> DeviceLock,
  1103. pIrpStack -> FileObject -> FsContext,
  1104. pIrpStack -> FileObject -> FsContext);
  1105. if (Owner != 0) {
  1106. if (Owner != pIrpStack -> FileObject -> FsContext) {
  1107. DebugTrace(TRACE_WARNING,("SSReadWrite: WARNING!! Device is locked\n"));
  1108. Status = STATUS_DEVICE_BUSY;
  1109. pIrp -> IoStatus.Information = 0;
  1110. goto SSReadWrite_Complete;
  1111. }
  1112. }
  1113. pMdl = pIrp -> MdlAddress;
  1114. //
  1115. // Allocate a SCSISCAN_CMD structure and initialize it.
  1116. //
  1117. pCmd = MyAllocatePool(NonPagedPool, sizeof(SCSISCAN_CMD));
  1118. if (NULL == pCmd) {
  1119. DebugTrace(TRACE_CRITICAL, ("SSReadWrite: ERROR!! cannot allocated SCSISCAN_CMD structure\n"));
  1120. DEBUG_BREAKPOINT();
  1121. pIrp->IoStatus.Information = 0;
  1122. Status = STATUS_INSUFFICIENT_RESOURCES;
  1123. goto SSReadWrite_Complete;
  1124. }
  1125. memset(pCmd,0, sizeof(SCSISCAN_CMD));
  1126. //
  1127. // Fill out SCSISCAN_CMD structure.
  1128. //
  1129. #if DBG
  1130. pCmd -> Reserved1 = 'dmCS';
  1131. #endif
  1132. pCmd -> Size = sizeof(SCSISCAN_CMD);
  1133. pCmd -> SrbFlags = SRB_FLAGS_DATA_IN;
  1134. pCmd -> CdbLength = 6;
  1135. pCmd -> SenseLength = SENSE_BUFFER_SIZE;
  1136. pCmd -> TransferLength = pIrpStack->Parameters.Read.Length;
  1137. pCmd -> pSenseBuffer = NULL;
  1138. //
  1139. // Point pSrbStatus to a reserved field in the SCSISCAN_CMD structure.
  1140. // The ReadFile / WriteFile code path never looks at it, but BuildTransferContext
  1141. // will complain if this pointer is NULL.
  1142. //
  1143. pCmd -> pSrbStatus = &(pCmd -> Reserved2);
  1144. //
  1145. // Set READ command anyways.
  1146. //
  1147. pCdb = (PCDB)pCmd -> Cdb;
  1148. pCdb -> CDB6READWRITE.OperationCode = SCSIOP_READ6;
  1149. //
  1150. // Set WRITE command if WriteFile called this function.
  1151. //
  1152. if (pIrpStack -> MajorFunction == IRP_MJ_WRITE) {
  1153. pCmd -> SrbFlags = SRB_FLAGS_DATA_OUT;
  1154. pCdb -> CDB6READWRITE.OperationCode = SCSIOP_WRITE6;
  1155. }
  1156. //
  1157. // Allocate a sense buffer.
  1158. //
  1159. pCmd -> pSenseBuffer = MyAllocatePool(NonPagedPool, SENSE_BUFFER_SIZE);
  1160. if (NULL == pCmd -> pSenseBuffer) {
  1161. DebugTrace(TRACE_CRITICAL, ("SSReadWrite: ERROR!! Cannot allocate sense buffer\n"));
  1162. DEBUG_BREAKPOINT();
  1163. pIrp->IoStatus.Information = 0;
  1164. Status = STATUS_INSUFFICIENT_RESOURCES;
  1165. goto SSReadWrite_Complete;
  1166. }
  1167. #if DBG
  1168. *(PULONG)(pCmd ->pSenseBuffer) = 'sneS';
  1169. #endif
  1170. //
  1171. // Build a transfer context.
  1172. //
  1173. pTransferContext = SSBuildTransferContext(pde, pIrp, pCmd, sizeof(SCSISCAN_CMD), pMdl, TRUE);
  1174. if (NULL == pTransferContext) {
  1175. DebugTrace(TRACE_ERROR,("SSReadWrite: ERROR!! Can't create transfer context!\n"));
  1176. DEBUG_BREAKPOINT();
  1177. MyFreePool(pCmd -> pSenseBuffer);
  1178. MyFreePool(pCmd);
  1179. pCmd = NULL;
  1180. pIrp -> IoStatus.Information = 0;
  1181. Status = STATUS_INSUFFICIENT_RESOURCES;
  1182. goto SSReadWrite_Complete;
  1183. }
  1184. //
  1185. // Fill in transfer length in the CDB.
  1186. //
  1187. pCdb -> PRINT.TransferLength[2] = ((PFOUR_BYTE)&(pTransferContext -> TransferLength)) -> Byte0;
  1188. pCdb -> PRINT.TransferLength[1] = ((PFOUR_BYTE)&(pTransferContext -> TransferLength)) -> Byte1;
  1189. pCdb -> PRINT.TransferLength[0] = ((PFOUR_BYTE)&(pTransferContext -> TransferLength)) -> Byte2;
  1190. //
  1191. // Save retry count in transfer context.
  1192. //
  1193. pTransferContext -> RetryCount = MAXIMUM_RETRIES;
  1194. //
  1195. // Mark IRP with status pending.
  1196. //
  1197. IoMarkIrpPending(pIrp);
  1198. //
  1199. // Set the completion routine and issue scanner request.
  1200. //
  1201. IoSetCompletionRoutine(pIrp, SSReadWriteIoComplete, pTransferContext, TRUE, TRUE, FALSE);
  1202. SSSendScannerRequest(pDeviceObject, pIrp, pTransferContext, FALSE);
  1203. DebugTrace(TRACE_PROC_LEAVE,("SSReadWrite: Leaving... Status=STATUS_PENDING\n"));
  1204. return STATUS_PENDING;
  1205. SSReadWrite_Complete:
  1206. //
  1207. // Free allocated command and sense buffers
  1208. //
  1209. if (pCmd ) {
  1210. if (pCmd -> pSenseBuffer) {
  1211. MyFreePool(pCmd -> pSenseBuffer);
  1212. }
  1213. MyFreePool(pCmd);
  1214. pCmd = NULL;
  1215. }
  1216. pIrp->IoStatus.Status = Status;
  1217. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  1218. SSDecrementIoCount( pDeviceObject );
  1219. DebugTrace(TRACE_PROC_LEAVE,("SSReadWrite: Leaving... Status=%x\n",Status));
  1220. return Status;
  1221. } // end SSReadWrite()
  1222. PTRANSFER_CONTEXT
  1223. SSBuildTransferContext(
  1224. PSCSISCAN_DEVICE_EXTENSION pde,
  1225. PIRP pIrp,
  1226. PSCSISCAN_CMD pCmd,
  1227. ULONG CmdLength,
  1228. PMDL pTransferMdl,
  1229. BOOLEAN AllowMultipleTransfer
  1230. )
  1231. /*++
  1232. Routine Description:
  1233. Arguments:
  1234. Return Value:
  1235. NULL if error
  1236. --*/
  1237. {
  1238. PMDL pSenseMdl;
  1239. PTRANSFER_CONTEXT pTransferContext;
  1240. PAGED_CODE();
  1241. DebugTrace(TRACE_PROC_ENTER,("SSBuildTransferContext: Enter...\n"));
  1242. //
  1243. // Initialize pointer
  1244. //
  1245. pTransferContext = NULL;
  1246. pSenseMdl = NULL;
  1247. //
  1248. // Validate the SCSISCAN_CMD structure.
  1249. //
  1250. if ( (0 == pCmd -> CdbLength) ||
  1251. (pCmd -> CdbLength > sizeof(pCmd -> Cdb)) )
  1252. {
  1253. DebugTrace(TRACE_WARNING,("SSBuildTransferContext: WARNING!! Badly formed SCSISCAN_CMD struture!\n"));
  1254. goto BuildTransferContext_Error;
  1255. }
  1256. #ifdef _WIN64
  1257. if(IoIs32bitProcess(pIrp)){
  1258. if(pCmd -> Size != sizeof(SCSISCAN_CMD_32)) {
  1259. DebugTrace(TRACE_WARNING,("SSBuildTransferContext: WARNING!! Badly formed SCSISCAN_CMD_32 struture!\n"));
  1260. goto BuildTransferContext_Error;
  1261. }
  1262. } else { // if(IoIs32bitProcess(pIrp))
  1263. #endif // _WIN64
  1264. if(pCmd -> Size != sizeof(SCSISCAN_CMD)){
  1265. DebugTrace(TRACE_WARNING,("SSBuildTransferContext: WARNING!! Badly formed SCSISCAN_CMD struture!\n"));
  1266. goto BuildTransferContext_Error;
  1267. }
  1268. #ifdef _WIN64
  1269. } // if(IoIs32bitProcess(pIrp))
  1270. #endif // _WIN64
  1271. //
  1272. // Verify that pSrbStatus is non-zero.
  1273. //
  1274. if (NULL == pCmd -> pSrbStatus) {
  1275. DebugTrace(TRACE_WARNING,("SSBuildTransferContext: WARNING!! NULL pointer for pSrbStatus!\n"));
  1276. goto BuildTransferContext_Error;
  1277. }
  1278. #if DBG
  1279. pCmd -> Reserved1 = 'dmCS';
  1280. #endif
  1281. //
  1282. // Verify that if TransferLength is non-zero, a transfer direction has also been specified.
  1283. //
  1284. if (0 != pCmd -> TransferLength) {
  1285. if (0 == (pCmd -> SrbFlags & (SRB_FLAGS_DATA_IN | SRB_FLAGS_DATA_OUT))) {
  1286. DebugTrace(TRACE_WARNING,("SSBuildTransferContext: WARNING!! Transfer length specified w/ no direction!\n"));
  1287. goto BuildTransferContext_Error;
  1288. }
  1289. }
  1290. //
  1291. // Verify that if the direction bits have been set, a transfer length has also be specified.
  1292. //
  1293. if (0 != (pCmd -> SrbFlags & (SRB_FLAGS_DATA_IN | SRB_FLAGS_DATA_OUT))) {
  1294. if (0 == pCmd -> TransferLength) {
  1295. DebugTrace(TRACE_WARNING,("SSBuildTransferContext: WARNING!! Direction bits is set w/ 0 transfer size!\n"));
  1296. goto BuildTransferContext_Error;
  1297. }
  1298. }
  1299. //
  1300. // Verify that if TransferLength is non-zero, then an associated MDL has also been specified.
  1301. // Also, verify that the transfer length does not exceed the transfer buffer size.
  1302. //
  1303. if (0 != pCmd -> TransferLength) {
  1304. if (NULL == pTransferMdl) {
  1305. DebugTrace(TRACE_WARNING,("SSBuildTransferContext: WARNING!! Non-zero transfer length w/ NULL buffer!\n"));
  1306. goto BuildTransferContext_Error;
  1307. }
  1308. if (pCmd -> TransferLength > MmGetMdlByteCount(pTransferMdl)) {
  1309. DebugTrace(TRACE_WARNING,("SSBuildTransferContext: WARNING!! Transfer length exceeds buffer size!\n"));
  1310. goto BuildTransferContext_Error;
  1311. }
  1312. }
  1313. //
  1314. // Verify that if SenseLength is non-zero, then pSenseBuffer is non-zero as well.
  1315. //
  1316. if (pCmd -> SenseLength) {
  1317. if (NULL == pCmd -> pSenseBuffer) {
  1318. DebugTrace(TRACE_WARNING,("SSBuildTransferContext: WARNING!! Non-zero sense length w/ NULL buffer!\n"));
  1319. goto BuildTransferContext_Error;
  1320. }
  1321. if (pCmd -> SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE) {
  1322. DebugTrace(TRACE_STATUS,("SSBuildTransferContext: Autosense disabled with NON-null sense buffer.\n"));
  1323. }
  1324. }
  1325. //
  1326. // Allocate transfer context
  1327. //
  1328. pTransferContext = MyAllocatePool(NonPagedPool, sizeof(TRANSFER_CONTEXT));
  1329. if (NULL == pTransferContext) {
  1330. DebugTrace(TRACE_CRITICAL,("SSBuildTransferContext: ERROR!! Failed to allocate transfer context\n"));
  1331. DEBUG_BREAKPOINT();
  1332. return NULL;
  1333. }
  1334. memset(pTransferContext, 0, sizeof(TRANSFER_CONTEXT));
  1335. #if DBG
  1336. pTransferContext -> Signature = 'refX';
  1337. #endif
  1338. pTransferContext -> pCmd = pCmd;
  1339. if (pCmd -> TransferLength) {
  1340. #ifdef WINNT
  1341. pTransferContext -> pTransferBuffer = MmGetMdlVirtualAddress(pTransferMdl);
  1342. #else
  1343. pTransferContext -> pTransferBuffer = MmGetSystemAddressForMdl(pTransferMdl);
  1344. #endif
  1345. if(NULL == pTransferContext -> pTransferBuffer){
  1346. DebugTrace(TRACE_ERROR,("SSBuildTransferContext: ERROR!! Failed to create address for MDL.\n"));
  1347. DEBUG_BREAKPOINT();
  1348. goto BuildTransferContext_Error;
  1349. }
  1350. pTransferContext -> RemainingTransferLength = pCmd -> TransferLength;
  1351. pTransferContext -> TransferLength = pCmd -> TransferLength;
  1352. //
  1353. // Adjust the transfer size to work within the limits of the hardware. Fail if the transfer is too
  1354. // big and the caller doesn't want the transfer to be split up.
  1355. //
  1356. SSAdjustTransferSize( pde, pTransferContext );
  1357. if (pTransferContext -> RemainingTransferLength !=
  1358. (LONG)pTransferContext -> TransferLength) {
  1359. if (!AllowMultipleTransfer) {
  1360. DebugTrace(TRACE_WARNING,("SSBuildTransferContext: WARNING!! Transfer exceeds hardware limits!\n"));
  1361. goto BuildTransferContext_Error;
  1362. }
  1363. }
  1364. }
  1365. pTransferContext -> pSenseBuffer = pCmd -> pSenseBuffer;
  1366. DebugTrace(TRACE_PROC_LEAVE,("SSBuildTransferContext: Leaving... Return=%x\n",pTransferContext));
  1367. return pTransferContext;
  1368. BuildTransferContext_Error:
  1369. if (pTransferContext) {
  1370. MyFreePool( pTransferContext );
  1371. }
  1372. DebugTrace(TRACE_PROC_LEAVE,("SSBuildTransferContext: Leaving... Return=NULL\n"));
  1373. return NULL;
  1374. } // end SSBuildTransferContext()
  1375. VOID
  1376. SSAdjustTransferSize(
  1377. PSCSISCAN_DEVICE_EXTENSION pde,
  1378. PTRANSFER_CONTEXT pTransferContext
  1379. )
  1380. /*++
  1381. Routine Description:
  1382. This is the entry called by the I/O system for scanner IO.
  1383. Arguments:
  1384. Return Value:
  1385. NT Status
  1386. --*/
  1387. {
  1388. ULONG MaxTransferLength;
  1389. ULONG nTransferPages;
  1390. PAGED_CODE();
  1391. MaxTransferLength = pde -> pAdapterDescriptor -> MaximumTransferLength;
  1392. //
  1393. // Make sure the transfer size does not exceed the limitations of the underlying hardware.
  1394. // If so, we will break the transfer up into chunks.
  1395. //
  1396. if (pTransferContext -> TransferLength > MaxTransferLength) {
  1397. DebugTrace(TRACE_STATUS,("Request size (0x%x) greater than maximum (0x%x)\n",
  1398. pTransferContext -> TransferLength,
  1399. MaxTransferLength));
  1400. pTransferContext -> TransferLength = MaxTransferLength;
  1401. }
  1402. //
  1403. // Calculate number of pages in this transfer.
  1404. //
  1405. nTransferPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(
  1406. pTransferContext -> pTransferBuffer,
  1407. pTransferContext -> TransferLength);
  1408. if (nTransferPages > pde -> pAdapterDescriptor -> MaximumPhysicalPages) {
  1409. DebugTrace(TRACE_STATUS,("Request number of pages (0x%x) greater than maximum (0x%x).\n",
  1410. nTransferPages,
  1411. pde -> pAdapterDescriptor -> MaximumPhysicalPages));
  1412. //
  1413. // Calculate maximum bytes to transfer that gaurantees that
  1414. // we will not exceed the maximum number of page breaks,
  1415. // assuming that the transfer may not be page alligned.
  1416. //
  1417. pTransferContext -> TransferLength = (pde -> pAdapterDescriptor -> MaximumPhysicalPages - 1) * PAGE_SIZE;
  1418. }
  1419. } // end SSAdjustTransferSize()
  1420. VOID
  1421. SSSetTransferLengthToCdb(
  1422. PCDB pCdb,
  1423. ULONG TransferLength
  1424. )
  1425. /*++
  1426. Routine Description:
  1427. Set transfer length to CDB due to its SCSI command.
  1428. Arguments:
  1429. pCdb - pointer to CDB
  1430. TransferLength - size of data to transfer
  1431. Return Value:
  1432. none
  1433. --*/
  1434. {
  1435. switch (pCdb->SEEK.OperationCode) {
  1436. case 0x24: // Scanner SetWindow command
  1437. case SCSIOP_READ_CAPACITY: // Scanner GetWindow command
  1438. case SCSIOP_READ: // Scanner Read command
  1439. case SCSIOP_WRITE: // Scanner Send Command
  1440. default: // All other commands
  1441. {
  1442. pCdb -> SEEK.Reserved2[2] = ((PFOUR_BYTE)&TransferLength) -> Byte0;
  1443. pCdb -> SEEK.Reserved2[1] = ((PFOUR_BYTE)&TransferLength) -> Byte1;
  1444. pCdb -> SEEK.Reserved2[0] = ((PFOUR_BYTE)&TransferLength) -> Byte2;
  1445. break;
  1446. }
  1447. case 0x34 : // Scanner GetDataBufferStatus Command
  1448. {
  1449. pCdb -> SEEK.Reserved2[2] = ((PFOUR_BYTE)&TransferLength) -> Byte0;
  1450. pCdb -> SEEK.Reserved2[1] = ((PFOUR_BYTE)&TransferLength) -> Byte1;
  1451. break;
  1452. }
  1453. }
  1454. } // end SSSetTransferLengthToCdb()
  1455. VOID
  1456. SSSendScannerRequest(
  1457. PDEVICE_OBJECT pDeviceObject,
  1458. PIRP pIrp,
  1459. PTRANSFER_CONTEXT pTransferContext,
  1460. BOOLEAN Retry
  1461. )
  1462. /*++
  1463. Routine Description:
  1464. Arguments:
  1465. Return Value:
  1466. None.
  1467. --*/
  1468. {
  1469. PSCSISCAN_DEVICE_EXTENSION pde;
  1470. PIO_STACK_LOCATION pIrpStack;
  1471. PIO_STACK_LOCATION pNextIrpStack;
  1472. PSRB pSrb;
  1473. PCDB pCdb;
  1474. PSCSISCAN_CMD pCmd;
  1475. DebugTrace(TRACE_PROC_ENTER,("SendScannerRequest pirp=0x%p TransferBuffer=0x%p\n", pIrp, pTransferContext->pTransferBuffer));
  1476. pde = (PSCSISCAN_DEVICE_EXTENSION)pDeviceObject -> DeviceExtension;
  1477. pIrpStack = IoGetCurrentIrpStackLocation( pIrp );
  1478. pNextIrpStack = IoGetNextIrpStackLocation( pIrp );
  1479. ASSERT(pTransferContext);
  1480. pSrb = &(pTransferContext -> Srb);
  1481. ASSERT(pSrb);
  1482. pCmd = pTransferContext -> pCmd;
  1483. ASSERT(pCmd);
  1484. //
  1485. // Write length to SRB.
  1486. //
  1487. pSrb -> Length = SCSI_REQUEST_BLOCK_SIZE;
  1488. //
  1489. // Set up IRP Address.
  1490. //
  1491. pSrb -> OriginalRequest = pIrp;
  1492. pSrb -> Function = SRB_FUNCTION_EXECUTE_SCSI;
  1493. pSrb -> DataBuffer = pTransferContext -> pTransferBuffer;
  1494. //
  1495. // Save byte count of transfer in SRB Extension.
  1496. //
  1497. pSrb -> DataTransferLength = pTransferContext -> TransferLength;
  1498. //
  1499. // Initialize the queue actions field.
  1500. //
  1501. pSrb -> QueueAction = SRB_SIMPLE_TAG_REQUEST;
  1502. //
  1503. // Queue sort key is not used.
  1504. //
  1505. pSrb -> QueueSortKey = 0;
  1506. //
  1507. // Indicate auto request sense by specifying buffer and size.
  1508. //
  1509. pSrb -> SenseInfoBuffer = pTransferContext -> pSenseBuffer;
  1510. pSrb -> SenseInfoBufferLength = pCmd -> SenseLength;
  1511. //
  1512. // Set timeout value in seconds.
  1513. //
  1514. pSrb -> TimeOutValue = pde -> TimeOutValue;
  1515. //
  1516. // Zero status fields
  1517. //
  1518. pSrb -> SrbStatus = pSrb -> ScsiStatus = 0;
  1519. pSrb -> NextSrb = 0;
  1520. //
  1521. // Get pointer to CDB in SRB.
  1522. //
  1523. pCdb = (PCDB)(pSrb -> Cdb);
  1524. //
  1525. // Set length of CDB.
  1526. //
  1527. pSrb -> CdbLength = pCmd -> CdbLength;
  1528. //
  1529. // Copy the user's CDB into our private CDB.
  1530. //
  1531. RtlCopyMemory(pCdb, pCmd -> Cdb, pCmd -> CdbLength);
  1532. //
  1533. // Set the srb flags.
  1534. //
  1535. pSrb -> SrbFlags = pCmd -> SrbFlags;
  1536. //
  1537. // Or in the default flags from the device object.
  1538. //
  1539. pSrb -> SrbFlags |= pde -> SrbFlags;
  1540. if (Retry) {
  1541. // Disable synchronous data transfers and
  1542. // disable tagged queuing. This fixes some errors.
  1543. DebugTrace(TRACE_STATUS,("SscsiScan :: Retrying \n"));
  1544. //
  1545. // Original code also added disable disconnect flag to SRB.
  1546. // That action would lock SCSI bus and in a case when paging drive is
  1547. // located on the same bus and scanner is taking long timeouts ( for example
  1548. // when it is mechanically locked) memory manager would hit timeout and
  1549. // bugcheck.
  1550. //
  1551. // pSrb -> SrbFlags |= SRB_FLAGS_DISABLE_DISCONNECT |
  1552. //
  1553. pSrb -> SrbFlags |= SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
  1554. pSrb -> SrbFlags &= ~SRB_FLAGS_QUEUE_ACTION_ENABLE;
  1555. DebugTrace(TRACE_STATUS,("SSSendScannerRequest: Retry branch .Srb flags=(0x%x) \n", pSrb -> SrbFlags));
  1556. pSrb -> QueueTag = SP_UNTAGGED;
  1557. }
  1558. //
  1559. // Set up major SCSI function.
  1560. //
  1561. pNextIrpStack -> MajorFunction = IRP_MJ_SCSI;
  1562. //
  1563. // Save SRB address in next stack for port driver.
  1564. //
  1565. pNextIrpStack -> Parameters.Scsi.Srb = pSrb;
  1566. //
  1567. // Print out SRB fields
  1568. //
  1569. // DebugTrace(MAX_TRACE,("SSSendScannerRequest: SRB ready. Flags=(%#X)Func=(%#x) DataLen=%d \nDataBuffer(16)=[%16s] \n",
  1570. DebugTrace(TRACE_STATUS,("SSSendScannerRequest: SRB ready. Flags=(%#X)Func=(%#x) DataLen=%d \nDataBuffer(16)=[%lx] \n",
  1571. pSrb -> SrbFlags ,pSrb -> Function,
  1572. pSrb -> DataTransferLength,
  1573. pSrb -> DataBuffer));
  1574. IoCallDriver(pde -> pStackDeviceObject, pIrp);
  1575. } // end SSSendScannerRequest()
  1576. NTSTATUS
  1577. SSReadWriteIoComplete(
  1578. IN PDEVICE_OBJECT pDeviceObject,
  1579. IN PIRP pIrp,
  1580. IN PTRANSFER_CONTEXT pTransferContext
  1581. )
  1582. /*++
  1583. Routine Description:
  1584. This routine executes when the port driver has completed a request.
  1585. It looks at the SRB status in the completing SRB and if not success
  1586. it checks for valid request sense buffer information. If valid, the
  1587. info is used to update status with more precise message of type of
  1588. error. This routine deallocates the SRB.
  1589. Arguments:
  1590. pDeviceObject - Supplies the device object which represents the logical
  1591. unit.
  1592. pIrp - Supplies the Irp which has completed.
  1593. Return Value:
  1594. NT status
  1595. --*/
  1596. {
  1597. PIO_STACK_LOCATION pIrpStack;
  1598. PIO_STACK_LOCATION pNextIrpStack;
  1599. NTSTATUS Status;
  1600. BOOLEAN Retry;
  1601. PSRB pSrb;
  1602. UCHAR SrbStatus;
  1603. PCDB pCdb;
  1604. PSCSISCAN_CMD pCmd;
  1605. DebugTrace(TRACE_PROC_ENTER,("ReadWriteIoComplete: Enter... IRP 0x%p.\n", pIrp));
  1606. ASSERT(NULL != pTransferContext);
  1607. //
  1608. // Initialize local.
  1609. //
  1610. Retry = FALSE;
  1611. pCdb = NULL;
  1612. pCmd = NULL;
  1613. pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  1614. pNextIrpStack = IoGetNextIrpStackLocation(pIrp);
  1615. Status = pIrp->IoStatus.Status;
  1616. pSrb = &(pTransferContext -> Srb);
  1617. SrbStatus = SRB_STATUS(pSrb -> SrbStatus);
  1618. if( (SrbStatus != SRB_STATUS_SUCCESS)
  1619. || (STATUS_SUCCESS != Status) )
  1620. {
  1621. DebugTrace(TRACE_ERROR,("ReadWriteIoComplete: ERROR!! Irp error. 0x%p SRB status:0x%p\n", Status, pSrb -> SrbStatus));
  1622. //
  1623. // Release the queue if it is frozen.
  1624. //
  1625. if (pSrb -> SrbStatus & SRB_STATUS_QUEUE_FROZEN) {
  1626. DebugTrace(TRACE_ERROR,("ReadWriteIoComplete: Release queue. IRP 0x%p.\n", pIrp));
  1627. ClassReleaseQueue(pDeviceObject);
  1628. }
  1629. Retry = ClassInterpretSenseInfo(
  1630. pDeviceObject,
  1631. pSrb,
  1632. pNextIrpStack->MajorFunction,
  1633. 0,
  1634. MAXIMUM_RETRIES - ((ULONG)(UINT_PTR)pIrpStack->Parameters.Others.Argument4),
  1635. &Status);
  1636. if (Retry && pTransferContext -> RetryCount--) {
  1637. DebugTrace(TRACE_STATUS,("ReadWriteIoComplete: Retry request 0x%p TransferBuffer=0x%p \n",
  1638. pIrp,pTransferContext->pTransferBuffer));
  1639. IoSetCompletionRoutine(pIrp, SSReadWriteIoComplete, pTransferContext, TRUE, TRUE, FALSE);
  1640. SSSendScannerRequest(pDeviceObject, pIrp, pTransferContext, TRUE);
  1641. return STATUS_MORE_PROCESSING_REQUIRED;
  1642. }
  1643. //
  1644. // If status is overrun, ignore it to support some bad devices.
  1645. //
  1646. if (SRB_STATUS_DATA_OVERRUN == SrbStatus) {
  1647. DebugTrace(TRACE_WARNING,("ReadWriteIoComplete: WARNING!! Data overrun IRP=0x%p. Ignoring...\n", pIrp));
  1648. pTransferContext -> NBytesTransferred += pSrb -> DataTransferLength;
  1649. Status = STATUS_SUCCESS;
  1650. } else {
  1651. DebugTrace(TRACE_STATUS,("ReadWriteIoComplete: Request failed. IRP 0x%p.\n", pIrp));
  1652. // DEBUG_BREAKPOINT();
  1653. pTransferContext -> NBytesTransferred = 0;
  1654. Status = STATUS_IO_DEVICE_ERROR;
  1655. }
  1656. } else {
  1657. pTransferContext -> NBytesTransferred += pSrb -> DataTransferLength;
  1658. pTransferContext -> RemainingTransferLength -= pSrb -> DataTransferLength;
  1659. pTransferContext -> pTransferBuffer += pSrb -> DataTransferLength;
  1660. if (pTransferContext -> RemainingTransferLength > 0) {
  1661. if ((LONG)(pTransferContext -> TransferLength) > pTransferContext -> RemainingTransferLength) {
  1662. pTransferContext -> TransferLength = pTransferContext -> RemainingTransferLength;
  1663. pCmd = pTransferContext -> pCmd;
  1664. pCdb = (PCDB)pCmd -> Cdb;
  1665. pCdb -> PRINT.TransferLength[2] = ((PFOUR_BYTE)&(pTransferContext -> TransferLength)) -> Byte0;
  1666. pCdb -> PRINT.TransferLength[1] = ((PFOUR_BYTE)&(pTransferContext -> TransferLength)) -> Byte1;
  1667. pCdb -> PRINT.TransferLength[0] = ((PFOUR_BYTE)&(pTransferContext -> TransferLength)) -> Byte2;
  1668. }
  1669. IoSetCompletionRoutine(pIrp, SSReadWriteIoComplete, pTransferContext, TRUE, TRUE, FALSE);
  1670. SSSendScannerRequest(pDeviceObject, pIrp, pTransferContext, FALSE);
  1671. return STATUS_MORE_PROCESSING_REQUIRED;
  1672. }
  1673. Status = STATUS_SUCCESS;
  1674. }
  1675. pIrp -> IoStatus.Information = pTransferContext -> NBytesTransferred;
  1676. MyFreePool(pTransferContext -> pCmd -> pSenseBuffer);
  1677. MyFreePool(pTransferContext -> pCmd);
  1678. MyFreePool(pTransferContext);
  1679. pIrp -> IoStatus.Status = Status;
  1680. SSDecrementIoCount( pDeviceObject );
  1681. return Status;
  1682. } // end SSReadWriteIoComplete()
  1683. NTSTATUS
  1684. SSIoctlIoComplete(
  1685. IN PDEVICE_OBJECT pDeviceObject,
  1686. IN PIRP pIrp,
  1687. IN PTRANSFER_CONTEXT pTransferContext
  1688. )
  1689. /*++
  1690. Routine Description:
  1691. This routine executes when an DevIoctl request has completed.
  1692. Arguments:
  1693. pDeviceObject - Supplies the device object which represents the logical
  1694. unit.
  1695. pIrp - Supplies the Irp which has completed.
  1696. pTransferContext - pointer to info about the request.
  1697. Return Value:
  1698. NT status
  1699. --*/
  1700. {
  1701. PIO_STACK_LOCATION pIrpStack;
  1702. NTSTATUS Status;
  1703. PSRB pSrb;
  1704. PSCSISCAN_CMD pCmd;
  1705. PCDB pCdb;
  1706. DebugTrace(TRACE_PROC_ENTER,("IoctlIoComplete: Enter... IRP=0x%p\n", pIrp));
  1707. ASSERT(NULL != pTransferContext);
  1708. pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  1709. pSrb = &(pTransferContext -> Srb);
  1710. pCmd = pTransferContext -> pCmd;
  1711. ASSERT(NULL != pCmd);
  1712. pCdb = NULL;
  1713. Status = pIrp->IoStatus.Status;
  1714. //
  1715. // Copy the SRB Status back into the user's SCSISCAN_CMD buffer.
  1716. //
  1717. *(pCmd -> pSrbStatus) = pSrb -> SrbStatus;
  1718. //
  1719. // If an error occurred on this transfer, release the frozen queue if necessary.
  1720. //
  1721. if( (SRB_STATUS(pSrb -> SrbStatus) != SRB_STATUS_SUCCESS)
  1722. || (STATUS_SUCCESS != Status) )
  1723. {
  1724. DebugTrace(TRACE_ERROR,("IoctlIoComplete: ERROR!! Irp error. Status=0x%x SRB status:0x%x\n", Status, pSrb -> SrbStatus));
  1725. if (pSrb -> SrbStatus & SRB_STATUS_QUEUE_FROZEN) {
  1726. DebugTrace(TRACE_ERROR,("IoctlIoComplete: Release queue. IRP 0x%p.\n", pIrp));
  1727. ClassReleaseQueue(pDeviceObject);
  1728. }
  1729. } else {
  1730. pTransferContext -> NBytesTransferred += pSrb -> DataTransferLength;
  1731. pTransferContext -> RemainingTransferLength -= pSrb -> DataTransferLength;
  1732. pTransferContext -> pTransferBuffer += pSrb -> DataTransferLength;
  1733. if (pTransferContext -> RemainingTransferLength > 0) {
  1734. if ((LONG)(pTransferContext -> TransferLength) > pTransferContext -> RemainingTransferLength) {
  1735. pTransferContext -> TransferLength = pTransferContext -> RemainingTransferLength;
  1736. pCmd = pTransferContext -> pCmd;
  1737. pCdb = (PCDB)pCmd -> Cdb;
  1738. //
  1739. // SCSISCAN only supports 10bytes CDB fragmentation.
  1740. //
  1741. ASSERT(pCmd->CdbLength == 10);
  1742. //
  1743. // Fill in transfer length in the CDB.
  1744. //
  1745. SSSetTransferLengthToCdb((PCDB)pCmd -> Cdb, pTransferContext -> TransferLength);
  1746. }
  1747. IoSetCompletionRoutine(pIrp, SSIoctlIoComplete, pTransferContext, TRUE, TRUE, FALSE);
  1748. SSSendScannerRequest(pDeviceObject, pIrp, pTransferContext, FALSE);
  1749. return STATUS_MORE_PROCESSING_REQUIRED;
  1750. }
  1751. Status = STATUS_SUCCESS;
  1752. }
  1753. //
  1754. // Clean up and return.
  1755. //
  1756. if (pTransferContext -> pSrbStatusMdl) {
  1757. MmUnlockPages(pTransferContext -> pSrbStatusMdl);
  1758. IoFreeMdl(pTransferContext -> pSrbStatusMdl);
  1759. //pTransferContext -> pSrbStatusMdl = NULL;
  1760. }
  1761. if (pTransferContext -> pSenseMdl) {
  1762. MmUnlockPages(pTransferContext -> pSenseMdl);
  1763. IoFreeMdl(pTransferContext -> pSenseMdl);
  1764. //pTransferContext -> pSenseMdl = NULL;
  1765. }
  1766. pIrp -> IoStatus.Information = pTransferContext -> NBytesTransferred;
  1767. pIrp -> IoStatus.Status = Status;
  1768. MyFreePool(pTransferContext);
  1769. SSDecrementIoCount( pDeviceObject );
  1770. return Status;
  1771. } // end SSIoctlIoComplete()
  1772. NTSTATUS
  1773. SSCreateSymbolicLink(
  1774. PSCSISCAN_DEVICE_EXTENSION pde
  1775. )
  1776. {
  1777. NTSTATUS Status;
  1778. UNICODE_STRING uName;
  1779. UNICODE_STRING uName2;
  1780. ANSI_STRING ansiName;
  1781. CHAR aName[32];
  1782. HANDLE hSwKey;
  1783. PAGED_CODE();
  1784. //
  1785. // Create the symbolic link for this device.
  1786. //
  1787. _snprintf(aName, sizeof(aName), "\\Device\\Scanner%d",pde -> DeviceInstance);
  1788. aName[ARRAYSIZE(aName)-1] = '\0';
  1789. RtlInitAnsiString(&ansiName, aName);
  1790. RtlAnsiStringToUnicodeString(&uName, &ansiName, TRUE);
  1791. _snprintf(aName, sizeof(aName), "\\DosDevices\\Scanner%d",pde -> DeviceInstance);
  1792. aName[ARRAYSIZE(aName)-1] = '\0';
  1793. RtlInitAnsiString(&ansiName, aName);
  1794. RtlAnsiStringToUnicodeString(&(pde -> SymbolicLinkName), &ansiName, TRUE);
  1795. Status = IoCreateSymbolicLink( &(pde -> SymbolicLinkName), &uName );
  1796. RtlFreeUnicodeString( &uName );
  1797. if (STATUS_SUCCESS != Status ) {
  1798. DebugTrace(MIN_TRACE,("Cannot create symbolic link.\n"));
  1799. DEBUG_BREAKPOINT();
  1800. Status = STATUS_NOT_SUPPORTED;
  1801. return Status;
  1802. }
  1803. //
  1804. // Now, stuff the symbolic link into the CreateFileName key so that STI can find the device.
  1805. //
  1806. IoOpenDeviceRegistryKey( pde -> pPhysicalDeviceObject,
  1807. PLUGPLAY_REGKEY_DRIVER, KEY_WRITE, &hSwKey);
  1808. RtlInitUnicodeString(&uName,L"CreateFileName");
  1809. _snprintf(aName, sizeof(aName), "\\\\.\\Scanner%d",pde -> DeviceInstance);
  1810. aName[ARRAYSIZE(aName)-1] = '\0';
  1811. RtlInitAnsiString(&ansiName, aName);
  1812. RtlAnsiStringToUnicodeString(&uName2, &ansiName, TRUE);
  1813. ZwSetValueKey(hSwKey,&uName,0,REG_SZ,uName2.Buffer,uName2.Length);
  1814. RtlFreeUnicodeString( &uName2 );
  1815. return STATUS_SUCCESS;
  1816. }
  1817. NTSTATUS
  1818. SSDestroySymbolicLink(
  1819. PSCSISCAN_DEVICE_EXTENSION pde
  1820. )
  1821. {
  1822. UNICODE_STRING uName;
  1823. UNICODE_STRING uName2;
  1824. ANSI_STRING ansiName;
  1825. CHAR aName[32];
  1826. HANDLE hSwKey;
  1827. PAGED_CODE();
  1828. DebugTrace(MIN_TRACE,("DestroySymbolicLink\n"));
  1829. //
  1830. // Delete the symbolic link to this device.
  1831. //
  1832. IoDeleteSymbolicLink( &(pde -> SymbolicLinkName) );
  1833. //
  1834. // Remove the CreateFile name from the s/w key.
  1835. //
  1836. IoOpenDeviceRegistryKey( pde -> pPhysicalDeviceObject,
  1837. PLUGPLAY_REGKEY_DRIVER, KEY_WRITE, &hSwKey);
  1838. RtlInitUnicodeString(&uName,L"CreateFileName");
  1839. memset(aName, 0, sizeof(aName));
  1840. RtlInitAnsiString(&ansiName, aName);
  1841. RtlAnsiStringToUnicodeString(&uName2, &ansiName, TRUE);
  1842. ZwSetValueKey(hSwKey,&uName,0,REG_SZ,uName2.Buffer,uName2.Length);
  1843. RtlFreeUnicodeString( &uName2 );
  1844. RtlFreeUnicodeString( &(pde -> SymbolicLinkName) );
  1845. ZwClose(hSwKey);
  1846. return STATUS_SUCCESS;
  1847. }
  1848. VOID
  1849. SSIncrementIoCount(
  1850. IN PDEVICE_OBJECT pDeviceObject
  1851. )
  1852. /*++
  1853. Routine Description:
  1854. Arguments:
  1855. Return Value:
  1856. --*/
  1857. {
  1858. PSCSISCAN_DEVICE_EXTENSION pde;
  1859. pde = (PSCSISCAN_DEVICE_EXTENSION)(pDeviceObject -> DeviceExtension);
  1860. InterlockedIncrement(&pde -> PendingIoCount);
  1861. }
  1862. LONG
  1863. SSDecrementIoCount(
  1864. IN PDEVICE_OBJECT pDeviceObject
  1865. )
  1866. /*++
  1867. Routine Description:
  1868. Arguments:
  1869. Return Value:
  1870. --*/
  1871. {
  1872. PSCSISCAN_DEVICE_EXTENSION pde;
  1873. LONG ioCount;
  1874. pde = (PSCSISCAN_DEVICE_EXTENSION)(pDeviceObject -> DeviceExtension);
  1875. ioCount = InterlockedDecrement(&pde -> PendingIoCount);
  1876. DebugTrace(TRACE_STATUS,("Pending io count = %x\n",ioCount));
  1877. if (0 == ioCount) {
  1878. KeSetEvent(&pde -> PendingIoEvent,
  1879. 1,
  1880. FALSE);
  1881. }
  1882. return ioCount;
  1883. }
  1884. NTSTATUS
  1885. SSDeferIrpCompletion(
  1886. IN PDEVICE_OBJECT pDeviceObject,
  1887. IN PIRP pIrp,
  1888. IN PVOID Context
  1889. )
  1890. /*++
  1891. Routine Description:
  1892. This routine is called when the port driver completes an IRP.
  1893. Arguments:
  1894. pDeviceObject - Pointer to the device object for the class device.
  1895. pIrp - Irp completed.
  1896. Context - Driver defined context.
  1897. Return Value:
  1898. The function value is the final status from the operation.
  1899. --*/
  1900. {
  1901. PKEVENT pEvent = Context;
  1902. KeSetEvent(pEvent,
  1903. 1,
  1904. FALSE);
  1905. return STATUS_MORE_PROCESSING_REQUIRED;
  1906. }
  1907. NTSTATUS
  1908. SSPower(
  1909. IN PDEVICE_OBJECT pDeviceObject,
  1910. IN PIRP pIrp
  1911. )
  1912. /*++
  1913. Routine Description:
  1914. Process the Power IRPs sent to the PDO for this device.
  1915. Arguments:
  1916. pDeviceObject - pointer to the functional device object (FDO) for this device.
  1917. pIrp - pointer to an I/O Request Packet
  1918. Return Value:
  1919. NT status code
  1920. --*/
  1921. {
  1922. NTSTATUS Status;
  1923. PSCSISCAN_DEVICE_EXTENSION pde;
  1924. PIO_STACK_LOCATION pIrpStack;
  1925. BOOLEAN hookIt = FALSE;
  1926. PAGED_CODE();
  1927. Status = STATUS_SUCCESS;
  1928. //
  1929. // Check arguments.
  1930. //
  1931. if( (NULL == pDeviceObject)
  1932. || (NULL == pDeviceObject->DeviceExtension)
  1933. || (NULL == pIrp) )
  1934. {
  1935. DebugTrace(TRACE_ERROR,("SSPower: ERROR!! Invalid parameter passed.\n"));
  1936. Status = STATUS_INVALID_PARAMETER;
  1937. DebugTrace(TRACE_PROC_LEAVE,("SSPower: Leaving.. Status = 0x%x.\n", Status));
  1938. return Status;
  1939. }
  1940. SSIncrementIoCount( pDeviceObject );
  1941. pde = (PSCSISCAN_DEVICE_EXTENSION)pDeviceObject -> DeviceExtension;
  1942. pIrpStack = IoGetCurrentIrpStackLocation( pIrp );
  1943. switch (pIrpStack -> MinorFunction) {
  1944. case IRP_MN_SET_POWER:
  1945. DebugTrace(MIN_TRACE,("IRP_MN_SET_POWER\n"));
  1946. PoStartNextPowerIrp(pIrp);
  1947. IoSkipCurrentIrpStackLocation(pIrp);
  1948. Status = PoCallDriver(pde -> pStackDeviceObject, pIrp);
  1949. SSDecrementIoCount(pDeviceObject);
  1950. break; /* IRP_MN_QUERY_POWER */
  1951. case IRP_MN_QUERY_POWER:
  1952. DebugTrace(MIN_TRACE,("IRP_MN_QUERY_POWER\n"));
  1953. PoStartNextPowerIrp(pIrp);
  1954. IoSkipCurrentIrpStackLocation(pIrp);
  1955. Status = PoCallDriver(pde -> pStackDeviceObject, pIrp);
  1956. SSDecrementIoCount(pDeviceObject);
  1957. break; /* IRP_MN_QUERY_POWER */
  1958. default:
  1959. DebugTrace(MIN_TRACE,("Unknown power message (%x)\n",pIrpStack->MinorFunction));
  1960. PoStartNextPowerIrp(pIrp);
  1961. IoSkipCurrentIrpStackLocation(pIrp);
  1962. Status = PoCallDriver(pde -> pStackDeviceObject, pIrp);
  1963. SSDecrementIoCount(pDeviceObject);
  1964. } /* irpStack->MinorFunction */
  1965. return Status;
  1966. }
  1967. VOID
  1968. SSUnload(
  1969. IN PDRIVER_OBJECT pDriverObject
  1970. )
  1971. /*++
  1972. Routine Description:
  1973. This routine is called when the driver is unloaded.
  1974. Arguments:
  1975. pDriverObject - Pointer to the driver object.evice object for the class device.
  1976. Return Value:
  1977. none.
  1978. --*/
  1979. {
  1980. PAGED_CODE();
  1981. DebugTrace(MIN_TRACE,("Driver unloaded.\n"));
  1982. }
  1983. NTSTATUS
  1984. ScsiScanHandleInterface(
  1985. PDEVICE_OBJECT DeviceObject,
  1986. PUNICODE_STRING InterfaceName,
  1987. BOOLEAN Create
  1988. )
  1989. /*++
  1990. Routine Description:
  1991. Arguments:
  1992. DeviceObject - Supplies the device object.
  1993. Return Value:
  1994. None.
  1995. --*/
  1996. {
  1997. NTSTATUS Status;
  1998. Status = STATUS_SUCCESS;
  1999. #ifndef _CHICAGO_
  2000. if (Create) {
  2001. Status=IoRegisterDeviceInterface(
  2002. DeviceObject,
  2003. &GUID_DEVINTERFACE_IMAGE,
  2004. NULL,
  2005. InterfaceName
  2006. );
  2007. DebugTrace(TRACE_STATUS,("Called IoRegisterDeviceInterface . Returned=0x%X\n",Status));
  2008. if (NT_SUCCESS(Status)) {
  2009. IoSetDeviceInterfaceState(
  2010. InterfaceName,
  2011. TRUE
  2012. );
  2013. DebugTrace(TRACE_STATUS,("Called IoSetDeviceInterfaceState(TRUE) . \n"));
  2014. }
  2015. } else {
  2016. if (InterfaceName->Buffer != NULL) {
  2017. IoSetDeviceInterfaceState(
  2018. InterfaceName,
  2019. FALSE
  2020. );
  2021. DebugTrace(TRACE_STATUS,("Called IoSetDeviceInterfaceState(FALSE) . \n"));
  2022. RtlFreeUnicodeString(
  2023. InterfaceName
  2024. );
  2025. InterfaceName->Buffer = NULL;
  2026. }
  2027. }
  2028. #endif // !_CHICAGO_
  2029. return Status;
  2030. }
  2031. NTSTATUS
  2032. SSCallNextDriverSynch(
  2033. IN PSCSISCAN_DEVICE_EXTENSION pde,
  2034. IN PIRP pIrp
  2035. )
  2036. /*++
  2037. Routine Description:
  2038. Calls lower driver and waits for result
  2039. Arguments:
  2040. DeviceExtension - pointer to device extension
  2041. Irp - pointer to IRP
  2042. Return Value:
  2043. none.
  2044. --*/
  2045. {
  2046. KEVENT Event;
  2047. PIO_STACK_LOCATION IrpStack;
  2048. NTSTATUS Status;
  2049. DebugTrace(TRACE_PROC_ENTER,("SSCallNextDriverSynch: Enter..\n"));
  2050. IrpStack = IoGetCurrentIrpStackLocation(pIrp);
  2051. //
  2052. // Copy IRP stack to the next.
  2053. //
  2054. IoCopyCurrentIrpStackLocationToNext(pIrp);
  2055. //
  2056. // Initialize synchronizing event.
  2057. //
  2058. KeInitializeEvent(&Event,
  2059. SynchronizationEvent,
  2060. FALSE);
  2061. //
  2062. // Set completion routine
  2063. //
  2064. IoSetCompletionRoutine(pIrp,
  2065. SSDeferIrpCompletion,
  2066. &Event,
  2067. TRUE,
  2068. TRUE,
  2069. TRUE);
  2070. //
  2071. // Call down
  2072. //
  2073. Status = IoCallDriver(pde -> pStackDeviceObject, pIrp);
  2074. if (Status == STATUS_PENDING) {
  2075. //
  2076. // Waiting for the completion.
  2077. //
  2078. DebugTrace(TRACE_STATUS,("SSCallNextDriverSynch: STATUS_PENDING. Wait for event.\n"));
  2079. KeWaitForSingleObject(&Event,
  2080. Executive,
  2081. KernelMode,
  2082. FALSE,
  2083. NULL);
  2084. Status = pIrp -> IoStatus.Status;
  2085. }
  2086. //
  2087. // Return
  2088. //
  2089. DebugTrace(TRACE_PROC_LEAVE,("SSCallNextDriverSynch: Leaving.. Status = %x\n", Status));
  2090. return (Status);
  2091. }