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.

423 lines
11 KiB

  1. /*--------------------------------------------------------------------------
  2. *
  3. * Copyright (C) Cyclades Corporation, 2000-2001.
  4. * All rights reserved.
  5. *
  6. * Cyclades-Z Enumerator Driver
  7. *
  8. * This file: cyclad-z.c
  9. *
  10. * Description: This module contains contains the entry points
  11. * for a standard bus PNP / WDM driver.
  12. *
  13. * Notes: This code supports Windows 2000 and Windows XP,
  14. * x86 and ia64 processors.
  15. *
  16. * Complies with Cyclades SW Coding Standard rev 1.3.
  17. *
  18. *--------------------------------------------------------------------------
  19. */
  20. /*-------------------------------------------------------------------------
  21. *
  22. * Change History
  23. *
  24. *--------------------------------------------------------------------------
  25. * Initial implementation based on Microsoft sample code.
  26. *
  27. *--------------------------------------------------------------------------
  28. */
  29. #include "pch.h"
  30. //
  31. // Declare some entry functions as pageable, and make DriverEntry
  32. // discardable
  33. //
  34. NTSTATUS DriverEntry(PDRIVER_OBJECT, PUNICODE_STRING);
  35. #ifdef ALLOC_PRAGMA
  36. #pragma alloc_text(INIT, DriverEntry)
  37. #pragma alloc_text(PAGE, Cycladz_DriverUnload)
  38. #endif
  39. NTSTATUS
  40. DriverEntry (
  41. IN PDRIVER_OBJECT DriverObject,
  42. IN PUNICODE_STRING UniRegistryPath
  43. )
  44. /*++
  45. Routine Description:
  46. Initialize the entry points of the driver.
  47. --*/
  48. {
  49. ULONG i;
  50. PRTL_QUERY_REGISTRY_TABLE QueryTable = NULL;
  51. ULONG breakOnEntryDefault = FALSE;
  52. ULONG shouldBreakOnEntry = FALSE;
  53. UNREFERENCED_PARAMETER (UniRegistryPath);
  54. Cycladz_KdPrint_Def (SER_DBG_SS_TRACE, ("Driver Entry\n"));
  55. Cycladz_KdPrint_Def (SER_DBG_SS_TRACE, ("RegPath: %x\n", UniRegistryPath));
  56. //
  57. // Get the BreakOnEntry from the registry
  58. //
  59. if (NULL == (QueryTable = ExAllocatePool(
  60. PagedPool,
  61. sizeof(RTL_QUERY_REGISTRY_TABLE)*2
  62. ))) {
  63. Cycladz_KdPrint_Def (SER_DBG_PNP_ERROR,
  64. ("Failed to allocate memory to query registry\n"));
  65. } else {
  66. RtlZeroMemory(
  67. QueryTable,
  68. sizeof(RTL_QUERY_REGISTRY_TABLE)*2
  69. );
  70. QueryTable[0].QueryRoutine = NULL;
  71. QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
  72. QueryTable[0].EntryContext = &shouldBreakOnEntry;
  73. QueryTable[0].Name = L"BreakOnEntry";
  74. QueryTable[0].DefaultType = REG_DWORD;
  75. QueryTable[0].DefaultData = &breakOnEntryDefault;
  76. QueryTable[0].DefaultLength= sizeof(ULONG);
  77. // BUGBUG: The rest of the table isn't filled in!
  78. if (!NT_SUCCESS(RtlQueryRegistryValues(
  79. RTL_REGISTRY_SERVICES,
  80. L"cyclad-z",
  81. QueryTable,
  82. NULL,
  83. NULL))) {
  84. Cycladz_KdPrint_Def (SER_DBG_PNP_ERROR,
  85. ("Failed to get BreakOnEntry level from registry. Using default\n"));
  86. shouldBreakOnEntry = breakOnEntryDefault;
  87. }
  88. ExFreePool( QueryTable );
  89. }
  90. if (shouldBreakOnEntry) {
  91. DbgBreakPoint();
  92. }
  93. DriverObject->MajorFunction [IRP_MJ_CREATE] =
  94. DriverObject->MajorFunction [IRP_MJ_CLOSE] = Cycladz_CreateClose;
  95. DriverObject->MajorFunction [IRP_MJ_PNP] = Cycladz_PnP;
  96. DriverObject->MajorFunction [IRP_MJ_POWER] = Cycladz_Power;
  97. DriverObject->MajorFunction [IRP_MJ_DEVICE_CONTROL] = Cycladz_IoCtl;
  98. DriverObject->MajorFunction [IRP_MJ_SYSTEM_CONTROL] = Cycladz_DispatchPassThrough;
  99. DriverObject->DriverUnload = Cycladz_DriverUnload;
  100. DriverObject->DriverExtension->AddDevice = Cycladz_AddDevice;
  101. return STATUS_SUCCESS;
  102. }
  103. NTSTATUS
  104. CycladzSyncCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp,
  105. IN PKEVENT CycladzSyncEvent)
  106. {
  107. UNREFERENCED_PARAMETER(DeviceObject);
  108. UNREFERENCED_PARAMETER(Irp);
  109. KeSetEvent(CycladzSyncEvent, IO_NO_INCREMENT, FALSE);
  110. return STATUS_MORE_PROCESSING_REQUIRED;
  111. }
  112. NTSTATUS
  113. Cycladz_CreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
  114. /*++
  115. Routine Description:
  116. Some outside source is trying to create a file against us.
  117. If this is for the FDO (the bus itself) then the caller is trying to
  118. open the propriatary conection to tell us which serial port to enumerate.
  119. If this is for the PDO (an object on the bus) then this is a client that
  120. wishes to use the serial port.
  121. --*/
  122. {
  123. PIO_STACK_LOCATION irpStack;
  124. NTSTATUS status;
  125. PFDO_DEVICE_DATA fdoData;
  126. KEVENT completionEvent;
  127. PDEVICE_OBJECT pNextDevice;
  128. UNREFERENCED_PARAMETER(DeviceObject);
  129. status = STATUS_INVALID_DEVICE_REQUEST;
  130. Irp->IoStatus.Information = 0;
  131. fdoData = DeviceObject->DeviceExtension;
  132. if (fdoData->IsFDO) {
  133. if (fdoData->DevicePnPState == Deleted){
  134. status = STATUS_DELETE_PENDING;
  135. } else {
  136. irpStack = IoGetCurrentIrpStackLocation(Irp);
  137. switch (irpStack->MajorFunction) {
  138. case IRP_MJ_CREATE:
  139. Cycladz_KdPrint_Def(SER_DBG_SS_TRACE, ("Create"));
  140. if ((fdoData->DevicePnPState == RemovePending) ||
  141. (fdoData->DevicePnPState == SurpriseRemovePending)) {
  142. status = STATUS_DELETE_PENDING;
  143. } else {
  144. status = STATUS_SUCCESS;
  145. }
  146. break;
  147. case IRP_MJ_CLOSE:
  148. Cycladz_KdPrint_Def (SER_DBG_SS_TRACE, ("Close \n"));
  149. status = STATUS_SUCCESS;
  150. break;
  151. }
  152. }
  153. }
  154. Irp->IoStatus.Status = status;
  155. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  156. return status;
  157. }
  158. NTSTATUS
  159. Cycladz_IoCtl (
  160. IN PDEVICE_OBJECT DeviceObject,
  161. IN PIRP Irp
  162. )
  163. /*++
  164. Routine Description:
  165. --*/
  166. {
  167. PIO_STACK_LOCATION irpStack;
  168. NTSTATUS status;
  169. PCOMMON_DEVICE_DATA commonData;
  170. PFDO_DEVICE_DATA fdoData;
  171. Cycladz_KdPrint_Def (SER_DBG_IOCTL_TRACE, ("Cycladz_IoCtl\n"));
  172. status = STATUS_SUCCESS;
  173. irpStack = IoGetCurrentIrpStackLocation (Irp);
  174. ASSERT (IRP_MJ_DEVICE_CONTROL == irpStack->MajorFunction);
  175. commonData = (PCOMMON_DEVICE_DATA) DeviceObject->DeviceExtension;
  176. fdoData = (PFDO_DEVICE_DATA) DeviceObject->DeviceExtension;
  177. //
  178. // We only take Device Control requests for the FDO.
  179. // That is the bus itself.
  180. if (!commonData->IsFDO) {
  181. //
  182. // These commands are only allowed to go to the FDO.
  183. //
  184. status = STATUS_INVALID_DEVICE_REQUEST;
  185. Irp->IoStatus.Status = status;
  186. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  187. return status;
  188. }
  189. status = Cycladz_IncIoCount (fdoData);
  190. if (!NT_SUCCESS (status)) {
  191. //
  192. // This bus has received the PlugPlay remove IRP. It will no longer
  193. // respond to external requests.
  194. //
  195. Irp->IoStatus.Status = status;
  196. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  197. return status;
  198. }
  199. // Actually, we don't handle any Ioctl.
  200. status = STATUS_INVALID_DEVICE_REQUEST;
  201. Cycladz_DecIoCount (fdoData);
  202. Irp->IoStatus.Status = status;
  203. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  204. return status;
  205. }
  206. VOID
  207. Cycladz_DriverUnload (
  208. IN PDRIVER_OBJECT Driver
  209. )
  210. /*++
  211. Routine Description:
  212. Clean up everything we did in driver entry.
  213. --*/
  214. {
  215. UNREFERENCED_PARAMETER (Driver);
  216. PAGED_CODE();
  217. //
  218. // All the device objects should be gone.
  219. //
  220. ASSERT (NULL == Driver->DeviceObject);
  221. //
  222. // Here we free any resources allocated in DriverEntry
  223. //
  224. return;
  225. }
  226. NTSTATUS
  227. Cycladz_IncIoCount (
  228. PFDO_DEVICE_DATA Data
  229. )
  230. {
  231. InterlockedIncrement (&Data->OutstandingIO);
  232. if (Data->DevicePnPState == Deleted) {
  233. if (0 == InterlockedDecrement (&Data->OutstandingIO)) {
  234. KeSetEvent (&Data->RemoveEvent, 0, FALSE);
  235. }
  236. return STATUS_DELETE_PENDING;
  237. }
  238. return STATUS_SUCCESS;
  239. }
  240. VOID
  241. Cycladz_DecIoCount (
  242. PFDO_DEVICE_DATA Data
  243. )
  244. {
  245. if (0 == InterlockedDecrement (&Data->OutstandingIO)) {
  246. KeSetEvent (&Data->RemoveEvent, 0, FALSE);
  247. }
  248. }
  249. NTSTATUS
  250. Cycladz_DispatchPassThrough(
  251. IN PDEVICE_OBJECT DeviceObject,
  252. IN PIRP Irp
  253. )
  254. /*++
  255. Routine Description:
  256. Passes a request on to the lower driver.
  257. --*/
  258. {
  259. PIO_STACK_LOCATION IrpStack =
  260. IoGetCurrentIrpStackLocation( Irp );
  261. #if 1
  262. Cycladz_KdPrint_Def (SER_DBG_SS_TRACE, (
  263. "[Cycladz_DispatchPassThrough] "
  264. "IRP: %8x; "
  265. "MajorFunction: %d\n",
  266. Irp,
  267. IrpStack->MajorFunction ));
  268. #endif
  269. //
  270. // Pass the IRP to the target
  271. //
  272. IoSkipCurrentIrpStackLocation (Irp);
  273. if (((PPDO_DEVICE_DATA) DeviceObject->DeviceExtension)->IsFDO) {
  274. return IoCallDriver(
  275. ((PFDO_DEVICE_DATA) DeviceObject->DeviceExtension)->TopOfStack,
  276. Irp );
  277. } else {
  278. return IoCallDriver(
  279. ((PFDO_DEVICE_DATA) ((PPDO_DEVICE_DATA) DeviceObject->
  280. DeviceExtension)->ParentFdo->DeviceExtension)->TopOfStack,
  281. Irp );
  282. }
  283. }
  284. void
  285. Cycladz_InitPDO (
  286. ULONG Index,
  287. PDEVICE_OBJECT Pdo,
  288. PFDO_DEVICE_DATA FdoData
  289. )
  290. /*
  291. Description:
  292. Common code to initialize a newly created cyclades-z pdo.
  293. Called either when the control panel exposes a device or when Cyclades-Z senses
  294. a new device was attached.
  295. Parameters:
  296. Pdo - The pdo
  297. FdoData - The fdo's device extension
  298. //Exposed - Was this pdo was found by serenum (FALSE) or was it was EXPOSEd by
  299. // a control panel applet (TRUE)? -> Removed in build 2072
  300. */
  301. {
  302. ULONG FdoFlags = FdoData->Self->Flags;
  303. PPDO_DEVICE_DATA pdoData = Pdo->DeviceExtension;
  304. HANDLE keyHandle;
  305. NTSTATUS status;
  306. //
  307. // Check the IO style
  308. //
  309. if (FdoFlags & DO_BUFFERED_IO) {
  310. Pdo->Flags |= DO_BUFFERED_IO;
  311. } else if (FdoFlags & DO_DIRECT_IO) {
  312. Pdo->Flags |= DO_DIRECT_IO;
  313. }
  314. //
  315. // Increment the pdo's stacksize so that it can pass irps through
  316. //
  317. Pdo->StackSize += FdoData->Self->StackSize;
  318. //
  319. // Initialize the rest of the device extension
  320. //
  321. pdoData->PortIndex = Index;
  322. pdoData->IsFDO = FALSE;
  323. pdoData->Self = Pdo;
  324. pdoData->ParentFdo = FdoData->Self;
  325. pdoData->Attached = TRUE; // attached to the bus
  326. INITIALIZE_PNP_STATE(pdoData);
  327. pdoData->DebugLevel = FdoData->DebugLevel; // Copy the debug level
  328. pdoData->DeviceState = PowerDeviceD0;
  329. pdoData->SystemState = PowerSystemWorking;
  330. //
  331. // Add the pdo to cyclades-z's list
  332. //
  333. ASSERT(FdoData->AttachedPDO[Index] == NULL);
  334. ASSERT(FdoData->PdoData[Index] == NULL);
  335. // ASSERT(FdoData->NumPDOs == 0); rem because NumPDOs can be > 0 in cyclad-z
  336. FdoData->AttachedPDO[Index] = Pdo;
  337. FdoData->PdoData[Index] = pdoData;
  338. FdoData->NumPDOs++;
  339. Pdo->Flags &= ~DO_DEVICE_INITIALIZING; // Moved to end in DDK final version
  340. Pdo->Flags |= DO_POWER_PAGABLE;
  341. }