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.

3631 lines
107 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_INSUFFICIENT_RESOURCES;
  102. }
  103. RtlZeroMemory(deviceObjName.Buffer, deviceObjName.MaximumLength
  104. + sizeof(WCHAR));
  105. #if defined(NEC_98)
  106. RtlAppendUnicodeToString(&deviceObjName, L"\\Device\\Ser101");
  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. #if defined(NEC_98)
  622. for (j = 0; (j < pResList->Count); j++) {
  623. pResDesc = &pResList->Descriptors[j];
  624. if (isMulti && pResDesc->Type == CmResourceTypePort) {
  625. pResDesc->ShareDisposition = CmResourceShareShared;
  626. SerialDump(SERPNPPOWER, ("------- Sharing I/O port for "
  627. "device %x\n", pLowerDevObj));
  628. }
  629. }
  630. #else
  631. gotISR = 0;
  632. gotInt = 0;
  633. SerialDump(SERPNPPOWER, ("------- List has %x resources in it\n",
  634. pResList->Count));
  635. for (j = 0; (j < pResList->Count); j++) {
  636. pResDesc = &pResList->Descriptors[j];
  637. switch (pResDesc->Type) {
  638. case CmResourceTypePort:
  639. if (isMulti
  640. && (pResDesc->u.Port.Length == SERIAL_STATUS_LENGTH)
  641. && !gotISR) {
  642. gotISR = 1;
  643. pResDesc->ShareDisposition = CmResourceShareShared;
  644. SerialDump(SERPNPPOWER, ("------- Sharing I/O port for "
  645. "device %x\n", pLowerDevObj));
  646. }
  647. break;
  648. case CmResourceTypeInterrupt:
  649. if (!gotInt) {
  650. gotInt = 1;
  651. if (pResDesc->ShareDisposition != CmResourceShareShared) {
  652. pResDesc->ShareDisposition = CmResourceShareShared;
  653. SerialDump(SERPNPPOWER, ("------- Sharing interrupt "
  654. "for device %x\n",
  655. pLowerDevObj));
  656. } else {
  657. pDevExt->InterruptShareable = TRUE;
  658. SerialDump(SERPNPPOWER, ("------- Globally sharing "
  659. " interrupt for device %x\n",
  660. pLowerDevObj));
  661. }
  662. }
  663. break;
  664. default:
  665. break;
  666. }
  667. //
  668. // If we found what we need, we can break out of the loop
  669. //
  670. if ((isMulti && gotInt && gotISR) || (!isMulti && gotInt)) {
  671. break;
  672. }
  673. }
  674. pResList = (PIO_RESOURCE_LIST)((PUCHAR)pResList
  675. + sizeof(IO_RESOURCE_LIST)
  676. + sizeof(IO_RESOURCE_DESCRIPTOR)
  677. * (pResList->Count - 1));
  678. #endif
  679. }
  680. PIrp->IoStatus.Status = STATUS_SUCCESS;
  681. SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  682. return STATUS_SUCCESS;
  683. }
  684. case IRP_MN_QUERY_PNP_DEVICE_STATE:
  685. {
  686. if (pDevExt->Flags & SERIAL_FLAGS_BROKENHW) {
  687. (PNP_DEVICE_STATE)PIrp->IoStatus.Information |= PNP_DEVICE_FAILED;
  688. PIrp->IoStatus.Status = STATUS_SUCCESS;
  689. }
  690. IoCopyCurrentIrpStackLocationToNext(PIrp);
  691. return SerialIoCallDriver(pDevExt, pLowerDevObj, PIrp);
  692. }
  693. case IRP_MN_STOP_DEVICE:
  694. {
  695. ULONG pendingIRPs;
  696. KIRQL oldIrql;
  697. SerialDump(SERPNPPOWER, ("SERIAL: Got IRP_MN_STOP_DEVICE Irp\n"));
  698. SerialDump(SERPNPPOWER, ("------- for device %x\n", pLowerDevObj));
  699. ASSERT(!pDevExt->PortOnAMultiportCard);
  700. SerialSetFlags(pDevExt, SERIAL_FLAGS_STOPPED);
  701. SerialSetAccept(pDevExt,SERIAL_PNPACCEPT_STOPPED);
  702. SerialClearAccept(pDevExt, SERIAL_PNPACCEPT_STOPPING);
  703. pDevExt->PNPState = SERIAL_PNP_STOPPING;
  704. //
  705. // From this point on all non-PNP IRP's will be queued
  706. //
  707. //
  708. // Decrement for entry here
  709. //
  710. InterlockedDecrement(&pDevExt->PendingIRPCnt);
  711. //
  712. // Decrement for stopping
  713. //
  714. pendingIRPs = InterlockedDecrement(&pDevExt->PendingIRPCnt);
  715. if (pendingIRPs) {
  716. KeWaitForSingleObject(&pDevExt->PendingIRPEvent, Executive,
  717. KernelMode, FALSE, NULL);
  718. }
  719. //
  720. // Re-increment the count for later
  721. //
  722. InterlockedIncrement(&pDevExt->PendingIRPCnt);
  723. //
  724. // We need to free resources...basically this is a remove
  725. // without the detach from the stack.
  726. //
  727. if (pDevExt->Flags & SERIAL_FLAGS_STARTED) {
  728. SerialReleaseResources(pDevExt);
  729. }
  730. //
  731. // Pass the irp down
  732. //
  733. PIrp->IoStatus.Status = STATUS_SUCCESS;
  734. IoSkipCurrentIrpStackLocation(PIrp);
  735. return IoCallDriver(pLowerDevObj, PIrp);
  736. }
  737. case IRP_MN_QUERY_STOP_DEVICE:
  738. {
  739. KIRQL oldIrql;
  740. SerialDump(SERPNPPOWER, ("SERIAL: Got IRP_MN_QUERY_STOP_DEVICE Irp\n")
  741. );
  742. SerialDump(SERPNPPOWER, ("------- for device %x\n", pLowerDevObj));
  743. //
  744. // See if we should succeed a stop query
  745. //
  746. if (pDevExt->PortOnAMultiportCard) {
  747. PIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  748. SerialDump(SERPNPPOWER, ("------- failing; multiport node\n"));
  749. SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  750. return STATUS_NOT_SUPPORTED;
  751. }
  752. //
  753. // If the device hasn't started yet, we ignore this request
  754. // and just pass it down.
  755. //
  756. if (pDevExt->PNPState != SERIAL_PNP_STARTED) {
  757. IoSkipCurrentIrpStackLocation(PIrp);
  758. return SerialIoCallDriver(pDevExt, pLowerDevObj, PIrp);
  759. }
  760. //
  761. // Lock around the open status
  762. //
  763. ExAcquireFastMutex(&pDevExt->OpenMutex);
  764. if (pDevExt->DeviceIsOpened) {
  765. ExReleaseFastMutex(&pDevExt->OpenMutex);
  766. PIrp->IoStatus.Status = STATUS_DEVICE_BUSY;
  767. SerialDump(SERPNPPOWER, ("------- failing; device open\n"));
  768. SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  769. return STATUS_DEVICE_BUSY;
  770. }
  771. pDevExt->PNPState = SERIAL_PNP_QSTOP;
  772. SerialSetAccept(pDevExt, SERIAL_PNPACCEPT_STOPPING);
  773. //
  774. // Unlock around the open status
  775. //
  776. ExReleaseFastMutex(&pDevExt->OpenMutex);
  777. PIrp->IoStatus.Status = STATUS_SUCCESS;
  778. IoCopyCurrentIrpStackLocationToNext(PIrp);
  779. return SerialIoCallDriver(pDevExt, pLowerDevObj, PIrp);
  780. }
  781. case IRP_MN_CANCEL_STOP_DEVICE:
  782. SerialDump(SERPNPPOWER, ("SERIAL: Got "
  783. "IRP_MN_CANCEL_STOP_DEVICE Irp\n"));
  784. SerialDump(SERPNPPOWER, ("------- for device %x\n", pLowerDevObj));
  785. if (pDevExt->PNPState == SERIAL_PNP_QSTOP) {
  786. //
  787. // Restore the device state
  788. //
  789. pDevExt->PNPState = SERIAL_PNP_STARTED;
  790. SerialClearAccept(pDevExt, SERIAL_PNPACCEPT_STOPPING);
  791. }
  792. PIrp->IoStatus.Status = STATUS_SUCCESS;
  793. IoCopyCurrentIrpStackLocationToNext(PIrp);
  794. return SerialIoCallDriver(pDevExt, pLowerDevObj, PIrp);
  795. case IRP_MN_CANCEL_REMOVE_DEVICE:
  796. SerialDump(SERPNPPOWER, ("SERIAL: Got "
  797. "IRP_MN_CANCEL_REMOVE_DEVICE Irp\n"));
  798. SerialDump(SERPNPPOWER, ("------- for device %x\n", pLowerDevObj));
  799. //
  800. // Restore the device state
  801. //
  802. pDevExt->PNPState = SERIAL_PNP_STARTED;
  803. SerialClearAccept(pDevExt, SERIAL_PNPACCEPT_REMOVING);
  804. PIrp->IoStatus.Status = STATUS_SUCCESS;
  805. IoCopyCurrentIrpStackLocationToNext(PIrp);
  806. return SerialIoCallDriver(pDevExt, pLowerDevObj, PIrp);
  807. case IRP_MN_QUERY_REMOVE_DEVICE:
  808. {
  809. KIRQL oldIrql;
  810. SerialDump(SERPNPPOWER, ("SERIAL: Got "
  811. "IRP_MN_QUERY_REMOVE_DEVICE Irp\n"));
  812. SerialDump(SERPNPPOWER, ("------- for device %x\n", pLowerDevObj));
  813. ExAcquireFastMutex(&pDevExt->OpenMutex);
  814. //
  815. // See if we should succeed a remove query
  816. //
  817. if (pDevExt->DeviceIsOpened) {
  818. ExReleaseFastMutex(&pDevExt->OpenMutex);
  819. PIrp->IoStatus.Status = STATUS_DEVICE_BUSY;
  820. SerialDump(SERPNPPOWER, ("------- failing; device open\n"));
  821. SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  822. return STATUS_DEVICE_BUSY;
  823. }
  824. pDevExt->PNPState = SERIAL_PNP_QREMOVE;
  825. SerialSetAccept(pDevExt, SERIAL_PNPACCEPT_REMOVING);
  826. ExReleaseFastMutex(&pDevExt->OpenMutex);
  827. PIrp->IoStatus.Status = STATUS_SUCCESS;
  828. IoCopyCurrentIrpStackLocationToNext(PIrp);
  829. return SerialIoCallDriver(pDevExt, pLowerDevObj, PIrp);
  830. }
  831. case IRP_MN_SURPRISE_REMOVAL:
  832. {
  833. ULONG pendingIRPs;
  834. KIRQL oldIrql;
  835. SerialDump(SERPNPPOWER, ("SERIAL: Got IRP_MN_SURPRISE_REMOVAL Irp\n"));
  836. SerialDump(SERPNPPOWER, ("------- for device %x\n", pLowerDevObj));
  837. //
  838. // Prevent any new I/O to the device
  839. //
  840. SerialSetAccept(pDevExt, SERIAL_PNPACCEPT_SURPRISE_REMOVING);
  841. //
  842. // Dismiss all pending requests
  843. //
  844. SerialKillPendingIrps(PDevObj);
  845. //
  846. // Wait for any pending requests we raced on.
  847. //
  848. //
  849. // Decrement once for ourselves
  850. //
  851. InterlockedDecrement(&pDevExt->PendingIRPCnt);
  852. //
  853. // Decrement for the remove
  854. //
  855. pendingIRPs = InterlockedDecrement(&pDevExt->PendingIRPCnt);
  856. if (pendingIRPs) {
  857. KeWaitForSingleObject(&pDevExt->PendingIRPEvent, Executive,
  858. KernelMode, FALSE, NULL);
  859. }
  860. //
  861. // Reset for subsequent remove
  862. //
  863. InterlockedIncrement(&pDevExt->PendingIRPCnt);
  864. //
  865. // Remove any external interfaces and release resources
  866. //
  867. SerialDisableInterfacesResources(PDevObj, FALSE);
  868. PIrp->IoStatus.Status = STATUS_SUCCESS;
  869. IoSkipCurrentIrpStackLocation(PIrp);
  870. return SerialIoCallDriver(pDevExt, pLowerDevObj, PIrp);
  871. }
  872. case IRP_MN_REMOVE_DEVICE:
  873. {
  874. ULONG pendingIRPs;
  875. KIRQL oldIrql;
  876. SerialDump(SERPNPPOWER, ("SERIAL: Got IRP_MN_REMOVE_DEVICE Irp\n"));
  877. SerialDump(SERPNPPOWER, ("------- for device %x\n", pLowerDevObj));
  878. //
  879. // If we get this, we have to remove
  880. //
  881. //
  882. // Mark as not accepting requests
  883. //
  884. SerialSetAccept(pDevExt, SERIAL_PNPACCEPT_REMOVING);
  885. //
  886. // Complete all pending requests
  887. //
  888. SerialKillPendingIrps(PDevObj);
  889. //
  890. // Decrement for this Irp itself
  891. //
  892. InterlockedDecrement(&pDevExt->PendingIRPCnt);
  893. //
  894. // Wait for any pending requests we raced on -- this decrement
  895. // is for our "placeholder".
  896. //
  897. pendingIRPs = InterlockedDecrement(&pDevExt->PendingIRPCnt);
  898. if (pendingIRPs) {
  899. KeWaitForSingleObject(&pDevExt->PendingIRPEvent, Executive,
  900. KernelMode, FALSE, NULL);
  901. }
  902. //
  903. // Remove us
  904. //
  905. SerialRemoveDevObj(PDevObj);
  906. //
  907. // Pass the irp down
  908. //
  909. PIrp->IoStatus.Status = STATUS_SUCCESS;
  910. IoCopyCurrentIrpStackLocationToNext(PIrp);
  911. //
  912. // We do decrement here because we incremented on entry here.
  913. //
  914. IoCallDriver(pLowerDevObj, PIrp);
  915. return STATUS_SUCCESS;
  916. }
  917. default:
  918. break;
  919. } // switch (pIrpStack->MinorFunction)
  920. //
  921. // Pass to driver beneath us
  922. //
  923. IoSkipCurrentIrpStackLocation(PIrp);
  924. status = SerialIoCallDriver(pDevExt, pLowerDevObj, PIrp);
  925. return status;
  926. }
  927. UINT32
  928. SerialReportMaxBaudRate(ULONG Bauds)
  929. /*++
  930. Routine Description:
  931. This routine returns the max baud rate given a selection of rates
  932. Arguments:
  933. Bauds - Bit-encoded list of supported bauds
  934. Return Value:
  935. The max baud rate listed in Bauds
  936. --*/
  937. {
  938. PAGED_CODE();
  939. if (Bauds & SERIAL_BAUD_128K) {
  940. return (128U * 1024U);
  941. }
  942. if (Bauds & SERIAL_BAUD_115200) {
  943. return 115200U;
  944. }
  945. if (Bauds & SERIAL_BAUD_56K) {
  946. return (56U * 1024U);
  947. }
  948. if (Bauds & SERIAL_BAUD_57600) {
  949. return 57600U;
  950. }
  951. if (Bauds & SERIAL_BAUD_38400) {
  952. return 38400U;
  953. }
  954. if (Bauds & SERIAL_BAUD_19200) {
  955. return 19200U;
  956. }
  957. if (Bauds & SERIAL_BAUD_14400) {
  958. return 14400U;
  959. }
  960. if (Bauds & SERIAL_BAUD_9600) {
  961. return 9600U;
  962. }
  963. if (Bauds & SERIAL_BAUD_7200) {
  964. return 7200U;
  965. }
  966. if (Bauds & SERIAL_BAUD_4800) {
  967. return 4800U;
  968. }
  969. if (Bauds & SERIAL_BAUD_2400) {
  970. return 2400U;
  971. }
  972. if (Bauds & SERIAL_BAUD_1800) {
  973. return 1800U;
  974. }
  975. if (Bauds & SERIAL_BAUD_1200) {
  976. return 1200U;
  977. }
  978. if (Bauds & SERIAL_BAUD_600) {
  979. return 600U;
  980. }
  981. if (Bauds & SERIAL_BAUD_300) {
  982. return 300U;
  983. }
  984. if (Bauds & SERIAL_BAUD_150) {
  985. return 150U;
  986. }
  987. if (Bauds & SERIAL_BAUD_134_5) {
  988. return 135U; // Close enough
  989. }
  990. if (Bauds & SERIAL_BAUD_110) {
  991. return 110U;
  992. }
  993. if (Bauds & SERIAL_BAUD_075) {
  994. return 75U;
  995. }
  996. //
  997. // We're in bad shape
  998. //
  999. return 0;
  1000. }
  1001. NTSTATUS
  1002. SerialFinishStartDevice(IN PDEVICE_OBJECT PDevObj,
  1003. IN PCM_RESOURCE_LIST PResList,
  1004. IN PCM_RESOURCE_LIST PTrResList,
  1005. PSERIAL_USER_DATA PUserData)
  1006. /*++
  1007. Routine Description:
  1008. This routine does serial-specific procedures to start a device. It
  1009. does this either for a legacy device detected by its registry entries,
  1010. or for a PnP device after the start IRP has been sent down the stack.
  1011. Arguments:
  1012. PDevObj - Pointer to the devobj that is starting
  1013. PResList - Pointer to the untranslated resources needed by this device
  1014. PTrResList - Pointer to the translated resources needed by this device
  1015. PUserData - Pointer to the user-specified resources/attributes
  1016. Return Value:
  1017. STATUS_SUCCESS on success, something else appropriate on failure
  1018. --*/
  1019. {
  1020. PSERIAL_DEVICE_EXTENSION pDevExt = PDevObj->DeviceExtension;
  1021. #if defined(NEC_98)
  1022. //
  1023. // This argument use at MACRO only.
  1024. //
  1025. PSERIAL_DEVICE_EXTENSION Extension = PDevObj->DeviceExtension;
  1026. #else
  1027. #endif //defined(NEC_98)
  1028. NTSTATUS status;
  1029. PCONFIG_DATA pConfig;
  1030. HANDLE pnpKey;
  1031. ULONG one = 1;
  1032. BOOLEAN allocedUserData = FALSE;
  1033. PAGED_CODE();
  1034. //
  1035. // See if this is a restart, and if so don't reallocate the world
  1036. //
  1037. if ((pDevExt->Flags & SERIAL_FLAGS_STOPPED)
  1038. && (pDevExt->Flags & SERIAL_FLAGS_STARTED)) {
  1039. SerialClearFlags(pDevExt, SERIAL_FLAGS_STOPPED);
  1040. pDevExt->PNPState = SERIAL_PNP_RESTARTING;
  1041. //
  1042. // Re-init resource-related things in the extension
  1043. //
  1044. pDevExt->TopLevelOurIsr = NULL;
  1045. pDevExt->TopLevelOurIsrContext = NULL;
  1046. pDevExt->OriginalController = SerialPhysicalZero;
  1047. pDevExt->OriginalInterruptStatus = SerialPhysicalZero;
  1048. pDevExt->OurIsr = NULL;
  1049. pDevExt->OurIsrContext = NULL;
  1050. pDevExt->Controller = NULL;
  1051. pDevExt->InterruptStatus = NULL;
  1052. pDevExt->Interrupt = NULL;
  1053. pDevExt->SpanOfController = 0;
  1054. pDevExt->SpanOfInterruptStatus = 0;
  1055. pDevExt->Vector = 0;
  1056. pDevExt->Irql = 0;
  1057. pDevExt->OriginalVector = 0;
  1058. pDevExt->OriginalIrql = 0;
  1059. pDevExt->AddressSpace = 0;
  1060. pDevExt->BusNumber = 0;
  1061. pDevExt->InterfaceType = 0;
  1062. pDevExt->CIsrSw = NULL;
  1063. ASSERT(PUserData == NULL);
  1064. PUserData = ExAllocatePool(PagedPool, sizeof(SERIAL_USER_DATA));
  1065. if (PUserData == NULL) {
  1066. return STATUS_INSUFFICIENT_RESOURCES;
  1067. }
  1068. allocedUserData = TRUE;
  1069. RtlZeroMemory(PUserData, sizeof(SERIAL_USER_DATA));
  1070. PUserData->DisablePort = FALSE;
  1071. PUserData->UserClockRate = pDevExt->ClockRate;
  1072. PUserData->TxFIFO = pDevExt->TxFifoAmount;
  1073. PUserData->PermitShareDefault = pDevExt->PermitShare;
  1074. //
  1075. // Map betweeen trigger and amount
  1076. //
  1077. switch (pDevExt->RxFifoTrigger) {
  1078. case SERIAL_1_BYTE_HIGH_WATER:
  1079. PUserData->RxFIFO = 1;
  1080. break;
  1081. case SERIAL_4_BYTE_HIGH_WATER:
  1082. PUserData->RxFIFO = 4;
  1083. break;
  1084. case SERIAL_8_BYTE_HIGH_WATER:
  1085. PUserData->RxFIFO = 8;
  1086. break;
  1087. case SERIAL_14_BYTE_HIGH_WATER:
  1088. PUserData->RxFIFO = 14;
  1089. break;
  1090. default:
  1091. PUserData->RxFIFO = 1;
  1092. }
  1093. } else {
  1094. //
  1095. // Mark as serenumerable -- toss status because we can
  1096. // still start without this key.
  1097. //
  1098. status = IoOpenDeviceRegistryKey(pDevExt->Pdo,
  1099. PLUGPLAY_REGKEY_DEVICE,
  1100. STANDARD_RIGHTS_WRITE, &pnpKey);
  1101. if (NT_SUCCESS(status)) {
  1102. ULONG powerPolicy = 0;
  1103. //
  1104. // Find out if we own power policy
  1105. //
  1106. SerialGetRegistryKeyValue(pnpKey, L"SerialRelinquishPowerPolicy",
  1107. sizeof(L"SerialRelinquishPowerPolicy"),
  1108. &powerPolicy, sizeof(ULONG));
  1109. pDevExt->OwnsPowerPolicy = powerPolicy ? FALSE : TRUE;
  1110. ZwClose(pnpKey);
  1111. }
  1112. }
  1113. //
  1114. // Allocate the config record.
  1115. //
  1116. pConfig = ExAllocatePool (PagedPool, sizeof(CONFIG_DATA));
  1117. if (pConfig == NULL) {
  1118. SerialLogError(pDevExt->DriverObject, NULL, SerialPhysicalZero,
  1119. SerialPhysicalZero, 0, 0, 0, 37, STATUS_SUCCESS,
  1120. SERIAL_INSUFFICIENT_RESOURCES, 0, NULL, 0, NULL);
  1121. SerialDump(SERERRORS, ("SERIAL: Couldn't allocate memory for the\n"
  1122. "------ user configuration record\n"));
  1123. status = STATUS_INSUFFICIENT_RESOURCES;
  1124. goto SerialFinishStartDeviceError;
  1125. }
  1126. RtlZeroMemory(pConfig, sizeof(CONFIG_DATA));
  1127. //
  1128. // Get the configuration info for the device.
  1129. //
  1130. status = SerialGetPortInfo(PDevObj, PResList, PTrResList, pConfig,
  1131. PUserData);
  1132. if (!NT_SUCCESS(status)) {
  1133. goto SerialFinishStartDeviceError;
  1134. }
  1135. //
  1136. // See if we are in the proper power state.
  1137. //
  1138. if (pDevExt->PowerState != PowerDeviceD0) {
  1139. status = SerialGotoPowerState(pDevExt->Pdo, pDevExt, PowerDeviceD0);
  1140. if (!NT_SUCCESS(status)) {
  1141. goto SerialFinishStartDeviceError;
  1142. }
  1143. }
  1144. //
  1145. // Find and initialize the controller
  1146. //
  1147. status = SerialFindInitController(PDevObj, pConfig);
  1148. if (!NT_SUCCESS(status)) {
  1149. goto SerialFinishStartDeviceError;
  1150. }
  1151. //
  1152. // The hardware that is set up to NOT interrupt, connect an interrupt.
  1153. //
  1154. //
  1155. // If a device doesn't already have an interrupt and it has an isr then
  1156. // we attempt to connect to the interrupt if it is not shareing with other
  1157. // serial devices. If we fail to connect to an interrupt we will delete
  1158. // this device.
  1159. //
  1160. if (pDevExt != NULL) {
  1161. SerialDump(SERDIAG5, ("SERIAL: pDevExt: Interrupt %x\n"
  1162. "------- OurIsr %x\n",
  1163. pDevExt->Interrupt, pDevExt->OurIsr));
  1164. } else {
  1165. SerialDump(SERERRORS, ("SERIAL: SerialFinishStartDevice got NULL "
  1166. "pDevExt\n"));
  1167. }
  1168. if ((!pDevExt->Interrupt) && (pDevExt->OurIsr)) {
  1169. SerialDump(
  1170. SERDIAG5,
  1171. ("SERIAL: About to connect to interrupt for port %wZ\n"
  1172. "------- address of extension is %x\n",
  1173. &pDevExt->DeviceName, pDevExt)
  1174. );
  1175. SerialDump(SERDIAG5, ("SERIAL: IoConnectInterrupt Args:\n"
  1176. "------- Interrupt %x\n"
  1177. "------- OurIsr %x\n"
  1178. "------- OurIsrContext %x\n"
  1179. "------- NULL\n"
  1180. "------- Vector %x\n"
  1181. "------- Irql %x\n"
  1182. "------- InterruptMode %x\n"
  1183. "------- InterruptShareable %x\n"
  1184. "------- ProcessorAffinity %x\n"
  1185. "------- FALSE\n",
  1186. &pDevExt->Interrupt,
  1187. SerialCIsrSw,
  1188. pDevExt->CIsrSw,
  1189. pDevExt->Vector,
  1190. pDevExt->Irql,
  1191. pConfig->InterruptMode,
  1192. pDevExt->InterruptShareable,
  1193. pConfig->Affinity
  1194. ));
  1195. //
  1196. // Do a just in time construction of the ISR switch.
  1197. //
  1198. pDevExt->CIsrSw->IsrFunc = pDevExt->OurIsr;
  1199. pDevExt->CIsrSw->Context = pDevExt->OurIsrContext;
  1200. status = IoConnectInterrupt(&pDevExt->Interrupt, SerialCIsrSw,
  1201. pDevExt->CIsrSw, NULL,
  1202. pDevExt->Vector, pDevExt->Irql,
  1203. pDevExt->Irql,
  1204. pConfig->InterruptMode,
  1205. pDevExt->InterruptShareable,
  1206. pConfig->Affinity, FALSE);
  1207. if (!NT_SUCCESS(status)) {
  1208. //
  1209. // Hmmm, how'd that happen? Somebody either
  1210. // didn't report their resources, or they
  1211. // sneaked in since the last time I looked.
  1212. //
  1213. // Oh well, delete this device.
  1214. //
  1215. SerialDump(SERERRORS, ("SERIAL: Couldn't connect to interrupt for "
  1216. "%wZ\n", &pDevExt->DeviceName));
  1217. SerialDump(SERERRORS, ("SERIAL: IoConnectInterrupt Args:\n"
  1218. "------- Interrupt %x\n"
  1219. "------- OurIsr %x\n"
  1220. "------- OurIsrContext %x\n"
  1221. "------- NULL\n"
  1222. "------- Vector %x\n"
  1223. "------- Irql %x\n"
  1224. "------- InterruptMode %x\n"
  1225. "------- InterruptShareable %x\n"
  1226. "------- ProcessorAffinity %x\n"
  1227. "------- FALSE\n",
  1228. &pDevExt->Interrupt,
  1229. SerialCIsrSw,
  1230. pDevExt->CIsrSw,
  1231. pDevExt->Vector,
  1232. pDevExt->Irql,
  1233. pConfig->InterruptMode,
  1234. pDevExt->InterruptShareable,
  1235. pConfig->Affinity
  1236. ));
  1237. SerialLogError(PDevObj->DriverObject, PDevObj,
  1238. pDevExt->OriginalController,
  1239. SerialPhysicalZero, 0, 0, 0, 1, status,
  1240. SERIAL_UNREPORTED_IRQL_CONFLICT,
  1241. pDevExt->DeviceName.Length + sizeof(WCHAR),
  1242. pDevExt->DeviceName.Buffer, 0, NULL);
  1243. status = SERIAL_UNREPORTED_IRQL_CONFLICT;
  1244. goto SerialFinishStartDeviceError;
  1245. }
  1246. }
  1247. SerialDump(SERDIAG5, ("Connected interrupt %08X\n", pDevExt->Interrupt));
  1248. //
  1249. // Add the PDevObj to the master list
  1250. //
  1251. InsertTailList(&SerialGlobals.AllDevObjs, &pDevExt->AllDevObjs);
  1252. //
  1253. // Reset the device.
  1254. //
  1255. //
  1256. // While the device isn't open, disable all interrupts.
  1257. //
  1258. DISABLE_ALL_INTERRUPTS (pDevExt->Controller);
  1259. if (pDevExt->Jensen) {
  1260. WRITE_MODEM_CONTROL(
  1261. pDevExt->Controller,
  1262. (UCHAR)SERIAL_MCR_OUT2
  1263. );
  1264. } else {
  1265. WRITE_MODEM_CONTROL(
  1266. pDevExt->Controller,
  1267. (UCHAR)0
  1268. );
  1269. }
  1270. //
  1271. // This should set up everything as it should be when
  1272. // a device is to be opened. We do need to lower the
  1273. // modem lines, and disable the recalcitrant fifo
  1274. // so that it will show up if the user boots to dos.
  1275. //
  1276. KeSynchronizeExecution(
  1277. pDevExt->Interrupt,
  1278. SerialReset,
  1279. pDevExt
  1280. );
  1281. KeSynchronizeExecution( //Disables the fifo.
  1282. pDevExt->Interrupt,
  1283. SerialMarkClose,
  1284. pDevExt
  1285. );
  1286. KeSynchronizeExecution(
  1287. pDevExt->Interrupt,
  1288. SerialClrRTS,
  1289. pDevExt
  1290. );
  1291. KeSynchronizeExecution(
  1292. pDevExt->Interrupt,
  1293. SerialClrDTR,
  1294. pDevExt
  1295. );
  1296. if (pDevExt->PNPState == SERIAL_PNP_ADDED ) {
  1297. //
  1298. // Do the external naming now that the device is accessible.
  1299. //
  1300. status = SerialDoExternalNaming(pDevExt, pDevExt->DeviceObject->
  1301. DriverObject);
  1302. if (!NT_SUCCESS(status)) {
  1303. SerialDump (SERERRORS,("SERIAL: External Naming Failed - Status %x\n",
  1304. status));
  1305. //
  1306. // Allow the device to start anyhow
  1307. //
  1308. status = STATUS_SUCCESS;
  1309. }
  1310. } else {
  1311. SerialDump(SERPNPPOWER, ("Not doing external naming -- state is %x\n",
  1312. pDevExt->PNPState));
  1313. }
  1314. SerialFinishStartDeviceError:;
  1315. if (!NT_SUCCESS (status)) {
  1316. SerialDump(SERDIAG1,("SERIAL: Cleaning up failed start\n"));
  1317. //
  1318. // Resources created by this routine will be cleaned up by the remove
  1319. //
  1320. if (pDevExt->PNPState == SERIAL_PNP_RESTARTING) {
  1321. //
  1322. // Kill all that lives and breathes -- we'll clean up the
  1323. // rest on the impending remove
  1324. //
  1325. SerialKillPendingIrps(PDevObj);
  1326. //
  1327. // In fact, pretend we're removing so we don't take any
  1328. // more irps
  1329. //
  1330. SerialSetAccept(pDevExt, SERIAL_PNPACCEPT_REMOVING);
  1331. SerialClearFlags(pDevExt, SERIAL_FLAGS_STARTED);
  1332. }
  1333. } else { // SUCCESS
  1334. //
  1335. // Fill in WMI hardware data
  1336. //
  1337. pDevExt->WmiHwData.IrqNumber = pDevExt->Irql;
  1338. pDevExt->WmiHwData.IrqLevel = pDevExt->Irql;
  1339. pDevExt->WmiHwData.IrqVector = pDevExt->Vector;
  1340. pDevExt->WmiHwData.IrqAffinityMask = pConfig->Affinity;
  1341. pDevExt->WmiHwData.InterruptType = pConfig->InterruptMode == Latched
  1342. ? SERIAL_WMI_INTTYPE_LATCHED : SERIAL_WMI_INTTYPE_LEVEL;
  1343. pDevExt->WmiHwData.BaseIOAddress = (ULONG_PTR)pDevExt->Controller;
  1344. //
  1345. // Fill in WMI device state data (as defaults)
  1346. //
  1347. pDevExt->WmiCommData.BaudRate = pDevExt->CurrentBaud;
  1348. pDevExt->WmiCommData.BitsPerByte = (pDevExt->LineControl & 0x03) + 5;
  1349. pDevExt->WmiCommData.ParityCheckEnable = (pDevExt->LineControl & 0x08)
  1350. ? TRUE : FALSE;
  1351. switch (pDevExt->LineControl & SERIAL_PARITY_MASK) {
  1352. case SERIAL_NONE_PARITY:
  1353. pDevExt->WmiCommData.Parity = SERIAL_WMI_PARITY_NONE;
  1354. break;
  1355. case SERIAL_ODD_PARITY:
  1356. pDevExt->WmiCommData.Parity = SERIAL_WMI_PARITY_ODD;
  1357. break;
  1358. case SERIAL_EVEN_PARITY:
  1359. pDevExt->WmiCommData.Parity = SERIAL_WMI_PARITY_EVEN;
  1360. break;
  1361. #if defined(NEC_98)
  1362. //
  1363. // COM1 of PC-9800 series is not support MarkParity and SpaceParity.
  1364. //
  1365. #else
  1366. case SERIAL_MARK_PARITY:
  1367. pDevExt->WmiCommData.Parity = SERIAL_WMI_PARITY_MARK;
  1368. break;
  1369. case SERIAL_SPACE_PARITY:
  1370. pDevExt->WmiCommData.Parity = SERIAL_WMI_PARITY_SPACE;
  1371. break;
  1372. #endif //defined(NEC_98)
  1373. default:
  1374. ASSERTMSG(0, "SERIAL: Illegal Parity setting for WMI");
  1375. pDevExt->WmiCommData.Parity = SERIAL_WMI_PARITY_NONE;
  1376. break;
  1377. }
  1378. pDevExt->WmiCommData.StopBits = pDevExt->LineControl & SERIAL_STOP_MASK
  1379. ? (pDevExt->WmiCommData.BitsPerByte == 5 ? SERIAL_WMI_STOP_1_5
  1380. : SERIAL_WMI_STOP_2) : SERIAL_WMI_STOP_1;
  1381. pDevExt->WmiCommData.XoffCharacter = pDevExt->SpecialChars.XoffChar;
  1382. pDevExt->WmiCommData.XoffXmitThreshold = pDevExt->HandFlow.XoffLimit;
  1383. pDevExt->WmiCommData.XonCharacter = pDevExt->SpecialChars.XonChar;
  1384. pDevExt->WmiCommData.XonXmitThreshold = pDevExt->HandFlow.XonLimit;
  1385. pDevExt->WmiCommData.MaximumBaudRate
  1386. = SerialReportMaxBaudRate(pDevExt->SupportedBauds);
  1387. pDevExt->WmiCommData.MaximumOutputBufferSize = (UINT32)((ULONG)-1);
  1388. pDevExt->WmiCommData.MaximumInputBufferSize = (UINT32)((ULONG)-1);
  1389. pDevExt->WmiCommData.Support16BitMode = FALSE;
  1390. pDevExt->WmiCommData.SupportDTRDSR = TRUE;
  1391. pDevExt->WmiCommData.SupportIntervalTimeouts = TRUE;
  1392. pDevExt->WmiCommData.SupportParityCheck = TRUE;
  1393. pDevExt->WmiCommData.SupportRTSCTS = TRUE;
  1394. pDevExt->WmiCommData.SupportXonXoff = TRUE;
  1395. pDevExt->WmiCommData.SettableBaudRate = TRUE;
  1396. pDevExt->WmiCommData.SettableDataBits = TRUE;
  1397. pDevExt->WmiCommData.SettableFlowControl = TRUE;
  1398. pDevExt->WmiCommData.SettableParity = TRUE;
  1399. pDevExt->WmiCommData.SettableParityCheck = TRUE;
  1400. pDevExt->WmiCommData.SettableStopBits = TRUE;
  1401. pDevExt->WmiCommData.IsBusy = FALSE;
  1402. //
  1403. // Fill in wmi perf data (all zero's)
  1404. //
  1405. RtlZeroMemory(&pDevExt->WmiPerfData, sizeof(pDevExt->WmiPerfData));
  1406. if (pDevExt->PNPState == SERIAL_PNP_ADDED) {
  1407. PULONG countSoFar = &IoGetConfigurationInformation()->SerialCount;
  1408. (*countSoFar)++;
  1409. //
  1410. // Register for WMI
  1411. //
  1412. pDevExt->WmiLibInfo.GuidCount = sizeof(SerialWmiGuidList) /
  1413. sizeof(WMIGUIDREGINFO);
  1414. pDevExt->WmiLibInfo.GuidList = SerialWmiGuidList;
  1415. ASSERT (pDevExt->WmiLibInfo.GuidCount == SERIAL_WMI_GUID_LIST_SIZE);
  1416. pDevExt->WmiLibInfo.QueryWmiRegInfo = SerialQueryWmiRegInfo;
  1417. pDevExt->WmiLibInfo.QueryWmiDataBlock = SerialQueryWmiDataBlock;
  1418. pDevExt->WmiLibInfo.SetWmiDataBlock = SerialSetWmiDataBlock;
  1419. pDevExt->WmiLibInfo.SetWmiDataItem = SerialSetWmiDataItem;
  1420. pDevExt->WmiLibInfo.ExecuteWmiMethod = NULL;
  1421. pDevExt->WmiLibInfo.WmiFunctionControl = NULL;
  1422. IoWMIRegistrationControl(PDevObj, WMIREG_ACTION_REGISTER);
  1423. }
  1424. if (pDevExt->PNPState == SERIAL_PNP_RESTARTING) {
  1425. //
  1426. // Release the stalled IRP's
  1427. //
  1428. SerialUnstallIrps(pDevExt);
  1429. }
  1430. pDevExt->PNPState = SERIAL_PNP_STARTED;
  1431. SerialClearAccept(pDevExt, ~SERIAL_PNPACCEPT_OK);
  1432. SerialSetFlags(pDevExt, SERIAL_FLAGS_STARTED);
  1433. }
  1434. if (pConfig) {
  1435. ExFreePool (pConfig);
  1436. }
  1437. if ((PUserData != NULL) && allocedUserData) {
  1438. ExFreePool(PUserData);
  1439. }
  1440. SerialDump (SERTRACECALLS, ("SERIAL: leaving SerialFinishStartDevice\n"));
  1441. return status;
  1442. }
  1443. NTSTATUS
  1444. SerialStartDevice(IN PDEVICE_OBJECT PDevObj, IN PIRP PIrp)
  1445. /*++
  1446. Routine Description:
  1447. This routine first passes the start device Irp down the stack then
  1448. it picks up the resources for the device, ititializes, puts it on any
  1449. appropriate lists (i.e shared interrupt or interrupt status) and
  1450. connects the interrupt.
  1451. Arguments:
  1452. PDevObj - Pointer to the device object for this device
  1453. PIrp - Pointer to the IRP for the current request
  1454. Return Value:
  1455. Return status
  1456. --*/
  1457. {
  1458. PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(PIrp);
  1459. NTSTATUS status = STATUS_NOT_IMPLEMENTED;
  1460. PSERIAL_DEVICE_EXTENSION pDevExt = PDevObj->DeviceExtension;
  1461. PDEVICE_OBJECT pLowerDevObj = pDevExt->LowerDeviceObject;
  1462. PAGED_CODE();
  1463. SerialDump (SERTRACECALLS, ("SERIAL: entering SerialStartDevice\n"));
  1464. //
  1465. // Pass this down to the next device object
  1466. //
  1467. KeInitializeEvent(&pDevExt->SerialStartEvent, SynchronizationEvent,
  1468. FALSE);
  1469. IoCopyCurrentIrpStackLocationToNext(PIrp);
  1470. IoSetCompletionRoutine(PIrp, SerialSyncCompletion,
  1471. &pDevExt->SerialStartEvent, TRUE, TRUE, TRUE);
  1472. status = IoCallDriver(pLowerDevObj, PIrp);
  1473. //
  1474. // Wait for lower drivers to be done with the Irp
  1475. //
  1476. if (status == STATUS_PENDING) {
  1477. KeWaitForSingleObject (&pDevExt->SerialStartEvent, Executive, KernelMode,
  1478. FALSE, NULL);
  1479. status = PIrp->IoStatus.Status;
  1480. }
  1481. if (!NT_SUCCESS(status)) {
  1482. SerialDump (SERERRORS, ("SERIAL: error with IoCallDriver %x\n", status));
  1483. return status;
  1484. }
  1485. //
  1486. // Do the serial specific items to start the device
  1487. //
  1488. status = SerialFinishStartDevice(PDevObj, pIrpStack->Parameters.StartDevice
  1489. .AllocatedResources,
  1490. pIrpStack->Parameters.StartDevice
  1491. .AllocatedResourcesTranslated, NULL);
  1492. return status;
  1493. }
  1494. NTSTATUS
  1495. SerialItemCallBack(
  1496. IN PVOID Context,
  1497. IN PUNICODE_STRING PathName,
  1498. IN INTERFACE_TYPE BusType,
  1499. IN ULONG BusNumber,
  1500. IN PKEY_VALUE_FULL_INFORMATION *BusInformation,
  1501. IN CONFIGURATION_TYPE ControllerType,
  1502. IN ULONG ControllerNumber,
  1503. IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation,
  1504. IN CONFIGURATION_TYPE PeripheralType,
  1505. IN ULONG PeripheralNumber,
  1506. IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation
  1507. )
  1508. /*++
  1509. Routine Description:
  1510. This routine is called to check if a particular item
  1511. is present in the registry.
  1512. Arguments:
  1513. Context - Pointer to a boolean.
  1514. PathName - unicode registry path. Not Used.
  1515. BusType - Internal, Isa, ...
  1516. BusNumber - Which bus if we are on a multibus system.
  1517. BusInformation - Configuration information about the bus. Not Used.
  1518. ControllerType - Controller type.
  1519. ControllerNumber - Which controller if there is more than one
  1520. controller in the system.
  1521. ControllerInformation - Array of pointers to the three pieces of
  1522. registry information.
  1523. PeripheralType - Should be a peripheral.
  1524. PeripheralNumber - Which peripheral - not used..
  1525. PeripheralInformation - Configuration information. Not Used.
  1526. Return Value:
  1527. STATUS_SUCCESS
  1528. --*/
  1529. {
  1530. PAGED_CODE();
  1531. *((BOOLEAN *)Context) = TRUE;
  1532. return STATUS_SUCCESS;
  1533. }
  1534. NTSTATUS
  1535. SerialControllerCallBack(
  1536. IN PVOID Context,
  1537. IN PUNICODE_STRING PathName,
  1538. IN INTERFACE_TYPE BusType,
  1539. IN ULONG BusNumber,
  1540. IN PKEY_VALUE_FULL_INFORMATION *BusInformation,
  1541. IN CONFIGURATION_TYPE ControllerType,
  1542. IN ULONG ControllerNumber,
  1543. IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation,
  1544. IN CONFIGURATION_TYPE PeripheralType,
  1545. IN ULONG PeripheralNumber,
  1546. IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation
  1547. )
  1548. /*++
  1549. Routine Description:
  1550. This routine is called to check if a particular item
  1551. is present in the registry.
  1552. Arguments:
  1553. Context - Pointer to a boolean.
  1554. PathName - unicode registry path. Not Used.
  1555. BusType - Internal, Isa, ...
  1556. BusNumber - Which bus if we are on a multibus system.
  1557. BusInformation - Configuration information about the bus. Not Used.
  1558. ControllerType - Controller type.
  1559. ControllerNumber - Which controller if there is more than one
  1560. controller in the system.
  1561. ControllerInformation - Array of pointers to the three pieces of
  1562. registry information.
  1563. PeripheralType - Should be a peripheral.
  1564. PeripheralNumber - Which peripheral - not used..
  1565. PeripheralInformation - Configuration information. Not Used.
  1566. Return Value:
  1567. STATUS_SUCCESS
  1568. --*/
  1569. {
  1570. PCM_FULL_RESOURCE_DESCRIPTOR controllerData;
  1571. PSERIAL_PTR_CTX pContext = (PSERIAL_PTR_CTX)Context;
  1572. ULONG i;
  1573. PAGED_CODE();
  1574. if (ControllerInformation[IoQueryDeviceConfigurationData]->DataLength == 0) {
  1575. pContext->isPointer = FALSE;
  1576. return STATUS_SUCCESS;
  1577. }
  1578. controllerData =
  1579. (PCM_FULL_RESOURCE_DESCRIPTOR)
  1580. (((PUCHAR)ControllerInformation[IoQueryDeviceConfigurationData])
  1581. + ControllerInformation[IoQueryDeviceConfigurationData]->DataOffset);
  1582. //
  1583. // See if this is the exact port we are testing
  1584. //
  1585. for (i = 0; i < controllerData->PartialResourceList.Count; i++) {
  1586. PCM_PARTIAL_RESOURCE_DESCRIPTOR partial
  1587. = &controllerData->PartialResourceList.PartialDescriptors[i];
  1588. switch (partial->Type) {
  1589. case CmResourceTypePort:
  1590. if (partial->u.Port.Start.QuadPart == pContext->Port.QuadPart) {
  1591. //
  1592. // Pointer on same controller. Bail out.
  1593. //
  1594. pContext->isPointer = SERIAL_FOUNDPOINTER_PORT;
  1595. return STATUS_SUCCESS;
  1596. }
  1597. case CmResourceTypeInterrupt:
  1598. if (partial->u.Interrupt.Vector == pContext->Vector) {
  1599. //
  1600. // Pointer sharing this interrupt. Bail out.
  1601. //
  1602. pContext->isPointer = SERIAL_FOUNDPOINTER_VECTOR;
  1603. return STATUS_SUCCESS;
  1604. }
  1605. default:
  1606. break;
  1607. }
  1608. }
  1609. pContext->isPointer = FALSE;
  1610. return STATUS_SUCCESS;
  1611. }
  1612. NTSTATUS
  1613. SerialGetPortInfo(IN PDEVICE_OBJECT PDevObj, IN PCM_RESOURCE_LIST PResList,
  1614. IN PCM_RESOURCE_LIST PTrResList, OUT PCONFIG_DATA PConfig,
  1615. IN PSERIAL_USER_DATA PUserData)
  1616. /*++
  1617. Routine Description:
  1618. This routine will get the configuration information and put
  1619. it and the translated values into CONFIG_DATA structures.
  1620. It first sets up with defaults and then queries the registry
  1621. to see if the user has overridden these defaults; if this is a legacy
  1622. multiport card, it uses the info in PUserData instead of groping the
  1623. registry again.
  1624. Arguments:
  1625. PDevObj - Pointer to the device object.
  1626. PResList - Pointer to the untranslated resources requested.
  1627. PTrResList - Pointer to the translated resources requested.
  1628. PConfig - Pointer to configuration info
  1629. PUserData - Pointer to data discovered in the registry for
  1630. legacy devices.
  1631. Return Value:
  1632. STATUS_SUCCESS if consistant configuration was found - otherwise.
  1633. returns STATUS_SERIAL_NO_DEVICE_INITED.
  1634. --*/
  1635. {
  1636. PSERIAL_DEVICE_EXTENSION pDevExt = PDevObj->DeviceExtension;
  1637. PDEVICE_OBJECT pLowerDevObj = pDevExt->LowerDeviceObject;
  1638. NTSTATUS status = STATUS_NOT_IMPLEMENTED;
  1639. CONFIGURATION_TYPE pointer = PointerPeripheral;
  1640. CONFIGURATION_TYPE controllerType = SerialController;
  1641. HANDLE keyHandle;
  1642. ULONG count;
  1643. ULONG i;
  1644. INTERFACE_TYPE interfaceType;
  1645. PCM_PARTIAL_RESOURCE_LIST pPartialResourceList, pPartialTrResourceList;
  1646. PCM_PARTIAL_RESOURCE_DESCRIPTOR pPartialResourceDesc, pPartialTrResourceDesc;
  1647. PCM_FULL_RESOURCE_DESCRIPTOR pFullResourceDesc = NULL,
  1648. pFullTrResourceDesc = NULL;
  1649. ULONG defaultInterruptMode;
  1650. ULONG defaultAddressSpace;
  1651. ULONG defaultInterfaceType;
  1652. ULONG defaultClockRate;
  1653. ULONG zero = 0;
  1654. SERIAL_PTR_CTX foundPointerCtx;
  1655. ULONG isMulti = 0;
  1656. ULONG gotInt = 0;
  1657. ULONG gotISR = 0;
  1658. ULONG gotIO = 0;
  1659. ULONG ioResIndex = 0;
  1660. ULONG curIoIndex = 0;
  1661. PAGED_CODE();
  1662. SerialDump(SERTRACECALLS, ("SERIAL: entering SerialGetPortInfo\n"));
  1663. SerialDump(SERPNPPOWER, ("SERIAL: resource pointer is %x\n", PResList));
  1664. SerialDump(SERPNPPOWER, ("SERIAL: TR resource pointer is %x\n", PTrResList));
  1665. if ((PResList == NULL) || (PTrResList == NULL)) {
  1666. //
  1667. // This shouldn't happen in theory
  1668. //
  1669. ASSERT(PResList != NULL);
  1670. ASSERT(PTrResList != NULL);
  1671. //
  1672. // This status is as appropriate as I can think of
  1673. //
  1674. return STATUS_INSUFFICIENT_RESOURCES;
  1675. }
  1676. //
  1677. // Each resource list should have only one set of resources
  1678. //
  1679. ASSERT(PResList->Count == 1);
  1680. ASSERT(PTrResList->Count == 1);
  1681. //
  1682. // See if this is a multiport device. This way we allow other
  1683. // pseudo-serial devices with extra resources to specify another range
  1684. // of I/O ports. If this is not a multiport, we only look at the first
  1685. // range. If it is a multiport, we look at the first two ranges.
  1686. //
  1687. status = IoOpenDeviceRegistryKey(pDevExt->Pdo, PLUGPLAY_REGKEY_DEVICE,
  1688. STANDARD_RIGHTS_WRITE, &keyHandle);
  1689. if (!NT_SUCCESS(status)) {
  1690. return status;
  1691. }
  1692. status = SerialGetRegistryKeyValue(keyHandle, L"MultiportDevice",
  1693. sizeof(L"MultiportDevice"), &isMulti,
  1694. sizeof (ULONG));
  1695. if (!NT_SUCCESS(status)) {
  1696. isMulti = 0;
  1697. }
  1698. status = SerialGetRegistryKeyValue(keyHandle, L"SerialIoResourcesIndex",
  1699. sizeof(L"SerialIoResourcesIndex"),
  1700. &ioResIndex, sizeof(ULONG));
  1701. if (!NT_SUCCESS(status)) {
  1702. ioResIndex = 0;
  1703. }
  1704. ZwClose(keyHandle);
  1705. pFullResourceDesc = &PResList->List[0];
  1706. pFullTrResourceDesc = &PTrResList->List[0];
  1707. //
  1708. // Ok, if we have a full resource descriptor. Let's take it apart.
  1709. //
  1710. if (pFullResourceDesc) {
  1711. pPartialResourceList = &pFullResourceDesc->PartialResourceList;
  1712. pPartialResourceDesc = pPartialResourceList->PartialDescriptors;
  1713. count = pPartialResourceList->Count;
  1714. //
  1715. // Pull out the stuff that is in the full descriptor.
  1716. //
  1717. PConfig->InterfaceType = pFullResourceDesc->InterfaceType;
  1718. PConfig->BusNumber = pFullResourceDesc->BusNumber;
  1719. //
  1720. // Now run through the partial resource descriptors looking for the port,
  1721. // interrupt, and clock rate.
  1722. //
  1723. PConfig->ClockRate = 1843200;
  1724. PConfig->InterruptStatus = SerialPhysicalZero;
  1725. PConfig->SpanOfInterruptStatus = SERIAL_STATUS_LENGTH;
  1726. for (i = 0; i < count; i++, pPartialResourceDesc++) {
  1727. switch (pPartialResourceDesc->Type) {
  1728. case CmResourceTypePort: {
  1729. #if defined(NEC_98)
  1730. //
  1731. // NEC98 can't decide by length.
  1732. //
  1733. if (gotIO == 0) { // This is the serial register set
  1734. gotIO = 1;
  1735. PConfig->Controller = pPartialResourceDesc->u.Port.Start;
  1736. PConfig->SpanOfController = SERIAL_REGISTER_SPAN;
  1737. PConfig->AddressSpace = pPartialResourceDesc->Flags;
  1738. }
  1739. #else
  1740. if (pPartialResourceDesc->u.Port.Length
  1741. == SERIAL_STATUS_LENGTH && (gotISR == 0)) { // This is an ISR
  1742. if (isMulti) {
  1743. gotISR = 1;
  1744. PConfig->InterruptStatus
  1745. = pPartialResourceDesc->u.Port.Start;
  1746. PConfig->SpanOfInterruptStatus
  1747. = pPartialResourceDesc->u.Port.Length;
  1748. PConfig->AddressSpace = pPartialResourceDesc->Flags;
  1749. }
  1750. } else {
  1751. if (gotIO == 0) { // This is the serial register set
  1752. if (curIoIndex == ioResIndex) {
  1753. gotIO = 1;
  1754. PConfig->Controller
  1755. = pPartialResourceDesc->u.Port.Start;
  1756. PConfig->SpanOfController = SERIAL_REGISTER_SPAN;
  1757. PConfig->AddressSpace = pPartialResourceDesc->Flags;
  1758. } else {
  1759. curIoIndex++;
  1760. }
  1761. }
  1762. }
  1763. #endif //defined(NEC_98)
  1764. break;
  1765. }
  1766. case CmResourceTypeInterrupt: {
  1767. if (gotInt == 0) {
  1768. gotInt = 1;
  1769. PConfig->OriginalIrql = pPartialResourceDesc->u.Interrupt.Level;
  1770. PConfig->OriginalVector
  1771. = pPartialResourceDesc->u.Interrupt.Vector;
  1772. PConfig->Affinity = pPartialResourceDesc->u.Interrupt.Affinity;
  1773. if (pPartialResourceDesc->Flags
  1774. & CM_RESOURCE_INTERRUPT_LATCHED) {
  1775. PConfig->InterruptMode = Latched;
  1776. } else {
  1777. PConfig->InterruptMode = LevelSensitive;
  1778. }
  1779. }
  1780. break;
  1781. }
  1782. case CmResourceTypeDeviceSpecific: {
  1783. PCM_SERIAL_DEVICE_DATA sDeviceData;
  1784. sDeviceData = (PCM_SERIAL_DEVICE_DATA)(pPartialResourceDesc + 1);
  1785. PConfig->ClockRate = sDeviceData->BaudClock;
  1786. break;
  1787. }
  1788. default: {
  1789. break;
  1790. }
  1791. } // switch (pPartialResourceDesc->Type)
  1792. } // for (i = 0; i < count; i++, pPartialResourceDesc++)
  1793. } // if (pFullResourceDesc)
  1794. //
  1795. // Do the same for the translated resources
  1796. //
  1797. gotInt = 0;
  1798. gotISR = 0;
  1799. gotIO = 0;
  1800. curIoIndex = 0;
  1801. if (pFullTrResourceDesc) {
  1802. pPartialTrResourceList = &pFullTrResourceDesc->PartialResourceList;
  1803. pPartialTrResourceDesc = pPartialTrResourceList->PartialDescriptors;
  1804. count = pPartialTrResourceList->Count;
  1805. //
  1806. // Reload PConfig with the translated values for later use
  1807. //
  1808. PConfig->InterfaceType = pFullTrResourceDesc->InterfaceType;
  1809. PConfig->BusNumber = pFullTrResourceDesc->BusNumber;
  1810. PConfig->TrInterruptStatus = SerialPhysicalZero;
  1811. for (i = 0; i < count; i++, pPartialTrResourceDesc++) {
  1812. switch (pPartialTrResourceDesc->Type) {
  1813. case CmResourceTypePort: {
  1814. #if defined(NEC_98)
  1815. //
  1816. // NEC98 can't decide by length.
  1817. //
  1818. if (gotIO == 0) { // This is the serial register set
  1819. gotIO = 1;
  1820. PConfig->TrController = pPartialTrResourceDesc->u.Port.Start;
  1821. PConfig->AddressSpace = pPartialTrResourceDesc->Flags;
  1822. }
  1823. #else
  1824. if (pPartialTrResourceDesc->u.Port.Length
  1825. == SERIAL_STATUS_LENGTH && (gotISR == 0)) { // This is an ISR
  1826. if (isMulti) {
  1827. gotISR = 1;
  1828. PConfig->TrInterruptStatus = pPartialTrResourceDesc
  1829. ->u.Port.Start;
  1830. }
  1831. } else { // This is the serial register set
  1832. if (gotIO == 0) {
  1833. if (curIoIndex == ioResIndex) {
  1834. gotIO = 1;
  1835. PConfig->TrController
  1836. = pPartialTrResourceDesc->u.Port.Start;
  1837. PConfig->AddressSpace
  1838. = pPartialTrResourceDesc->Flags;
  1839. } else {
  1840. curIoIndex++;
  1841. }
  1842. }
  1843. }
  1844. #endif //defined(NEC_98)
  1845. break;
  1846. }
  1847. case CmResourceTypeInterrupt: {
  1848. if (gotInt == 0) {
  1849. gotInt = 1;
  1850. PConfig->TrVector = pPartialTrResourceDesc->u.Interrupt.Vector;
  1851. PConfig->TrIrql = pPartialTrResourceDesc->u.Interrupt.Level;
  1852. PConfig->Affinity = pPartialTrResourceDesc->u.Interrupt.Affinity;
  1853. }
  1854. break;
  1855. }
  1856. default: {
  1857. break;
  1858. }
  1859. } // switch (pPartialTrResourceDesc->Type)
  1860. } // for (i = 0; i < count; i++, pPartialTrResourceDesc++)
  1861. } // if (pFullTrResourceDesc)
  1862. //
  1863. // Initialize a config data structure with default values for those that
  1864. // may not already be initialized.
  1865. //
  1866. PConfig->PortIndex = 0;
  1867. PConfig->DisablePort = 0;
  1868. PConfig->PermitSystemWideShare = FALSE;
  1869. PConfig->MaskInverted = 0;
  1870. PConfig->Indexed = 0;
  1871. PConfig->ForceFifoEnable = driverDefaults.ForceFifoEnableDefault;
  1872. PConfig->RxFIFO = driverDefaults.RxFIFODefault;
  1873. PConfig->TxFIFO = driverDefaults.TxFIFODefault;
  1874. PConfig->PermitShare = driverDefaults.PermitShareDefault;
  1875. PConfig->LogFifo = driverDefaults.LogFifoDefault;
  1876. PConfig->Jensen = driverDefaults.JensenDetected;
  1877. //
  1878. // Query the registry to look for the first bus on
  1879. // the system (that isn't the internal bus - we assume
  1880. // that the firmware code knows about those ports). We
  1881. // will use that as the default bus if no bustype or bus
  1882. // number is specified in the "user" configuration records.
  1883. //
  1884. defaultInterfaceType = (ULONG)Isa;
  1885. defaultClockRate = 1843200;
  1886. for (interfaceType = 0;
  1887. interfaceType < MaximumInterfaceType;
  1888. interfaceType++
  1889. ) {
  1890. ULONG busZero = 0;
  1891. BOOLEAN foundOne = FALSE;
  1892. if (interfaceType != Internal) {
  1893. IoQueryDeviceDescription(
  1894. &interfaceType,
  1895. &busZero,
  1896. NULL,
  1897. NULL,
  1898. NULL,
  1899. NULL,
  1900. SerialItemCallBack,
  1901. &foundOne
  1902. );
  1903. if (foundOne) {
  1904. defaultInterfaceType = (ULONG)interfaceType;
  1905. if (defaultInterfaceType == MicroChannel) {
  1906. defaultInterruptMode = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
  1907. }
  1908. break;
  1909. }
  1910. } // if (interfaceType != Internal)
  1911. } // for (interfaceType = 0
  1912. //
  1913. // Get any user data associated with the port now and override the
  1914. // values passed in if applicable. If this a legacy device, this
  1915. // is where we may actually get the parameters.
  1916. //
  1917. //
  1918. // Open the "Device Parameters" section of registry for this device object.
  1919. // If PUserData is NULL, this is PnP enumerated and we need to check,
  1920. // otherwise we are doing a legacy device and have the info already.
  1921. //
  1922. if (PUserData == NULL) {
  1923. status = IoOpenDeviceRegistryKey (pDevExt->Pdo,
  1924. PLUGPLAY_REGKEY_DEVICE,
  1925. STANDARD_RIGHTS_READ,
  1926. &keyHandle);
  1927. if (!NT_SUCCESS(status)) {
  1928. SerialDump(SERERRORS, ("SERIAL: IoOpenDeviceRegistryKey failed - %x "
  1929. "\n", status));
  1930. goto PortInfoCleanUp;
  1931. } else {
  1932. status = SerialGetRegistryKeyValue (keyHandle,
  1933. L"DisablePort",
  1934. sizeof(L"DisablePort"),
  1935. &PConfig->DisablePort,
  1936. sizeof (ULONG));
  1937. status = SerialGetRegistryKeyValue (keyHandle,
  1938. L"ForceFifoEnable",
  1939. sizeof(L"ForceFifoEnable"),
  1940. &PConfig->ForceFifoEnable,
  1941. sizeof (ULONG));
  1942. status = SerialGetRegistryKeyValue (keyHandle,
  1943. L"RxFIFO",
  1944. sizeof(L"RxFIFO"),
  1945. &PConfig->RxFIFO,
  1946. sizeof (ULONG));
  1947. status = SerialGetRegistryKeyValue (keyHandle,
  1948. L"TxFIFO",
  1949. sizeof(L"TxFIFO"),
  1950. &PConfig->TxFIFO,
  1951. sizeof (ULONG));
  1952. status = SerialGetRegistryKeyValue (keyHandle,
  1953. L"MaskInverted",
  1954. sizeof(L"MaskInverted"),
  1955. &PConfig->MaskInverted,
  1956. sizeof (ULONG));
  1957. status = SerialGetRegistryKeyValue (keyHandle,
  1958. L"Share System Interrupt",
  1959. sizeof(L"Share System Interrupt"),
  1960. &PConfig->PermitShare,
  1961. sizeof (ULONG));
  1962. status = SerialGetRegistryKeyValue (keyHandle,
  1963. L"PortIndex",
  1964. sizeof(L"PortIndex"),
  1965. &PConfig->PortIndex,
  1966. sizeof (ULONG));
  1967. status = SerialGetRegistryKeyValue(keyHandle, L"Indexed",
  1968. sizeof(L"Indexed"),
  1969. &PConfig->Indexed,
  1970. sizeof(ULONG));
  1971. status = SerialGetRegistryKeyValue (keyHandle,
  1972. L"ClockRate",
  1973. sizeof(L"ClockRate"),
  1974. &PConfig->ClockRate,
  1975. sizeof (ULONG));
  1976. if (!NT_SUCCESS(status)) {
  1977. PConfig->ClockRate = defaultClockRate;
  1978. }
  1979. ZwClose (keyHandle);
  1980. }
  1981. } else {
  1982. //
  1983. // This was a legacy device, either use a driver default or copy over
  1984. // the user-specified values.
  1985. //
  1986. ULONG badValue = (ULONG)-1;
  1987. PConfig->DisablePort = (PUserData->DisablePort == badValue)
  1988. ? 0
  1989. : PUserData->DisablePort;
  1990. PConfig->ForceFifoEnable = (PUserData->ForceFIFOEnable == badValue)
  1991. ? PUserData->ForceFIFOEnableDefault
  1992. : PUserData->ForceFIFOEnable;
  1993. PConfig->RxFIFO = (PUserData->RxFIFO == badValue)
  1994. ? PUserData->RxFIFODefault
  1995. : PUserData->RxFIFO;
  1996. PConfig->Indexed = (PUserData->UserIndexed == badValue)
  1997. ? 0
  1998. : PUserData->UserIndexed;
  1999. PConfig->TxFIFO = (PUserData->TxFIFO == badValue)
  2000. ? PUserData->TxFIFODefault
  2001. : PUserData->TxFIFO;
  2002. PConfig->MaskInverted = (PUserData->MaskInverted == badValue)
  2003. ? 0
  2004. : PUserData->MaskInverted;
  2005. PConfig->ClockRate = (PUserData->UserClockRate == badValue)
  2006. ? defaultClockRate
  2007. : PUserData->UserClockRate;
  2008. PConfig->PermitShare = PUserData->PermitShareDefault;
  2009. PConfig->PortIndex = PUserData->UserPortIndex;
  2010. }
  2011. //
  2012. // Do some error checking on the configuration info we have.
  2013. //
  2014. // Make sure that the interrupt is non zero (which we defaulted
  2015. // it to).
  2016. //
  2017. // Make sure that the portaddress is non zero (which we defaulted
  2018. // it to).
  2019. //
  2020. // Make sure that the DosDevices is not NULL (which we defaulted
  2021. // it to).
  2022. //
  2023. // We need to make sure that if an interrupt status
  2024. // was specified, that a port index was also specfied,
  2025. // and if so that the port index is <= maximum ports
  2026. // on a board.
  2027. //
  2028. // We should also validate that the bus type and number
  2029. // are correct.
  2030. //
  2031. // We will also validate that the interrupt mode makes
  2032. // sense for the bus.
  2033. //
  2034. if (!PConfig->Controller.LowPart) {
  2035. //
  2036. // Ehhhh! Lose Game.
  2037. //
  2038. SerialLogError(
  2039. PDevObj->DriverObject,
  2040. NULL,
  2041. PConfig->Controller,
  2042. SerialPhysicalZero,
  2043. 0,
  2044. 0,
  2045. 0,
  2046. 58,
  2047. STATUS_SUCCESS,
  2048. SERIAL_INVALID_USER_CONFIG,
  2049. 0,
  2050. NULL,
  2051. sizeof(L"PortAddress") + sizeof(WCHAR),
  2052. L"PortAddress"
  2053. );
  2054. SerialDump (SERERRORS,
  2055. ("SERIAL: Bogus port address %x\n",
  2056. PConfig->Controller.LowPart));
  2057. status = SERIAL_INVALID_USER_CONFIG;
  2058. goto PortInfoCleanUp;
  2059. }
  2060. if (!PConfig->OriginalVector) {
  2061. //
  2062. // Ehhhh! Lose Game.
  2063. //
  2064. SerialLogError(
  2065. pDevExt->DriverObject,
  2066. NULL,
  2067. PConfig->Controller,
  2068. SerialPhysicalZero,
  2069. 0,
  2070. 0,
  2071. 0,
  2072. 59,
  2073. STATUS_SUCCESS,
  2074. SERIAL_INVALID_USER_CONFIG,
  2075. pDevExt->DeviceName.Length,
  2076. pDevExt->DeviceName.Buffer,
  2077. sizeof (L"Interrupt"),
  2078. L"Interrupt"
  2079. );
  2080. SerialDump (SERERRORS,("SERIAL: Bogus vector %x\n",
  2081. PConfig->OriginalVector));
  2082. status = SERIAL_INVALID_USER_CONFIG;
  2083. goto PortInfoCleanUp;
  2084. }
  2085. if (PConfig->InterruptStatus.LowPart != 0) {
  2086. if (PConfig->PortIndex == MAXULONG) {
  2087. //
  2088. // Ehhhh! Lose Game.
  2089. //
  2090. SerialLogError(
  2091. pDevExt->DriverObject,
  2092. NULL,
  2093. PConfig->Controller,
  2094. SerialPhysicalZero,
  2095. 0,
  2096. 0,
  2097. 0,
  2098. 30,
  2099. STATUS_SUCCESS,
  2100. SERIAL_INVALID_PORT_INDEX,
  2101. 0,
  2102. NULL,
  2103. 0,
  2104. NULL
  2105. );
  2106. SerialDump (SERERRORS,
  2107. ("SERIAL: Bogus port index %x\n", PConfig->PortIndex));
  2108. status = SERIAL_INVALID_PORT_INDEX;
  2109. goto PortInfoCleanUp;
  2110. } else if (!PConfig->PortIndex) {
  2111. //
  2112. // So sorry, you must have a non-zero port index.
  2113. //
  2114. SerialLogError(
  2115. pDevExt->DriverObject,
  2116. NULL,
  2117. PConfig->Controller,
  2118. SerialPhysicalZero,
  2119. 0,
  2120. 0,
  2121. 0,
  2122. 31,
  2123. STATUS_SUCCESS,
  2124. SERIAL_INVALID_PORT_INDEX,
  2125. 0,
  2126. NULL,
  2127. 0,
  2128. NULL
  2129. );
  2130. SerialDump(
  2131. SERERRORS,
  2132. ("SERIAL: Port index must be > 0 for any\n"
  2133. "------- port on a multiport card: %x\n",
  2134. PConfig->PortIndex)
  2135. );
  2136. status = SERIAL_INVALID_PORT_INDEX;
  2137. goto PortInfoCleanUp;
  2138. } else {
  2139. if (PConfig->Indexed) {
  2140. if (PConfig->PortIndex > SERIAL_MAX_PORTS_INDEXED) {
  2141. SerialLogError(
  2142. pDevExt->DriverObject,
  2143. NULL,
  2144. PConfig->Controller,
  2145. SerialPhysicalZero,
  2146. 0,
  2147. 0,
  2148. 0,
  2149. 32,
  2150. STATUS_SUCCESS,
  2151. SERIAL_PORT_INDEX_TOO_HIGH,
  2152. 0,
  2153. NULL,
  2154. 0,
  2155. NULL
  2156. );
  2157. SerialDump (SERERRORS,
  2158. ("SERIAL: port index to large %x\n",
  2159. PConfig->PortIndex));
  2160. status = SERIAL_PORT_INDEX_TOO_HIGH;
  2161. goto PortInfoCleanUp;
  2162. }
  2163. } else {
  2164. if (PConfig->PortIndex > SERIAL_MAX_PORTS_NONINDEXED) {
  2165. SerialLogError(
  2166. pDevExt->DriverObject,
  2167. NULL,
  2168. PConfig->Controller,
  2169. SerialPhysicalZero,
  2170. 0,
  2171. 0,
  2172. 0,
  2173. 33,
  2174. STATUS_SUCCESS,
  2175. SERIAL_PORT_INDEX_TOO_HIGH,
  2176. 0,
  2177. NULL,
  2178. 0,
  2179. NULL
  2180. );
  2181. SerialDump (SERERRORS,
  2182. ("SERIAL: port index to large %x\n",
  2183. PConfig->PortIndex));
  2184. status = SERIAL_PORT_INDEX_TOO_HIGH;
  2185. goto PortInfoCleanUp;
  2186. }
  2187. }
  2188. } // else (if !PConfig->PortIndex)
  2189. } // if (PConfig->InterruptStatus != 0)
  2190. //
  2191. // We don't want to cause the hal to have a bad day,
  2192. // so let's check the interface type and bus number.
  2193. //
  2194. // We only need to check the registry if they aren't
  2195. // equal to the defaults.
  2196. //
  2197. if (PConfig->BusNumber != 0) {
  2198. BOOLEAN foundIt;
  2199. if (PConfig->InterfaceType >= MaximumInterfaceType) {
  2200. //
  2201. // Ehhhh! Lose Game.
  2202. //
  2203. SerialLogError(
  2204. pDevExt->DriverObject,
  2205. NULL,
  2206. PConfig->Controller,
  2207. SerialPhysicalZero,
  2208. 0,
  2209. 0,
  2210. 0,
  2211. 34,
  2212. STATUS_SUCCESS,
  2213. SERIAL_UNKNOWN_BUS,
  2214. 0,
  2215. NULL,
  2216. 0,
  2217. NULL
  2218. );
  2219. SerialDump (SERERRORS,
  2220. ("SERIAL: Invalid Bus type %x\n", PConfig->BusNumber));
  2221. status = SERIAL_UNKNOWN_BUS;
  2222. goto PortInfoCleanUp;
  2223. }
  2224. IoQueryDeviceDescription(
  2225. (INTERFACE_TYPE *)&PConfig->InterfaceType,
  2226. &zero,
  2227. NULL,
  2228. NULL,
  2229. NULL,
  2230. NULL,
  2231. SerialItemCallBack,
  2232. &foundIt
  2233. );
  2234. if (!foundIt) {
  2235. SerialLogError(
  2236. pDevExt->DriverObject,
  2237. NULL,
  2238. PConfig->Controller,
  2239. SerialPhysicalZero,
  2240. 0,
  2241. 0,
  2242. 0,
  2243. 35,
  2244. STATUS_SUCCESS,
  2245. SERIAL_BUS_NOT_PRESENT,
  2246. 0,
  2247. NULL,
  2248. 0,
  2249. NULL
  2250. );
  2251. SerialDump(
  2252. SERERRORS,
  2253. ("SERIAL: There aren't that many of those\n"
  2254. "------- busses on this system,%x\n",
  2255. PConfig->BusNumber)
  2256. );
  2257. status = SERIAL_BUS_NOT_PRESENT;
  2258. goto PortInfoCleanUp;
  2259. }
  2260. } // if (PConfig->BusNumber != 0)
  2261. if ((PConfig->InterfaceType == MicroChannel) &&
  2262. (PConfig->InterruptMode == CM_RESOURCE_INTERRUPT_LATCHED)) {
  2263. SerialLogError(
  2264. pDevExt->DriverObject,
  2265. NULL,
  2266. PConfig->Controller,
  2267. SerialPhysicalZero,
  2268. 0,
  2269. 0,
  2270. 0,
  2271. 36,
  2272. STATUS_SUCCESS,
  2273. SERIAL_BUS_INTERRUPT_CONFLICT,
  2274. 0,
  2275. NULL,
  2276. 0,
  2277. NULL
  2278. );
  2279. SerialDump(
  2280. SERERRORS,
  2281. ("SERIAL: Latched interrupts and MicroChannel\n"
  2282. "------- busses don't mix\n")
  2283. );
  2284. status = SERIAL_BUS_INTERRUPT_CONFLICT;
  2285. goto PortInfoCleanUp;
  2286. }
  2287. status = STATUS_SUCCESS;
  2288. //
  2289. // Dump out the port configuration.
  2290. //
  2291. SerialDump(SERDIAG1, ("SERIAL: Com Port address: %x\n",
  2292. PConfig->Controller.LowPart));
  2293. SerialDump(SERDIAG1, ("SERIAL: Com Interrupt Status: %x\n",
  2294. PConfig->InterruptStatus));
  2295. SerialDump(SERDIAG1, ("SERIAL: Com Port Index: %x\n",
  2296. PConfig->PortIndex));
  2297. SerialDump(SERDIAG1, ("SERIAL: Com Port ClockRate: %x\n",
  2298. PConfig->ClockRate));
  2299. SerialDump(SERDIAG1, ("SERIAL: Com Port BusNumber: %x\n",
  2300. PConfig->BusNumber));
  2301. SerialDump(SERDIAG1, ("SERIAL: Com AddressSpace: %x\n",
  2302. PConfig->AddressSpace));
  2303. SerialDump(SERDIAG1, ("SERIAL: Com InterruptMode: %x\n",
  2304. PConfig->InterruptMode));
  2305. SerialDump(SERDIAG1, ("SERIAL: Com InterfaceType: %x\n",
  2306. PConfig->InterfaceType));
  2307. SerialDump(SERDIAG1, ("SERIAL: Com OriginalVector: %x\n",
  2308. PConfig->OriginalVector));
  2309. SerialDump(SERDIAG1, ("SERIAL: Com OriginalIrql: %x\n",
  2310. PConfig->OriginalIrql));
  2311. SerialDump(SERDIAG1, ("SERIAL: Com Indexed: %x\n",
  2312. PConfig->Indexed));
  2313. PortInfoCleanUp:;
  2314. return status;
  2315. }
  2316. NTSTATUS
  2317. SerialDoExternalNaming(IN PSERIAL_DEVICE_EXTENSION PDevExt,
  2318. IN PDRIVER_OBJECT PDrvObj)
  2319. /*++
  2320. Routine Description:
  2321. This routine will be used to create a symbolic link
  2322. to the driver name in the given object directory.
  2323. It will also create an entry in the device map for
  2324. this device - IF we could create the symbolic link.
  2325. Arguments:
  2326. Extension - Pointer to the device extension.
  2327. Return Value:
  2328. None.
  2329. --*/
  2330. {
  2331. NTSTATUS status = STATUS_SUCCESS;
  2332. HANDLE keyHandle;
  2333. WCHAR *pRegName = NULL;
  2334. UNICODE_STRING linkName;
  2335. PDEVICE_OBJECT pLowerDevObj, pDevObj;
  2336. ULONG bufLen;
  2337. PAGED_CODE();
  2338. pDevObj = PDevExt->DeviceObject;
  2339. pLowerDevObj = PDevExt->LowerDeviceObject;
  2340. status = IoOpenDeviceRegistryKey(PDevExt->Pdo, PLUGPLAY_REGKEY_DEVICE,
  2341. STANDARD_RIGHTS_READ, &keyHandle);
  2342. //
  2343. // Check to see if we are allowed to do external naming; if not,
  2344. // then we just return success
  2345. //
  2346. if (status != STATUS_SUCCESS) {
  2347. return status;
  2348. }
  2349. SerialGetRegistryKeyValue(keyHandle, L"SerialSkipExternalNaming",
  2350. sizeof(L"SerialSkipExternalNaming"),
  2351. &PDevExt->SkipNaming, sizeof(ULONG));
  2352. if (PDevExt->SkipNaming) {
  2353. ZwClose(keyHandle);
  2354. return STATUS_SUCCESS;
  2355. }
  2356. RtlZeroMemory(&linkName, sizeof(UNICODE_STRING));
  2357. linkName.MaximumLength = SYMBOLIC_NAME_LENGTH*sizeof(WCHAR);
  2358. linkName.Buffer = ExAllocatePool(PagedPool, linkName.MaximumLength
  2359. + sizeof(WCHAR));
  2360. if (linkName.Buffer == NULL) {
  2361. SerialLogError(PDrvObj, pDevObj, SerialPhysicalZero, SerialPhysicalZero,
  2362. 0, 0, 0, 19, STATUS_SUCCESS, SERIAL_INSUFFICIENT_RESOURCES,
  2363. 0, NULL, 0, NULL);
  2364. SerialDump(SERERRORS, ("SERIAL: Couldn't allocate memory for device name"
  2365. "\n"));
  2366. status = STATUS_INSUFFICIENT_RESOURCES;
  2367. ZwClose(keyHandle);
  2368. goto SerialDoExternalNamingError;
  2369. }
  2370. RtlZeroMemory(linkName.Buffer, linkName.MaximumLength + sizeof(WCHAR));
  2371. pRegName = ExAllocatePool(PagedPool, SYMBOLIC_NAME_LENGTH * sizeof(WCHAR)
  2372. + sizeof(WCHAR));
  2373. if (pRegName == NULL) {
  2374. SerialLogError(PDrvObj, pDevObj, SerialPhysicalZero, SerialPhysicalZero,
  2375. 0, 0, 0, 19, STATUS_SUCCESS, SERIAL_INSUFFICIENT_RESOURCES,
  2376. 0, NULL, 0, NULL);
  2377. SerialDump(SERERRORS, ("SERIAL: Couldn't allocate memory for buffer"
  2378. "\n"));
  2379. status = STATUS_INSUFFICIENT_RESOURCES;
  2380. ZwClose(keyHandle);
  2381. goto SerialDoExternalNamingError;
  2382. }
  2383. //
  2384. // Fetch PortName which contains the suggested REG_SZ symbolic name.
  2385. //
  2386. status = SerialGetRegistryKeyValue(keyHandle, L"PortName",
  2387. sizeof(L"PortName"), pRegName,
  2388. SYMBOLIC_NAME_LENGTH * sizeof(WCHAR));
  2389. if (!NT_SUCCESS(status)) {
  2390. //
  2391. // This is for PCMCIA which currently puts the name under Identifier.
  2392. //
  2393. status = SerialGetRegistryKeyValue(keyHandle, L"Identifier",
  2394. sizeof(L"Identifier"),
  2395. pRegName, SYMBOLIC_NAME_LENGTH
  2396. * sizeof(WCHAR));
  2397. if (!NT_SUCCESS(status)) {
  2398. //
  2399. // Hmm. Either we have to pick a name or bail...
  2400. //
  2401. // ...we will bail.
  2402. //
  2403. SerialDump(SERERRORS, ("SERIAL: Getting PortName/Identifier failed - "
  2404. "%x\n", status));
  2405. ZwClose (keyHandle);
  2406. goto SerialDoExternalNamingError;
  2407. }
  2408. }
  2409. ZwClose (keyHandle);
  2410. bufLen = wcslen(pRegName) * sizeof(WCHAR) + sizeof(UNICODE_NULL);
  2411. PDevExt->WmiIdentifier.Buffer = ExAllocatePool(PagedPool, bufLen);
  2412. if (PDevExt->WmiIdentifier.Buffer == NULL) {
  2413. SerialLogError(PDrvObj, pDevObj, SerialPhysicalZero, SerialPhysicalZero,
  2414. 0, 0, 0, 19, STATUS_SUCCESS, SERIAL_INSUFFICIENT_RESOURCES,
  2415. 0, NULL, 0, NULL);
  2416. SerialDump(SERERRORS,
  2417. ("SERIAL: Couldn't allocate memory for WMI name\n"));
  2418. status = STATUS_INSUFFICIENT_RESOURCES;
  2419. goto SerialDoExternalNamingError;
  2420. }
  2421. RtlZeroMemory(PDevExt->WmiIdentifier.Buffer, bufLen);
  2422. PDevExt->WmiIdentifier.Length = 0;
  2423. PDevExt->WmiIdentifier.MaximumLength = (USHORT)bufLen - sizeof(WCHAR);
  2424. RtlAppendUnicodeToString(&PDevExt->WmiIdentifier, pRegName);
  2425. //
  2426. // Create the "\\DosDevices\\<symbolicName>" string
  2427. //
  2428. RtlAppendUnicodeToString(&linkName, L"\\");
  2429. RtlAppendUnicodeToString(&linkName, DEFAULT_DIRECTORY);
  2430. RtlAppendUnicodeToString(&linkName, L"\\");
  2431. RtlAppendUnicodeToString(&linkName, pRegName);
  2432. //
  2433. // Allocate Pool and save the symbolic link name in the device extension.
  2434. //
  2435. PDevExt->SymbolicLinkName.MaximumLength = linkName.Length + sizeof(WCHAR);
  2436. PDevExt->SymbolicLinkName.Buffer
  2437. = ExAllocatePool(PagedPool, PDevExt->SymbolicLinkName.MaximumLength);
  2438. if (!PDevExt->SymbolicLinkName.Buffer) {
  2439. SerialLogError(PDrvObj, pDevObj, SerialPhysicalZero, SerialPhysicalZero,
  2440. 0, 0, 0, 19, STATUS_SUCCESS, SERIAL_INSUFFICIENT_RESOURCES,
  2441. 0, NULL, 0, NULL);
  2442. SerialDump(SERERRORS,
  2443. ("SERIAL: Couldn't allocate memory for symbolic link name\n"));
  2444. status = STATUS_INSUFFICIENT_RESOURCES;
  2445. goto SerialDoExternalNamingError;
  2446. }
  2447. //
  2448. // Zero fill it.
  2449. //
  2450. RtlZeroMemory(PDevExt->SymbolicLinkName.Buffer,
  2451. PDevExt->SymbolicLinkName.MaximumLength);
  2452. RtlAppendUnicodeStringToString(&PDevExt->SymbolicLinkName,
  2453. &linkName);
  2454. PDevExt->DosName.Buffer = ExAllocatePool(PagedPool, 64 + sizeof(WCHAR));
  2455. if (!PDevExt->DosName.Buffer) {
  2456. SerialLogError(PDrvObj, pDevObj, SerialPhysicalZero, SerialPhysicalZero,
  2457. 0, 0, 0, 19, STATUS_SUCCESS, SERIAL_INSUFFICIENT_RESOURCES,
  2458. 0, NULL, 0, NULL);
  2459. SerialDump(SERERRORS,
  2460. ("SERIAL: Couldn't allocate memory for Dos name\n"));
  2461. status = STATUS_INSUFFICIENT_RESOURCES;
  2462. goto SerialDoExternalNamingError;
  2463. }
  2464. PDevExt->DosName.MaximumLength = 64 + sizeof(WCHAR);
  2465. //
  2466. // Zero fill it.
  2467. //
  2468. PDevExt->DosName.Length = 0;
  2469. RtlZeroMemory(PDevExt->DosName.Buffer,
  2470. PDevExt->DosName.MaximumLength);
  2471. RtlAppendUnicodeToString(&PDevExt->DosName, pRegName);
  2472. RtlZeroMemory(((PUCHAR)(&PDevExt->DosName.Buffer[0]))
  2473. + PDevExt->DosName.Length, sizeof(WCHAR));
  2474. SerialDump(SERDIAG1, ("SERIAL: DosName is %wZ\n",
  2475. &PDevExt->DosName));
  2476. //
  2477. status = IoCreateSymbolicLink (&PDevExt->SymbolicLinkName,
  2478. &PDevExt->DeviceName);
  2479. if (!NT_SUCCESS(status)) {
  2480. //
  2481. // Oh well, couldn't create the symbolic link. No point
  2482. // in trying to create the device map entry.
  2483. //
  2484. SerialLogError(PDrvObj, pDevObj, SerialPhysicalZero, SerialPhysicalZero,
  2485. 0, 0, 0, 52, status, SERIAL_NO_SYMLINK_CREATED,
  2486. PDevExt->DeviceName.Length + sizeof(WCHAR),
  2487. PDevExt->DeviceName.Buffer, 0, NULL);
  2488. SerialDump(
  2489. SERERRORS,
  2490. ("SERIAL: Couldn't create the symbolic link\n"
  2491. "------- for port %wZ\n",
  2492. &PDevExt->DeviceName)
  2493. );
  2494. goto SerialDoExternalNamingError;
  2495. }
  2496. PDevExt->CreatedSymbolicLink = TRUE;
  2497. status = RtlWriteRegistryValue(RTL_REGISTRY_DEVICEMAP, L"SERIALCOMM",
  2498. PDevExt->DeviceName.Buffer, REG_SZ,
  2499. PDevExt->DosName.Buffer,
  2500. PDevExt->DosName.Length + sizeof(WCHAR));
  2501. if (!NT_SUCCESS(status)) {
  2502. SerialLogError(PDrvObj, pDevObj, SerialPhysicalZero, SerialPhysicalZero,
  2503. 0, 0, 0, 53, status, SERIAL_NO_DEVICE_MAP_CREATED,
  2504. PDevExt->DeviceName.Length + sizeof(WCHAR),
  2505. PDevExt->DeviceName.Buffer, 0, NULL);
  2506. SerialDump(SERERRORS, ("SERIAL: Couldn't create the device map entry\n"
  2507. "------- for port %wZ\n", &PDevExt->DeviceName));
  2508. goto SerialDoExternalNamingError;
  2509. }
  2510. PDevExt->CreatedSerialCommEntry = TRUE;
  2511. //
  2512. // Make the device visible via a device association as well.
  2513. // The reference string is the eight digit device index
  2514. //
  2515. status = IoRegisterDeviceInterface(PDevExt->Pdo, (LPGUID)&GUID_CLASS_COMPORT,
  2516. NULL, &PDevExt->DeviceClassSymbolicName);
  2517. if (!NT_SUCCESS(status)) {
  2518. SerialDump(SERERRORS, ("SERIAL: Couldn't register class association\n"
  2519. "------- for port %wZ\n",
  2520. &PDevExt->DeviceName));
  2521. PDevExt->DeviceClassSymbolicName.Buffer = NULL;
  2522. goto SerialDoExternalNamingError;
  2523. }
  2524. //
  2525. // Now set the symbolic link for the association
  2526. //
  2527. status = IoSetDeviceInterfaceState(&PDevExt->DeviceClassSymbolicName,
  2528. TRUE);
  2529. if (!NT_SUCCESS(status)) {
  2530. SerialDump(SERERRORS, ("SERIAL: Couldn't set class association\n"
  2531. "------- for port %wZ\n",
  2532. &PDevExt->DeviceName));
  2533. }
  2534. SerialDoExternalNamingError:;
  2535. //
  2536. // Clean up error conditions
  2537. //
  2538. if (!NT_SUCCESS(status)) {
  2539. if (PDevExt->DosName.Buffer != NULL) {
  2540. ExFreePool(PDevExt->DosName.Buffer);
  2541. PDevExt->DosName.Buffer = NULL;
  2542. }
  2543. if (PDevExt->CreatedSymbolicLink == TRUE) {
  2544. IoDeleteSymbolicLink(&PDevExt->SymbolicLinkName);
  2545. PDevExt->CreatedSymbolicLink = FALSE;
  2546. }
  2547. if (PDevExt->SymbolicLinkName.Buffer != NULL) {
  2548. ExFreePool(PDevExt->SymbolicLinkName.Buffer);
  2549. PDevExt->SymbolicLinkName.Buffer = NULL;
  2550. }
  2551. if (PDevExt->DeviceName.Buffer != NULL) {
  2552. RtlDeleteRegistryValue(RTL_REGISTRY_DEVICEMAP, SERIAL_DEVICE_MAP,
  2553. PDevExt->DeviceName.Buffer);
  2554. }
  2555. if (PDevExt->DeviceClassSymbolicName.Buffer) {
  2556. IoSetDeviceInterfaceState (&PDevExt->DeviceClassSymbolicName, FALSE);
  2557. }
  2558. if (PDevExt->WmiIdentifier.Buffer != NULL) {
  2559. ExFreePool(PDevExt->WmiIdentifier.Buffer);
  2560. PDevExt->WmiIdentifier.Buffer = NULL;
  2561. }
  2562. }
  2563. //
  2564. // Always clean up our temp buffers.
  2565. //
  2566. if (linkName.Buffer != NULL) {
  2567. ExFreePool(linkName.Buffer);
  2568. }
  2569. if (pRegName != NULL) {
  2570. ExFreePool(pRegName);
  2571. }
  2572. return status;
  2573. }
  2574. VOID
  2575. SerialUndoExternalNaming(IN PSERIAL_DEVICE_EXTENSION Extension)
  2576. /*++
  2577. Routine Description:
  2578. This routine will be used to delete a symbolic link
  2579. to the driver name in the given object directory.
  2580. It will also delete an entry in the device map for
  2581. this device if the symbolic link had been created.
  2582. Arguments:
  2583. Extension - Pointer to the device extension.
  2584. Return Value:
  2585. None.
  2586. --*/
  2587. {
  2588. NTSTATUS status;
  2589. PAGED_CODE();
  2590. SerialDump(
  2591. SERDIAG3,
  2592. ("SERIAL: In SerialUndoExternalNaming for\n"
  2593. "------- extension: %x of port %wZ\n",
  2594. Extension,&Extension->DeviceName)
  2595. );
  2596. //
  2597. // Maybe there is nothing for us to do
  2598. //
  2599. if (Extension->SkipNaming) {
  2600. return;
  2601. }
  2602. //
  2603. // We're cleaning up here. One reason we're cleaning up
  2604. // is that we couldn't allocate space for the directory
  2605. // name or the symbolic link.
  2606. //
  2607. if (Extension->SymbolicLinkName.Buffer &&
  2608. Extension->CreatedSymbolicLink) {
  2609. if (Extension->DeviceClassSymbolicName.Buffer) {
  2610. status = IoSetDeviceInterfaceState (&Extension->
  2611. DeviceClassSymbolicName,
  2612. FALSE);
  2613. //
  2614. // IoRegisterDeviceClassInterface() allocated this string for us,
  2615. // and we no longer need it.
  2616. //
  2617. ExFreePool( Extension->DeviceClassSymbolicName.Buffer );
  2618. }
  2619. IoDeleteSymbolicLink (&Extension->SymbolicLinkName);
  2620. }
  2621. if (Extension->WmiIdentifier.Buffer) {
  2622. ExFreePool(Extension->WmiIdentifier.Buffer);
  2623. Extension->WmiIdentifier.MaximumLength
  2624. = Extension->WmiIdentifier.Length = 0;
  2625. Extension->WmiIdentifier.Buffer = NULL;
  2626. }
  2627. //
  2628. // We're cleaning up here. One reason we're cleaning up
  2629. // is that we couldn't allocate space for the NtNameOfPort.
  2630. //
  2631. if ((Extension->DeviceName.Buffer != NULL)
  2632. && Extension->CreatedSerialCommEntry) {
  2633. status = RtlDeleteRegistryValue(RTL_REGISTRY_DEVICEMAP, SERIAL_DEVICE_MAP,
  2634. Extension->DeviceName.Buffer);
  2635. if (!NT_SUCCESS(status)) {
  2636. SerialLogError(
  2637. Extension->DeviceObject->DriverObject,
  2638. Extension->DeviceObject,
  2639. Extension->OriginalController,
  2640. SerialPhysicalZero,
  2641. 0,
  2642. 0,
  2643. 0,
  2644. 55,
  2645. status,
  2646. SERIAL_NO_DEVICE_MAP_DELETED,
  2647. Extension->DeviceName.Length+sizeof(WCHAR),
  2648. Extension->DeviceName.Buffer,
  2649. 0,
  2650. NULL
  2651. );
  2652. SerialDump(
  2653. SERERRORS,
  2654. ("SERIAL: Couldn't delete value entry %wZ\n",
  2655. &Extension->DeviceName)
  2656. );
  2657. }
  2658. }
  2659. }