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.

597 lines
12 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. initunlo.c
  5. Abstract:
  6. This module contains the code that is very specific to initialization
  7. and unload operations in the irenum driver
  8. Author:
  9. Brian Lieuallen, 7-13-2000
  10. Environment:
  11. Kernel mode
  12. Revision History :
  13. --*/
  14. #include "internal.h"
  15. #define OBJECT_DIRECTORY L"\\DosDevices\\"
  16. #pragma alloc_text(PAGE, WaitForLowerDriverToCompleteIrp)
  17. NTSTATUS
  18. IoCompletionSetEvent(
  19. IN PDEVICE_OBJECT DeviceObject,
  20. IN PIRP Irp,
  21. IN PKEVENT pdoIoCompletedEvent
  22. )
  23. {
  24. #if DBG
  25. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
  26. UCHAR *Pnp="PnP";
  27. UCHAR *Power="Power";
  28. UCHAR *Create="Create";
  29. UCHAR *Close="Close";
  30. UCHAR *Other="Other";
  31. PUCHAR IrpType;
  32. switch(irpSp->MajorFunction) {
  33. case IRP_MJ_PNP:
  34. IrpType=Pnp;
  35. break;
  36. case IRP_MJ_CREATE:
  37. IrpType=Create;
  38. break;
  39. case IRP_MJ_CLOSE:
  40. IrpType=Close;
  41. break;
  42. default:
  43. IrpType=Other;
  44. break;
  45. }
  46. D_PNP(DbgPrint("IRCOMM: Setting event for %s wait, completed with %08lx\n",IrpType,Irp->IoStatus.Status);)
  47. #endif
  48. KeSetEvent(pdoIoCompletedEvent, IO_NO_INCREMENT, FALSE);
  49. return STATUS_MORE_PROCESSING_REQUIRED;
  50. }
  51. NTSTATUS
  52. WaitForLowerDriverToCompleteIrp(
  53. PDEVICE_OBJECT TargetDeviceObject,
  54. PIRP Irp,
  55. BOOLEAN CopyCurrentToNext
  56. )
  57. {
  58. NTSTATUS Status;
  59. KEVENT Event;
  60. #if DBG
  61. PIO_STACK_LOCATION IrpSp=IoGetCurrentIrpStackLocation(Irp);
  62. #endif
  63. KeInitializeEvent(
  64. &Event,
  65. NotificationEvent,
  66. FALSE
  67. );
  68. if (CopyCurrentToNext) {
  69. IoCopyCurrentIrpStackLocationToNext(Irp);
  70. }
  71. IoSetCompletionRoutine(
  72. Irp,
  73. IoCompletionSetEvent,
  74. &Event,
  75. TRUE,
  76. TRUE,
  77. TRUE
  78. );
  79. Status = IoCallDriver(TargetDeviceObject, Irp);
  80. if (Status == STATUS_PENDING) {
  81. D_TRACE(DbgPrint("IRCOMM: Waiting for PDO\n");)
  82. KeWaitForSingleObject(
  83. &Event,
  84. Executive,
  85. KernelMode,
  86. FALSE,
  87. NULL
  88. );
  89. }
  90. #if DBG
  91. ASSERT(IrpSp == IoGetCurrentIrpStackLocation(Irp));
  92. RtlZeroMemory(&Event,sizeof(Event));
  93. #endif
  94. return Irp->IoStatus.Status;
  95. }
  96. #if DBG
  97. NTSTATUS
  98. UnhandledPnpIrpCompletion(
  99. IN PDEVICE_OBJECT DeviceObject,
  100. IN PIRP Irp,
  101. IN PVOID Context
  102. )
  103. {
  104. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
  105. D_PNP(DbgPrint("IRCOMM: Forwarded IRP, MN func=%d, completed with %08lx\n",irpSp->MinorFunction,Irp->IoStatus.Status);)
  106. return STATUS_SUCCESS;
  107. }
  108. #endif
  109. NTSTATUS
  110. ForwardIrp(
  111. PDEVICE_OBJECT NextDevice,
  112. PIRP Irp
  113. )
  114. {
  115. #if DBG
  116. IoMarkIrpPending(Irp);
  117. IoCopyCurrentIrpStackLocationToNext(Irp);
  118. IoSetCompletionRoutine(
  119. Irp,
  120. UnhandledPnpIrpCompletion,
  121. NULL,
  122. TRUE,
  123. TRUE,
  124. TRUE
  125. );
  126. IoCallDriver(NextDevice, Irp);
  127. return STATUS_PENDING;
  128. #else
  129. IoSkipCurrentIrpStackLocation(Irp);
  130. return IoCallDriver(NextDevice, Irp);
  131. #endif
  132. }
  133. NTSTATUS
  134. GetRegistryKeyValue (
  135. IN PDEVICE_OBJECT Pdo,
  136. IN ULONG DevInstKeyType,
  137. IN PWCHAR KeyNameString,
  138. IN ULONG ExpectedRegType,
  139. OUT PVOID Data,
  140. IN ULONG DataLength
  141. )
  142. /*++
  143. Routine Description:
  144. Reads a registry key value from an already opened registry key.
  145. Arguments:
  146. Handle Handle to the opened registry key
  147. KeyNameString ANSI string to the desired key
  148. KeyNameStringLength Length of the KeyNameString
  149. Data Buffer to place the key value in
  150. DataLength Length of the data buffer
  151. Return Value:
  152. STATUS_SUCCESS if all works, otherwise status of system call that
  153. went wrong.
  154. --*/
  155. {
  156. UNICODE_STRING keyName;
  157. ULONG length;
  158. PKEY_VALUE_PARTIAL_INFORMATION PartialInfo;
  159. NTSTATUS ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  160. HANDLE Handle;
  161. PAGED_CODE();
  162. ntStatus = IoOpenDeviceRegistryKey(
  163. Pdo,
  164. DevInstKeyType,
  165. STANDARD_RIGHTS_READ,
  166. &Handle
  167. );
  168. if (NT_SUCCESS(ntStatus)) {
  169. RtlInitUnicodeString (&keyName, KeyNameString);
  170. length = sizeof(*PartialInfo) + DataLength;
  171. PartialInfo = ALLOCATE_PAGED_POOL(length);
  172. if (PartialInfo) {
  173. ntStatus = ZwQueryValueKey (Handle,
  174. &keyName,
  175. KeyValuePartialInformation,
  176. PartialInfo,
  177. length,
  178. &length);
  179. if (NT_SUCCESS(ntStatus)) {
  180. //
  181. // If there is enough room in the data buffer, copy the output
  182. //
  183. if (ExpectedRegType == PartialInfo->Type) {
  184. //
  185. // The value read is of the type expected
  186. //
  187. if (DataLength >= PartialInfo->DataLength) {
  188. RtlCopyMemory (Data,
  189. PartialInfo->Data,
  190. PartialInfo->DataLength);
  191. } else {
  192. ntStatus=STATUS_BUFFER_TOO_SMALL;
  193. }
  194. } else {
  195. //
  196. // we did not get the type supplied
  197. //
  198. ntStatus=STATUS_OBJECT_TYPE_MISMATCH;
  199. }
  200. } else {
  201. D_ERROR(DbgPrint("MODEM: could not query value, %08lx\n",ntStatus);)
  202. }
  203. FREE_POOL(PartialInfo);
  204. } else {
  205. ntStatus=STATUS_INSUFFICIENT_RESOURCES;
  206. }
  207. ZwClose(Handle);
  208. } else {
  209. D_ERROR(DbgPrint("MODEM: could open device reg key, %08lx\n",ntStatus);)
  210. }
  211. return ntStatus;
  212. }
  213. NTSTATUS
  214. IrCommHandleSymbolicLink(
  215. PDEVICE_OBJECT Pdo,
  216. PUNICODE_STRING InterfaceName,
  217. BOOLEAN Create
  218. )
  219. {
  220. UNICODE_STRING SymbolicLink;
  221. UNICODE_STRING PdoName;
  222. ULONG StringLength;
  223. NTSTATUS Status;
  224. PdoName.Buffer=NULL;
  225. SymbolicLink.Buffer=NULL;
  226. SymbolicLink.Length=0;
  227. SymbolicLink.MaximumLength=sizeof(WCHAR)*256;
  228. SymbolicLink.Buffer=ALLOCATE_PAGED_POOL(SymbolicLink.MaximumLength+sizeof(WCHAR));
  229. if (SymbolicLink.Buffer == NULL) {
  230. return STATUS_INSUFFICIENT_RESOURCES;
  231. }
  232. RtlZeroMemory(
  233. SymbolicLink.Buffer,
  234. SymbolicLink.MaximumLength+sizeof(WCHAR)
  235. );
  236. RtlAppendUnicodeToString(
  237. &SymbolicLink,
  238. OBJECT_DIRECTORY
  239. );
  240. Status=GetRegistryKeyValue(
  241. Pdo,
  242. PLUGPLAY_REGKEY_DEVICE,
  243. L"PortName",
  244. REG_SZ,
  245. SymbolicLink.Buffer+(SymbolicLink.Length/sizeof(WCHAR)),
  246. (ULONG)SymbolicLink.MaximumLength-SymbolicLink.Length
  247. );
  248. if (!NT_SUCCESS(Status)) {
  249. goto Exit;
  250. }
  251. SymbolicLink.Length=(USHORT)wcslen(SymbolicLink.Buffer)*sizeof(WCHAR);
  252. //
  253. // Get the PDO name so we can point the symbolic to that
  254. //
  255. PdoName.Length=0;
  256. PdoName.MaximumLength=sizeof(WCHAR)*256;
  257. PdoName.Buffer=ALLOCATE_PAGED_POOL(PdoName.MaximumLength+sizeof(WCHAR));
  258. if (PdoName.Buffer == NULL) {
  259. Status=STATUS_INSUFFICIENT_RESOURCES;
  260. goto Exit;
  261. }
  262. Status=IoGetDeviceProperty(
  263. Pdo,
  264. DevicePropertyPhysicalDeviceObjectName,
  265. (ULONG)PdoName.MaximumLength,
  266. PdoName.Buffer,
  267. &StringLength
  268. );
  269. if (!NT_SUCCESS(Status)) {
  270. goto Exit;
  271. }
  272. PdoName.Length+=(USHORT)StringLength-sizeof(UNICODE_NULL);
  273. if (Create) {
  274. Status=IoCreateSymbolicLink(
  275. &SymbolicLink,
  276. &PdoName
  277. );
  278. if (!NT_SUCCESS(Status)) {
  279. D_ERROR(DbgPrint("IRCOMM: IoCreateSymbolicLink() failed %08lx\n",Status);)
  280. } else {
  281. Status = RtlWriteRegistryValue(
  282. RTL_REGISTRY_DEVICEMAP,
  283. L"SERIALCOMM",
  284. PdoName.Buffer,
  285. REG_SZ,
  286. SymbolicLink.Buffer+((sizeof(OBJECT_DIRECTORY)-sizeof(UNICODE_NULL))/sizeof(WCHAR)),
  287. SymbolicLink.Length - (sizeof(OBJECT_DIRECTORY) - sizeof(UNICODE_NULL))
  288. );
  289. }
  290. Status=IoRegisterDeviceInterface(
  291. Pdo,
  292. &GUID_CLASS_COMPORT,
  293. NULL,
  294. InterfaceName
  295. );
  296. if (NT_SUCCESS(Status)) {
  297. IoSetDeviceInterfaceState(
  298. InterfaceName,
  299. TRUE
  300. );
  301. } else {
  302. D_ERROR(DbgPrint("IRCOMM: IoRegisterDeviceInterface() failed %08lx\n",Status);)
  303. }
  304. } else {
  305. if (InterfaceName->Buffer != NULL) {
  306. IoSetDeviceInterfaceState(
  307. InterfaceName,
  308. FALSE
  309. );
  310. RtlFreeUnicodeString(
  311. InterfaceName
  312. );
  313. }
  314. RtlDeleteRegistryValue(
  315. RTL_REGISTRY_DEVICEMAP,
  316. L"SERIALCOMM",
  317. PdoName.Buffer
  318. );
  319. Status=IoDeleteSymbolicLink(
  320. &SymbolicLink
  321. );
  322. }
  323. Exit:
  324. if ( SymbolicLink.Buffer != NULL) {
  325. FREE_POOL(SymbolicLink.Buffer);
  326. }
  327. if (PdoName.Buffer != NULL) {
  328. FREE_POOL(PdoName.Buffer);
  329. }
  330. return Status;
  331. }
  332. NTSTATUS
  333. QueryPdoInformation(
  334. PDEVICE_OBJECT Pdo,
  335. ULONG InformationType,
  336. PVOID Buffer,
  337. ULONG BufferLength
  338. )
  339. {
  340. PDEVICE_OBJECT deviceObject=Pdo;
  341. PIRP irp;
  342. PIO_STACK_LOCATION irpSp;
  343. NTSTATUS Status;
  344. //
  345. // Get a pointer to the topmost device object in the stack of devices,
  346. // beginning with the deviceObject.
  347. //
  348. while (deviceObject->AttachedDevice) {
  349. deviceObject = deviceObject->AttachedDevice;
  350. }
  351. //
  352. // Begin by allocating the IRP for this request. Do not charge quota to
  353. // the current process for this IRP.
  354. //
  355. irp = IoAllocateIrp(deviceObject->StackSize+1, FALSE);
  356. if (irp == NULL){
  357. return STATUS_INSUFFICIENT_RESOURCES;
  358. }
  359. #if DBG
  360. IoSetNextIrpStackLocation(irp);
  361. irpSp = IoGetCurrentIrpStackLocation(irp);
  362. irpSp->MajorFunction=IRP_MJ_PNP;
  363. irpSp->MinorFunction=IRP_MN_READ_CONFIG;
  364. #endif
  365. irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  366. irp->IoStatus.Information = 0;
  367. //
  368. // Get a pointer to the stack location of the first driver which will be
  369. // invoked. This is where the function codes and parameters are set.
  370. //
  371. irpSp = IoGetNextIrpStackLocation(irp);
  372. irpSp->MajorFunction=IRP_MJ_PNP;
  373. irpSp->MinorFunction=IRP_MN_READ_CONFIG;
  374. irpSp->Parameters.ReadWriteConfig.WhichSpace=InformationType;
  375. irpSp->Parameters.ReadWriteConfig.Offset=0;
  376. irpSp->Parameters.ReadWriteConfig.Buffer=Buffer;
  377. irpSp->Parameters.ReadWriteConfig.Length=BufferLength;
  378. Status=WaitForLowerDriverToCompleteIrp(
  379. deviceObject,
  380. irp,
  381. LEAVE_NEXT_AS_IS
  382. );
  383. IoFreeIrp(irp);
  384. return Status;
  385. }
  386. #if 0
  387. VOID
  388. DumpBuffer(
  389. PUCHAR Data,
  390. ULONG Length
  391. )
  392. {
  393. ULONG i;
  394. for (i=0; i<Length; i++) {
  395. DbgPrint("%02x ",*Data);
  396. Data++;
  397. if (((i & 0xf) == 0) && (i != 0)) {
  398. DbgPrint("\n");
  399. }
  400. }
  401. return;
  402. }
  403. #endif