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.

3619 lines
106 KiB

  1. /*++
  2. Copyright (c) 1991, 1992, 1993 - 1997 Microsoft Corporation
  3. Module Name:
  4. pnp.c
  5. Abstract:
  6. This module contains the code that handles the plug and play
  7. IRPs for the serial driver.
  8. Environment:
  9. Kernel mode
  10. Revision History :
  11. --*/
  12. #include "precomp.h"
  13. #define ALLF 0xffffffff
  14. static const PHYSICAL_ADDRESS SerialPhysicalZero = {0};
  15. #ifdef ALLOC_PRAGMA
  16. #pragma alloc_text(PAGESRP0, SerialCreateDevObj)
  17. #pragma alloc_text(PAGESRP0, SerialAddDevice)
  18. #pragma alloc_text(PAGESRP0, SerialPnpDispatch)
  19. #pragma alloc_text(PAGESRP0, SerialStartDevice)
  20. #pragma alloc_text(PAGESRP0, SerialFinishStartDevice)
  21. #pragma alloc_text(PAGESRP0, SerialGetPortInfo)
  22. #pragma alloc_text(PAGESRP0, SerialDoExternalNaming)
  23. #pragma alloc_text(PAGESRP0, SerialReportMaxBaudRate)
  24. #pragma alloc_text(PAGESRP0, SerialControllerCallBack)
  25. #pragma alloc_text(PAGESRP0, SerialItemCallBack)
  26. #pragma alloc_text(PAGESRP0, SerialUndoExternalNaming)
  27. #endif // ALLOC_PRAGMA
  28. //
  29. // Instantiate the GUID
  30. //
  31. #if !defined(FAR)
  32. #define FAR
  33. #endif // !defined(FAR)
  34. #include <initguid.h>
  35. DEFINE_GUID(GUID_CLASS_COMPORT, 0x86e0d1e0L, 0x8089, 0x11d0, 0x9c, 0xe4, 0x08,
  36. 0x00, 0x3e, 0x30, 0x1f, 0x73);
  37. #if DBG
  38. UCHAR *SerSystemCapString[] = {
  39. "PowerSystemUnspecified",
  40. "PowerSystemWorking",
  41. "PowerSystemSleeping1",
  42. "PowerSystemSleeping2",
  43. "PowerSystemSleeping3",
  44. "PowerSystemHibernate",
  45. "PowerSystemShutdown",
  46. "PowerSystemMaximum"
  47. };
  48. UCHAR *SerDeviceCapString[] = {
  49. "PowerDeviceUnspecified",
  50. "PowerDeviceD0",
  51. "PowerDeviceD1",
  52. "PowerDeviceD2",
  53. "PowerDeviceD3",
  54. "PowerDeviceMaximum"
  55. };
  56. #endif // DBG
  57. NTSTATUS
  58. SerialSyncCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp,
  59. IN PKEVENT SerialSyncEvent)
  60. {
  61. KeSetEvent(SerialSyncEvent, IO_NO_INCREMENT, FALSE);
  62. return STATUS_MORE_PROCESSING_REQUIRED;
  63. }
  64. NTSTATUS
  65. SerialCreateDevObj(IN PDRIVER_OBJECT DriverObject,
  66. OUT PDEVICE_OBJECT *NewDeviceObject)
  67. /*++
  68. Routine Description:
  69. This routine will create and initialize a functional device object to
  70. be attached to a Serial controller PDO.
  71. Arguments:
  72. DriverObject - a pointer to the driver object this is created under
  73. NewDeviceObject - a location to store the pointer to the new device object
  74. Return Value:
  75. STATUS_SUCCESS if everything was successful
  76. reason for failure otherwise
  77. --*/
  78. {
  79. UNICODE_STRING deviceObjName;
  80. PDEVICE_OBJECT deviceObject = NULL;
  81. PSERIAL_DEVICE_EXTENSION pDevExt;
  82. NTSTATUS status = STATUS_SUCCESS;
  83. static ULONG currentInstance = 0;
  84. UNICODE_STRING instanceStr;
  85. WCHAR instanceNumberBuffer[20];
  86. PAGED_CODE();
  87. SerialDump (SERTRACECALLS,("SERIAL: Enter SerialCreateDevObj\n"));
  88. //
  89. // Zero out allocated memory pointers so we know if they must be freed
  90. //
  91. RtlZeroMemory(&deviceObjName, sizeof(UNICODE_STRING));
  92. deviceObjName.MaximumLength = DEVICE_OBJECT_NAME_LENGTH * sizeof(WCHAR);
  93. deviceObjName.Buffer = ExAllocatePool(PagedPool, deviceObjName.MaximumLength
  94. + sizeof(WCHAR));
  95. if (deviceObjName.Buffer == NULL) {
  96. SerialLogError(DriverObject, NULL, SerialPhysicalZero, SerialPhysicalZero,
  97. 0, 0, 0, 19, STATUS_SUCCESS, SERIAL_INSUFFICIENT_RESOURCES,
  98. 0, NULL, 0, NULL);
  99. SerialDump(SERERRORS, ("SERIAL: Couldn't allocate memory for device name"
  100. "\n"));
  101. return STATUS_SUCCESS;
  102. }
  103. RtlZeroMemory(deviceObjName.Buffer, deviceObjName.MaximumLength
  104. + sizeof(WCHAR));
  105. #if defined(NEC_98)
  106. RtlAppendUnicodeToString(&deviceObjName, L"\\Device\\Ser71051");
  107. #else
  108. RtlAppendUnicodeToString(&deviceObjName, L"\\Device\\Serial");
  109. #endif //defined(NEC_98)
  110. RtlInitUnicodeString(&instanceStr, NULL);
  111. instanceStr.MaximumLength = sizeof(instanceNumberBuffer);
  112. instanceStr.Buffer = instanceNumberBuffer;
  113. RtlIntegerToUnicodeString(currentInstance++, 10, &instanceStr);
  114. RtlAppendUnicodeStringToString(&deviceObjName, &instanceStr);
  115. //
  116. // Create the device object
  117. //
  118. status = IoCreateDevice(DriverObject, sizeof(SERIAL_DEVICE_EXTENSION),
  119. &deviceObjName, FILE_DEVICE_SERIAL_PORT,
  120. FILE_DEVICE_SECURE_OPEN, TRUE, &deviceObject);
  121. if (!NT_SUCCESS(status)) {
  122. SerialDump(SERERRORS, ("SerialAddDevice: Create device failed - %x \n",
  123. status));
  124. goto SerialCreateDevObjError;
  125. }
  126. ASSERT(deviceObject != NULL);
  127. //
  128. // The device object has a pointer to an area of non-paged
  129. // pool allocated for this device. This will be the device
  130. // extension. Zero it out.
  131. //
  132. pDevExt = deviceObject->DeviceExtension;
  133. RtlZeroMemory(pDevExt, sizeof(SERIAL_DEVICE_EXTENSION));
  134. //
  135. // Initialize the count of IRP's pending
  136. //
  137. pDevExt->PendingIRPCnt = 1;
  138. //
  139. // Initialize the count of DPC's pending
  140. //
  141. pDevExt->DpcCount = 1;
  142. //
  143. // Allocate Pool and save the nt device name in the device extension.
  144. //
  145. pDevExt->DeviceName.Buffer =
  146. ExAllocatePool(PagedPool, deviceObjName.Length + sizeof(WCHAR));
  147. if (!pDevExt->DeviceName.Buffer) {
  148. SerialLogError(
  149. DriverObject,
  150. NULL,
  151. SerialPhysicalZero,
  152. SerialPhysicalZero,
  153. 0,
  154. 0,
  155. 0,
  156. 19,
  157. STATUS_SUCCESS,
  158. SERIAL_INSUFFICIENT_RESOURCES,
  159. 0,
  160. NULL,
  161. 0,
  162. NULL
  163. );
  164. SerialDump(
  165. SERERRORS,
  166. ("SERIAL: Couldn't allocate memory for DeviceName\n"));
  167. status = STATUS_INSUFFICIENT_RESOURCES;
  168. goto SerialCreateDevObjError;
  169. }
  170. pDevExt->DeviceName.MaximumLength = deviceObjName.Length
  171. + sizeof(WCHAR);
  172. //
  173. // Zero fill it.
  174. //
  175. RtlZeroMemory(pDevExt->DeviceName.Buffer,
  176. pDevExt->DeviceName.MaximumLength);
  177. RtlAppendUnicodeStringToString(&pDevExt->DeviceName, &deviceObjName);
  178. pDevExt->NtNameForPort.Buffer = ExAllocatePool(PagedPool,
  179. deviceObjName.MaximumLength);
  180. if (pDevExt->NtNameForPort.Buffer == NULL) {
  181. SerialDump(SERERRORS, ("SerialAddDevice: Cannot allocate memory for "
  182. "NtName\n"));
  183. status = STATUS_INSUFFICIENT_RESOURCES;
  184. goto SerialCreateDevObjError;
  185. }
  186. pDevExt->NtNameForPort.MaximumLength = deviceObjName.MaximumLength;
  187. RtlAppendUnicodeStringToString(&pDevExt->NtNameForPort,
  188. &deviceObjName);
  189. //
  190. // Set up the device extension.
  191. //
  192. pDevExt->DeviceIsOpened = FALSE;
  193. pDevExt->DeviceObject = deviceObject;
  194. pDevExt->DriverObject = DriverObject;
  195. pDevExt->DeviceObject = deviceObject;
  196. pDevExt->PowerState = PowerDeviceD0;
  197. pDevExt->TxFifoAmount = driverDefaults.TxFIFODefault;
  198. pDevExt->CreatedSymbolicLink = TRUE;
  199. pDevExt->OwnsPowerPolicy = TRUE;
  200. InitializeListHead(&pDevExt->CommonInterruptObject);
  201. InitializeListHead(&pDevExt->TopLevelSharers);
  202. InitializeListHead(&pDevExt->MultiportSiblings);
  203. InitializeListHead(&pDevExt->AllDevObjs);
  204. InitializeListHead(&pDevExt->ReadQueue);
  205. InitializeListHead(&pDevExt->WriteQueue);
  206. InitializeListHead(&pDevExt->MaskQueue);
  207. InitializeListHead(&pDevExt->PurgeQueue);
  208. InitializeListHead(&pDevExt->StalledIrpQueue);
  209. ExInitializeFastMutex(&pDevExt->OpenMutex);
  210. ExInitializeFastMutex(&pDevExt->CloseMutex);
  211. KeInitializeEvent(&pDevExt->PendingIRPEvent, SynchronizationEvent, FALSE);
  212. KeInitializeEvent(&pDevExt->PendingDpcEvent, SynchronizationEvent, FALSE);
  213. KeInitializeEvent(&pDevExt->PowerD0Event, SynchronizationEvent, FALSE);
  214. deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  215. *NewDeviceObject = deviceObject;
  216. ExFreePool(deviceObjName.Buffer);
  217. SerialDump (SERTRACECALLS,("SERIAL: Leave SerialCreateDevObj\n") );
  218. return STATUS_SUCCESS;
  219. SerialCreateDevObjError:
  220. SerialDump (SERERRORS,("SERIAL: SerialCreateDevObj Error, Cleaning up\n") );
  221. //
  222. // Free the allocated strings for the NT and symbolic names if they exist.
  223. //
  224. if (deviceObjName.Buffer != NULL) {
  225. ExFreePool(deviceObjName.Buffer);
  226. }
  227. if (deviceObject) {
  228. if (pDevExt->NtNameForPort.Buffer != NULL) {
  229. ExFreePool(pDevExt->NtNameForPort.Buffer);
  230. }
  231. if (pDevExt->DeviceName.Buffer != NULL) {
  232. ExFreePool(pDevExt->DeviceName.Buffer);
  233. }
  234. IoDeleteDevice(deviceObject);
  235. }
  236. *NewDeviceObject = NULL;
  237. SerialDump (SERTRACECALLS,("SERIAL: Leave SerialCreateDevObj\n") );
  238. return status;
  239. }
  240. NTSTATUS
  241. SerialAddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PPdo)
  242. /*++
  243. Routine Description:
  244. This routine creates a functional device object for com ports in the
  245. system and attaches them to the physical device objects for the ports
  246. Arguments:
  247. DriverObject - a pointer to the object for this driver
  248. PPdo - a pointer to the PDO in the stack we need to attach to
  249. Return Value:
  250. status from device creation and initialization
  251. --*/
  252. {
  253. PDEVICE_OBJECT pNewDevObj = NULL;
  254. PDEVICE_OBJECT pLowerDevObj = NULL;
  255. NTSTATUS status;
  256. PSERIAL_DEVICE_EXTENSION pDevExt;
  257. PAGED_CODE();
  258. SerialDump(SERTRACECALLS, ("SERIAL: Enter SerialAddDevice with PPdo "
  259. "0x%x\n", PPdo));
  260. if (PPdo == NULL) {
  261. //
  262. // Return no more devices
  263. //
  264. SerialDump(SERERRORS, ("SerialAddDevice: Enumeration request, returning"
  265. " NO_MORE_ENTRIES\n"));
  266. return (STATUS_NO_MORE_ENTRIES);
  267. }
  268. //
  269. // create and initialize the new device object
  270. //
  271. status = SerialCreateDevObj(DriverObject, &pNewDevObj);
  272. if (!NT_SUCCESS(status)) {
  273. SerialDump(SERERRORS,
  274. ("SerialAddDevice - error creating new devobj [%#08lx]\n",
  275. status));
  276. return status;
  277. }
  278. //
  279. // Layer our DO on top of the lower device object
  280. // The return value is a pointer to the device object to which the
  281. // DO is actually attached.
  282. //
  283. pLowerDevObj = IoAttachDeviceToDeviceStack(pNewDevObj, PPdo);
  284. //
  285. // No status. Do the best we can.
  286. //
  287. ASSERT(pLowerDevObj != NULL);
  288. pDevExt = pNewDevObj->DeviceExtension;
  289. pDevExt->LowerDeviceObject = pLowerDevObj;
  290. pDevExt->Pdo = PPdo;
  291. //
  292. // Specify that this driver only supports buffered IO. This basically
  293. // means that the IO system copies the users data to and from
  294. // system supplied buffers.
  295. //
  296. // Also specify that we are power pagable.
  297. //
  298. pNewDevObj->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
  299. SerialDump(SERTRACECALLS, ("SERIAL: Leave SerialAddDevice\n"));
  300. return status;
  301. }
  302. NTSTATUS
  303. SerialPnpDispatch(IN PDEVICE_OBJECT PDevObj, IN PIRP PIrp)
  304. /*++
  305. Routine Description:
  306. This is a dispatch routine for the IRPs that come to the driver with the
  307. IRP_MJ_PNP major code (plug-and-play IRPs).
  308. Arguments:
  309. PDevObj - Pointer to the device object for this device
  310. PIrp - Pointer to the IRP for the current request
  311. Return Value:
  312. The function value is the final status of the call
  313. --*/
  314. {
  315. PSERIAL_DEVICE_EXTENSION pDevExt = PDevObj->DeviceExtension;
  316. PDEVICE_OBJECT pLowerDevObj = pDevExt->LowerDeviceObject;
  317. PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(PIrp);
  318. NTSTATUS status;
  319. PDEVICE_CAPABILITIES pDevCaps;
  320. PAGED_CODE();
  321. if ((status = SerialIRPPrologue(PIrp, pDevExt)) != STATUS_SUCCESS) {
  322. SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  323. return status;
  324. }
  325. switch (pIrpStack->MinorFunction) {
  326. case IRP_MN_QUERY_CAPABILITIES: {
  327. PKEVENT pQueryCapsEvent;
  328. SYSTEM_POWER_STATE cap;
  329. SerialDump(SERPNPPOWER, ("SERIAL: Got IRP_MN_QUERY_DEVICE_CAPABILITIES "
  330. "IRP\n"));
  331. pQueryCapsEvent = ExAllocatePool(NonPagedPool, sizeof(KEVENT));
  332. if (pQueryCapsEvent == NULL) {
  333. PIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  334. SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  335. return STATUS_INSUFFICIENT_RESOURCES;
  336. }
  337. KeInitializeEvent(pQueryCapsEvent, SynchronizationEvent, FALSE);
  338. IoCopyCurrentIrpStackLocationToNext(PIrp);
  339. IoSetCompletionRoutine(PIrp, SerialSyncCompletion, pQueryCapsEvent,
  340. TRUE, TRUE, TRUE);
  341. status = IoCallDriver(pLowerDevObj, PIrp);
  342. //
  343. // Wait for lower drivers to be done with the Irp
  344. //
  345. if (status == STATUS_PENDING) {
  346. KeWaitForSingleObject(pQueryCapsEvent, Executive, KernelMode, FALSE,
  347. NULL);
  348. }
  349. ExFreePool(pQueryCapsEvent);
  350. status = PIrp->IoStatus.Status;
  351. if (pIrpStack->Parameters.DeviceCapabilities.Capabilities == NULL) {
  352. goto errQueryCaps;
  353. }
  354. //
  355. // Save off their power capabilities
  356. //
  357. SerialDump(SERPNPPOWER, ("SERIAL: Mapping power capabilities\n"));
  358. pIrpStack = IoGetCurrentIrpStackLocation(PIrp);
  359. pDevCaps = pIrpStack->Parameters.DeviceCapabilities.Capabilities;
  360. for (cap = PowerSystemSleeping1; cap < PowerSystemMaximum;
  361. cap++) {
  362. SerialDump(SERPNPPOWER, (" SERIAL: %d: %s <--> %s\n",
  363. cap, SerSystemCapString[cap],
  364. SerDeviceCapString[pDevCaps->DeviceState[cap]]
  365. ));
  366. pDevExt->DeviceStateMap[cap] = pDevCaps->DeviceState[cap];
  367. }
  368. pDevExt->DeviceStateMap[PowerSystemUnspecified]
  369. = PowerDeviceUnspecified;
  370. pDevExt->DeviceStateMap[PowerSystemWorking]
  371. = PowerDeviceD0;
  372. pDevExt->SystemWake = pDevCaps->SystemWake;
  373. pDevExt->DeviceWake = pDevCaps->DeviceWake;
  374. errQueryCaps:;
  375. SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  376. return status;
  377. }
  378. case IRP_MN_QUERY_DEVICE_RELATIONS:
  379. //
  380. // We just pass this down -- serenum enumerates our bus for us.
  381. //
  382. SerialDump (SERPNPPOWER, ("SERIAL: Got IRP_MN_QUERY_DEVICE_RELATIONS "
  383. "Irp\n"));
  384. switch (pIrpStack->Parameters.QueryDeviceRelations.Type) {
  385. case BusRelations:
  386. SerialDump(SERPNPPOWER, ("------- BusRelations Query\n"));
  387. break;
  388. case EjectionRelations:
  389. SerialDump(SERPNPPOWER, ("------- EjectionRelations Query\n"));
  390. break;
  391. case PowerRelations:
  392. SerialDump(SERPNPPOWER, ("------- PowerRelations Query\n"));
  393. break;
  394. case RemovalRelations:
  395. SerialDump(SERPNPPOWER, ("------- RemovalRelations Query\n"));
  396. break;
  397. case TargetDeviceRelation:
  398. SerialDump(SERPNPPOWER, ("------- TargetDeviceRelation Query\n"));
  399. break;
  400. default:
  401. SerialDump(SERPNPPOWER, ("------- Unknown Query\n"));
  402. break;
  403. }
  404. IoSkipCurrentIrpStackLocation(PIrp);
  405. status = SerialIoCallDriver(pDevExt, pLowerDevObj, PIrp);
  406. return status;
  407. case IRP_MN_QUERY_INTERFACE:
  408. SerialDump (SERPNPPOWER, ("SERIAL: Got IRP_MN_QUERY_INTERFACE Irp\n"));
  409. break;
  410. case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
  411. SerialDump (SERPNPPOWER, ("SERIAL: Got "
  412. "IRP_MN_QUERY_RESOURCE_REQUIREMENTS Irp\n"));
  413. break;
  414. case IRP_MN_START_DEVICE: {
  415. PVOID startLockPtr;
  416. SerialDump (SERPNPPOWER, ("SERIAL: Got IRP_MN_START_DEVICE Irp\n"));
  417. //
  418. // SerialStartDevice will pass this Irp to the next driver,
  419. // and process it as completion so just complete it here.
  420. //
  421. SerialLockPagableSectionByHandle(SerialGlobals.PAGESER_Handle);
  422. //
  423. // We used to make sure the stack was powered up, but now it
  424. // is supposed to be done implicitly by start_device.
  425. // If that wasn't the case we would just make this call:
  426. //
  427. // status = SerialGotoPowerState(PDevObj, pDevExt, PowerDeviceD0);
  428. //
  429. pDevExt->PowerState = PowerDeviceD0;
  430. status = SerialStartDevice(PDevObj, PIrp);
  431. (void)SerialGotoPowerState(PDevObj, pDevExt, PowerDeviceD3);
  432. SerialUnlockPagableImageSection(SerialGlobals.PAGESER_Handle);
  433. PIrp->IoStatus.Status = status;
  434. SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  435. return status;
  436. }
  437. case IRP_MN_READ_CONFIG:
  438. SerialDump (SERPNPPOWER, ("SERIAL: Got IRP_MN_READ_CONFIG Irp\n"));
  439. break;
  440. case IRP_MN_WRITE_CONFIG:
  441. SerialDump (SERPNPPOWER, ("SERIAL: Got IRP_MN_WRITE_CONFIG Irp\n"));
  442. break;
  443. case IRP_MN_EJECT:
  444. SerialDump (SERPNPPOWER, ("SERIAL: Got IRP_MN_EJECT Irp\n"));
  445. break;
  446. case IRP_MN_SET_LOCK:
  447. SerialDump (SERPNPPOWER, ("SERIAL: Got IRP_MN_SET_LOCK Irp\n"));
  448. break;
  449. case IRP_MN_QUERY_ID: {
  450. UNICODE_STRING pIdBuf;
  451. PWCHAR pPnpIdStr;
  452. ULONG pnpIdStrLen;
  453. ULONG isMulti = 0;
  454. HANDLE pnpKey;
  455. SerialDump(SERPNPPOWER, ("SERIAL: Got IRP_MN_QUERY_ID Irp\n"));
  456. if (pIrpStack->Parameters.QueryId.IdType != BusQueryHardwareIDs
  457. && pIrpStack->Parameters.QueryId.IdType != BusQueryCompatibleIDs) {
  458. IoSkipCurrentIrpStackLocation(PIrp);
  459. return SerialIoCallDriver(pDevExt, pLowerDevObj, PIrp);
  460. }
  461. if (pIrpStack->Parameters.QueryId.IdType == BusQueryCompatibleIDs) {
  462. PIrp->IoStatus.Status = STATUS_SUCCESS;
  463. IoSkipCurrentIrpStackLocation(PIrp);
  464. return SerialIoCallDriver(pDevExt, pLowerDevObj, PIrp);
  465. }
  466. status = IoOpenDeviceRegistryKey(pDevExt->Pdo, PLUGPLAY_REGKEY_DEVICE,
  467. STANDARD_RIGHTS_WRITE, &pnpKey);
  468. if (!NT_SUCCESS(status)) {
  469. PIrp->IoStatus.Status = status;
  470. SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  471. return status;
  472. }
  473. status = SerialGetRegistryKeyValue (pnpKey, L"MultiportDevice",
  474. sizeof(L"MultiportDevice"),
  475. &isMulti,
  476. sizeof (ULONG));
  477. ZwClose(pnpKey);
  478. if (!NT_SUCCESS(status)) {
  479. PIrp->IoStatus.Status = status;
  480. SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  481. return status;
  482. }
  483. pPnpIdStr = isMulti ? SERIAL_PNP_MULTI_ID_STR : SERIAL_PNP_ID_STR;
  484. pnpIdStrLen = isMulti ? sizeof(SERIAL_PNP_MULTI_ID_STR)
  485. : sizeof(SERIAL_PNP_ID_STR);
  486. if (PIrp->IoStatus.Information != 0) {
  487. ULONG curStrLen;
  488. ULONG allocLen = 0;
  489. PWSTR curStr = (PWSTR)PIrp->IoStatus.Information;
  490. //
  491. // We have to walk the strings to count the amount of space to
  492. // reallocate
  493. //
  494. while ((curStrLen = wcslen(curStr)) != 0) {
  495. allocLen += curStrLen * sizeof(WCHAR) + sizeof(UNICODE_NULL);
  496. curStr += curStrLen + 1;
  497. }
  498. allocLen += sizeof(UNICODE_NULL);
  499. pIdBuf.Buffer = ExAllocatePool(PagedPool, allocLen
  500. + pnpIdStrLen
  501. + sizeof(WCHAR));
  502. if (pIdBuf.Buffer == NULL) {
  503. //
  504. // Clean up after other drivers since we are
  505. // sending the irp back up.
  506. //
  507. ExFreePool((PWSTR)PIrp->IoStatus.Information);
  508. PIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  509. PIrp->IoStatus.Information = 0;
  510. SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  511. return STATUS_INSUFFICIENT_RESOURCES;
  512. }
  513. pIdBuf.MaximumLength = (USHORT)(allocLen + pnpIdStrLen);
  514. pIdBuf.Length = (USHORT)allocLen - sizeof(UNICODE_NULL);
  515. RtlZeroMemory(pIdBuf.Buffer, pIdBuf.MaximumLength + sizeof(WCHAR));
  516. RtlCopyMemory(pIdBuf.Buffer, (PWSTR)PIrp->IoStatus.Information,
  517. allocLen);
  518. RtlAppendUnicodeToString(&pIdBuf, pPnpIdStr);
  519. //
  520. // Free what the previous driver allocated
  521. //
  522. ExFreePool((PWSTR)PIrp->IoStatus.Information);
  523. } else {
  524. SerialDump(SERPNPPOWER, ("SERIAL: ID is sole ID\n"));
  525. pIdBuf.Buffer = ExAllocatePool(PagedPool, pnpIdStrLen
  526. + sizeof(WCHAR) * 2);
  527. if (pIdBuf.Buffer == NULL) {
  528. PIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  529. PIrp->IoStatus.Information = 0;
  530. SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  531. return STATUS_INSUFFICIENT_RESOURCES;
  532. }
  533. pIdBuf.MaximumLength = (USHORT)pnpIdStrLen;
  534. pIdBuf.Length = 0;
  535. RtlZeroMemory(pIdBuf.Buffer, pIdBuf.MaximumLength + sizeof(WCHAR)
  536. * 2);
  537. RtlAppendUnicodeToString(&pIdBuf, pPnpIdStr);
  538. }
  539. PIrp->IoStatus.Information = (ULONG_PTR)pIdBuf.Buffer;
  540. PIrp->IoStatus.Status = STATUS_SUCCESS;
  541. IoCopyCurrentIrpStackLocationToNext(PIrp);
  542. return SerialIoCallDriver(pDevExt, pLowerDevObj, PIrp);
  543. }
  544. case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: {
  545. HANDLE pnpKey;
  546. PKEVENT pResFiltEvent;
  547. ULONG isMulti = 0;
  548. PIO_RESOURCE_REQUIREMENTS_LIST pReqList;
  549. PIO_RESOURCE_LIST pResList;
  550. PIO_RESOURCE_DESCRIPTOR pResDesc;
  551. ULONG i, j;
  552. ULONG reqCnt;
  553. ULONG gotISR;
  554. ULONG gotInt;
  555. ULONG listNum;
  556. SerialDump(SERPNPPOWER, ("SERIAL: Got "
  557. "IRP_MN_FILTER_RESOURCE_REQUIREMENTS Irp\n"));
  558. SerialDump(SERPNPPOWER, ("------- for device %x\n", pLowerDevObj));
  559. pResFiltEvent = ExAllocatePool(NonPagedPool, sizeof(KEVENT));
  560. if (pResFiltEvent == NULL) {
  561. PIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  562. SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  563. return STATUS_INSUFFICIENT_RESOURCES;
  564. }
  565. KeInitializeEvent(pResFiltEvent, SynchronizationEvent, FALSE);
  566. IoCopyCurrentIrpStackLocationToNext(PIrp);
  567. IoSetCompletionRoutine(PIrp, SerialSyncCompletion, pResFiltEvent,
  568. TRUE, TRUE, TRUE);
  569. status = IoCallDriver(pLowerDevObj, PIrp);
  570. //
  571. // Wait for lower drivers to be done with the Irp
  572. //
  573. if (status == STATUS_PENDING) {
  574. KeWaitForSingleObject (pResFiltEvent, Executive, KernelMode, FALSE,
  575. NULL);
  576. }
  577. ExFreePool(pResFiltEvent);
  578. if (PIrp->IoStatus.Information == 0) {
  579. if (pIrpStack->Parameters.FilterResourceRequirements
  580. .IoResourceRequirementList == 0) {
  581. SerialDump(SERPNPPOWER, ("------- Can't filter NULL resources!"
  582. "\n"));
  583. status = PIrp->IoStatus.Status;
  584. SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  585. return status;
  586. }
  587. PIrp->IoStatus.Information = (ULONG_PTR)pIrpStack->Parameters
  588. .FilterResourceRequirements
  589. .IoResourceRequirementList;
  590. }
  591. status = IoOpenDeviceRegistryKey(pDevExt->Pdo, PLUGPLAY_REGKEY_DEVICE,
  592. STANDARD_RIGHTS_WRITE, &pnpKey);
  593. if (!NT_SUCCESS(status)) {
  594. PIrp->IoStatus.Status = status;
  595. SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  596. return status;
  597. }
  598. //
  599. // No matter what we add our filter if we can and return success.
  600. //
  601. status = SerialGetRegistryKeyValue (pnpKey, L"MultiportDevice",
  602. sizeof(L"MultiportDevice"),
  603. &isMulti,
  604. sizeof (ULONG));
  605. ZwClose(pnpKey);
  606. //
  607. // Force ISR ports in IO_RES_REQ_LIST to shared status
  608. // Force interrupts to shared status
  609. //
  610. //
  611. // We will only process the first list -- multiport boards
  612. // should not have alternative resources
  613. //
  614. pReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)PIrp->IoStatus.Information;
  615. pResList = &pReqList->List[0];
  616. SerialDump(SERPNPPOWER, ("------- List has %x lists "
  617. "(including alternatives)\n",
  618. pReqList->AlternativeLists));
  619. for (listNum = 0; listNum < (pReqList->AlternativeLists);
  620. listNum++) {
  621. gotISR = 0;
  622. gotInt = 0;
  623. SerialDump(SERPNPPOWER, ("------- List has %x resources in it\n",
  624. pResList->Count));
  625. for (j = 0; (j < pResList->Count); j++) {
  626. pResDesc = &pResList->Descriptors[j];
  627. switch (pResDesc->Type) {
  628. case CmResourceTypePort:
  629. if (isMulti
  630. && (pResDesc->u.Port.Length == SERIAL_STATUS_LENGTH)
  631. && !gotISR) {
  632. gotISR = 1;
  633. pResDesc->ShareDisposition = CmResourceShareShared;
  634. SerialDump(SERPNPPOWER, ("------- Sharing I/O port for "
  635. "device %x\n", pLowerDevObj));
  636. }
  637. break;
  638. case CmResourceTypeInterrupt:
  639. if (!gotInt) {
  640. gotInt = 1;
  641. if (pResDesc->ShareDisposition != CmResourceShareShared) {
  642. pResDesc->ShareDisposition = CmResourceShareShared;
  643. SerialDump(SERPNPPOWER, ("------- Sharing interrupt "
  644. "for device %x\n",
  645. pLowerDevObj));
  646. } else {
  647. pDevExt->InterruptShareable = TRUE;
  648. SerialDump(SERPNPPOWER, ("------- Globally sharing "
  649. " interrupt for device %x\n",
  650. pLowerDevObj));
  651. }
  652. }
  653. break;
  654. default:
  655. break;
  656. }
  657. //
  658. // If we found what we need, we can break out of the loop
  659. //
  660. if ((isMulti && gotInt && gotISR) || (!isMulti && gotInt)) {
  661. break;
  662. }
  663. }
  664. pResList = (PIO_RESOURCE_LIST)((PUCHAR)pResList
  665. + sizeof(IO_RESOURCE_LIST)
  666. + sizeof(IO_RESOURCE_DESCRIPTOR)
  667. * (pResList->Count - 1));
  668. }
  669. PIrp->IoStatus.Status = STATUS_SUCCESS;
  670. SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  671. return STATUS_SUCCESS;
  672. }
  673. case IRP_MN_QUERY_PNP_DEVICE_STATE:
  674. {
  675. if (pDevExt->Flags & SERIAL_FLAGS_BROKENHW) {
  676. (PNP_DEVICE_STATE)PIrp->IoStatus.Information |= PNP_DEVICE_FAILED;
  677. PIrp->IoStatus.Status = STATUS_SUCCESS;
  678. }
  679. IoCopyCurrentIrpStackLocationToNext(PIrp);
  680. return SerialIoCallDriver(pDevExt, pLowerDevObj, PIrp);
  681. }
  682. case IRP_MN_STOP_DEVICE:
  683. {
  684. ULONG pendingIRPs;
  685. KIRQL oldIrql;
  686. SerialDump(SERPNPPOWER, ("SERIAL: Got IRP_MN_STOP_DEVICE Irp\n"));
  687. SerialDump(SERPNPPOWER, ("------- for device %x\n", pLowerDevObj));
  688. ASSERT(!pDevExt->PortOnAMultiportCard);
  689. SerialSetFlags(pDevExt, SERIAL_FLAGS_STOPPED);
  690. SerialSetAccept(pDevExt,SERIAL_PNPACCEPT_STOPPED);
  691. SerialClearAccept(pDevExt, SERIAL_PNPACCEPT_STOPPING);
  692. pDevExt->PNPState = SERIAL_PNP_STOPPING;
  693. //
  694. // From this point on all non-PNP IRP's will be queued
  695. //
  696. //
  697. // Decrement for entry here
  698. //
  699. InterlockedDecrement(&pDevExt->PendingIRPCnt);
  700. //
  701. // Decrement for stopping
  702. //
  703. pendingIRPs = InterlockedDecrement(&pDevExt->PendingIRPCnt);
  704. if (pendingIRPs) {
  705. KeWaitForSingleObject(&pDevExt->PendingIRPEvent, Executive,
  706. KernelMode, FALSE, NULL);
  707. }
  708. //
  709. // Re-increment the count for later
  710. //
  711. InterlockedIncrement(&pDevExt->PendingIRPCnt);
  712. //
  713. // We need to free resources...basically this is a remove
  714. // without the detach from the stack.
  715. //
  716. if (pDevExt->Flags & SERIAL_FLAGS_STARTED) {
  717. SerialReleaseResources(pDevExt);
  718. }
  719. //
  720. // Pass the irp down
  721. //
  722. PIrp->IoStatus.Status = STATUS_SUCCESS;
  723. IoSkipCurrentIrpStackLocation(PIrp);
  724. return IoCallDriver(pLowerDevObj, PIrp);
  725. }
  726. case IRP_MN_QUERY_STOP_DEVICE:
  727. {
  728. KIRQL oldIrql;
  729. SerialDump(SERPNPPOWER, ("SERIAL: Got IRP_MN_QUERY_STOP_DEVICE Irp\n")
  730. );
  731. SerialDump(SERPNPPOWER, ("------- for device %x\n", pLowerDevObj));
  732. //
  733. // See if we should succeed a stop query
  734. //
  735. if (pDevExt->PortOnAMultiportCard) {
  736. PIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  737. SerialDump(SERPNPPOWER, ("------- failing; multiport node\n"));
  738. SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  739. return STATUS_NOT_SUPPORTED;
  740. }
  741. //
  742. // If the device hasn't started yet, we ignore this request
  743. // and just pass it down.
  744. //
  745. if (pDevExt->PNPState != SERIAL_PNP_STARTED) {
  746. IoSkipCurrentIrpStackLocation(PIrp);
  747. return SerialIoCallDriver(pDevExt, pLowerDevObj, PIrp);
  748. }
  749. //
  750. // Lock around the open status
  751. //
  752. ExAcquireFastMutex(&pDevExt->OpenMutex);
  753. if (pDevExt->DeviceIsOpened) {
  754. ExReleaseFastMutex(&pDevExt->OpenMutex);
  755. PIrp->IoStatus.Status = STATUS_DEVICE_BUSY;
  756. SerialDump(SERPNPPOWER, ("------- failing; device open\n"));
  757. SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  758. return STATUS_DEVICE_BUSY;
  759. }
  760. pDevExt->PNPState = SERIAL_PNP_QSTOP;
  761. SerialSetAccept(pDevExt, SERIAL_PNPACCEPT_STOPPING);
  762. //
  763. // Unlock around the open status
  764. //
  765. ExReleaseFastMutex(&pDevExt->OpenMutex);
  766. PIrp->IoStatus.Status = STATUS_SUCCESS;
  767. IoCopyCurrentIrpStackLocationToNext(PIrp);
  768. return SerialIoCallDriver(pDevExt, pLowerDevObj, PIrp);
  769. }
  770. case IRP_MN_CANCEL_STOP_DEVICE:
  771. SerialDump(SERPNPPOWER, ("SERIAL: Got "
  772. "IRP_MN_CANCEL_STOP_DEVICE Irp\n"));
  773. SerialDump(SERPNPPOWER, ("------- for device %x\n", pLowerDevObj));
  774. if (pDevExt->PNPState == SERIAL_PNP_QSTOP) {
  775. //
  776. // Restore the device state
  777. //
  778. pDevExt->PNPState = SERIAL_PNP_STARTED;
  779. SerialClearAccept(pDevExt, SERIAL_PNPACCEPT_STOPPING);
  780. }
  781. PIrp->IoStatus.Status = STATUS_SUCCESS;
  782. IoCopyCurrentIrpStackLocationToNext(PIrp);
  783. return SerialIoCallDriver(pDevExt, pLowerDevObj, PIrp);
  784. case IRP_MN_CANCEL_REMOVE_DEVICE:
  785. SerialDump(SERPNPPOWER, ("SERIAL: Got "
  786. "IRP_MN_CANCEL_REMOVE_DEVICE Irp\n"));
  787. SerialDump(SERPNPPOWER, ("------- for device %x\n", pLowerDevObj));
  788. //
  789. // Restore the device state
  790. //
  791. pDevExt->PNPState = SERIAL_PNP_STARTED;
  792. SerialClearAccept(pDevExt, SERIAL_PNPACCEPT_REMOVING);
  793. PIrp->IoStatus.Status = STATUS_SUCCESS;
  794. IoCopyCurrentIrpStackLocationToNext(PIrp);
  795. return SerialIoCallDriver(pDevExt, pLowerDevObj, PIrp);
  796. case IRP_MN_QUERY_REMOVE_DEVICE:
  797. {
  798. KIRQL oldIrql;
  799. SerialDump(SERPNPPOWER, ("SERIAL: Got "
  800. "IRP_MN_QUERY_REMOVE_DEVICE Irp\n"));
  801. SerialDump(SERPNPPOWER, ("------- for device %x\n", pLowerDevObj));
  802. ExAcquireFastMutex(&pDevExt->OpenMutex);
  803. //
  804. // See if we should succeed a remove query
  805. //
  806. if (pDevExt->DeviceIsOpened) {
  807. ExReleaseFastMutex(&pDevExt->OpenMutex);
  808. PIrp->IoStatus.Status = STATUS_DEVICE_BUSY;
  809. SerialDump(SERPNPPOWER, ("------- failing; device open\n"));
  810. SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  811. return STATUS_DEVICE_BUSY;
  812. }
  813. pDevExt->PNPState = SERIAL_PNP_QREMOVE;
  814. SerialSetAccept(pDevExt, SERIAL_PNPACCEPT_REMOVING);
  815. ExReleaseFastMutex(&pDevExt->OpenMutex);
  816. PIrp->IoStatus.Status = STATUS_SUCCESS;
  817. IoCopyCurrentIrpStackLocationToNext(PIrp);
  818. return SerialIoCallDriver(pDevExt, pLowerDevObj, PIrp);
  819. }
  820. case IRP_MN_SURPRISE_REMOVAL:
  821. {
  822. ULONG pendingIRPs;
  823. KIRQL oldIrql;
  824. SerialDump(SERPNPPOWER, ("SERIAL: Got IRP_MN_SURPRISE_REMOVAL Irp\n"));
  825. SerialDump(SERPNPPOWER, ("------- for device %x\n", pLowerDevObj));
  826. //
  827. // Prevent any new I/O to the device
  828. //
  829. SerialSetAccept(pDevExt, SERIAL_PNPACCEPT_SURPRISE_REMOVING);
  830. //
  831. // Dismiss all pending requests
  832. //
  833. SerialKillPendingIrps(PDevObj);
  834. //
  835. // Wait for any pending requests we raced on.
  836. //
  837. //
  838. // Decrement once for ourselves
  839. //
  840. InterlockedDecrement(&pDevExt->PendingIRPCnt);
  841. //
  842. // Decrement for the remove
  843. //
  844. pendingIRPs = InterlockedDecrement(&pDevExt->PendingIRPCnt);
  845. if (pendingIRPs) {
  846. KeWaitForSingleObject(&pDevExt->PendingIRPEvent, Executive,
  847. KernelMode, FALSE, NULL);
  848. }
  849. //
  850. // Reset for subsequent remove
  851. //
  852. InterlockedIncrement(&pDevExt->PendingIRPCnt);
  853. //
  854. // Remove any external interfaces and release resources
  855. //
  856. SerialDisableInterfacesResources(PDevObj, FALSE);
  857. PIrp->IoStatus.Status = STATUS_SUCCESS;
  858. IoSkipCurrentIrpStackLocation(PIrp);
  859. return SerialIoCallDriver(pDevExt, pLowerDevObj, PIrp);
  860. }
  861. case IRP_MN_REMOVE_DEVICE:
  862. {
  863. ULONG pendingIRPs;
  864. KIRQL oldIrql;
  865. SerialDump(SERPNPPOWER, ("SERIAL: Got IRP_MN_REMOVE_DEVICE Irp\n"));
  866. SerialDump(SERPNPPOWER, ("------- for device %x\n", pLowerDevObj));
  867. //
  868. // If we get this, we have to remove
  869. //
  870. //
  871. // Mark as not accepting requests
  872. //
  873. SerialSetAccept(pDevExt, SERIAL_PNPACCEPT_REMOVING);
  874. //
  875. // Complete all pending requests
  876. //
  877. SerialKillPendingIrps(PDevObj);
  878. //
  879. // Decrement for this Irp itself
  880. //
  881. InterlockedDecrement(&pDevExt->PendingIRPCnt);
  882. //
  883. // Wait for any pending requests we raced on -- this decrement
  884. // is for our "placeholder".
  885. //
  886. pendingIRPs = InterlockedDecrement(&pDevExt->PendingIRPCnt);
  887. if (pendingIRPs) {
  888. KeWaitForSingleObject(&pDevExt->PendingIRPEvent, Executive,
  889. KernelMode, FALSE, NULL);
  890. }
  891. //
  892. // Remove us
  893. //
  894. SerialRemoveDevObj(PDevObj);
  895. //
  896. // Pass the irp down
  897. //
  898. PIrp->IoStatus.Status = STATUS_SUCCESS;
  899. IoCopyCurrentIrpStackLocationToNext(PIrp);
  900. //
  901. // We do decrement here because we incremented on entry here.
  902. //
  903. IoCallDriver(pLowerDevObj, PIrp);
  904. return STATUS_SUCCESS;
  905. }
  906. default:
  907. break;
  908. } // switch (pIrpStack->MinorFunction)
  909. //
  910. // Pass to driver beneath us
  911. //
  912. IoSkipCurrentIrpStackLocation(PIrp);
  913. status = SerialIoCallDriver(pDevExt, pLowerDevObj, PIrp);
  914. return status;
  915. }
  916. UINT32
  917. SerialReportMaxBaudRate(ULONG Bauds)
  918. /*++
  919. Routine Description:
  920. This routine returns the max baud rate given a selection of rates
  921. Arguments:
  922. Bauds - Bit-encoded list of supported bauds
  923. Return Value:
  924. The max baud rate listed in Bauds
  925. --*/
  926. {
  927. PAGED_CODE();
  928. if (Bauds & SERIAL_BAUD_128K) {
  929. return (128U * 1024U);
  930. }
  931. if (Bauds & SERIAL_BAUD_115200) {
  932. return 115200U;
  933. }
  934. if (Bauds & SERIAL_BAUD_56K) {
  935. return (56U * 1024U);
  936. }
  937. if (Bauds & SERIAL_BAUD_57600) {
  938. return 57600U;
  939. }
  940. if (Bauds & SERIAL_BAUD_38400) {
  941. return 38400U;
  942. }
  943. if (Bauds & SERIAL_BAUD_19200) {
  944. return 19200U;
  945. }
  946. if (Bauds & SERIAL_BAUD_14400) {
  947. return 14400U;
  948. }
  949. if (Bauds & SERIAL_BAUD_9600) {
  950. return 9600U;
  951. }
  952. if (Bauds & SERIAL_BAUD_7200) {
  953. return 7200U;
  954. }
  955. if (Bauds & SERIAL_BAUD_4800) {
  956. return 4800U;
  957. }
  958. if (Bauds & SERIAL_BAUD_2400) {
  959. return 2400U;
  960. }
  961. if (Bauds & SERIAL_BAUD_1800) {
  962. return 1800U;
  963. }
  964. if (Bauds & SERIAL_BAUD_1200) {
  965. return 1200U;
  966. }
  967. if (Bauds & SERIAL_BAUD_600) {
  968. return 600U;
  969. }
  970. if (Bauds & SERIAL_BAUD_300) {
  971. return 300U;
  972. }
  973. if (Bauds & SERIAL_BAUD_150) {
  974. return 150U;
  975. }
  976. if (Bauds & SERIAL_BAUD_134_5) {
  977. return 135U; // Close enough
  978. }
  979. if (Bauds & SERIAL_BAUD_110) {
  980. return 110U;
  981. }
  982. if (Bauds & SERIAL_BAUD_075) {
  983. return 75U;
  984. }
  985. //
  986. // We're in bad shape
  987. //
  988. return 0;
  989. }
  990. NTSTATUS
  991. SerialFinishStartDevice(IN PDEVICE_OBJECT PDevObj,
  992. IN PCM_RESOURCE_LIST PResList,
  993. IN PCM_RESOURCE_LIST PTrResList,
  994. PSERIAL_USER_DATA PUserData)
  995. /*++
  996. Routine Description:
  997. This routine does serial-specific procedures to start a device. It
  998. does this either for a legacy device detected by its registry entries,
  999. or for a PnP device after the start IRP has been sent down the stack.
  1000. Arguments:
  1001. PDevObj - Pointer to the devobj that is starting
  1002. PResList - Pointer to the untranslated resources needed by this device
  1003. PTrResList - Pointer to the translated resources needed by this device
  1004. PUserData - Pointer to the user-specified resources/attributes
  1005. Return Value:
  1006. STATUS_SUCCESS on success, something else appropriate on failure
  1007. --*/
  1008. {
  1009. PSERIAL_DEVICE_EXTENSION pDevExt = PDevObj->DeviceExtension;
  1010. #if defined(NEC_98)
  1011. //
  1012. // This argument use at MACRO only.
  1013. //
  1014. PSERIAL_DEVICE_EXTENSION Extension = PDevObj->DeviceExtension;
  1015. #else
  1016. #endif //defined(NEC_98)
  1017. NTSTATUS status;
  1018. PCONFIG_DATA pConfig;
  1019. HANDLE pnpKey;
  1020. ULONG one = 1;
  1021. PAGED_CODE();
  1022. //
  1023. // See if this is a restart, and if so don't reallocate the world
  1024. //
  1025. if ((pDevExt->Flags & SERIAL_FLAGS_STOPPED)
  1026. && (pDevExt->Flags & SERIAL_FLAGS_STARTED)) {
  1027. SerialClearFlags(pDevExt, SERIAL_FLAGS_STOPPED);
  1028. pDevExt->PNPState = SERIAL_PNP_RESTARTING;
  1029. //
  1030. // Re-init resource-related things in the extension
  1031. //
  1032. pDevExt->TopLevelOurIsr = NULL;
  1033. pDevExt->TopLevelOurIsrContext = NULL;
  1034. pDevExt->OriginalController = SerialPhysicalZero;
  1035. pDevExt->OriginalInterruptStatus = SerialPhysicalZero;
  1036. pDevExt->OurIsr = NULL;
  1037. pDevExt->OurIsrContext = NULL;
  1038. pDevExt->Controller = NULL;
  1039. pDevExt->InterruptStatus = NULL;
  1040. pDevExt->Interrupt = NULL;
  1041. pDevExt->SpanOfController = 0;
  1042. pDevExt->SpanOfInterruptStatus = 0;
  1043. pDevExt->Vector = 0;
  1044. pDevExt->Irql = 0;
  1045. pDevExt->OriginalVector = 0;
  1046. pDevExt->OriginalIrql = 0;
  1047. pDevExt->AddressSpace = 0;
  1048. pDevExt->BusNumber = 0;
  1049. pDevExt->InterfaceType = 0;
  1050. pDevExt->CIsrSw = NULL;
  1051. ASSERT(PUserData == NULL);
  1052. PUserData = ExAllocatePool(PagedPool, sizeof(SERIAL_USER_DATA));
  1053. if (PUserData == NULL) {
  1054. return STATUS_INSUFFICIENT_RESOURCES;
  1055. }
  1056. RtlZeroMemory(PUserData, sizeof(SERIAL_USER_DATA));
  1057. PUserData->DisablePort = FALSE;
  1058. PUserData->UserClockRate = pDevExt->ClockRate;
  1059. PUserData->TxFIFO = pDevExt->TxFifoAmount;
  1060. PUserData->PermitShareDefault = pDevExt->PermitShare;
  1061. //
  1062. // Map betweeen trigger and amount
  1063. //
  1064. switch (pDevExt->RxFifoTrigger) {
  1065. case SERIAL_1_BYTE_HIGH_WATER:
  1066. PUserData->RxFIFO = 1;
  1067. break;
  1068. case SERIAL_4_BYTE_HIGH_WATER:
  1069. PUserData->RxFIFO = 4;
  1070. break;
  1071. case SERIAL_8_BYTE_HIGH_WATER:
  1072. PUserData->RxFIFO = 8;
  1073. break;
  1074. case SERIAL_14_BYTE_HIGH_WATER:
  1075. PUserData->RxFIFO = 14;
  1076. break;
  1077. default:
  1078. PUserData->RxFIFO = 1;
  1079. }
  1080. } else {
  1081. //
  1082. // Mark as serenumerable -- toss status because we can
  1083. // still start without this key.
  1084. //
  1085. status = IoOpenDeviceRegistryKey(pDevExt->Pdo,
  1086. PLUGPLAY_REGKEY_DEVICE,
  1087. STANDARD_RIGHTS_WRITE, &pnpKey);
  1088. if (NT_SUCCESS(status)) {
  1089. ULONG powerPolicy = 0;
  1090. //
  1091. // Find out if we own power policy
  1092. //
  1093. SerialGetRegistryKeyValue(pnpKey, L"SerialRelinquishPowerPolicy",
  1094. sizeof(L"SerialRelinquishPowerPolicy"),
  1095. &powerPolicy, sizeof(ULONG));
  1096. pDevExt->OwnsPowerPolicy = powerPolicy ? FALSE : TRUE;
  1097. ZwClose(pnpKey);
  1098. }
  1099. }
  1100. //
  1101. // Allocate the config record.
  1102. //
  1103. pConfig = ExAllocatePool (PagedPool, sizeof(CONFIG_DATA));
  1104. if (pConfig == NULL) {
  1105. SerialLogError(pDevExt->DriverObject, NULL, SerialPhysicalZero,
  1106. SerialPhysicalZero, 0, 0, 0, 37, STATUS_SUCCESS,
  1107. SERIAL_INSUFFICIENT_RESOURCES, 0, NULL, 0, NULL);
  1108. SerialDump(SERERRORS, ("SERIAL: Couldn't allocate memory for the\n"
  1109. "------ user configuration record\n"));
  1110. status = STATUS_INSUFFICIENT_RESOURCES;
  1111. goto SerialFinishStartDeviceError;
  1112. }
  1113. RtlZeroMemory(pConfig, sizeof(CONFIG_DATA));
  1114. //
  1115. // Get the configuration info for the device.
  1116. //
  1117. status = SerialGetPortInfo(PDevObj, PResList, PTrResList, pConfig,
  1118. PUserData);
  1119. if (!NT_SUCCESS(status)) {
  1120. goto SerialFinishStartDeviceError;
  1121. }
  1122. //
  1123. // See if we are in the proper power state.
  1124. //
  1125. if (pDevExt->PowerState != PowerDeviceD0) {
  1126. status = SerialGotoPowerState(pDevExt->Pdo, pDevExt, PowerDeviceD0);
  1127. if (!NT_SUCCESS(status)) {
  1128. goto SerialFinishStartDeviceError;
  1129. }
  1130. }
  1131. //
  1132. // Find and initialize the controller
  1133. //
  1134. status = SerialFindInitController(PDevObj, pConfig);
  1135. if (!NT_SUCCESS(status)) {
  1136. goto SerialFinishStartDeviceError;
  1137. }
  1138. //
  1139. // The hardware that is set up to NOT interrupt, connect an interrupt.
  1140. //
  1141. //
  1142. // If a device doesn't already have an interrupt and it has an isr then
  1143. // we attempt to connect to the interrupt if it is not shareing with other
  1144. // serial devices. If we fail to connect to an interrupt we will delete
  1145. // this device.
  1146. //
  1147. if (pDevExt != NULL) {
  1148. SerialDump(SERDIAG5, ("SERIAL: pDevExt: Interrupt %x\n"
  1149. "------- OurIsr %x\n",
  1150. pDevExt->Interrupt, pDevExt->OurIsr));
  1151. } else {
  1152. SerialDump(SERERRORS, ("SERIAL: SerialFinishStartDevice got NULL "
  1153. "pDevExt\n"));
  1154. }
  1155. if ((!pDevExt->Interrupt) && (pDevExt->OurIsr)) {
  1156. SerialDump(
  1157. SERDIAG5,
  1158. ("SERIAL: About to connect to interrupt for port %wZ\n"
  1159. "------- address of extension is %x\n",
  1160. &pDevExt->DeviceName, pDevExt)
  1161. );
  1162. SerialDump(SERDIAG5, ("SERIAL: IoConnectInterrupt Args:\n"
  1163. "------- Interrupt %x\n"
  1164. "------- OurIsr %x\n"
  1165. "------- OurIsrContext %x\n"
  1166. "------- NULL\n"
  1167. "------- Vector %x\n"
  1168. "------- Irql %x\n"
  1169. "------- InterruptMode %x\n"
  1170. "------- InterruptShareable %x\n"
  1171. "------- ProcessorAffinity %x\n"
  1172. "------- FALSE\n",
  1173. &pDevExt->Interrupt,
  1174. SerialCIsrSw,
  1175. pDevExt->CIsrSw,
  1176. pDevExt->Vector,
  1177. pDevExt->Irql,
  1178. pConfig->InterruptMode,
  1179. pDevExt->InterruptShareable,
  1180. pConfig->Affinity
  1181. ));
  1182. //
  1183. // Do a just in time construction of the ISR switch.
  1184. //
  1185. pDevExt->CIsrSw->IsrFunc = pDevExt->OurIsr;
  1186. pDevExt->CIsrSw->Context = pDevExt->OurIsrContext;
  1187. status = IoConnectInterrupt(&pDevExt->Interrupt, SerialCIsrSw,
  1188. pDevExt->CIsrSw, NULL,
  1189. pDevExt->Vector, pDevExt->Irql,
  1190. pDevExt->Irql,
  1191. pConfig->InterruptMode,
  1192. pDevExt->InterruptShareable,
  1193. pConfig->Affinity, FALSE);
  1194. if (!NT_SUCCESS(status)) {
  1195. //
  1196. // Hmmm, how'd that happen? Somebody either
  1197. // didn't report their resources, or they
  1198. // sneaked in since the last time I looked.
  1199. //
  1200. // Oh well, delete this device.
  1201. //
  1202. SerialDump(SERERRORS, ("SERIAL: Couldn't connect to interrupt for "
  1203. "%wZ\n", &pDevExt->DeviceName));
  1204. SerialDump(SERERRORS, ("SERIAL: IoConnectInterrupt Args:\n"
  1205. "------- Interrupt %x\n"
  1206. "------- OurIsr %x\n"
  1207. "------- OurIsrContext %x\n"
  1208. "------- NULL\n"
  1209. "------- Vector %x\n"
  1210. "------- Irql %x\n"
  1211. "------- InterruptMode %x\n"
  1212. "------- InterruptShareable %x\n"
  1213. "------- ProcessorAffinity %x\n"
  1214. "------- FALSE\n",
  1215. &pDevExt->Interrupt,
  1216. SerialCIsrSw,
  1217. pDevExt->CIsrSw,
  1218. pDevExt->Vector,
  1219. pDevExt->Irql,
  1220. pConfig->InterruptMode,
  1221. pDevExt->InterruptShareable,
  1222. pConfig->Affinity
  1223. ));
  1224. SerialLogError(PDevObj->DriverObject, PDevObj,
  1225. pDevExt->OriginalController,
  1226. SerialPhysicalZero, 0, 0, 0, 1, status,
  1227. SERIAL_UNREPORTED_IRQL_CONFLICT,
  1228. pDevExt->DeviceName.Length + sizeof(WCHAR),
  1229. pDevExt->DeviceName.Buffer, 0, NULL);
  1230. status = SERIAL_UNREPORTED_IRQL_CONFLICT;
  1231. goto SerialFinishStartDeviceError;
  1232. }
  1233. }
  1234. SerialDump(SERDIAG5, ("Connected interrupt %08X\n", pDevExt->Interrupt));
  1235. //
  1236. // Add the PDevObj to the master list
  1237. //
  1238. InsertTailList(&SerialGlobals.AllDevObjs, &pDevExt->AllDevObjs);
  1239. //
  1240. // Reset the device.
  1241. //
  1242. //
  1243. // While the device isn't open, disable all interrupts.
  1244. //
  1245. DISABLE_ALL_INTERRUPTS (pDevExt->Controller);
  1246. if (pDevExt->Jensen) {
  1247. WRITE_MODEM_CONTROL(
  1248. pDevExt->Controller,
  1249. (UCHAR)SERIAL_MCR_OUT2
  1250. );
  1251. } else {
  1252. WRITE_MODEM_CONTROL(
  1253. pDevExt->Controller,
  1254. (UCHAR)0
  1255. );
  1256. }
  1257. //
  1258. // This should set up everything as it should be when
  1259. // a device is to be opened. We do need to lower the
  1260. // modem lines, and disable the recalcitrant fifo
  1261. // so that it will show up if the user boots to dos.
  1262. //
  1263. KeSynchronizeExecution(
  1264. pDevExt->Interrupt,
  1265. SerialReset,
  1266. pDevExt
  1267. );
  1268. KeSynchronizeExecution( //Disables the fifo.
  1269. pDevExt->Interrupt,
  1270. SerialMarkClose,
  1271. pDevExt
  1272. );
  1273. KeSynchronizeExecution(
  1274. pDevExt->Interrupt,
  1275. SerialClrRTS,
  1276. pDevExt
  1277. );
  1278. KeSynchronizeExecution(
  1279. pDevExt->Interrupt,
  1280. SerialClrDTR,
  1281. pDevExt
  1282. );
  1283. if (pDevExt->PNPState == SERIAL_PNP_ADDED ) {
  1284. //
  1285. // Do the external naming now that the device is accessible.
  1286. //
  1287. status = SerialDoExternalNaming(pDevExt, pDevExt->DeviceObject->
  1288. DriverObject);
  1289. if (!NT_SUCCESS(status)) {
  1290. SerialDump (SERERRORS,("SERIAL: External Naming Failed - Status %x\n",
  1291. status));
  1292. //
  1293. // Allow the device to start anyhow
  1294. //
  1295. status = STATUS_SUCCESS;
  1296. }
  1297. } else {
  1298. SerialDump(SERPNPPOWER, ("Not doing external naming -- state is %x\n",
  1299. pDevExt->PNPState));
  1300. }
  1301. SerialFinishStartDeviceError:;
  1302. if (!NT_SUCCESS (status)) {
  1303. SerialDump(SERDIAG1,("SERIAL: Cleaning up failed start\n"));
  1304. //
  1305. // Resources created by this routine will be cleaned up by the remove
  1306. //
  1307. if (pDevExt->PNPState == SERIAL_PNP_RESTARTING) {
  1308. //
  1309. // Kill all that lives and breathes -- we'll clean up the
  1310. // rest on the impending remove
  1311. //
  1312. SerialKillPendingIrps(PDevObj);
  1313. //
  1314. // In fact, pretend we're removing so we don't take any
  1315. // more irps
  1316. //
  1317. SerialSetAccept(pDevExt, SERIAL_PNPACCEPT_REMOVING);
  1318. SerialClearFlags(pDevExt, SERIAL_FLAGS_STARTED);
  1319. }
  1320. } else { // SUCCESS
  1321. //
  1322. // Fill in WMI hardware data
  1323. //
  1324. pDevExt->WmiHwData.IrqNumber = pDevExt->Irql;
  1325. pDevExt->WmiHwData.IrqLevel = pDevExt->Irql;
  1326. pDevExt->WmiHwData.IrqVector = pDevExt->Vector;
  1327. pDevExt->WmiHwData.IrqAffinityMask = pConfig->Affinity;
  1328. pDevExt->WmiHwData.InterruptType = pConfig->InterruptMode == Latched
  1329. ? SERIAL_WMI_INTTYPE_LATCHED : SERIAL_WMI_INTTYPE_LEVEL;
  1330. pDevExt->WmiHwData.BaseIOAddress = (ULONG_PTR)pDevExt->Controller;
  1331. //
  1332. // Fill in WMI device state data (as defaults)
  1333. //
  1334. pDevExt->WmiCommData.BaudRate = pDevExt->CurrentBaud;
  1335. pDevExt->WmiCommData.BitsPerByte = (pDevExt->LineControl & 0x03) + 5;
  1336. pDevExt->WmiCommData.ParityCheckEnable = (pDevExt->LineControl & 0x08)
  1337. ? TRUE : FALSE;
  1338. switch (pDevExt->LineControl & SERIAL_PARITY_MASK) {
  1339. case SERIAL_NONE_PARITY:
  1340. pDevExt->WmiCommData.Parity = SERIAL_WMI_PARITY_NONE;
  1341. break;
  1342. case SERIAL_ODD_PARITY:
  1343. pDevExt->WmiCommData.Parity = SERIAL_WMI_PARITY_ODD;
  1344. break;
  1345. case SERIAL_EVEN_PARITY:
  1346. pDevExt->WmiCommData.Parity = SERIAL_WMI_PARITY_EVEN;
  1347. break;
  1348. #if defined(NEC_98)
  1349. //
  1350. // COM1 of PC-9800 series is not support MarkParity and SpaceParity.
  1351. //
  1352. #else
  1353. case SERIAL_MARK_PARITY:
  1354. pDevExt->WmiCommData.Parity = SERIAL_WMI_PARITY_MARK;
  1355. break;
  1356. case SERIAL_SPACE_PARITY:
  1357. pDevExt->WmiCommData.Parity = SERIAL_WMI_PARITY_SPACE;
  1358. break;
  1359. #endif //defined(NEC_98)
  1360. default:
  1361. ASSERTMSG(0, "SERIAL: Illegal Parity setting for WMI");
  1362. pDevExt->WmiCommData.Parity = SERIAL_WMI_PARITY_NONE;
  1363. break;
  1364. }
  1365. pDevExt->WmiCommData.StopBits = pDevExt->LineControl & SERIAL_STOP_MASK
  1366. ? (pDevExt->WmiCommData.BitsPerByte == 5 ? SERIAL_WMI_STOP_1_5
  1367. : SERIAL_WMI_STOP_2) : SERIAL_WMI_STOP_1;
  1368. pDevExt->WmiCommData.XoffCharacter = pDevExt->SpecialChars.XoffChar;
  1369. pDevExt->WmiCommData.XoffXmitThreshold = pDevExt->HandFlow.XoffLimit;
  1370. pDevExt->WmiCommData.XonCharacter = pDevExt->SpecialChars.XonChar;
  1371. pDevExt->WmiCommData.XonXmitThreshold = pDevExt->HandFlow.XonLimit;
  1372. pDevExt->WmiCommData.MaximumBaudRate
  1373. = SerialReportMaxBaudRate(pDevExt->SupportedBauds);
  1374. pDevExt->WmiCommData.MaximumOutputBufferSize = (UINT32)((ULONG)-1);
  1375. pDevExt->WmiCommData.MaximumInputBufferSize = (UINT32)((ULONG)-1);
  1376. pDevExt->WmiCommData.Support16BitMode = FALSE;
  1377. pDevExt->WmiCommData.SupportDTRDSR = TRUE;
  1378. pDevExt->WmiCommData.SupportIntervalTimeouts = TRUE;
  1379. pDevExt->WmiCommData.SupportParityCheck = TRUE;
  1380. pDevExt->WmiCommData.SupportRTSCTS = TRUE;
  1381. pDevExt->WmiCommData.SupportXonXoff = TRUE;
  1382. pDevExt->WmiCommData.SettableBaudRate = TRUE;
  1383. pDevExt->WmiCommData.SettableDataBits = TRUE;
  1384. pDevExt->WmiCommData.SettableFlowControl = TRUE;
  1385. pDevExt->WmiCommData.SettableParity = TRUE;
  1386. pDevExt->WmiCommData.SettableParityCheck = TRUE;
  1387. pDevExt->WmiCommData.SettableStopBits = TRUE;
  1388. pDevExt->WmiCommData.IsBusy = FALSE;
  1389. //
  1390. // Fill in wmi perf data (all zero's)
  1391. //
  1392. RtlZeroMemory(&pDevExt->WmiPerfData, sizeof(pDevExt->WmiPerfData));
  1393. if (pDevExt->PNPState == SERIAL_PNP_ADDED) {
  1394. PULONG countSoFar = &IoGetConfigurationInformation()->SerialCount;
  1395. (*countSoFar)++;
  1396. //
  1397. // Register for WMI
  1398. //
  1399. pDevExt->WmiLibInfo.GuidCount = sizeof(SerialWmiGuidList) /
  1400. sizeof(WMIGUIDREGINFO);
  1401. pDevExt->WmiLibInfo.GuidList = SerialWmiGuidList;
  1402. ASSERT (pDevExt->WmiLibInfo.GuidCount == SERIAL_WMI_GUID_LIST_SIZE);
  1403. pDevExt->WmiLibInfo.QueryWmiRegInfo = SerialQueryWmiRegInfo;
  1404. pDevExt->WmiLibInfo.QueryWmiDataBlock = SerialQueryWmiDataBlock;
  1405. pDevExt->WmiLibInfo.SetWmiDataBlock = SerialSetWmiDataBlock;
  1406. pDevExt->WmiLibInfo.SetWmiDataItem = SerialSetWmiDataItem;
  1407. pDevExt->WmiLibInfo.ExecuteWmiMethod = NULL;
  1408. pDevExt->WmiLibInfo.WmiFunctionControl = NULL;
  1409. IoWMIRegistrationControl(PDevObj, WMIREG_ACTION_REGISTER);
  1410. }
  1411. if (pDevExt->PNPState == SERIAL_PNP_RESTARTING) {
  1412. //
  1413. // Release the stalled IRP's
  1414. //
  1415. SerialUnstallIrps(pDevExt);
  1416. }
  1417. pDevExt->PNPState = SERIAL_PNP_STARTED;
  1418. SerialClearAccept(pDevExt, ~SERIAL_PNPACCEPT_OK);
  1419. SerialSetFlags(pDevExt, SERIAL_FLAGS_STARTED);
  1420. }
  1421. if (pConfig) {
  1422. ExFreePool (pConfig);
  1423. }
  1424. if ((PUserData != NULL)
  1425. && (pDevExt->PNPState == SERIAL_PNP_RESTARTING)) {
  1426. ExFreePool(PUserData);
  1427. }
  1428. SerialDump (SERTRACECALLS, ("SERIAL: leaving SerialFinishStartDevice\n"));
  1429. return status;
  1430. }
  1431. NTSTATUS
  1432. SerialStartDevice(IN PDEVICE_OBJECT PDevObj, IN PIRP PIrp)
  1433. /*++
  1434. Routine Description:
  1435. This routine first passes the start device Irp down the stack then
  1436. it picks up the resources for the device, ititializes, puts it on any
  1437. appropriate lists (i.e shared interrupt or interrupt status) and
  1438. connects the interrupt.
  1439. Arguments:
  1440. PDevObj - Pointer to the device object for this device
  1441. PIrp - Pointer to the IRP for the current request
  1442. Return Value:
  1443. Return status
  1444. --*/
  1445. {
  1446. PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(PIrp);
  1447. NTSTATUS status = STATUS_NOT_IMPLEMENTED;
  1448. PSERIAL_DEVICE_EXTENSION pDevExt = PDevObj->DeviceExtension;
  1449. PDEVICE_OBJECT pLowerDevObj = pDevExt->LowerDeviceObject;
  1450. PAGED_CODE();
  1451. SerialDump (SERTRACECALLS, ("SERIAL: entering SerialStartDevice\n"));
  1452. //
  1453. // Pass this down to the next device object
  1454. //
  1455. KeInitializeEvent(&pDevExt->SerialStartEvent, SynchronizationEvent,
  1456. FALSE);
  1457. IoCopyCurrentIrpStackLocationToNext(PIrp);
  1458. IoSetCompletionRoutine(PIrp, SerialSyncCompletion,
  1459. &pDevExt->SerialStartEvent, TRUE, TRUE, TRUE);
  1460. status = IoCallDriver(pLowerDevObj, PIrp);
  1461. //
  1462. // Wait for lower drivers to be done with the Irp
  1463. //
  1464. if (status == STATUS_PENDING) {
  1465. KeWaitForSingleObject (&pDevExt->SerialStartEvent, Executive, KernelMode,
  1466. FALSE, NULL);
  1467. status = PIrp->IoStatus.Status;
  1468. }
  1469. if (!NT_SUCCESS(status)) {
  1470. SerialDump (SERERRORS, ("SERIAL: error with IoCallDriver %x\n", status));
  1471. return status;
  1472. }
  1473. //
  1474. // Do the serial specific items to start the device
  1475. //
  1476. status = SerialFinishStartDevice(PDevObj, pIrpStack->Parameters.StartDevice
  1477. .AllocatedResources,
  1478. pIrpStack->Parameters.StartDevice
  1479. .AllocatedResourcesTranslated, NULL);
  1480. return status;
  1481. }
  1482. NTSTATUS
  1483. SerialItemCallBack(
  1484. IN PVOID Context,
  1485. IN PUNICODE_STRING PathName,
  1486. IN INTERFACE_TYPE BusType,
  1487. IN ULONG BusNumber,
  1488. IN PKEY_VALUE_FULL_INFORMATION *BusInformation,
  1489. IN CONFIGURATION_TYPE ControllerType,
  1490. IN ULONG ControllerNumber,
  1491. IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation,
  1492. IN CONFIGURATION_TYPE PeripheralType,
  1493. IN ULONG PeripheralNumber,
  1494. IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation
  1495. )
  1496. /*++
  1497. Routine Description:
  1498. This routine is called to check if a particular item
  1499. is present in the registry.
  1500. Arguments:
  1501. Context - Pointer to a boolean.
  1502. PathName - unicode registry path. Not Used.
  1503. BusType - Internal, Isa, ...
  1504. BusNumber - Which bus if we are on a multibus system.
  1505. BusInformation - Configuration information about the bus. Not Used.
  1506. ControllerType - Controller type.
  1507. ControllerNumber - Which controller if there is more than one
  1508. controller in the system.
  1509. ControllerInformation - Array of pointers to the three pieces of
  1510. registry information.
  1511. PeripheralType - Should be a peripheral.
  1512. PeripheralNumber - Which peripheral - not used..
  1513. PeripheralInformation - Configuration information. Not Used.
  1514. Return Value:
  1515. STATUS_SUCCESS
  1516. --*/
  1517. {
  1518. PAGED_CODE();
  1519. *((BOOLEAN *)Context) = TRUE;
  1520. return STATUS_SUCCESS;
  1521. }
  1522. NTSTATUS
  1523. SerialControllerCallBack(
  1524. IN PVOID Context,
  1525. IN PUNICODE_STRING PathName,
  1526. IN INTERFACE_TYPE BusType,
  1527. IN ULONG BusNumber,
  1528. IN PKEY_VALUE_FULL_INFORMATION *BusInformation,
  1529. IN CONFIGURATION_TYPE ControllerType,
  1530. IN ULONG ControllerNumber,
  1531. IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation,
  1532. IN CONFIGURATION_TYPE PeripheralType,
  1533. IN ULONG PeripheralNumber,
  1534. IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation
  1535. )
  1536. /*++
  1537. Routine Description:
  1538. This routine is called to check if a particular item
  1539. is present in the registry.
  1540. Arguments:
  1541. Context - Pointer to a boolean.
  1542. PathName - unicode registry path. Not Used.
  1543. BusType - Internal, Isa, ...
  1544. BusNumber - Which bus if we are on a multibus system.
  1545. BusInformation - Configuration information about the bus. Not Used.
  1546. ControllerType - Controller type.
  1547. ControllerNumber - Which controller if there is more than one
  1548. controller in the system.
  1549. ControllerInformation - Array of pointers to the three pieces of
  1550. registry information.
  1551. PeripheralType - Should be a peripheral.
  1552. PeripheralNumber - Which peripheral - not used..
  1553. PeripheralInformation - Configuration information. Not Used.
  1554. Return Value:
  1555. STATUS_SUCCESS
  1556. --*/
  1557. {
  1558. PCM_FULL_RESOURCE_DESCRIPTOR controllerData;
  1559. PSERIAL_PTR_CTX pContext = (PSERIAL_PTR_CTX)Context;
  1560. ULONG i;
  1561. PAGED_CODE();
  1562. if (ControllerInformation[IoQueryDeviceConfigurationData]->DataLength == 0) {
  1563. pContext->isPointer = FALSE;
  1564. return STATUS_SUCCESS;
  1565. }
  1566. controllerData =
  1567. (PCM_FULL_RESOURCE_DESCRIPTOR)
  1568. (((PUCHAR)ControllerInformation[IoQueryDeviceConfigurationData])
  1569. + ControllerInformation[IoQueryDeviceConfigurationData]->DataOffset);
  1570. //
  1571. // See if this is the exact port we are testing
  1572. //
  1573. for (i = 0; i < controllerData->PartialResourceList.Count; i++) {
  1574. PCM_PARTIAL_RESOURCE_DESCRIPTOR partial
  1575. = &controllerData->PartialResourceList.PartialDescriptors[i];
  1576. switch (partial->Type) {
  1577. case CmResourceTypePort:
  1578. if (partial->u.Port.Start.QuadPart == pContext->Port.QuadPart) {
  1579. //
  1580. // Pointer on same controller. Bail out.
  1581. //
  1582. pContext->isPointer = SERIAL_FOUNDPOINTER_PORT;
  1583. return STATUS_SUCCESS;
  1584. }
  1585. case CmResourceTypeInterrupt:
  1586. if (partial->u.Interrupt.Vector == pContext->Vector) {
  1587. //
  1588. // Pointer sharing this interrupt. Bail out.
  1589. //
  1590. pContext->isPointer = SERIAL_FOUNDPOINTER_VECTOR;
  1591. return STATUS_SUCCESS;
  1592. }
  1593. default:
  1594. break;
  1595. }
  1596. }
  1597. pContext->isPointer = FALSE;
  1598. return STATUS_SUCCESS;
  1599. }
  1600. NTSTATUS
  1601. SerialGetPortInfo(IN PDEVICE_OBJECT PDevObj, IN PCM_RESOURCE_LIST PResList,
  1602. IN PCM_RESOURCE_LIST PTrResList, OUT PCONFIG_DATA PConfig,
  1603. IN PSERIAL_USER_DATA PUserData)
  1604. /*++
  1605. Routine Description:
  1606. This routine will get the configuration information and put
  1607. it and the translated values into CONFIG_DATA structures.
  1608. It first sets up with defaults and then queries the registry
  1609. to see if the user has overridden these defaults; if this is a legacy
  1610. multiport card, it uses the info in PUserData instead of groping the
  1611. registry again.
  1612. Arguments:
  1613. PDevObj - Pointer to the device object.
  1614. PResList - Pointer to the untranslated resources requested.
  1615. PTrResList - Pointer to the translated resources requested.
  1616. PConfig - Pointer to configuration info
  1617. PUserData - Pointer to data discovered in the registry for
  1618. legacy devices.
  1619. Return Value:
  1620. STATUS_SUCCESS if consistant configuration was found - otherwise.
  1621. returns STATUS_SERIAL_NO_DEVICE_INITED.
  1622. --*/
  1623. {
  1624. PSERIAL_DEVICE_EXTENSION pDevExt = PDevObj->DeviceExtension;
  1625. PDEVICE_OBJECT pLowerDevObj = pDevExt->LowerDeviceObject;
  1626. NTSTATUS status = STATUS_NOT_IMPLEMENTED;
  1627. CONFIGURATION_TYPE pointer = PointerPeripheral;
  1628. CONFIGURATION_TYPE controllerType = SerialController;
  1629. HANDLE keyHandle;
  1630. ULONG count;
  1631. ULONG i;
  1632. INTERFACE_TYPE interfaceType;
  1633. PCM_PARTIAL_RESOURCE_LIST pPartialResourceList, pPartialTrResourceList;
  1634. PCM_PARTIAL_RESOURCE_DESCRIPTOR pPartialResourceDesc, pPartialTrResourceDesc;
  1635. PCM_FULL_RESOURCE_DESCRIPTOR pFullResourceDesc = NULL,
  1636. pFullTrResourceDesc = NULL;
  1637. ULONG defaultInterruptMode;
  1638. ULONG defaultAddressSpace;
  1639. ULONG defaultInterfaceType;
  1640. ULONG defaultClockRate;
  1641. ULONG zero = 0;
  1642. SERIAL_PTR_CTX foundPointerCtx;
  1643. ULONG isMulti = 0;
  1644. ULONG gotInt = 0;
  1645. ULONG gotISR = 0;
  1646. ULONG gotIO = 0;
  1647. ULONG ioResIndex = 0;
  1648. ULONG curIoIndex = 0;
  1649. PAGED_CODE();
  1650. SerialDump(SERTRACECALLS, ("SERIAL: entering SerialGetPortInfo\n"));
  1651. SerialDump(SERPNPPOWER, ("SERIAL: resource pointer is %x\n", PResList));
  1652. SerialDump(SERPNPPOWER, ("SERIAL: TR resource pointer is %x\n", PTrResList));
  1653. if ((PResList == NULL) || (PTrResList == NULL)) {
  1654. //
  1655. // This shouldn't happen in theory
  1656. //
  1657. ASSERT(PResList != NULL);
  1658. ASSERT(PTrResList != NULL);
  1659. //
  1660. // This status is as appropriate as I can think of
  1661. //
  1662. return STATUS_INSUFFICIENT_RESOURCES;
  1663. }
  1664. //
  1665. // Each resource list should have only one set of resources
  1666. //
  1667. ASSERT(PResList->Count == 1);
  1668. ASSERT(PTrResList->Count == 1);
  1669. //
  1670. // See if this is a multiport device. This way we allow other
  1671. // pseudo-serial devices with extra resources to specify another range
  1672. // of I/O ports. If this is not a multiport, we only look at the first
  1673. // range. If it is a multiport, we look at the first two ranges.
  1674. //
  1675. status = IoOpenDeviceRegistryKey(pDevExt->Pdo, PLUGPLAY_REGKEY_DEVICE,
  1676. STANDARD_RIGHTS_WRITE, &keyHandle);
  1677. if (!NT_SUCCESS(status)) {
  1678. return status;
  1679. }
  1680. status = SerialGetRegistryKeyValue(keyHandle, L"MultiportDevice",
  1681. sizeof(L"MultiportDevice"), &isMulti,
  1682. sizeof (ULONG));
  1683. if (!NT_SUCCESS(status)) {
  1684. isMulti = 0;
  1685. }
  1686. status = SerialGetRegistryKeyValue(keyHandle, L"SerialIoResourcesIndex",
  1687. sizeof(L"SerialIoResourcesIndex"),
  1688. &ioResIndex, sizeof(ULONG));
  1689. if (!NT_SUCCESS(status)) {
  1690. ioResIndex = 0;
  1691. }
  1692. ZwClose(keyHandle);
  1693. pFullResourceDesc = &PResList->List[0];
  1694. pFullTrResourceDesc = &PTrResList->List[0];
  1695. //
  1696. // Ok, if we have a full resource descriptor. Let's take it apart.
  1697. //
  1698. if (pFullResourceDesc) {
  1699. pPartialResourceList = &pFullResourceDesc->PartialResourceList;
  1700. pPartialResourceDesc = pPartialResourceList->PartialDescriptors;
  1701. count = pPartialResourceList->Count;
  1702. //
  1703. // Pull out the stuff that is in the full descriptor.
  1704. //
  1705. PConfig->InterfaceType = pFullResourceDesc->InterfaceType;
  1706. PConfig->BusNumber = pFullResourceDesc->BusNumber;
  1707. //
  1708. // Now run through the partial resource descriptors looking for the port,
  1709. // interrupt, and clock rate.
  1710. //
  1711. PConfig->ClockRate = 1843200;
  1712. PConfig->InterruptStatus = SerialPhysicalZero;
  1713. PConfig->SpanOfInterruptStatus = SERIAL_STATUS_LENGTH;
  1714. for (i = 0; i < count; i++, pPartialResourceDesc++) {
  1715. switch (pPartialResourceDesc->Type) {
  1716. case CmResourceTypePort: {
  1717. #if defined(NEC_98)
  1718. //
  1719. // NEC98 can't decide by length.
  1720. //
  1721. if (pPartialResourceDesc->u.Port.Start.LowPart
  1722. == 0x130 && (gotIO == 0)) { // This is the serial register set
  1723. gotIO = 1;
  1724. PConfig->Controller = pPartialResourceDesc->u.Port.Start;
  1725. PConfig->SpanOfController = SERIAL_REGISTER_SPAN;
  1726. PConfig->AddressSpace = pPartialResourceDesc->Flags;
  1727. }
  1728. #else
  1729. if (pPartialResourceDesc->u.Port.Length
  1730. == SERIAL_STATUS_LENGTH && (gotISR == 0)) { // This is an ISR
  1731. if (isMulti) {
  1732. gotISR = 1;
  1733. PConfig->InterruptStatus
  1734. = pPartialResourceDesc->u.Port.Start;
  1735. PConfig->SpanOfInterruptStatus
  1736. = pPartialResourceDesc->u.Port.Length;
  1737. PConfig->AddressSpace = pPartialResourceDesc->Flags;
  1738. }
  1739. } else {
  1740. if (gotIO == 0) { // This is the serial register set
  1741. if (curIoIndex == ioResIndex) {
  1742. gotIO = 1;
  1743. PConfig->Controller
  1744. = pPartialResourceDesc->u.Port.Start;
  1745. PConfig->SpanOfController = SERIAL_REGISTER_SPAN;
  1746. PConfig->AddressSpace = pPartialResourceDesc->Flags;
  1747. } else {
  1748. curIoIndex++;
  1749. }
  1750. }
  1751. }
  1752. #endif //defined(NEC_98)
  1753. break;
  1754. }
  1755. case CmResourceTypeInterrupt: {
  1756. if (gotInt == 0) {
  1757. gotInt = 1;
  1758. PConfig->OriginalIrql = pPartialResourceDesc->u.Interrupt.Level;
  1759. PConfig->OriginalVector
  1760. = pPartialResourceDesc->u.Interrupt.Vector;
  1761. PConfig->Affinity = pPartialResourceDesc->u.Interrupt.Affinity;
  1762. if (pPartialResourceDesc->Flags
  1763. & CM_RESOURCE_INTERRUPT_LATCHED) {
  1764. PConfig->InterruptMode = Latched;
  1765. } else {
  1766. PConfig->InterruptMode = LevelSensitive;
  1767. }
  1768. }
  1769. break;
  1770. }
  1771. case CmResourceTypeDeviceSpecific: {
  1772. PCM_SERIAL_DEVICE_DATA sDeviceData;
  1773. sDeviceData = (PCM_SERIAL_DEVICE_DATA)(pPartialResourceDesc + 1);
  1774. PConfig->ClockRate = sDeviceData->BaudClock;
  1775. break;
  1776. }
  1777. default: {
  1778. break;
  1779. }
  1780. } // switch (pPartialResourceDesc->Type)
  1781. } // for (i = 0; i < count; i++, pPartialResourceDesc++)
  1782. } // if (pFullResourceDesc)
  1783. //
  1784. // Do the same for the translated resources
  1785. //
  1786. gotInt = 0;
  1787. gotISR = 0;
  1788. gotIO = 0;
  1789. curIoIndex = 0;
  1790. if (pFullTrResourceDesc) {
  1791. pPartialTrResourceList = &pFullTrResourceDesc->PartialResourceList;
  1792. pPartialTrResourceDesc = pPartialTrResourceList->PartialDescriptors;
  1793. count = pPartialTrResourceList->Count;
  1794. //
  1795. // Reload PConfig with the translated values for later use
  1796. //
  1797. PConfig->InterfaceType = pFullTrResourceDesc->InterfaceType;
  1798. PConfig->BusNumber = pFullTrResourceDesc->BusNumber;
  1799. PConfig->TrInterruptStatus = SerialPhysicalZero;
  1800. for (i = 0; i < count; i++, pPartialTrResourceDesc++) {
  1801. switch (pPartialTrResourceDesc->Type) {
  1802. case CmResourceTypePort: {
  1803. #if defined(NEC_98)
  1804. //
  1805. // NEC98 can't decide by length.
  1806. //
  1807. if (pPartialTrResourceDesc->u.Port.Start.LowPart
  1808. == 0x130 && (gotIO == 0)) { // This is the serial register set
  1809. gotIO = 1;
  1810. PConfig->TrController = pPartialTrResourceDesc->u.Port.Start;
  1811. PConfig->AddressSpace = pPartialTrResourceDesc->Flags;
  1812. }
  1813. #else
  1814. if (pPartialTrResourceDesc->u.Port.Length
  1815. == SERIAL_STATUS_LENGTH && (gotISR == 0)) { // This is an ISR
  1816. if (isMulti) {
  1817. gotISR = 1;
  1818. PConfig->TrInterruptStatus = pPartialTrResourceDesc
  1819. ->u.Port.Start;
  1820. }
  1821. } else { // This is the serial register set
  1822. if (gotIO == 0) {
  1823. if (curIoIndex == ioResIndex) {
  1824. gotIO = 1;
  1825. PConfig->TrController
  1826. = pPartialTrResourceDesc->u.Port.Start;
  1827. PConfig->AddressSpace
  1828. = pPartialTrResourceDesc->Flags;
  1829. } else {
  1830. curIoIndex++;
  1831. }
  1832. }
  1833. }
  1834. #endif //defined(NEC_98)
  1835. break;
  1836. }
  1837. case CmResourceTypeInterrupt: {
  1838. if (gotInt == 0) {
  1839. gotInt = 1;
  1840. PConfig->TrVector = pPartialTrResourceDesc->u.Interrupt.Vector;
  1841. PConfig->TrIrql = pPartialTrResourceDesc->u.Interrupt.Level;
  1842. PConfig->Affinity = pPartialTrResourceDesc->u.Interrupt.Affinity;
  1843. }
  1844. break;
  1845. }
  1846. default: {
  1847. break;
  1848. }
  1849. } // switch (pPartialTrResourceDesc->Type)
  1850. } // for (i = 0; i < count; i++, pPartialTrResourceDesc++)
  1851. } // if (pFullTrResourceDesc)
  1852. //
  1853. // Initialize a config data structure with default values for those that
  1854. // may not already be initialized.
  1855. //
  1856. PConfig->PortIndex = 0;
  1857. PConfig->DisablePort = 0;
  1858. PConfig->PermitSystemWideShare = FALSE;
  1859. PConfig->MaskInverted = 0;
  1860. PConfig->Indexed = 0;
  1861. PConfig->ForceFifoEnable = driverDefaults.ForceFifoEnableDefault;
  1862. PConfig->RxFIFO = driverDefaults.RxFIFODefault;
  1863. PConfig->TxFIFO = driverDefaults.TxFIFODefault;
  1864. PConfig->PermitShare = driverDefaults.PermitShareDefault;
  1865. PConfig->LogFifo = driverDefaults.LogFifoDefault;
  1866. PConfig->Jensen = driverDefaults.JensenDetected;
  1867. //
  1868. // Query the registry to look for the first bus on
  1869. // the system (that isn't the internal bus - we assume
  1870. // that the firmware code knows about those ports). We
  1871. // will use that as the default bus if no bustype or bus
  1872. // number is specified in the "user" configuration records.
  1873. //
  1874. defaultInterfaceType = (ULONG)Isa;
  1875. defaultClockRate = 1843200;
  1876. for (interfaceType = 0;
  1877. interfaceType < MaximumInterfaceType;
  1878. interfaceType++
  1879. ) {
  1880. ULONG busZero = 0;
  1881. BOOLEAN foundOne = FALSE;
  1882. if (interfaceType != Internal) {
  1883. IoQueryDeviceDescription(
  1884. &interfaceType,
  1885. &busZero,
  1886. NULL,
  1887. NULL,
  1888. NULL,
  1889. NULL,
  1890. SerialItemCallBack,
  1891. &foundOne
  1892. );
  1893. if (foundOne) {
  1894. defaultInterfaceType = (ULONG)interfaceType;
  1895. if (defaultInterfaceType == MicroChannel) {
  1896. defaultInterruptMode = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
  1897. }
  1898. break;
  1899. }
  1900. } // if (interfaceType != Internal)
  1901. } // for (interfaceType = 0
  1902. //
  1903. // Get any user data associated with the port now and override the
  1904. // values passed in if applicable. If this a legacy device, this
  1905. // is where we may actually get the parameters.
  1906. //
  1907. //
  1908. // Open the "Device Parameters" section of registry for this device object.
  1909. // If PUserData is NULL, this is PnP enumerated and we need to check,
  1910. // otherwise we are doing a legacy device and have the info already.
  1911. //
  1912. if (PUserData == NULL) {
  1913. status = IoOpenDeviceRegistryKey (pDevExt->Pdo,
  1914. PLUGPLAY_REGKEY_DEVICE,
  1915. STANDARD_RIGHTS_READ,
  1916. &keyHandle);
  1917. if (!NT_SUCCESS(status)) {
  1918. SerialDump(SERERRORS, ("SERIAL: IoOpenDeviceRegistryKey failed - %x "
  1919. "\n", status));
  1920. goto PortInfoCleanUp;
  1921. } else {
  1922. status = SerialGetRegistryKeyValue (keyHandle,
  1923. L"DisablePort",
  1924. sizeof(L"DisablePort"),
  1925. &PConfig->DisablePort,
  1926. sizeof (ULONG));
  1927. status = SerialGetRegistryKeyValue (keyHandle,
  1928. L"ForceFifoEnable",
  1929. sizeof(L"ForceFifoEnable"),
  1930. &PConfig->ForceFifoEnable,
  1931. sizeof (ULONG));
  1932. status = SerialGetRegistryKeyValue (keyHandle,
  1933. L"RxFIFO",
  1934. sizeof(L"RxFIFO"),
  1935. &PConfig->RxFIFO,
  1936. sizeof (ULONG));
  1937. status = SerialGetRegistryKeyValue (keyHandle,
  1938. L"TxFIFO",
  1939. sizeof(L"TxFIFO"),
  1940. &PConfig->TxFIFO,
  1941. sizeof (ULONG));
  1942. status = SerialGetRegistryKeyValue (keyHandle,
  1943. L"MaskInverted",
  1944. sizeof(L"MaskInverted"),
  1945. &PConfig->MaskInverted,
  1946. sizeof (ULONG));
  1947. status = SerialGetRegistryKeyValue (keyHandle,
  1948. L"Share System Interrupt",
  1949. sizeof(L"Share System Interrupt"),
  1950. &PConfig->PermitShare,
  1951. sizeof (ULONG));
  1952. status = SerialGetRegistryKeyValue (keyHandle,
  1953. L"PortIndex",
  1954. sizeof(L"PortIndex"),
  1955. &PConfig->PortIndex,
  1956. sizeof (ULONG));
  1957. status = SerialGetRegistryKeyValue(keyHandle, L"Indexed",
  1958. sizeof(L"Indexed"),
  1959. &PConfig->Indexed,
  1960. sizeof(ULONG));
  1961. status = SerialGetRegistryKeyValue (keyHandle,
  1962. L"ClockRate",
  1963. sizeof(L"ClockRate"),
  1964. &PConfig->ClockRate,
  1965. sizeof (ULONG));
  1966. if (!NT_SUCCESS(status)) {
  1967. PConfig->ClockRate = defaultClockRate;
  1968. }
  1969. ZwClose (keyHandle);
  1970. }
  1971. } else {
  1972. //
  1973. // This was a legacy device, either use a driver default or copy over
  1974. // the user-specified values.
  1975. //
  1976. ULONG badValue = (ULONG)-1;
  1977. PConfig->DisablePort = (PUserData->DisablePort == badValue)
  1978. ? 0
  1979. : PUserData->DisablePort;
  1980. PConfig->ForceFifoEnable = (PUserData->ForceFIFOEnable == badValue)
  1981. ? PUserData->ForceFIFOEnableDefault
  1982. : PUserData->ForceFIFOEnable;
  1983. PConfig->RxFIFO = (PUserData->RxFIFO == badValue)
  1984. ? PUserData->RxFIFODefault
  1985. : PUserData->RxFIFO;
  1986. PConfig->Indexed = (PUserData->UserIndexed == badValue)
  1987. ? 0
  1988. : PUserData->UserIndexed;
  1989. PConfig->TxFIFO = (PUserData->TxFIFO == badValue)
  1990. ? PUserData->TxFIFODefault
  1991. : PUserData->TxFIFO;
  1992. PConfig->MaskInverted = (PUserData->MaskInverted == badValue)
  1993. ? 0
  1994. : PUserData->MaskInverted;
  1995. PConfig->ClockRate = (PUserData->UserClockRate == badValue)
  1996. ? defaultClockRate
  1997. : PUserData->UserClockRate;
  1998. PConfig->PermitShare = PUserData->PermitShareDefault;
  1999. PConfig->PortIndex = PUserData->UserPortIndex;
  2000. }
  2001. //
  2002. // Do some error checking on the configuration info we have.
  2003. //
  2004. // Make sure that the interrupt is non zero (which we defaulted
  2005. // it to).
  2006. //
  2007. // Make sure that the portaddress is non zero (which we defaulted
  2008. // it to).
  2009. //
  2010. // Make sure that the DosDevices is not NULL (which we defaulted
  2011. // it to).
  2012. //
  2013. // We need to make sure that if an interrupt status
  2014. // was specified, that a port index was also specfied,
  2015. // and if so that the port index is <= maximum ports
  2016. // on a board.
  2017. //
  2018. // We should also validate that the bus type and number
  2019. // are correct.
  2020. //
  2021. // We will also validate that the interrupt mode makes
  2022. // sense for the bus.
  2023. //
  2024. if (!PConfig->Controller.LowPart) {
  2025. //
  2026. // Ehhhh! Lose Game.
  2027. //
  2028. SerialLogError(
  2029. PDevObj->DriverObject,
  2030. NULL,
  2031. PConfig->Controller,
  2032. SerialPhysicalZero,
  2033. 0,
  2034. 0,
  2035. 0,
  2036. 58,
  2037. STATUS_SUCCESS,
  2038. SERIAL_INVALID_USER_CONFIG,
  2039. 0,
  2040. NULL,
  2041. sizeof(L"PortAddress") + sizeof(WCHAR),
  2042. L"PortAddress"
  2043. );
  2044. SerialDump (SERERRORS,
  2045. ("SERIAL: Bogus port address %x\n",
  2046. PConfig->Controller.LowPart));
  2047. status = SERIAL_INVALID_USER_CONFIG;
  2048. goto PortInfoCleanUp;
  2049. }
  2050. if (!PConfig->OriginalVector) {
  2051. //
  2052. // Ehhhh! Lose Game.
  2053. //
  2054. SerialLogError(
  2055. pDevExt->DriverObject,
  2056. NULL,
  2057. PConfig->Controller,
  2058. SerialPhysicalZero,
  2059. 0,
  2060. 0,
  2061. 0,
  2062. 59,
  2063. STATUS_SUCCESS,
  2064. SERIAL_INVALID_USER_CONFIG,
  2065. pDevExt->DeviceName.Length,
  2066. pDevExt->DeviceName.Buffer,
  2067. sizeof (L"Interrupt"),
  2068. L"Interrupt"
  2069. );
  2070. SerialDump (SERERRORS,("SERIAL: Bogus vector %x\n",
  2071. PConfig->OriginalVector));
  2072. status = SERIAL_INVALID_USER_CONFIG;
  2073. goto PortInfoCleanUp;
  2074. }
  2075. if (PConfig->InterruptStatus.LowPart != 0) {
  2076. if (PConfig->PortIndex == MAXULONG) {
  2077. //
  2078. // Ehhhh! Lose Game.
  2079. //
  2080. SerialLogError(
  2081. pDevExt->DriverObject,
  2082. NULL,
  2083. PConfig->Controller,
  2084. SerialPhysicalZero,
  2085. 0,
  2086. 0,
  2087. 0,
  2088. 30,
  2089. STATUS_SUCCESS,
  2090. SERIAL_INVALID_PORT_INDEX,
  2091. 0,
  2092. NULL,
  2093. 0,
  2094. NULL
  2095. );
  2096. SerialDump (SERERRORS,
  2097. ("SERIAL: Bogus port index %x\n", PConfig->PortIndex));
  2098. status = SERIAL_INVALID_PORT_INDEX;
  2099. goto PortInfoCleanUp;
  2100. } else if (!PConfig->PortIndex) {
  2101. //
  2102. // So sorry, you must have a non-zero port index.
  2103. //
  2104. SerialLogError(
  2105. pDevExt->DriverObject,
  2106. NULL,
  2107. PConfig->Controller,
  2108. SerialPhysicalZero,
  2109. 0,
  2110. 0,
  2111. 0,
  2112. 31,
  2113. STATUS_SUCCESS,
  2114. SERIAL_INVALID_PORT_INDEX,
  2115. 0,
  2116. NULL,
  2117. 0,
  2118. NULL
  2119. );
  2120. SerialDump(
  2121. SERERRORS,
  2122. ("SERIAL: Port index must be > 0 for any\n"
  2123. "------- port on a multiport card: %x\n",
  2124. PConfig->PortIndex)
  2125. );
  2126. status = SERIAL_INVALID_PORT_INDEX;
  2127. goto PortInfoCleanUp;
  2128. } else {
  2129. if (PConfig->Indexed) {
  2130. if (PConfig->PortIndex > SERIAL_MAX_PORTS_INDEXED) {
  2131. SerialLogError(
  2132. pDevExt->DriverObject,
  2133. NULL,
  2134. PConfig->Controller,
  2135. SerialPhysicalZero,
  2136. 0,
  2137. 0,
  2138. 0,
  2139. 32,
  2140. STATUS_SUCCESS,
  2141. SERIAL_PORT_INDEX_TOO_HIGH,
  2142. 0,
  2143. NULL,
  2144. 0,
  2145. NULL
  2146. );
  2147. SerialDump (SERERRORS,
  2148. ("SERIAL: port index to large %x\n",
  2149. PConfig->PortIndex));
  2150. status = SERIAL_PORT_INDEX_TOO_HIGH;
  2151. goto PortInfoCleanUp;
  2152. }
  2153. } else {
  2154. if (PConfig->PortIndex > SERIAL_MAX_PORTS_NONINDEXED) {
  2155. SerialLogError(
  2156. pDevExt->DriverObject,
  2157. NULL,
  2158. PConfig->Controller,
  2159. SerialPhysicalZero,
  2160. 0,
  2161. 0,
  2162. 0,
  2163. 33,
  2164. STATUS_SUCCESS,
  2165. SERIAL_PORT_INDEX_TOO_HIGH,
  2166. 0,
  2167. NULL,
  2168. 0,
  2169. NULL
  2170. );
  2171. SerialDump (SERERRORS,
  2172. ("SERIAL: port index to large %x\n",
  2173. PConfig->PortIndex));
  2174. status = SERIAL_PORT_INDEX_TOO_HIGH;
  2175. goto PortInfoCleanUp;
  2176. }
  2177. }
  2178. } // else (if !PConfig->PortIndex)
  2179. } // if (PConfig->InterruptStatus != 0)
  2180. //
  2181. // We don't want to cause the hal to have a bad day,
  2182. // so let's check the interface type and bus number.
  2183. //
  2184. // We only need to check the registry if they aren't
  2185. // equal to the defaults.
  2186. //
  2187. if (PConfig->BusNumber != 0) {
  2188. BOOLEAN foundIt;
  2189. if (PConfig->InterfaceType >= MaximumInterfaceType) {
  2190. //
  2191. // Ehhhh! Lose Game.
  2192. //
  2193. SerialLogError(
  2194. pDevExt->DriverObject,
  2195. NULL,
  2196. PConfig->Controller,
  2197. SerialPhysicalZero,
  2198. 0,
  2199. 0,
  2200. 0,
  2201. 34,
  2202. STATUS_SUCCESS,
  2203. SERIAL_UNKNOWN_BUS,
  2204. 0,
  2205. NULL,
  2206. 0,
  2207. NULL
  2208. );
  2209. SerialDump (SERERRORS,
  2210. ("SERIAL: Invalid Bus type %x\n", PConfig->BusNumber));
  2211. status = SERIAL_UNKNOWN_BUS;
  2212. goto PortInfoCleanUp;
  2213. }
  2214. IoQueryDeviceDescription(
  2215. (INTERFACE_TYPE *)&PConfig->InterfaceType,
  2216. &zero,
  2217. NULL,
  2218. NULL,
  2219. NULL,
  2220. NULL,
  2221. SerialItemCallBack,
  2222. &foundIt
  2223. );
  2224. if (!foundIt) {
  2225. SerialLogError(
  2226. pDevExt->DriverObject,
  2227. NULL,
  2228. PConfig->Controller,
  2229. SerialPhysicalZero,
  2230. 0,
  2231. 0,
  2232. 0,
  2233. 35,
  2234. STATUS_SUCCESS,
  2235. SERIAL_BUS_NOT_PRESENT,
  2236. 0,
  2237. NULL,
  2238. 0,
  2239. NULL
  2240. );
  2241. SerialDump(
  2242. SERERRORS,
  2243. ("SERIAL: There aren't that many of those\n"
  2244. "------- busses on this system,%x\n",
  2245. PConfig->BusNumber)
  2246. );
  2247. status = SERIAL_BUS_NOT_PRESENT;
  2248. goto PortInfoCleanUp;
  2249. }
  2250. } // if (PConfig->BusNumber != 0)
  2251. if ((PConfig->InterfaceType == MicroChannel) &&
  2252. (PConfig->InterruptMode == CM_RESOURCE_INTERRUPT_LATCHED)) {
  2253. SerialLogError(
  2254. pDevExt->DriverObject,
  2255. NULL,
  2256. PConfig->Controller,
  2257. SerialPhysicalZero,
  2258. 0,
  2259. 0,
  2260. 0,
  2261. 36,
  2262. STATUS_SUCCESS,
  2263. SERIAL_BUS_INTERRUPT_CONFLICT,
  2264. 0,
  2265. NULL,
  2266. 0,
  2267. NULL
  2268. );
  2269. SerialDump(
  2270. SERERRORS,
  2271. ("SERIAL: Latched interrupts and MicroChannel\n"
  2272. "------- busses don't mix\n")
  2273. );
  2274. status = SERIAL_BUS_INTERRUPT_CONFLICT;
  2275. goto PortInfoCleanUp;
  2276. }
  2277. status = STATUS_SUCCESS;
  2278. //
  2279. // Dump out the port configuration.
  2280. //
  2281. SerialDump(SERDIAG1, ("SERIAL: Com Port address: %x\n",
  2282. PConfig->Controller.LowPart));
  2283. SerialDump(SERDIAG1, ("SERIAL: Com Interrupt Status: %x\n",
  2284. PConfig->InterruptStatus));
  2285. SerialDump(SERDIAG1, ("SERIAL: Com Port Index: %x\n",
  2286. PConfig->PortIndex));
  2287. SerialDump(SERDIAG1, ("SERIAL: Com Port ClockRate: %x\n",
  2288. PConfig->ClockRate));
  2289. SerialDump(SERDIAG1, ("SERIAL: Com Port BusNumber: %x\n",
  2290. PConfig->BusNumber));
  2291. SerialDump(SERDIAG1, ("SERIAL: Com AddressSpace: %x\n",
  2292. PConfig->AddressSpace));
  2293. SerialDump(SERDIAG1, ("SERIAL: Com InterruptMode: %x\n",
  2294. PConfig->InterruptMode));
  2295. SerialDump(SERDIAG1, ("SERIAL: Com InterfaceType: %x\n",
  2296. PConfig->InterfaceType));
  2297. SerialDump(SERDIAG1, ("SERIAL: Com OriginalVector: %x\n",
  2298. PConfig->OriginalVector));
  2299. SerialDump(SERDIAG1, ("SERIAL: Com OriginalIrql: %x\n",
  2300. PConfig->OriginalIrql));
  2301. SerialDump(SERDIAG1, ("SERIAL: Com Indexed: %x\n",
  2302. PConfig->Indexed));
  2303. PortInfoCleanUp:;
  2304. return status;
  2305. }
  2306. NTSTATUS
  2307. SerialDoExternalNaming(IN PSERIAL_DEVICE_EXTENSION PDevExt,
  2308. IN PDRIVER_OBJECT PDrvObj)
  2309. /*++
  2310. Routine Description:
  2311. This routine will be used to create a symbolic link
  2312. to the driver name in the given object directory.
  2313. It will also create an entry in the device map for
  2314. this device - IF we could create the symbolic link.
  2315. Arguments:
  2316. Extension - Pointer to the device extension.
  2317. Return Value:
  2318. None.
  2319. --*/
  2320. {
  2321. NTSTATUS status = STATUS_SUCCESS;
  2322. HANDLE keyHandle;
  2323. WCHAR *pRegName = NULL;
  2324. UNICODE_STRING linkName;
  2325. PDEVICE_OBJECT pLowerDevObj, pDevObj;
  2326. ULONG bufLen;
  2327. PAGED_CODE();
  2328. pDevObj = PDevExt->DeviceObject;
  2329. pLowerDevObj = PDevExt->LowerDeviceObject;
  2330. status = IoOpenDeviceRegistryKey(PDevExt->Pdo, PLUGPLAY_REGKEY_DEVICE,
  2331. STANDARD_RIGHTS_READ, &keyHandle);
  2332. //
  2333. // Check to see if we are allowed to do external naming; if not,
  2334. // then we just return success
  2335. //
  2336. if (status != STATUS_SUCCESS) {
  2337. return status;
  2338. }
  2339. SerialGetRegistryKeyValue(keyHandle, L"SerialSkipExternalNaming",
  2340. sizeof(L"SerialSkipExternalNaming"),
  2341. &PDevExt->SkipNaming, sizeof(ULONG));
  2342. if (PDevExt->SkipNaming) {
  2343. ZwClose(keyHandle);
  2344. return STATUS_SUCCESS;
  2345. }
  2346. RtlZeroMemory(&linkName, sizeof(UNICODE_STRING));
  2347. linkName.MaximumLength = SYMBOLIC_NAME_LENGTH*sizeof(WCHAR);
  2348. linkName.Buffer = ExAllocatePool(PagedPool, linkName.MaximumLength
  2349. + sizeof(WCHAR));
  2350. if (linkName.Buffer == NULL) {
  2351. SerialLogError(PDrvObj, pDevObj, SerialPhysicalZero, SerialPhysicalZero,
  2352. 0, 0, 0, 19, STATUS_SUCCESS, SERIAL_INSUFFICIENT_RESOURCES,
  2353. 0, NULL, 0, NULL);
  2354. SerialDump(SERERRORS, ("SERIAL: Couldn't allocate memory for device name"
  2355. "\n"));
  2356. status = STATUS_INSUFFICIENT_RESOURCES;
  2357. ZwClose(keyHandle);
  2358. goto SerialDoExternalNamingError;
  2359. }
  2360. RtlZeroMemory(linkName.Buffer, linkName.MaximumLength + sizeof(WCHAR));
  2361. pRegName = ExAllocatePool(PagedPool, SYMBOLIC_NAME_LENGTH * sizeof(WCHAR)
  2362. + sizeof(WCHAR));
  2363. if (pRegName == NULL) {
  2364. SerialLogError(PDrvObj, pDevObj, SerialPhysicalZero, SerialPhysicalZero,
  2365. 0, 0, 0, 19, STATUS_SUCCESS, SERIAL_INSUFFICIENT_RESOURCES,
  2366. 0, NULL, 0, NULL);
  2367. SerialDump(SERERRORS, ("SERIAL: Couldn't allocate memory for buffer"
  2368. "\n"));
  2369. status = STATUS_INSUFFICIENT_RESOURCES;
  2370. ZwClose(keyHandle);
  2371. goto SerialDoExternalNamingError;
  2372. }
  2373. //
  2374. // Fetch PortName which contains the suggested REG_SZ symbolic name.
  2375. //
  2376. status = SerialGetRegistryKeyValue(keyHandle, L"PortName",
  2377. sizeof(L"PortName"), pRegName,
  2378. SYMBOLIC_NAME_LENGTH * sizeof(WCHAR));
  2379. if (!NT_SUCCESS(status)) {
  2380. //
  2381. // This is for PCMCIA which currently puts the name under Identifier.
  2382. //
  2383. status = SerialGetRegistryKeyValue(keyHandle, L"Identifier",
  2384. sizeof(L"Identifier"),
  2385. pRegName, SYMBOLIC_NAME_LENGTH
  2386. * sizeof(WCHAR));
  2387. if (!NT_SUCCESS(status)) {
  2388. //
  2389. // Hmm. Either we have to pick a name or bail...
  2390. //
  2391. // ...we will bail.
  2392. //
  2393. SerialDump(SERERRORS, ("SERIAL: Getting PortName/Identifier failed - "
  2394. "%x\n", status));
  2395. ZwClose (keyHandle);
  2396. goto SerialDoExternalNamingError;
  2397. }
  2398. }
  2399. ZwClose (keyHandle);
  2400. bufLen = wcslen(pRegName) * sizeof(WCHAR) + sizeof(UNICODE_NULL);
  2401. PDevExt->WmiIdentifier.Buffer = ExAllocatePool(PagedPool, bufLen);
  2402. if (PDevExt->WmiIdentifier.Buffer == NULL) {
  2403. SerialLogError(PDrvObj, pDevObj, SerialPhysicalZero, SerialPhysicalZero,
  2404. 0, 0, 0, 19, STATUS_SUCCESS, SERIAL_INSUFFICIENT_RESOURCES,
  2405. 0, NULL, 0, NULL);
  2406. SerialDump(SERERRORS,
  2407. ("SERIAL: Couldn't allocate memory for WMI name\n"));
  2408. status = STATUS_INSUFFICIENT_RESOURCES;
  2409. goto SerialDoExternalNamingError;
  2410. }
  2411. RtlZeroMemory(PDevExt->WmiIdentifier.Buffer, bufLen);
  2412. PDevExt->WmiIdentifier.Length = 0;
  2413. PDevExt->WmiIdentifier.MaximumLength = (USHORT)bufLen - sizeof(WCHAR);
  2414. RtlAppendUnicodeToString(&PDevExt->WmiIdentifier, pRegName);
  2415. //
  2416. // Create the "\\DosDevices\\<symbolicName>" string
  2417. //
  2418. RtlAppendUnicodeToString(&linkName, L"\\");
  2419. RtlAppendUnicodeToString(&linkName, DEFAULT_DIRECTORY);
  2420. RtlAppendUnicodeToString(&linkName, L"\\");
  2421. RtlAppendUnicodeToString(&linkName, pRegName);
  2422. //
  2423. // Allocate Pool and save the symbolic link name in the device extension.
  2424. //
  2425. PDevExt->SymbolicLinkName.MaximumLength = linkName.Length + sizeof(WCHAR);
  2426. PDevExt->SymbolicLinkName.Buffer
  2427. = ExAllocatePool(PagedPool, PDevExt->SymbolicLinkName.MaximumLength);
  2428. if (!PDevExt->SymbolicLinkName.Buffer) {
  2429. SerialLogError(PDrvObj, pDevObj, SerialPhysicalZero, SerialPhysicalZero,
  2430. 0, 0, 0, 19, STATUS_SUCCESS, SERIAL_INSUFFICIENT_RESOURCES,
  2431. 0, NULL, 0, NULL);
  2432. SerialDump(SERERRORS,
  2433. ("SERIAL: Couldn't allocate memory for symbolic link name\n"));
  2434. status = STATUS_INSUFFICIENT_RESOURCES;
  2435. goto SerialDoExternalNamingError;
  2436. }
  2437. //
  2438. // Zero fill it.
  2439. //
  2440. RtlZeroMemory(PDevExt->SymbolicLinkName.Buffer,
  2441. PDevExt->SymbolicLinkName.MaximumLength);
  2442. RtlAppendUnicodeStringToString(&PDevExt->SymbolicLinkName,
  2443. &linkName);
  2444. PDevExt->DosName.Buffer = ExAllocatePool(PagedPool, 64 + sizeof(WCHAR));
  2445. if (!PDevExt->DosName.Buffer) {
  2446. SerialLogError(PDrvObj, pDevObj, SerialPhysicalZero, SerialPhysicalZero,
  2447. 0, 0, 0, 19, STATUS_SUCCESS, SERIAL_INSUFFICIENT_RESOURCES,
  2448. 0, NULL, 0, NULL);
  2449. SerialDump(SERERRORS,
  2450. ("SERIAL: Couldn't allocate memory for Dos name\n"));
  2451. status = STATUS_INSUFFICIENT_RESOURCES;
  2452. goto SerialDoExternalNamingError;
  2453. }
  2454. PDevExt->DosName.MaximumLength = 64 + sizeof(WCHAR);
  2455. //
  2456. // Zero fill it.
  2457. //
  2458. PDevExt->DosName.Length = 0;
  2459. RtlZeroMemory(PDevExt->DosName.Buffer,
  2460. PDevExt->DosName.MaximumLength);
  2461. RtlAppendUnicodeToString(&PDevExt->DosName, pRegName);
  2462. RtlZeroMemory(((PUCHAR)(&PDevExt->DosName.Buffer[0]))
  2463. + PDevExt->DosName.Length, sizeof(WCHAR));
  2464. SerialDump(SERDIAG1, ("SERIAL: DosName is %wZ\n",
  2465. &PDevExt->DosName));
  2466. //
  2467. status = IoCreateSymbolicLink (&PDevExt->SymbolicLinkName,
  2468. &PDevExt->DeviceName);
  2469. if (!NT_SUCCESS(status)) {
  2470. //
  2471. // Oh well, couldn't create the symbolic link. No point
  2472. // in trying to create the device map entry.
  2473. //
  2474. SerialLogError(PDrvObj, pDevObj, SerialPhysicalZero, SerialPhysicalZero,
  2475. 0, 0, 0, 52, status, SERIAL_NO_SYMLINK_CREATED,
  2476. PDevExt->DeviceName.Length + sizeof(WCHAR),
  2477. PDevExt->DeviceName.Buffer, 0, NULL);
  2478. SerialDump(
  2479. SERERRORS,
  2480. ("SERIAL: Couldn't create the symbolic link\n"
  2481. "------- for port %wZ\n",
  2482. &PDevExt->DeviceName)
  2483. );
  2484. goto SerialDoExternalNamingError;
  2485. }
  2486. PDevExt->CreatedSymbolicLink = TRUE;
  2487. status = RtlWriteRegistryValue(RTL_REGISTRY_DEVICEMAP, L"SERIALCOMM",
  2488. PDevExt->DeviceName.Buffer, REG_SZ,
  2489. PDevExt->DosName.Buffer,
  2490. PDevExt->DosName.Length + sizeof(WCHAR));
  2491. if (!NT_SUCCESS(status)) {
  2492. SerialLogError(PDrvObj, pDevObj, SerialPhysicalZero, SerialPhysicalZero,
  2493. 0, 0, 0, 53, status, SERIAL_NO_DEVICE_MAP_CREATED,
  2494. PDevExt->DeviceName.Length + sizeof(WCHAR),
  2495. PDevExt->DeviceName.Buffer, 0, NULL);
  2496. SerialDump(SERERRORS, ("SERIAL: Couldn't create the device map entry\n"
  2497. "------- for port %wZ\n", &PDevExt->DeviceName));
  2498. goto SerialDoExternalNamingError;
  2499. }
  2500. PDevExt->CreatedSerialCommEntry = TRUE;
  2501. //
  2502. // Make the device visible via a device association as well.
  2503. // The reference string is the eight digit device index
  2504. //
  2505. status = IoRegisterDeviceInterface(PDevExt->Pdo, (LPGUID)&GUID_CLASS_COMPORT,
  2506. NULL, &PDevExt->DeviceClassSymbolicName);
  2507. if (!NT_SUCCESS(status)) {
  2508. SerialDump(SERERRORS, ("SERIAL: Couldn't register class association\n"
  2509. "------- for port %wZ\n",
  2510. &PDevExt->DeviceName));
  2511. PDevExt->DeviceClassSymbolicName.Buffer = NULL;
  2512. goto SerialDoExternalNamingError;
  2513. }
  2514. //
  2515. // Now set the symbolic link for the association
  2516. //
  2517. status = IoSetDeviceInterfaceState(&PDevExt->DeviceClassSymbolicName,
  2518. TRUE);
  2519. if (!NT_SUCCESS(status)) {
  2520. SerialDump(SERERRORS, ("SERIAL: Couldn't set class association\n"
  2521. "------- for port %wZ\n",
  2522. &PDevExt->DeviceName));
  2523. }
  2524. SerialDoExternalNamingError:;
  2525. //
  2526. // Clean up error conditions
  2527. //
  2528. if (!NT_SUCCESS(status)) {
  2529. if (PDevExt->DosName.Buffer != NULL) {
  2530. ExFreePool(PDevExt->DosName.Buffer);
  2531. PDevExt->DosName.Buffer = NULL;
  2532. }
  2533. if (PDevExt->CreatedSymbolicLink == TRUE) {
  2534. IoDeleteSymbolicLink(&PDevExt->SymbolicLinkName);
  2535. PDevExt->CreatedSymbolicLink = FALSE;
  2536. }
  2537. if (PDevExt->SymbolicLinkName.Buffer != NULL) {
  2538. ExFreePool(PDevExt->SymbolicLinkName.Buffer);
  2539. PDevExt->SymbolicLinkName.Buffer = NULL;
  2540. }
  2541. if (PDevExt->DeviceName.Buffer != NULL) {
  2542. RtlDeleteRegistryValue(RTL_REGISTRY_DEVICEMAP, SERIAL_DEVICE_MAP,
  2543. PDevExt->DeviceName.Buffer);
  2544. }
  2545. if (PDevExt->DeviceClassSymbolicName.Buffer) {
  2546. IoSetDeviceInterfaceState (&PDevExt->DeviceClassSymbolicName, FALSE);
  2547. }
  2548. if (PDevExt->WmiIdentifier.Buffer != NULL) {
  2549. ExFreePool(PDevExt->WmiIdentifier.Buffer);
  2550. PDevExt->WmiIdentifier.Buffer = NULL;
  2551. }
  2552. }
  2553. //
  2554. // Always clean up our temp buffers.
  2555. //
  2556. if (linkName.Buffer != NULL) {
  2557. ExFreePool(linkName.Buffer);
  2558. }
  2559. if (pRegName != NULL) {
  2560. ExFreePool(pRegName);
  2561. }
  2562. return status;
  2563. }
  2564. VOID
  2565. SerialUndoExternalNaming(IN PSERIAL_DEVICE_EXTENSION Extension)
  2566. /*++
  2567. Routine Description:
  2568. This routine will be used to delete a symbolic link
  2569. to the driver name in the given object directory.
  2570. It will also delete an entry in the device map for
  2571. this device if the symbolic link had been created.
  2572. Arguments:
  2573. Extension - Pointer to the device extension.
  2574. Return Value:
  2575. None.
  2576. --*/
  2577. {
  2578. NTSTATUS status;
  2579. PAGED_CODE();
  2580. SerialDump(
  2581. SERDIAG3,
  2582. ("SERIAL: In SerialUndoExternalNaming for\n"
  2583. "------- extension: %x of port %wZ\n",
  2584. Extension,&Extension->DeviceName)
  2585. );
  2586. //
  2587. // Maybe there is nothing for us to do
  2588. //
  2589. if (Extension->SkipNaming) {
  2590. return;
  2591. }
  2592. //
  2593. // We're cleaning up here. One reason we're cleaning up
  2594. // is that we couldn't allocate space for the directory
  2595. // name or the symbolic link.
  2596. //
  2597. if (Extension->SymbolicLinkName.Buffer &&
  2598. Extension->CreatedSymbolicLink) {
  2599. if (Extension->DeviceClassSymbolicName.Buffer) {
  2600. status = IoSetDeviceInterfaceState (&Extension->
  2601. DeviceClassSymbolicName,
  2602. FALSE);
  2603. //
  2604. // IoRegisterDeviceClassInterface() allocated this string for us,
  2605. // and we no longer need it.
  2606. //
  2607. ExFreePool( Extension->DeviceClassSymbolicName.Buffer );
  2608. }
  2609. IoDeleteSymbolicLink (&Extension->SymbolicLinkName);
  2610. }
  2611. if (Extension->WmiIdentifier.Buffer) {
  2612. ExFreePool(Extension->WmiIdentifier.Buffer);
  2613. Extension->WmiIdentifier.MaximumLength
  2614. = Extension->WmiIdentifier.Length = 0;
  2615. Extension->WmiIdentifier.Buffer = NULL;
  2616. }
  2617. //
  2618. // We're cleaning up here. One reason we're cleaning up
  2619. // is that we couldn't allocate space for the NtNameOfPort.
  2620. //
  2621. if ((Extension->DeviceName.Buffer != NULL)
  2622. && Extension->CreatedSerialCommEntry) {
  2623. status = RtlDeleteRegistryValue(RTL_REGISTRY_DEVICEMAP, SERIAL_DEVICE_MAP,
  2624. Extension->DeviceName.Buffer);
  2625. if (!NT_SUCCESS(status)) {
  2626. SerialLogError(
  2627. Extension->DeviceObject->DriverObject,
  2628. Extension->DeviceObject,
  2629. Extension->OriginalController,
  2630. SerialPhysicalZero,
  2631. 0,
  2632. 0,
  2633. 0,
  2634. 55,
  2635. status,
  2636. SERIAL_NO_DEVICE_MAP_DELETED,
  2637. Extension->DeviceName.Length+sizeof(WCHAR),
  2638. Extension->DeviceName.Buffer,
  2639. 0,
  2640. NULL
  2641. );
  2642. SerialDump(
  2643. SERERRORS,
  2644. ("SERIAL: Couldn't delete value entry %wZ\n",
  2645. &Extension->DeviceName)
  2646. );
  2647. }
  2648. }
  2649. }