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.

843 lines
27 KiB

  1. /*----------------------------------------------------------------------
  2. pnpadd.c - Handle pnp adding devices.
  3. |----------------------------------------------------------------------*/
  4. #include "precomp.h"
  5. #ifdef NT50
  6. NTSTATUS AddBoardDevice(
  7. IN PDRIVER_OBJECT DriverObject,
  8. IN PDEVICE_OBJECT Pdo,
  9. OUT PDEVICE_OBJECT *NewDevObj);
  10. NTSTATUS AddPortDevice(
  11. IN PDRIVER_OBJECT DriverObject,
  12. IN PDEVICE_OBJECT Pdo,
  13. OUT PDEVICE_OBJECT *NewDevObj,
  14. IN int port_index);
  15. NTSTATUS CheckPortName(
  16. IN PDEVICE_OBJECT Pdo,
  17. IN PSERIAL_DEVICE_EXTENSION ParentExt,
  18. IN int port_index);
  19. #define CFG_ID_ISA_BRD_INDEX 0
  20. #define CFG_ID_NODE_INDEX 1
  21. static int read_config_data(PDEVICE_OBJECT Pdo, int *ret_val, int val_id);
  22. static int write_config_data(PDEVICE_OBJECT Pdo, int val, int val_id);
  23. static int derive_unique_node_index(int *ret_val);
  24. static int GetPnpIdStr(PDEVICE_OBJECT Pdo, char *ret_val);
  25. /*----------------------------------------------------------------------
  26. SerialAddDevice -
  27. This routine creates a functional device object for boards or
  28. com ports in the system and attaches them to the physical device
  29. objects for the boards or ports.
  30. Arguments:
  31. DriverObject - a pointer to the object for this driver
  32. PhysicalDeviceObject - a pointer to the physical object we need to attach to
  33. Return Value:
  34. status from device creation and initialization
  35. |----------------------------------------------------------------------*/
  36. NTSTATUS SerialAddDevice(
  37. IN PDRIVER_OBJECT DriverObject,
  38. IN PDEVICE_OBJECT Pdo)
  39. {
  40. PDEVICE_OBJECT fdo = NULL;
  41. PDEVICE_OBJECT lowerDevice = NULL;
  42. PDEVICE_OBJECT NewDevObj = NULL;
  43. NTSTATUS status;
  44. #if DBG_STACK
  45. int i;
  46. #endif
  47. int stat;
  48. int board_device = 1; // asume pnp board device(not pnp port)
  49. //PDEVICE_OBJECT deviceOjbect;
  50. PSERIAL_DEVICE_EXTENSION deviceExtension;
  51. ULONG resultLength;
  52. USTR_240 *us; // equal to 240 normal chars length
  53. char *ptr;
  54. int port_index;
  55. // Using stack array instead of static buffer for unicode conversion
  56. char cstr[320];
  57. //char temp_szNt50DevObjName[80];
  58. #if DBG_STACK
  59. DWORD stkchkend;
  60. DWORD stkchk;
  61. DWORD *stkptr;
  62. #endif
  63. MyKdPrint(D_PnpAdd,("RK:SerialAddDevice Start DrvObj:%x, PDO:%x\n",
  64. DriverObject, Pdo))
  65. MyKdPrint(D_Pnp, ("SerialAddDevice\n"))
  66. #if DBG_STACK
  67. stkchk = 0;
  68. stkptr = (DWORD *)&DriverObject;
  69. for (i=0; i<50; i++)
  70. {
  71. stkchk += *stkptr++;
  72. }
  73. #endif
  74. //PAGED_CODE();
  75. if (Pdo == NULL) {
  76. // Bugbug: This is where enumeration occurs.
  77. // One possible use for this is to add the user defined
  78. // ports from the registry
  79. // For now: just return no more devices
  80. MyKdPrint(D_Error, ("NullPDO.\n"))
  81. return (STATUS_NO_MORE_ENTRIES);
  82. }
  83. us = ExAllocatePool(NonPagedPool, sizeof(USTR_240));
  84. if ( us == NULL ) {
  85. MyKdPrint(D_Error, ("SerialAddDevice no memory.\n"))
  86. return STATUS_INSUFFICIENT_RESOURCES;
  87. }
  88. // configure the unicode string to: point the buffer ptr to the wstr.
  89. us->ustr.Buffer = us->wstr;
  90. us->ustr.Length = 0;
  91. us->ustr.MaximumLength = sizeof(USTR_240) - sizeof(UNICODE_STRING);
  92. // get the friendly name
  93. // "Comtrol xxxx xx" for board, "Comtrol Port(COM24)" for port.
  94. status = IoGetDeviceProperty (Pdo,
  95. DevicePropertyFriendlyName,
  96. us->ustr.MaximumLength,
  97. us->ustr.Buffer,
  98. &resultLength);
  99. us->ustr.Length = (USHORT) resultLength;
  100. // ptr = UToC1(&us->ustr);
  101. ptr = UToCStr( cstr,
  102. &us->ustr,
  103. sizeof( cstr ));
  104. MyKdPrint(D_Pnp, ("FriendlyName:%s\n", ptr))
  105. // get the class-name
  106. // "MultiPortSerial" for board, "Ports" for port.
  107. status = IoGetDeviceProperty (Pdo,
  108. DevicePropertyClassName, // Ports
  109. us->ustr.MaximumLength,
  110. us->ustr.Buffer,
  111. &resultLength);
  112. us->ustr.Length = (USHORT) resultLength;
  113. // ptr = UToC1(&us->ustr);
  114. ptr = UToCStr( cstr,
  115. &us->ustr,
  116. sizeof( cstr ));
  117. MyKdPrint(D_Pnp, ("ClassName:%s\n", ptr))
  118. if (my_toupper(*ptr) == 'P') // "Ports"
  119. {
  120. MyKdPrint(D_Pnp, ("A Port!\n"))
  121. board_device = 0; // its a port pnp device
  122. }
  123. // else it's the default: a board device
  124. // get the dev-desc
  125. // "RocketPort Port0" for port, "RocketPort 8 Port, ISA-BUS" for board
  126. status = IoGetDeviceProperty (Pdo,
  127. DevicePropertyDeviceDescription,
  128. us->ustr.MaximumLength,
  129. us->ustr.Buffer,
  130. &resultLength);
  131. us->ustr.Length = (USHORT) resultLength;
  132. // ptr = UToC1(&us->ustr);
  133. ptr = UToCStr( cstr,
  134. &us->ustr,
  135. sizeof( cstr ));
  136. MyKdPrint(D_Pnp, ("DevDesc:%s\n", ptr))
  137. // Find out what the PnP manager thinks my NT Hardware ID is
  138. // "CtmPort0000" for port, "rckt1002" for isa-board
  139. // for pci we are getting a huge string, 400 bytes long, not good...
  140. status = IoGetDeviceProperty (Pdo,
  141. DevicePropertyHardwareID, // port0000
  142. us->ustr.MaximumLength,
  143. us->ustr.Buffer,
  144. &resultLength);
  145. MyKdPrint(D_Pnp, ("status:%d\n", status))
  146. us->ustr.Length = (USHORT) resultLength;
  147. MyKdPrint(D_Pnp, ("Len:%d\n",resultLength))
  148. // ptr = UToC1(&us->ustr);
  149. ptr = UToCStr( cstr,
  150. &us->ustr,
  151. sizeof( cstr ));
  152. MyKdPrint(D_Pnp, ("DevHdwID:%s\n", ptr))
  153. if (board_device) // record board type according to pnp
  154. {
  155. // if (strlen(ptr) < 12)
  156. // {
  157. // i = gethint(&ptr[4], NULL);
  158. // MyKdPrint(D_Pnp, ("HdwID:%d\n", i))
  159. // Hardware_Id = i;
  160. // }
  161. }
  162. else // its a port pnp device, find the port-index
  163. {
  164. while ((*ptr != 0) && (*ptr != '0'))
  165. ++ptr;
  166. port_index = getint(ptr, NULL);
  167. MyKdPrint(D_Pnp, ("port_index:%d\n", port_index))
  168. }
  169. #if 0
  170. // key name
  171. // {50906CB8-BA12-11D1-BF5D-0000F805F530}\0001 for board
  172. status = IoGetDeviceProperty (Pdo,
  173. DevicePropertyDriverKeyName, // 4D36....
  174. us->ustr.MaximumLength,
  175. us->ustr.Buffer,
  176. &resultLength);
  177. us->ustr.Length = (USHORT) resultLength;
  178. MyKdPrint(D_Pnp, ("KeyName:%s\n", UToC1(&us->ustr)))
  179. // Find out what the PnP manager thinks my NT Hardware ID is
  180. // \Device\003354 typical
  181. status = IoGetDeviceProperty (Pdo,
  182. DevicePropertyPhysicalDeviceObjectName, // \Device\003354
  183. us->ustr.MaximumLength,
  184. us->ustr.Buffer,
  185. &resultLength);
  186. us->ustr.Length = (USHORT) resultLength;
  187. MyKdPrint(D_Pnp, ("DevName:%s\n", UToC1(&us->ustr)))
  188. if (board_device)
  189. {
  190. int i,j;
  191. // we need to use this later as this is what our config data is
  192. // stored under. Since we want to read in our config before
  193. // creating the board and port extensions(where the config
  194. // record eventually ends up), we setup the first entry in
  195. // the static array of device configuration records as our
  196. // own as a temporary measure so our read options routine
  197. // has a place to put the config data.
  198. strcpy(temp_szNt50DevObjName, UToC1(&us->ustr));
  199. // strip off the forward slashes
  200. i=0;
  201. j=0;
  202. while (temp_szNt50DevObjName[i] != 0)
  203. {
  204. if (temp_szNt50DevObjName[i] != '\\')
  205. temp_szNt50DevObjName[j++] = temp_szNt50DevObjName[i];
  206. i++;
  207. }
  208. temp_szNt50DevObjName[j] = 0;
  209. }
  210. #endif
  211. ExFreePool(us);
  212. us = NULL;
  213. MyKdPrint(D_Pnp, ("CreateFdo\n"))
  214. if (board_device)
  215. {
  216. status = AddBoardDevice(DriverObject, Pdo, &NewDevObj);
  217. if (status != STATUS_SUCCESS)
  218. {
  219. MyKdPrint(D_Error, ("Err, Creating Board Obj\n"))
  220. return status;
  221. }
  222. deviceExtension = NewDevObj->DeviceExtension;
  223. //strcpy(deviceExtension->config->szNt50DevObjName, temp_szNt50DevObjName);
  224. // read in our device configuration from the registry
  225. stat = read_device_options(deviceExtension);
  226. } // board device
  227. else
  228. {
  229. status = AddPortDevice(DriverObject, Pdo, &NewDevObj, port_index);
  230. }
  231. if (status != STATUS_SUCCESS)
  232. {
  233. MyKdPrint(D_Error,("Error on NewPort Create!\n"))
  234. return status;
  235. }
  236. fdo = NewDevObj;
  237. // Layer our FDO on top of the PDO
  238. // The return value is a pointer to the device object to which the
  239. // fdo is actually attached.
  240. lowerDevice = IoAttachDeviceToDeviceStack(fdo, Pdo);
  241. MyKdPrint(D_PnpAdd,("RK:SerialAddDevice New FDO:%x, Ext:%x TopOfStack:%x\n",
  242. fdo, fdo->DeviceExtension, lowerDevice))
  243. // No status. Do the best we can.
  244. MyAssert(lowerDevice);
  245. // fdo source, pdo is target, save handle to lower device object
  246. deviceExtension = fdo->DeviceExtension;
  247. deviceExtension->LowerDeviceObject = lowerDevice;
  248. deviceExtension->Pdo = Pdo; // save off the handle to the pdo
  249. // Set the stack requirement for this device object to 2 + the size of the
  250. // lower device's stack size. This will allow the same Irp that comes in
  251. // for Open and Close calls to be used for the PoCallDriver calls to change
  252. // the power state of the device.
  253. // fdo->StackSize = lowerDevice->StackSize + 2;
  254. fdo->Flags |= DO_POWER_PAGABLE;
  255. #if DBG_STACK
  256. stkchkend = 0;
  257. stkptr = (DWORD *)&DriverObject;
  258. for (i=0; i<50; i++)
  259. {
  260. stkchkend += *stkptr++;
  261. }
  262. if (stkchkend != stkchk)
  263. {
  264. MyKdPrint(D_Error, ("Err, ******** STACK CHECK FAIL!!!!\n"))
  265. }
  266. else
  267. {
  268. MyKdPrint(D_Error, ("OK Stack chk\n"))
  269. }
  270. #endif
  271. MyKdPrint(D_PnpAdd, ("End SerialAddDevice\n"))
  272. MyKdPrint(D_Pnp, ("End SerialAddDevice\n"))
  273. return status;
  274. }
  275. /*----------------------------------------------------------------------
  276. AddBoardDevice - Setup and Create a board device in response to
  277. AddDevice ioctl.
  278. |----------------------------------------------------------------------*/
  279. NTSTATUS AddBoardDevice(
  280. IN PDRIVER_OBJECT DriverObject,
  281. IN PDEVICE_OBJECT Pdo,
  282. OUT PDEVICE_OBJECT *NewDevObj)
  283. {
  284. PSERIAL_DEVICE_EXTENSION NewExtension = NULL;
  285. NTSTATUS status = STATUS_SUCCESS;
  286. char tmpstr[110];
  287. ULONG Hardware_ID = 0;
  288. int num_ports = 0;
  289. int stat;
  290. static int max_isa_board_index = 0;
  291. int device_node_index = -1;
  292. int isa_board_index = -1;
  293. MyKdPrint(D_Pnp, ("AddBoardDevice\n"))
  294. // Find out what the PnP manager thinks my NT pnp Hardware ID is
  295. tmpstr[0] = 0;
  296. stat = GetPnpIdStr(Pdo, tmpstr);
  297. if (stat)
  298. {
  299. MyKdPrint(D_Error, ("Err, HdwID 1B\n"))
  300. }
  301. MyKdPrint(D_Test, ("DevHdwID:%s\n", tmpstr))
  302. // Parse this info, tells us what type of board we have
  303. stat = HdwIDStrToID(&Hardware_ID, tmpstr);
  304. if (stat)
  305. {
  306. MyKdPrint(D_Error, ("Err, HdwID 1A:%s\n", tmpstr))
  307. }
  308. MyKdPrint(D_Pnp, ("HdwID:%x\n", Hardware_ID))
  309. // Read in our Node Index, see if we are new...
  310. stat = read_config_data(Pdo, &device_node_index, CFG_ID_NODE_INDEX);
  311. if (stat) // not exist
  312. {
  313. derive_unique_node_index(&device_node_index);
  314. MyKdPrint(D_Test, ("Derive Node ID:%d\n", device_node_index))
  315. stat = write_config_data(Pdo, device_node_index, CFG_ID_NODE_INDEX);
  316. }
  317. else
  318. {
  319. MyKdPrint(D_Test, ("Node ID:%d\n", device_node_index))
  320. }
  321. if (device_node_index < 0)
  322. device_node_index = 0;
  323. #ifdef S_RK
  324. // try to order the ISA boards
  325. if ((Hardware_ID >= 0x1000) && (Hardware_ID <= 0x2fff)) // its ISA
  326. {
  327. stat = read_config_data(Pdo, &isa_board_index, CFG_ID_ISA_BRD_INDEX);
  328. MyKdPrint(D_Pnp,("Read isa_board_index:%d\n", isa_board_index))
  329. }
  330. #endif
  331. //----- create a board device
  332. Driver.Stop_Poll = 1; // flag to stop poll access
  333. if (Driver.driver_ext == NULL)
  334. {
  335. status = CreateDriverDevice(Driver.GlobalDriverObject,
  336. &NewExtension); // create the driver device
  337. #ifdef S_VS
  338. init_eth_start();
  339. #endif
  340. }
  341. status = CreateBoardDevice(Driver.GlobalDriverObject,
  342. &NewExtension); // create the board device
  343. *NewDevObj = NewExtension->DeviceObject;
  344. if (status != STATUS_SUCCESS)
  345. {
  346. Driver.Stop_Poll = 0; // flag to stop poll access
  347. Eprintf("CreateBoardDevice Err1A");
  348. return status;
  349. }
  350. // DoPnpAssoc(Pdo);
  351. // copy over our key name used to find config info in the registry
  352. Sprintf(NewExtension->config->szNt50DevObjName, "Device%d", device_node_index);
  353. #if 0
  354. //strcpy(NewExtension->config->szNt50DevObjName, PnpKeyName);
  355. #endif
  356. NewExtension->config->Hardware_ID = Hardware_ID;
  357. num_ports = id_to_num_ports(Hardware_ID);
  358. MyKdPrint(D_Test, ("NumPorts:%d\n", num_ports))
  359. // read in our device configuration from the registry
  360. stat = read_device_options(NewExtension);
  361. //if (!(Hardware_ID == NET_DEVICE_VS1000)) // jam in
  362. // NewExtension->config->NumPorts = num_ports;
  363. if (NewExtension->config->NumPorts == 0)
  364. NewExtension->config->NumPorts = num_ports;
  365. // check for ModemDevice, etc.
  366. if (IsModemDevice(Hardware_ID))
  367. NewExtension->config->ModemDevice = 1;
  368. MyKdPrint(D_Pnp, ("Num Ports:%d\n",NewExtension->config->NumPorts))
  369. #ifdef S_RK
  370. // try to order the ISA boards
  371. if ((Hardware_ID >= 0x1000) && (Hardware_ID <= 0x2fff)) // its ISA
  372. {
  373. if (isa_board_index == -1) // new
  374. {
  375. isa_board_index = max_isa_board_index;
  376. stat = write_config_data(Pdo, isa_board_index, CFG_ID_ISA_BRD_INDEX);
  377. MyKdPrint(D_Pnp,("Save IsaIndex:%d\n", isa_board_index))
  378. }
  379. // bump so next isa board gets new index
  380. if (max_isa_board_index >= isa_board_index)
  381. max_isa_board_index = isa_board_index + 1;
  382. NewExtension->config->ISABrdIndex = isa_board_index;
  383. } // isa board
  384. #endif
  385. Driver.Stop_Poll = 0; // flag to stop poll access
  386. status = STATUS_SUCCESS;
  387. return status;
  388. }
  389. /*----------------------------------------------------------------------
  390. derive_unique_node_index -
  391. |----------------------------------------------------------------------*/
  392. static int derive_unique_node_index(int *ret_val)
  393. {
  394. HANDLE DrvHandle = NULL;
  395. HANDLE DevHandle = NULL;
  396. char tmpstr[40];
  397. int i, stat;
  398. // force a creation of "Parameters" if not exist
  399. stat = our_open_driver_reg(&DrvHandle, KEY_ALL_ACCESS);
  400. for (i=0; i< 100; i++)
  401. {
  402. Sprintf(tmpstr,"Device%d", i);
  403. stat = our_open_key(&DevHandle,
  404. DrvHandle, tmpstr, KEY_READ);
  405. if (stat) // does not exist
  406. {
  407. // create it, so next one won't pick up the same
  408. stat = our_open_key(&DevHandle,
  409. DrvHandle, tmpstr, KEY_ALL_ACCESS);
  410. ZwClose(DevHandle);
  411. ZwClose(DrvHandle);
  412. *ret_val = i;
  413. return 0; // ok
  414. }
  415. }
  416. ZwClose(DevHandle);
  417. ZwClose(DrvHandle);
  418. return 1; // err
  419. }
  420. /*----------------------------------------------------------------------
  421. GetPnpIdStr -
  422. |----------------------------------------------------------------------*/
  423. static int GetPnpIdStr(PDEVICE_OBJECT Pdo, char *ret_val)
  424. {
  425. NTSTATUS status = STATUS_SUCCESS;
  426. UNICODE_STRING ustr;
  427. ULONG resultLength = 0;
  428. char *ptr;
  429. // configure the unicode string to: point the buffer ptr to the wstr.
  430. ustr.Buffer = ExAllocatePool(PagedPool, 1002);
  431. if ( ustr.Buffer == NULL ) {
  432. return -1;
  433. }
  434. ustr.Length = 0;
  435. ustr.MaximumLength = 1000;
  436. MyKdPrint(D_Pnp, ("AddBoardDevice\n"))
  437. // Find out what the PnP manager thinks my NT Hardware ID is
  438. // "CtmPort0000" for port, "rckt1002" for isa-board
  439. // for pci we are getting a multi-wstring, 400 bytes long with
  440. // "PCI\VEN_11FE&DEV_0003&SUBSYS00000...",0,"PCI\VEN.."
  441. status = IoGetDeviceProperty (Pdo,
  442. DevicePropertyHardwareID, // port0000
  443. ustr.MaximumLength,
  444. ustr.Buffer,
  445. &resultLength);
  446. ustr.Length = (USHORT) resultLength;
  447. if (ustr.Length > 100)
  448. ustr.Length = 100; // limit
  449. ptr = UToC1(&ustr);
  450. strcpy(ret_val, ptr);
  451. ExFreePool(ustr.Buffer);
  452. MyKdPrint(D_Pnp, ("DevHdwID:%s\n", ret_val))
  453. return 0;
  454. }
  455. #if 0
  456. /*----------------------------------------------------------------------
  457. DoPnpAssoc - Weird pnp stuff I haven't figured out yet
  458. |----------------------------------------------------------------------*/
  459. static int DoPnpAssoc(PDEVICE_OBJECT Pdo)
  460. {
  461. if (!Driver.NoPnpPorts)
  462. {
  463. #ifdef DO_BUS_SHINGLES
  464. //
  465. // Tell the PlugPlay system that this device will need an interface
  466. // device class shingle.
  467. //
  468. // It may be that the driver cannot hang the shingle until it starts
  469. // the device itself, so that it can query some of its properties.
  470. // (Aka the shingles guid (or ref string) is based on the properties
  471. // of the device.)
  472. //
  473. status = IoRegisterDeviceInterface (
  474. Pdo, // BusPhysicalDeviceObject
  475. (LPGUID) &GUID_CTMPORT_BUS_ENUMERATOR,
  476. NULL, // No ref string
  477. &NewExtension->DevClassAssocName);
  478. #endif
  479. //
  480. // If for any reason you need to save values in a safe location that
  481. // clients of this DeviceClassAssociate might be interested in reading
  482. // here is the time to do so, with the function
  483. // IoOpenDeviceClassRegistryKey
  484. // the symbolic link name used is was returned in
  485. // deviceData->DevClassAssocName (the same name which is returned by
  486. // IoGetDeviceClassAssociations and the SetupAPI equivs.
  487. //
  488. //status = IoGetDeviceProperty (BusPhysicalDeviceObject,
  489. // DevicePropertyPhysicalDeviceObjectName,
  490. // 0,
  491. // NULL,
  492. // &nameLength);
  493. //IoGetDeviceProperty (BusPhysicalDeviceObject,
  494. // DevicePropertyPhysicalDeviceObjectName,
  495. // nameLength,
  496. // deviceName,
  497. // &nameLength);
  498. //Game_KdPrint (deviceData, GAME_DBG_SS_TRACE,
  499. // ("AddDevice: %x to %x->%x (%ws) \n",
  500. // deviceObject,
  501. // NewExtension->TopOfStack,
  502. // BusPhysicalDeviceObject,
  503. // deviceName));
  504. //
  505. // Turn on the shingle and point it to the given device object.
  506. //
  507. #ifdef DO_BUS_SHINGLES
  508. status = IoSetDeviceInterfaceState (
  509. &NewExtension->DevClassAssocName,
  510. TRUE);
  511. if (!NT_SUCCESS (status)) {
  512. Game_KdPrint (deviceData, GAME_DBG_SS_ERROR,
  513. ("AddDevice: IoSetDeviceClass failed (%x)", status));
  514. return status;
  515. }
  516. #endif
  517. //IoInvalidateDeviceRelations (NewExtension->DeviceObject, BusRelations);
  518. } // !NoPnpPorts
  519. #endif
  520. /*----------------------------------------------------------------------
  521. write_config_data -
  522. |----------------------------------------------------------------------*/
  523. static int write_config_data(PDEVICE_OBJECT Pdo, int val, int val_id)
  524. {
  525. HANDLE keyHandle;
  526. NTSTATUS status = STATUS_SUCCESS;
  527. USTR_40 uname;
  528. status = IoOpenDeviceRegistryKey(Pdo, PLUGPLAY_REGKEY_DRIVER,
  529. KEY_WRITE, &keyHandle);
  530. if (!NT_SUCCESS(status))
  531. {
  532. MyKdPrint(D_Error, ("Err7V\n"))
  533. return 1;
  534. }
  535. switch(val_id)
  536. {
  537. case CFG_ID_ISA_BRD_INDEX:
  538. CToUStr((PUNICODE_STRING)&uname, "isa_board_index", sizeof(uname));
  539. break;
  540. case CFG_ID_NODE_INDEX:
  541. CToUStr((PUNICODE_STRING)&uname, "CtmNodeId", sizeof(uname));
  542. break;
  543. }
  544. status = ZwSetValueKey (keyHandle,
  545. (PUNICODE_STRING) &uname,
  546. 0, // type optional
  547. REG_DWORD,
  548. &val,
  549. sizeof(REG_DWORD));
  550. if (!NT_SUCCESS(status))
  551. {
  552. MyKdPrint(D_Error, ("Err8V\n"))
  553. }
  554. ZwClose(keyHandle);
  555. return 0;
  556. }
  557. /*----------------------------------------------------------------------
  558. read_config_data -
  559. |----------------------------------------------------------------------*/
  560. static int read_config_data(PDEVICE_OBJECT Pdo, int *ret_val, int val_id)
  561. {
  562. HANDLE keyHandle;
  563. NTSTATUS status = STATUS_SUCCESS;
  564. ULONG tmparr[100];
  565. USTR_40 uname;
  566. PKEY_VALUE_PARTIAL_INFORMATION parInfo =
  567. (PKEY_VALUE_PARTIAL_INFORMATION) &tmparr[0];
  568. ULONG length;
  569. int ret_stat = 1; // err
  570. //----- go grab some configuration info from registry
  571. // PLUGPLAY_REGKEY_DRIVER opens up the control\class\{guid}\node
  572. // PLUGPLAY_REGKEY_DEVICE opens up the enum\enum-type\node\Device Parameters
  573. status = IoOpenDeviceRegistryKey(Pdo,
  574. PLUGPLAY_REGKEY_DRIVER,
  575. STANDARD_RIGHTS_READ,
  576. &keyHandle);
  577. if (!NT_SUCCESS(status))
  578. {
  579. return 2; // err
  580. }
  581. switch(val_id)
  582. {
  583. case CFG_ID_ISA_BRD_INDEX:
  584. CToUStr((PUNICODE_STRING)&uname, "isa_board_index", sizeof(uname));
  585. break;
  586. case CFG_ID_NODE_INDEX:
  587. CToUStr((PUNICODE_STRING)&uname, "CtmNodeId", sizeof(uname));
  588. break;
  589. }
  590. // try to order the ISA boards
  591. status = ZwQueryValueKey (keyHandle,
  592. (PUNICODE_STRING) &uname,
  593. KeyValuePartialInformation,
  594. parInfo,
  595. sizeof(tmparr),
  596. &length);
  597. if (NT_SUCCESS(status))
  598. {
  599. if (parInfo->Type == REG_DWORD)
  600. {
  601. ret_stat = 0; // ok
  602. *ret_val = *((ULONG *) &parInfo->Data[0]);
  603. //MyKdPrint(D_Pnp,("Read isa_board_index:%d\n", isa_board_index))
  604. }
  605. }
  606. ZwClose(keyHandle);
  607. return ret_stat;
  608. }
  609. /*----------------------------------------------------------------------
  610. AddPortDevice - Setup and Create a pnp port device in response to
  611. AddDevice ioctl. This can be caused by either:
  612. * pdo port objects ejected from our driver at board startup.
  613. |----------------------------------------------------------------------*/
  614. NTSTATUS AddPortDevice(
  615. IN PDRIVER_OBJECT DriverObject,
  616. IN PDEVICE_OBJECT Pdo,
  617. OUT PDEVICE_OBJECT *NewDevObj,
  618. IN int port_index)
  619. {
  620. NTSTATUS status = STATUS_SUCCESS;
  621. PSERIAL_DEVICE_EXTENSION NewExtension;
  622. PSERIAL_DEVICE_EXTENSION ext;
  623. PSERIAL_DEVICE_EXTENSION ParExt;
  624. MyKdPrint(D_Pnp, ("AddPortDevice\n"))
  625. // Find the parent device
  626. ext = (PSERIAL_DEVICE_EXTENSION) Pdo->DeviceExtension;
  627. if (ext == NULL)
  628. {
  629. MyKdPrint(D_Pnp, ("Er7E\n"))
  630. return STATUS_SERIAL_NO_DEVICE_INITED;
  631. }
  632. else
  633. ParExt = ext->board_ext;
  634. CheckPortName(Pdo, ParExt, port_index);
  635. //----- create a port device
  636. Driver.Stop_Poll = 1; // flag to stop poll access
  637. status = CreatePortDevice(
  638. Driver.GlobalDriverObject,
  639. ParExt, // parent ext.
  640. &NewExtension, // new device ext.
  641. port_index, // port index, channel number
  642. 1); // is_fdo
  643. if (status != STATUS_SUCCESS)
  644. {
  645. Driver.Stop_Poll = 0; // flag to stop poll access
  646. MyKdPrint(D_Error, ("Error Creating Port\n"))
  647. return STATUS_SERIAL_NO_DEVICE_INITED;
  648. }
  649. if (status == STATUS_SUCCESS)
  650. {
  651. *NewDevObj = NewExtension->DeviceObject;
  652. status = StartPortHardware(NewExtension, port_index);
  653. if (status != STATUS_SUCCESS)
  654. {
  655. Driver.Stop_Poll = 0; // flag to stop poll access
  656. MyKdPrint(D_Error, ("5D\n"))
  657. // bugbug: should delete our port here
  658. return STATUS_SERIAL_NO_DEVICE_INITED;
  659. }
  660. }
  661. if (!NT_SUCCESS(status)) {
  662. Driver.Stop_Poll = 0; // flag to stop poll access
  663. Eprintf("CreateBoardDevice Err1A");
  664. return status;
  665. }
  666. Driver.Stop_Poll = 0; // flag to stop poll access
  667. status = STATUS_SUCCESS;
  668. return status;
  669. }
  670. /*----------------------------------------------------------------------
  671. CheckPortName - Make sure the port-name for us in the registry works.
  672. Get the pnp-port name held in the enum branch, if ours does not match,
  673. then change it to match(use the pnp-port name.)
  674. |----------------------------------------------------------------------*/
  675. NTSTATUS CheckPortName(
  676. IN PDEVICE_OBJECT Pdo,
  677. IN PSERIAL_DEVICE_EXTENSION ParentExt,
  678. IN int port_index)
  679. {
  680. HANDLE keyHandle;
  681. NTSTATUS status;
  682. char namestr[20];
  683. PORT_CONFIG *port_config;
  684. MyKdPrint(D_Pnp, ("CheckPortName\n"))
  685. //----- go grab PORTNAME configuration info from registry
  686. // serial keeps params under ENUM branch so we open DEVICE not DRIVER
  687. // which is considered CLASS area.
  688. // opens: enum\device\node\Device Parameters area
  689. // status = IoOpenDeviceRegistryKey(Pdo, PLUGPLAY_REGKEY_DRIVER,
  690. namestr[0] = 0;
  691. status = IoOpenDeviceRegistryKey(Pdo,
  692. PLUGPLAY_REGKEY_DEVICE,
  693. STANDARD_RIGHTS_READ,
  694. &keyHandle);
  695. // go get "Device Parameters\PortName"="COM5"
  696. // also, key params: PollingPeriod=, Serenumerable=
  697. if (NT_SUCCESS(status))
  698. {
  699. status = get_reg_value(keyHandle, namestr, "PortName", 15);
  700. if (status) // err
  701. {
  702. namestr[0] = 0;
  703. MyKdPrint(D_Error, ("No PortName\n"))
  704. }
  705. else
  706. {
  707. MyKdPrint(D_Pnp, ("PortName:%s\n", namestr))
  708. }
  709. ZwClose(keyHandle);
  710. }
  711. if ((strlen(namestr) > 10) || (strlen(namestr) <= 0))
  712. {
  713. MyKdPrint(D_Error, ("Bad PortName Er1E\n"))
  714. }
  715. port_config = &ParentExt->config->port[port_index];
  716. if (my_lstricmp(port_config->Name, namestr) != 0) // it does not match!
  717. {
  718. MyKdPrint(D_Pnp, ("port name fixup to:%s, from%s\n",
  719. namestr, port_config->Name))
  720. // fix it, use one assigned by port class installer
  721. strcpy(port_config->Name, namestr);
  722. write_port_name(ParentExt, port_index);
  723. }
  724. return 0;
  725. }
  726. #endif // nt50