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.

389 lines
14 KiB

  1. //-------------------------------------------------------------------
  2. // This is driver object
  3. // It defines interface with specific system
  4. // Author: Sergey Ivanov
  5. // Log:
  6. // 06/08/99 - implemented
  7. //-------------------------------------------------------------------
  8. #include "driver.h"
  9. #ifdef WDM_KERNEL
  10. #pragma message("******** WDM build... ********")
  11. #endif
  12. #include "usbreader.h"
  13. // Walter Oney
  14. // @func Determine if we're running under Windows 98 or Windows 2000
  15. // @rdesc TRUE if running under Windows 98, FALSE if under Windows 2000
  16. // @comm This function calls IoIsWdmVersionAvailable to see if the OS
  17. // supports WDM version 1.10. Win98 and Win98 2d ed support 1.00, whereas
  18. // Win2K supports 1.10.
  19. #pragma PAGEDCODE
  20. BOOLEAN GENERIC_EXPORT isWin98()
  21. { // IsWin98
  22. #ifdef _X86_
  23. return !IoIsWdmVersionAvailable(1, 0x10);
  24. #else
  25. return FALSE;
  26. #endif // _X86_
  27. }// IsWin98
  28. #pragma LOCKEDCODE
  29. #if DEBUG && defined(_X86_)
  30. extern "C" VOID __declspec(naked) __cdecl _chkesp()
  31. {
  32. _asm je okay
  33. ASSERT(!DRIVERNAME " - Stack pointer mismatch!");
  34. okay:
  35. _asm ret
  36. }
  37. #endif // DBG
  38. // This will fix some linker problem
  39. int __cdecl _purecall(VOID) {return 0;};
  40. #pragma LOCKEDDATA
  41. BOOLEAN SystemWin98 = TRUE;
  42. ULONG ObjectCounter = 0;
  43. #pragma INITCODE
  44. // Driver main entry...(Actually, it could have any name...)
  45. NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath)
  46. {
  47. DBG_PRINT ("\n");
  48. DBG_PRINT ("*** DriverEntry: DriverObject %8.8lX ***\n", DriverObject);
  49. if(SystemWin98 = isWin98())
  50. {
  51. DBG_PRINT("======== WINDOWS 98 DETECTED ========\n");
  52. }
  53. else
  54. DBG_PRINT("======== WINDOWS 2000 DETECTED ========\n");
  55. // Create driver kernel...
  56. #pragma message("********** Compiling WDM driver version *********")
  57. DBG_PRINT (" Loading WDM kernel\n");
  58. kernel = CKernel::loadWDMKernel();
  59. if(!kernel)
  60. {
  61. // LOG ERROR!
  62. DBG_PRINT ("ERROR: At loading WDM kernel! ***\n");
  63. return STATUS_UNSUCCESSFUL;
  64. }
  65. DBG_PRINT (" Creating unicode string for registry path...\n");
  66. kernel->RegistryPath = new (NonPagedPool)CUString(RegistryPath);
  67. if (!ALLOCATED_OK(kernel->RegistryPath))
  68. {
  69. // LOG ERROR!
  70. DISPOSE_OBJECT(kernel->RegistryPath);
  71. DISPOSE_OBJECT(kernel);
  72. DBG_PRINT ("ERROR: At allocating WDM registry path! ***\n");
  73. return STATUS_UNSUCCESSFUL;
  74. }
  75. DBG_PRINT (" Registering WDM system callbacks\n");
  76. DriverObject->DriverExtension->AddDevice = WDM_AddDevice;
  77. DriverObject->DriverUnload = WDM_Unload;
  78. DriverObject->MajorFunction[IRP_MJ_CREATE] = open;
  79. DriverObject->MajorFunction[IRP_MJ_CLOSE] = close;
  80. DriverObject->MajorFunction[IRP_MJ_WRITE] = write;
  81. DriverObject->MajorFunction[IRP_MJ_READ] = read;
  82. // The mechanism for handling read and write requests for a device that uses
  83. // interrupts includes a Start I/O routine, an interrupt service routine, and
  84. // a deferred procedure call routine that finishes handling interrupts. We
  85. // need to supply the StartIo routine address here.
  86. //DriverObject->DriverStartIo = startIo;
  87. DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = WDM_SystemControl;
  88. DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = deviceControl;
  89. DriverObject->MajorFunction[IRP_MJ_PNP] = pnpRequest;
  90. DriverObject->MajorFunction[IRP_MJ_POWER] = powerRequest;
  91. DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = flush;
  92. DriverObject->MajorFunction[IRP_MJ_CLEANUP] = cleanup;
  93. DBG_PRINT ("**** Driver was initialized successfully! ****\n");
  94. return STATUS_SUCCESS;
  95. }
  96. NTSTATUS
  97. WDM_SystemControl(
  98. PDEVICE_OBJECT DeviceObject,
  99. PIRP Irp
  100. )
  101. {
  102. NTSTATUS status = STATUS_SUCCESS;
  103. CDevice *device;
  104. device = kernel->getRegisteredDevice(DeviceObject);
  105. IoSkipCurrentIrpStackLocation(Irp);
  106. status = IoCallDriver(device->getLowerDriver(), Irp);
  107. return status;
  108. }
  109. #pragma PAGEDCODE
  110. VOID WDM_Unload(IN PDRIVER_OBJECT DriverObject)
  111. {
  112. PAGED_CODE();
  113. DBG_PRINT ("\n*** Unload: Driver %8.8lX ***\n", DriverObject);
  114. kernel->dispose();
  115. DBG_PRINT("*** Object counter before unload %d\n",ObjectCounter);
  116. DBG_PRINT (">>>>>>> All active devices were removed! Driver was unloaded! <<<<<<\n");
  117. }
  118. #pragma PAGEDCODE
  119. // C wrapper functions for driver object
  120. LONG WDM_AddDevice(IN PDRIVER_OBJECT DriverObject,IN PDEVICE_OBJECT DeviceObject)
  121. {
  122. NTSTATUS status = STATUS_UNSUCCESSFUL;
  123. // Get registry about device type installation
  124. // switch depends of device.
  125. // Create device object
  126. // Check device type and create device specific objects
  127. // like serial, usb, PCMCIA and so on...
  128. // Specific objects can overwrite base class functions.
  129. // For now we will create USB device object
  130. //TODO recognize device type dinamically...
  131. #pragma message("********** Compiling USB READER driver version *********")
  132. //status = WDM_Add_USBDevice(DriverObject,DeviceObject);
  133. DBG_PRINT ("Adding USB reader...\n");
  134. status = WDM_Add_USBReader(DriverObject,DeviceObject);
  135. return status;
  136. }
  137. // We decided to support different devices at system...
  138. // It requires to have different callback functions for different devices.
  139. // So let's create wrappers and redirect requests to specific devices.
  140. // CALLBACK WRAPPER FUNCTIONS
  141. // This callbacks should be defined at any device object
  142. #pragma LOCKEDCODE
  143. IMPLEMENT_CALLBACK_LONG1(open,IN PIRP);
  144. IMPLEMENT_CALLBACK_LONG1(close,IN PIRP);
  145. IMPLEMENT_CALLBACK_LONG1(read,IN PIRP);
  146. IMPLEMENT_CALLBACK_LONG1(write,IN PIRP);
  147. IMPLEMENT_CALLBACK_VOID1(startIo,IN PIRP);
  148. IMPLEMENT_CALLBACK_LONG1(deviceControl,IN PIRP);
  149. IMPLEMENT_CALLBACK_LONG1(flush,IN PIRP);
  150. IMPLEMENT_CALLBACK_LONG1(cleanup,IN PIRP);
  151. IMPLEMENT_CALLBACK_LONG1(powerRequest,IN PIRP);
  152. // Support callbacks
  153. IMPLEMENT_CALLBACK_VOID1(cancelPendingIrp,IN PIRP);
  154. #pragma LOCKEDCODE
  155. NTSTATUS pnpRequest(IN PDEVICE_OBJECT fdo,IN PIRP Irp)
  156. {
  157. CDevice* device;
  158. //CUSBReader* device;// TO CHANGE LATER....
  159. NTSTATUS status;
  160. PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
  161. ULONG MinorFunction = stack->MinorFunction;
  162. //device = (CUSBReader*) kernel->getRegisteredDevice(fdo);// TO CHANGE LATER....
  163. device = kernel->getRegisteredDevice(fdo);// TO CHANGE LATER....
  164. if(!device)
  165. {
  166. DBG_PRINT ("*** PnP: Device was already removed...***\n");
  167. Irp->IoStatus.Status = STATUS_INVALID_DEVICE_STATE;
  168. Irp->IoStatus.Information = 0;
  169. ::IoCompleteRequest(Irp,IO_NO_INCREMENT);
  170. return STATUS_INVALID_DEVICE_STATE;
  171. }
  172. status = device->pnpRequest(Irp);
  173. if(MinorFunction == IRP_MN_REMOVE_DEVICE)
  174. {
  175. //Child devices will be removed by BUS...
  176. if(device->getObjectType()!= CHILD_DEVICE)
  177. {
  178. PDEVICE_OBJECT DeviceObject = device->getSystemObject();
  179. // Sometimes Unload can interrupt standard PnP sequence
  180. // and remove device before we finish...
  181. DBG_PRINT ("*** PnP: Disposing device -> %8.8lX ***\n", device);
  182. device->dispose();
  183. if(DeviceObject)
  184. {
  185. DBG_PRINT("Deleting device object %8.8lX from system...\n",DeviceObject);
  186. DBG_PRINT("<<<<< OBJECT REFERENCE COUNT ON REMOVE %d\n",DeviceObject->ReferenceCount);
  187. IoDeleteDevice(DeviceObject);
  188. }
  189. }
  190. }
  191. return status;
  192. }
  193. #pragma PAGEDCODE
  194. LONG WDM_Add_USBReader(IN PDRIVER_OBJECT DriverObject,IN PDEVICE_OBJECT DeviceObject)
  195. {
  196. NTSTATUS status;
  197. WCHAR wcTemp[256];
  198. ULONG junk;
  199. CLogger* logger = kernel->getLogger();
  200. DBG_PRINT("*** AddDevice: DriverObject %8.8lX, DeviceObject %8.8lX ***\n", DriverObject, DeviceObject);
  201. DBG_PRINT(" Creating WDM USB reader...\n");
  202. CUSBReader* reader = kernel->createUSBReader();
  203. if(ALLOCATED_OK(reader))
  204. {
  205. reader->acquireRemoveLock();
  206. DBG_PRINT ("Call USB reader object to add the reader...\n");
  207. status = reader->add(DriverObject,DeviceObject);
  208. if(!NT_SUCCESS(status))
  209. {
  210. DBG_PRINT ("###### Add() reports error! Disposing reader...\n");
  211. reader->dispose();
  212. return status;
  213. }
  214. else//Register our device object and device class
  215. {
  216. DBG_PRINT (" Registering new reader %8.8lX at kernel...\n",reader);
  217. //kernel->registerObject(reader->getSystemObject(),(CDevice*)reader);
  218. kernel->registerObject(reader->getSystemObject(),(CUSBReader*)reader);
  219. }
  220. {
  221. CUString* ustrTmp;
  222. ANSI_STRING astrTmp;
  223. UNICODE_STRING valname;
  224. ULONG size = 0;
  225. HANDLE hkey;
  226. DBG_PRINT ("=====================================================\n");
  227. // Set default values..
  228. reader->setVendorName("Gemplus",sizeof("Gemplus"));
  229. reader->setDeviceType("GemPC430",sizeof("GemPC430"));
  230. // Get Hardware ID
  231. status = IoGetDeviceProperty(DeviceObject, DevicePropertyHardwareID, sizeof(wcTemp), wcTemp, &junk);
  232. if(NT_SUCCESS(status))
  233. {
  234. DBG_PRINT(" Device Hardware ID - %ws\n", wcTemp);
  235. }
  236. status = IoGetDeviceProperty(DeviceObject, DevicePropertyDeviceDescription, sizeof(wcTemp), wcTemp, &junk);
  237. if(NT_SUCCESS(status))
  238. {
  239. DBG_PRINT(" Device description - %ws\n", wcTemp);
  240. }
  241. status = IoGetDeviceProperty(DeviceObject, DevicePropertyManufacturer, sizeof(wcTemp), wcTemp, &junk);
  242. if(NT_SUCCESS(status))
  243. {
  244. DBG_PRINT(" Device Manufacturer - %ws\n", wcTemp);
  245. }
  246. // Get OEM IfdType if present
  247. status = IoOpenDeviceRegistryKey(DeviceObject, PLUGPLAY_REGKEY_DEVICE, KEY_READ, &hkey);
  248. if (NT_SUCCESS(status))
  249. {
  250. // Get Vendor name...
  251. RtlInitUnicodeString(&valname, L"VendorName");
  252. size = 0;
  253. status = ZwQueryValueKey(hkey, &valname, KeyValuePartialInformation, NULL, 0, &size);
  254. if (status != STATUS_OBJECT_NAME_NOT_FOUND && size)
  255. {
  256. PKEY_VALUE_PARTIAL_INFORMATION vpip = (PKEY_VALUE_PARTIAL_INFORMATION) ExAllocatePool(NonPagedPool, size);
  257. if(vpip)
  258. {
  259. status = ZwQueryValueKey(hkey, &valname, KeyValuePartialInformation, vpip, size, &size);
  260. if (NT_SUCCESS(status))
  261. {
  262. DBG_PRINT(" OEM Vendor name found - '%ws' \n", vpip->Data);
  263. // Copy string into the driver...
  264. ustrTmp = new(NonPagedPool) CUString((PWCHAR)vpip->Data);
  265. if(ALLOCATED_OK(ustrTmp))
  266. {
  267. RtlUnicodeStringToAnsiString(&astrTmp,&ustrTmp->m_String,TRUE);
  268. reader->setVendorName(astrTmp.Buffer,astrTmp.Length);
  269. RtlFreeAnsiString(&astrTmp);
  270. }
  271. DISPOSE_OBJECT(ustrTmp);
  272. }
  273. ExFreePool(vpip);
  274. }
  275. }
  276. // Get IfdType...
  277. RtlInitUnicodeString(&valname, L"IfdType");
  278. size = 0;
  279. status = ZwQueryValueKey(hkey, &valname, KeyValuePartialInformation, NULL, 0, &size);
  280. if (status != STATUS_OBJECT_NAME_NOT_FOUND && size)
  281. {
  282. PKEY_VALUE_PARTIAL_INFORMATION vpip = (PKEY_VALUE_PARTIAL_INFORMATION) ExAllocatePool(NonPagedPool, size);
  283. if(vpip)
  284. {
  285. status = ZwQueryValueKey(hkey, &valname, KeyValuePartialInformation, vpip, size, &size);
  286. if (NT_SUCCESS(status))
  287. {
  288. DBG_PRINT(" OEM IfdType found - '%ws' \n", vpip->Data);
  289. // Copy string into the driver...
  290. ustrTmp = new(NonPagedPool) CUString((PWCHAR)vpip->Data);
  291. if(ALLOCATED_OK(ustrTmp))
  292. {
  293. RtlUnicodeStringToAnsiString(&astrTmp,&ustrTmp->m_String,TRUE);
  294. reader->setDeviceType(astrTmp.Buffer,astrTmp.Length);
  295. RtlFreeAnsiString(&astrTmp);
  296. }
  297. DISPOSE_OBJECT(ustrTmp);
  298. }
  299. ExFreePool(vpip);
  300. }
  301. }
  302. ZwClose(hkey);
  303. }
  304. DBG_PRINT ("=====================================================\n");
  305. }
  306. status = STATUS_SUCCESS;
  307. DBG_PRINT("**** Initializing SmartCardSystem... ****\n");
  308. reader->initializeSmartCardSystem();
  309. DBG_PRINT("**** Creating reader interface type %d, protocol %d ****\n",READER_INTERFACE_GEMCORE,READER_PROTOCOL_LV);
  310. if(!reader->createInterface(READER_INTERFACE_GEMCORE,READER_PROTOCOL_LV,reader))
  311. {
  312. DBG_PRINT("**** Failed to create reader interface... ****\n");
  313. if(ALLOCATED_OK(logger)) logger->logEvent(GRCLASS_FAILED_TO_CREATE_INTERFACE,DeviceObject);
  314. //Close and unregister reader...
  315. reader->dispose();
  316. return STATUS_UNSUCCESSFUL;
  317. }
  318. DBG_PRINT("**** USB reader successfuly loaded! ****\n");
  319. reader->releaseRemoveLock();
  320. //if(ALLOCATED_OK(logger)) logger->logEvent(GRCLASS_START_OK, reader->getSystemObject());
  321. return status;
  322. }
  323. else
  324. {
  325. DISPOSE_OBJECT(reader);
  326. DBG_PRINT("#### Failed to create USB reader...\n");
  327. if(ALLOCATED_OK(logger)) logger->logEvent(GRCLASS_FAILED_TO_CREATE_READER,DeviceObject);
  328. }
  329. return STATUS_UNSUCCESSFUL;
  330. }