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.

1978 lines
58 KiB

  1. /*-----------------------------------------------------------------------
  2. | nt50.c - NT5.0 specific code for VSLinkA/RocketPort Windows Install
  3. Program.
  4. This compiles into a DLL library which is installed(via INF) into
  5. the SYSTEM directory. The INF file also hooks us into the system
  6. as a property page associated with the device. Also, our co-installer
  7. DLL calls into us as well to perform configuration tasks(initial
  8. install, un-install).
  9. The .NumDevices option is used to save the number of Devices in
  10. our configuration. Under NT50, we don't use it as such. This setup
  11. dll only concerns itself with 1 device, and lets NT5.0 OS handle
  12. the list of devices. So NumDevices always gets set to 1 under NT5.0
  13. even if we have more than one device which our driver is controlling.
  14. 11-24-98 - add some code toward clean up of files after uninstall, kpb.
  15. Copyright 1998. Comtrol(TM) Corporation.
  16. |-----------------------------------------------------------------------*/
  17. #include "precomp.h"
  18. #include <msports.h>
  19. #define D_Level 0x40
  20. static int write_config(int clear_it);
  21. static int FindPortNodes(void);
  22. static int read_config(void);
  23. static int get_pnp_devicedesc(TCHAR *name);
  24. static int nt5_get_pnp_dev_id(int *id);
  25. static void uninstall_device(void);
  26. int get_device_name(void);
  27. int do_nt50_install(void);
  28. BOOL WINAPI ClassInsProc(
  29. int func_num, // our function to carry out.
  30. LPVOID our_info); // points to our data struct
  31. static int get_pnp_setup_info(void);
  32. static int get_device_property(char *ret_name, int max_size);
  33. static int get_pnp_isa_address(void);
  34. static void test_config(void);
  35. // following can be turned on to provide a User Interface during the
  36. // install time of the driver. Only problem is that NT5.0 fires up
  37. // the driver first, and are ports
  38. //#define TRY_UI 1
  39. #ifdef TRY_UI
  40. int DoCLassPropPages(HWND hwndOwner);
  41. int FillClassPropertySheets(PROPSHEETPAGE *psp, LPARAM our_params);
  42. BOOL WINAPI ClassSheet(
  43. IN HWND hDlg,
  44. IN UINT uMessage,
  45. IN WPARAM wParam,
  46. IN LPARAM lParam);
  47. #endif
  48. //#define DO_SHOWIT
  49. #ifdef DO_SHOWIT
  50. #define ShowMess(s) OutputDebugString(s);
  51. static void show_install_info(OUR_INFO *pi);
  52. static void show_debug_info(OUR_INFO *pi,
  53. ULONG dev_id,
  54. TCHAR *desc_str);
  55. static int DumpPnpTree(void);
  56. static void show_tree_node(DEVINST devInst,
  57. ULONG dev_id,
  58. TCHAR *desc_str);
  59. static void show_tree_node_reg(DEVINST devInst,
  60. TCHAR *key_name);
  61. static TCHAR *spdrp_names[] = {
  62. TEXT("DEVICEDESC"),
  63. TEXT("HARDWAREID"),
  64. TEXT("COMPATIBLEIDS"),
  65. TEXT("NTDEVICEPATHS"),
  66. TEXT("SERVICE"),
  67. TEXT("CONFIGURATION"), // x5
  68. TEXT("CONFIGURATIONVECTOR"),
  69. TEXT("CLASS"),
  70. TEXT("CLASSGUID"),
  71. TEXT("DRIVER"),
  72. TEXT("CONFIGFLAGS"), // xA
  73. TEXT("MFG"),
  74. TEXT("FRIENDLYNAME"),
  75. TEXT("LOCATION_INFORMATION"),
  76. TEXT("PHYSICAL_DEVICE_OBJECT_NAME"),
  77. TEXT("CAPABILITIES"),
  78. TEXT("UI_NUMBER"), // x10
  79. TEXT("UPPERFILTERS"),
  80. TEXT("LOWERFILTERS"),
  81. TEXT("BUSTYPEGUID"), // x13
  82. TEXT("LEGACYBUSTYPE"),
  83. TEXT("BUSNUMBER"),
  84. TEXT("invalid")};
  85. static TCHAR *cm_drp_names[] = {
  86. TEXT("DEVICEDESC"), // DeviceDesc REG_SZ property (RW)
  87. TEXT("HARDWAREID"), // HardwareID REG_MULTI_SZ property (RW)
  88. TEXT("COMPATIBLEIDS"), // CompatibleIDs REG_MULTI_SZ property (RW)
  89. TEXT("NTDEVICEPATHS"), // Unsupported, DO NOT USE
  90. TEXT("SERVICE"), // Service REG_SZ property (RW)
  91. TEXT("CONFIGURATION"), // Configuration REG_RESOURCE_LIST property (R)
  92. TEXT("CONFIGURATIONVECTOR"), // ConfigurationVector REG_RESOURCE_REQUIREMENTS_LIST property (R)
  93. TEXT("CLASS"), // Class REG_SZ property (RW)
  94. TEXT("CLASSGUID"), // ClassGUID REG_SZ property (RW)
  95. TEXT("DRIVER"), // Driver REG_SZ property (RW)
  96. TEXT("CONFIGFLAGS"), // ConfigFlags REG_DWORD property (RW)
  97. TEXT("MFG"), // Mfg REG_SZ property (RW)
  98. TEXT("FRIENDLYNAME"), // 0x0d FriendlyName REG_SZ property (RW)
  99. TEXT("LOCATION_INFORMATION"), // LocationInformation REG_SZ property (RW)
  100. TEXT("PHYSICAL_DEVICE_OBJECT_NAME"), // PhysicalDeviceObjectName REG_SZ property (R)
  101. TEXT("CAPABILITIES"), // 0x10 Capabilities REG_DWORD property (R)
  102. TEXT("UI_NUMBER"), // UiNumber REG_DWORD property (R)
  103. TEXT("UPPERFILTERS"), // UpperFilters REG_MULTI_SZ property (RW)
  104. TEXT("LOWERFILTERS"), // LowerFilters REG_MULTI_SZ property (RW)
  105. TEXT("BUSTYPEGUID"), // Bus Type Guid, GUID, (R)
  106. TEXT("LEGACYBUSTYPE"), // Legacy bus type, INTERFACE_TYPE, (R)
  107. TEXT("BUSNUMBER"), // x16 Bus Number, DWORD, (R)
  108. TEXT("invalid")};
  109. // these are under Control\Class\Guid\Node
  110. static TCHAR *dev_node_key_names[] = {
  111. TEXT("ProviderName"),
  112. TEXT("MatchingDeviceId"),
  113. TEXT("DriverDesc"),
  114. TEXT("InfPath"),
  115. TEXT("InfSection"),
  116. TEXT("isa_board_index"),
  117. NULL};
  118. static TCHAR glob_ourstr[4000];
  119. /*----------------------------------------------------------
  120. show_install_info - show all the driver install info.
  121. |------------------------------------------------------------*/
  122. static void show_install_info(OUR_INFO *pi)
  123. {
  124. int i;
  125. //if (MessageBox( GetFocus(), TEXT("Want Info?"), TEXT("aclass"), MB_YESNO | MB_ICONINFORMATION ) ==
  126. // IDYES)
  127. {
  128. ShowMess(TEXT("**SPDRP****"));
  129. glob_ourstr[0] = 0;
  130. for (i=0; i<(SPDRP_MAXIMUM_PROPERTY-1); i++)
  131. {
  132. show_debug_info(pi, i, spdrp_names[i]);
  133. }
  134. ShowMess(glob_ourstr);
  135. //MessageBox( GetFocus(), glob_ourstr, TEXT("aclass"), MB_OK | MB_ICONINFORMATION );
  136. }
  137. }
  138. /*----------------------------------------------------------
  139. show_debug_info -
  140. |------------------------------------------------------------*/
  141. static void show_debug_info(OUR_INFO *pi,
  142. ULONG dev_id,
  143. TCHAR *desc_str)
  144. {
  145. static TCHAR tmpstr[500];
  146. static TCHAR showstr[500];
  147. TCHAR smstr[40];
  148. ULONG RegType;
  149. ULONG ReqSize,i;
  150. unsigned char *b_ptr;
  151. int stat;
  152. showstr[0] = 0;
  153. RegType = 0;
  154. ReqSize = 0;
  155. stat = SetupDiGetDeviceRegistryProperty(pi->DeviceInfoSet,
  156. pi->DeviceInfoData,
  157. dev_id,
  158. &RegType, // reg data type
  159. (PBYTE)tmpstr,
  160. sizeof(tmpstr),
  161. &ReqSize); // size thing
  162. if (stat == FALSE)
  163. {
  164. stat = GetLastError();
  165. if (stat == 13)
  166. {
  167. return; // don't display this
  168. }
  169. wsprintf(showstr, TEXT("Error:%d[%xH] ReqSize:%d"), stat, stat, ReqSize);
  170. }
  171. else if (RegType == REG_SZ)
  172. {
  173. wsprintf(showstr, TEXT("SZ:%s"), tmpstr);
  174. }
  175. else if (RegType == REG_DWORD)
  176. {
  177. wsprintf(showstr, TEXT("Dword:%xH"), *((ULONG *) tmpstr));
  178. }
  179. else if (RegType == REG_EXPAND_SZ)
  180. {
  181. wsprintf(showstr, TEXT("EXP_SZ:%s"), tmpstr);
  182. }
  183. else if (RegType == REG_MULTI_SZ)
  184. {
  185. wsprintf(showstr, TEXT("MULTI_SZ:%s"), tmpstr);
  186. }
  187. else if (RegType == REG_BINARY)
  188. {
  189. lstrcpy(showstr, TEXT("BIN:"));
  190. b_ptr = (unsigned char *)tmpstr;
  191. for (i=0; i<ReqSize; i++)
  192. {
  193. if ((b_ptr[i] >= 0x20) && (b_ptr[i] < 0x80))
  194. wsprintf(smstr, TEXT("%c"), b_ptr[i]);
  195. else
  196. wsprintf(smstr, TEXT("<%x>"), b_ptr[i]);
  197. lstrcat(showstr, smstr);
  198. if (i > 200) break;
  199. }
  200. }
  201. else
  202. {
  203. wsprintf(showstr, TEXT("BadType:%xH"), RegType);
  204. }
  205. if (lstrlen(showstr) > 200)
  206. showstr[200] = 0;
  207. if (lstrlen(glob_ourstr) < 3700)
  208. {
  209. lstrcat(glob_ourstr, desc_str);
  210. lstrcat(glob_ourstr, TEXT(" - "));
  211. lstrcat(glob_ourstr, showstr);
  212. lstrcat(glob_ourstr, TEXT("\n"));
  213. }
  214. }
  215. /*-----------------------------------------------------------------------------
  216. | DumpPnpTree - Dump the pnp tree devnodes.
  217. |-----------------------------------------------------------------------------*/
  218. static int DumpPnpTree(void)
  219. {
  220. DEVINST devInst;
  221. DEVINST devInstNext;
  222. CONFIGRET cr;
  223. ULONG walkDone = 0;
  224. ULONG len;
  225. static CHAR buf[800];
  226. HKEY hKey;
  227. int di,pi;
  228. ULONG val_type;
  229. #if DBG
  230. //DebugBreak();
  231. #endif
  232. //cr = CM_Locate_DevNode(&devInst, NULL, 0);
  233. // Get Root DevNode
  234. //
  235. cr = CM_Locate_DevNode(&devInst, NULL, 0);
  236. if (cr != CR_SUCCESS)
  237. {
  238. return 1; // err
  239. }
  240. // Do a depth first search for the DevNode with a matching parameter
  241. while (!walkDone)
  242. {
  243. cr = CR_SUCCESS;
  244. glob_ourstr[0] = 0;
  245. lstrcat(glob_ourstr,TEXT("-CM_DRP-----"));
  246. for (di=CM_DRP_MIN; di<CM_DRP_MAX; di++)
  247. {
  248. show_tree_node(devInst, di, cm_drp_names[di-CM_DRP_MIN]);
  249. }
  250. lstrcat(glob_ourstr,TEXT("-KEYS--"));
  251. di = 0;
  252. while (dev_node_key_names[di] != NULL)
  253. {
  254. show_tree_node_reg(devInst, dev_node_key_names[di]);
  255. ++di;
  256. }
  257. ShowMess(glob_ourstr);
  258. #if 0
  259. // Get the DriverName value
  260. //
  261. buf[0] = 0;
  262. len = sizeof(buf);
  263. cr = CM_Get_DevNode_Registry_Property(devInst,
  264. CM_DRP_CLASS, NULL, buf, &len, 0);
  265. if (cr == CR_SUCCESS && strcmp("Ports", buf) == 0)
  266. {
  267. //P_TRACE("Ports");
  268. // grab the "MatchingDeviceId"
  269. cr = CM_Open_DevNode_Key(
  270. devInst,
  271. KEY_READ, // IN REGSAM samDesired,
  272. 0, // IN ULONG ulHardwareProfile,
  273. RegDisposition_OpenExisting,
  274. &hKey, //OUT PHKEY phkDevice,
  275. CM_REGISTRY_SOFTWARE); // IN ULONG ulFlags
  276. if (cr == CR_SUCCESS)
  277. {
  278. buf[0] = 0;
  279. len = sizeof(buf);
  280. cr = RegQueryValueEx(hKey,
  281. TEXT("MatchingDeviceId"),
  282. 0,
  283. &val_type,
  284. (PBYTE) buf,
  285. &len);
  286. if (cr != ERROR_SUCCESS)
  287. {
  288. buf[0] = 0;
  289. }
  290. RegCloseKey(hKey);
  291. } // if openreg
  292. } // if "Ports"
  293. #endif
  294. // This DevNode didn't match, go down a level to the first child.
  295. //
  296. cr = CM_Get_Child(&devInstNext,
  297. devInst,
  298. 0);
  299. if (cr == CR_SUCCESS)
  300. {
  301. devInst = devInstNext;
  302. continue;
  303. }
  304. // Can't go down any further, go across to the next sibling. If
  305. // there are no more siblings, go back up until there is a sibling.
  306. // If we can't go up any further, we're back at the root and we're
  307. // done.
  308. //
  309. for (;;)
  310. {
  311. cr = CM_Get_Sibling(&devInstNext,
  312. devInst,
  313. 0);
  314. if (cr == CR_SUCCESS)
  315. {
  316. devInst = devInstNext;
  317. break;
  318. }
  319. cr = CM_Get_Parent(&devInstNext,
  320. devInst,
  321. 0);
  322. if (cr == CR_SUCCESS)
  323. {
  324. devInst = devInstNext;
  325. }
  326. else
  327. {
  328. walkDone = 1;
  329. break;
  330. }
  331. } // for (;;)
  332. } // while (!walkDone)
  333. return 2; // done;
  334. }
  335. /*----------------------------------------------------------
  336. show_tree_node -
  337. |------------------------------------------------------------*/
  338. static void show_tree_node(DEVINST devInst,
  339. ULONG dev_id,
  340. TCHAR *desc_str)
  341. {
  342. CONFIGRET cr;
  343. static TCHAR tmpstr[500];
  344. static TCHAR showstr[500];
  345. TCHAR smstr[40];
  346. ULONG RegType;
  347. ULONG ReqSize,i;
  348. unsigned char *b_ptr;
  349. int stat;
  350. showstr[0] = 0;
  351. RegType = 0;
  352. ReqSize = 0;
  353. cr = CM_Get_DevNode_Registry_Property(devInst,
  354. dev_id, &RegType, tmpstr, &ReqSize, 0);
  355. if (cr != CR_SUCCESS)
  356. {
  357. stat = GetLastError();
  358. if (stat == 997)
  359. {
  360. return; // don't display this
  361. }
  362. wsprintf(showstr, TEXT("Error:%d[%xH] ReqSize:%d"), stat, stat, ReqSize);
  363. //MessageBox( GetFocus(), showstr, desc_str, MB_OK | MB_ICONINFORMATION );
  364. }
  365. else if (RegType == REG_SZ)
  366. {
  367. wsprintf(showstr, TEXT("SZ:%s"), tmpstr);
  368. //MessageBox( GetFocus(), showstr, desc_str, MB_OK | MB_ICONINFORMATION );
  369. }
  370. else if (RegType == REG_DWORD)
  371. {
  372. wsprintf(showstr, TEXT("Dword:%xH"), *((ULONG *) tmpstr));
  373. //MessageBox( GetFocus(), showstr, desc_str, MB_OK | MB_ICONINFORMATION );
  374. }
  375. else if (RegType == REG_EXPAND_SZ)
  376. {
  377. wsprintf(showstr, TEXT("EXP_SZ:%s"), tmpstr);
  378. //MessageBox( GetFocus(), showstr, desc_str, MB_OK | MB_ICONINFORMATION );
  379. }
  380. else if (RegType == REG_MULTI_SZ)
  381. {
  382. wsprintf(showstr, TEXT("MULTI_SZ:%s"), tmpstr);
  383. //MessageBox( GetFocus(), showstr, desc_str, MB_OK | MB_ICONINFORMATION );
  384. }
  385. else if (RegType == REG_BINARY)
  386. {
  387. lstrcpy(showstr, TEXT("BIN:"));
  388. b_ptr = (unsigned char *)tmpstr;
  389. for (i=0; i<ReqSize; i++)
  390. {
  391. if ((b_ptr[i] >= 0x20) && (b_ptr[i] < 0x80))
  392. wsprintf(smstr, TEXT("%c"), b_ptr[i]);
  393. else
  394. wsprintf(smstr, TEXT("<%x>"), b_ptr[i]);
  395. lstrcat(showstr, smstr);
  396. if (i > 200) break;
  397. }
  398. //MessageBox( GetFocus(), showstr, desc_str, MB_OK | MB_ICONINFORMATION );
  399. }
  400. else
  401. {
  402. wsprintf(showstr, TEXT("BadType:%xH"), RegType);
  403. //MessageBox( GetFocus(), tmpstr, desc_str, MB_OK | MB_ICONINFORMATION );
  404. }
  405. if (lstrlen(showstr) > 200)
  406. showstr[200] = 0;
  407. if (lstrlen(glob_ourstr) < 3700)
  408. {
  409. lstrcat(glob_ourstr, desc_str);
  410. lstrcat(glob_ourstr, TEXT(" - "));
  411. lstrcat(glob_ourstr, showstr);
  412. lstrcat(glob_ourstr, TEXT("\n"));
  413. }
  414. }
  415. /*----------------------------------------------------------
  416. show_tree_node_reg -
  417. |------------------------------------------------------------*/
  418. static void show_tree_node_reg(DEVINST devInst,
  419. TCHAR *key_name)
  420. {
  421. CONFIGRET cr;
  422. static TCHAR tmpstr[500];
  423. static TCHAR showstr[500];
  424. TCHAR smstr[40];
  425. ULONG RegType;
  426. ULONG ReqSize,i;
  427. unsigned char *b_ptr;
  428. int stat;
  429. TCHAR *desc_str = key_name;
  430. HKEY hKey;
  431. showstr[0] = 0;
  432. cr = CM_Open_DevNode_Key(
  433. devInst,
  434. KEY_READ, // IN REGSAM samDesired,
  435. 0, // IN ULONG ulHardwareProfile,
  436. RegDisposition_OpenExisting,
  437. &hKey, //OUT PHKEY phkDevice,
  438. CM_REGISTRY_SOFTWARE); // IN ULONG ulFlags
  439. if (cr == CR_SUCCESS)
  440. {
  441. RegType = 0;
  442. ReqSize = 0;
  443. tmpstr[0] = 0;
  444. ReqSize = sizeof(tmpstr);
  445. cr = RegQueryValueEx(hKey,
  446. key_name,
  447. 0,
  448. &RegType,
  449. (PBYTE) tmpstr,
  450. &ReqSize);
  451. if (cr != ERROR_SUCCESS)
  452. {
  453. tmpstr[0] = 0;
  454. }
  455. RegCloseKey(hKey);
  456. } // if openreg
  457. else
  458. {
  459. tmpstr[0] = 0;
  460. ShowMess(TEXT("**Error Opening Key!\n"));
  461. }
  462. if (cr != CR_SUCCESS)
  463. {
  464. stat = GetLastError();
  465. //if (stat == 997)
  466. //{
  467. // return; // don't display this
  468. //}
  469. wsprintf(showstr, TEXT("Error:%d[%xH] ReqSize:%d"), stat, stat, ReqSize);
  470. //MessageBox( GetFocus(), showstr, desc_str, MB_OK | MB_ICONINFORMATION );
  471. }
  472. else if (RegType == REG_SZ)
  473. {
  474. wsprintf(showstr, TEXT("SZ:%s"), tmpstr);
  475. //MessageBox( GetFocus(), showstr, desc_str, MB_OK | MB_ICONINFORMATION );
  476. }
  477. else if (RegType == REG_DWORD)
  478. {
  479. wsprintf(showstr, TEXT("Dword:%xH"), *((ULONG *) tmpstr));
  480. //MessageBox( GetFocus(), showstr, desc_str, MB_OK | MB_ICONINFORMATION );
  481. }
  482. else if (RegType == REG_EXPAND_SZ)
  483. {
  484. wsprintf(showstr, TEXT("EXP_SZ:%s"), tmpstr);
  485. //MessageBox( GetFocus(), showstr, desc_str, MB_OK | MB_ICONINFORMATION );
  486. }
  487. else if (RegType == REG_MULTI_SZ)
  488. {
  489. wsprintf(showstr, TEXT("MULTI_SZ:%s"), tmpstr);
  490. //MessageBox( GetFocus(), showstr, desc_str, MB_OK | MB_ICONINFORMATION );
  491. }
  492. else if (RegType == REG_BINARY)
  493. {
  494. lstrcpy(showstr, TEXT("BIN:"));
  495. b_ptr = (unsigned char *)tmpstr;
  496. for (i=0; i<ReqSize; i++)
  497. {
  498. if ((b_ptr[i] >= 0x20) && (b_ptr[i] < 0x80))
  499. wsprintf(smstr, TEXT("%c"), b_ptr[i]);
  500. else
  501. wsprintf(smstr, TEXT("<%x>"), b_ptr[i]);
  502. lstrcat(showstr, smstr);
  503. if (i > 200) break;
  504. }
  505. //MessageBox( GetFocus(), showstr, desc_str, MB_OK | MB_ICONINFORMATION );
  506. }
  507. else
  508. {
  509. wsprintf(showstr, TEXT("BadType:%xH"), RegType);
  510. //MessageBox( GetFocus(), tmpstr, desc_str, MB_OK | MB_ICONINFORMATION );
  511. }
  512. if (lstrlen(showstr) > 200)
  513. showstr[200] = 0;
  514. if (lstrlen(glob_ourstr) < 3700)
  515. {
  516. lstrcat(glob_ourstr, desc_str);
  517. lstrcat(glob_ourstr, TEXT(" - "));
  518. lstrcat(glob_ourstr, showstr);
  519. lstrcat(glob_ourstr, TEXT("\n"));
  520. }
  521. }
  522. #endif
  523. // we are a DLL, so we need a LibMain...
  524. /*----------------------------------------------------------
  525. LibMain -
  526. |-------------------------------------------------------------*/
  527. BOOL APIENTRY LibMain( HANDLE hDll, DWORD dwReason, LPVOID lpReserved )
  528. {
  529. //DMess("LibMain");
  530. switch( dwReason )
  531. {
  532. case DLL_PROCESS_ATTACH:
  533. glob_hinst = hDll;
  534. DisableThreadLibraryCalls((struct HINSTANCE__ *) hDll);
  535. break;
  536. case DLL_PROCESS_DETACH:
  537. break;
  538. case DLL_THREAD_DETACH:
  539. break;
  540. case DLL_THREAD_ATTACH:
  541. default:
  542. break;
  543. }
  544. return TRUE;
  545. }
  546. /*----------------------------------------------------------
  547. DevicePropPage - DLL Entry Point from NT5.0 PnP manager to
  548. add property sheets. Not the entry point for NT4.0,
  549. see nt40.c code WinMain().
  550. Exported Entry-point for adding additional device manager
  551. property
  552. sheet pages. Registry specifies this routine under
  553. Control\Class\PortNode::EnumPropPage32="vssetup.dll,DevicePropPage"
  554. entry. This entry-point gets called only when the Device
  555. Manager asks for additional property pages.
  556. Arguments:
  557. LPVOID pinfo - points to PROPSHEETPAGE_REQUEST, see setupapi.h
  558. LPFNADDPROPSHEETPAGE pfnAdd - function ptr to call to add sheet.
  559. LPARAM lParam - add sheet functions private data handle.
  560. Return Value:
  561. TRUE on success
  562. FALSE if pages could not be added
  563. |------------------------------------------------------------*/
  564. BOOL WINAPI DevicePropPage(
  565. LPVOID pinfo, // points to PROPSHEETPAGE_REQUEST, see setupapi.h
  566. LPFNADDPROPSHEETPAGE pfnAdd, // add sheet function
  567. LPARAM lParam) // add sheet function data handle?
  568. {
  569. PSP_PROPSHEETPAGE_REQUEST ppr = (PSP_PROPSHEETPAGE_REQUEST) pinfo;
  570. PROPSHEETPAGE psp[NUM_DRIVER_SHEETS];
  571. HPROPSHEETPAGE hpage[NUM_DRIVER_SHEETS];
  572. OUR_INFO *pi;
  573. int i;
  574. int stat;
  575. setup_init(); // build our main structs
  576. pi = glob_info; // temporary kludge, unless we don't need re-entrantancy
  577. // copy the important port handles
  578. pi->DeviceInfoSet = ppr->DeviceInfoSet;
  579. pi->DeviceInfoData = ppr->DeviceInfoData;
  580. #ifdef DO_SHOWIT
  581. if (MessageBox( GetFocus(), TEXT("Want Info?"), TEXT("aclass"), MB_YESNO | MB_ICONINFORMATION ) ==
  582. IDYES)
  583. {
  584. show_install_info(pi);
  585. DumpPnpTree();
  586. }
  587. #endif
  588. //glob_hwnd = hDlg;
  589. wi->NumDevices = 0;
  590. // get the name that NT associates with this device, so we can
  591. // store and retrieve config information based on this also.
  592. stat = get_device_name();
  593. if (stat)
  594. {
  595. // something is seriously wrong if we can't get our device
  596. // name. This is something NT uses as a name.
  597. DbgPrintf(D_Error, (TEXT("err5f\n")));
  598. }
  599. wi->NumDevices = 1; // for pnp, devices are independent
  600. get_pnp_setup_info(); // read in pnp info
  601. get_pnp_devicedesc(wi->dev[0].Name); // read in pnp description
  602. get_nt_config(wi); // get configured vslink device settings.
  603. if (wi->dev[0].ModelName[0] == 0)
  604. {
  605. #ifdef S_RK
  606. if ((wi->dev[0].HardwareId == PCI_DEVICE_RPLUS2) ||
  607. (wi->dev[0].HardwareId == PCI_DEVICE_422RPLUS2) ||
  608. (wi->dev[0].HardwareId == PCI_DEVICE_RPLUS4) ||
  609. (wi->dev[0].HardwareId == PCI_DEVICE_RPLUS8))
  610. {
  611. strcpy(wi->dev[0].ModelName, szRocketPortPlus);
  612. }
  613. else if ((wi->dev[0].HardwareId == ISA_DEVICE_RMODEM4) ||
  614. (wi->dev[0].HardwareId == ISA_DEVICE_RMODEM8) ||
  615. (wi->dev[0].HardwareId == PCI_DEVICE_RMODEM6) ||
  616. (wi->dev[0].HardwareId == PCI_DEVICE_RMODEM4))
  617. {
  618. strcpy(wi->dev[0].ModelName, szRocketModem);
  619. }
  620. else
  621. {
  622. strcpy(wi->dev[0].ModelName, szRocketPort);
  623. }
  624. //szRocketPort485
  625. #endif
  626. #ifdef S_VS
  627. if (wi->dev[0].HardwareId == NET_DEVICE_VS2000)
  628. {
  629. strcpy(wi->dev[0].ModelName, szVS2000);
  630. }
  631. else if ((wi->dev[0].HardwareId == NET_DEVICE_RHUB8) ||
  632. (wi->dev[0].HardwareId == NET_DEVICE_RHUB4))
  633. {
  634. strcpy(wi->dev[0].ModelName, szSerialHub);
  635. }
  636. else // if (wi->dev[0].HardwareId == NET_DEVICE_VS1000)
  637. {
  638. strcpy(wi->dev[0].ModelName, szVS1000);
  639. }
  640. #endif
  641. }
  642. validate_config(1);
  643. //test_config();
  644. // if 0 dev-nodes setup, add 1 for the user.
  645. if (wi->NumDevices == 0)
  646. {
  647. ++wi->NumDevices;
  648. validate_device(&wi->dev[0], 1);
  649. }
  650. copy_setup_init(); // make a copy of config data for change detection
  651. FillDriverPropertySheets(&psp[0], (LPARAM)pi);
  652. // allocate our "Setting" sheet
  653. for (i=0; i<NUM_DRIVER_SHEETS; i++)
  654. {
  655. hpage[i] = CreatePropertySheetPage(&psp[i]);
  656. if (!hpage[i])
  657. {
  658. DbgPrintf(D_Error,(TEXT("err1a\n")));
  659. return FALSE;
  660. }
  661. // add the thing in.
  662. if (!pfnAdd(hpage[i], lParam))
  663. {
  664. DbgPrintf(D_Error,(TEXT("err1b\n")));
  665. DestroyPropertySheetPage(hpage[i]); // error, dump it
  666. return FALSE;
  667. }
  668. }
  669. return TRUE;
  670. }
  671. /*------------------------------------------------------------------------
  672. | ClassInsProc - Class Install entry for NT5.0 setup of driver.
  673. The co-class installer file(ctmasetp.dll,..) gets called at inital
  674. setup time, and calls us to bring up an initial user interface,
  675. or to handle other items.
  676. |------------------------------------------------------------------------*/
  677. BOOL WINAPI ClassInsProc(
  678. int func_num, // our function to carry out.
  679. LPVOID our_info) // points to our data struct
  680. {
  681. int stat;
  682. //TCHAR tmpstr[200];
  683. typedef struct {
  684. ULONG size;
  685. HDEVINFO DeviceInfoSet; // a plug & play context handle
  686. PSP_DEVINFO_DATA DeviceInfoData; // a plug & play context handle
  687. } CLASS_OUR_INFO;
  688. CLASS_OUR_INFO *ci;
  689. OUR_INFO *pi;
  690. int i;
  691. switch (func_num)
  692. {
  693. case 0x40: // RocketPort Class Install time.
  694. case 0x41: // RocketPort Class Install time, quite install
  695. case 0x80: // VS Class Install time.
  696. case 0x81: // VS Class Install time, quite install
  697. #if 0
  698. // don't pop up user interface on install, just use defaults
  699. // as best we can for now.
  700. ci = (CLASS_OUR_INFO *) our_info;
  701. setup_init(); // build our main structs
  702. pi = glob_info; // temporary kludge, unless we don't need re-entrantancy
  703. // copy the important port handles
  704. pi->DeviceInfoSet = ci->DeviceInfoSet;
  705. pi->DeviceInfoData = ci->DeviceInfoData;
  706. //glob_hwnd = hDlg;
  707. wi->NumDevices = 1;
  708. // get the name that NT associates with this device, so we can
  709. // store and retrieve config information based on this also.
  710. stat = get_device_name();
  711. {
  712. get_pnp_setup_info();
  713. get_nt_config(wi); // get configured vslink device settings.
  714. //validate_config();
  715. }
  716. if (stat)
  717. {
  718. // something is seriously wrong if we can't get our device
  719. // name. This is something NT uses as a name.
  720. DbgPrintf(D_Error,(TEXT("err5f\n")));
  721. }
  722. // if 0 dev-nodes setup, add 1 for the user.
  723. if (wi->NumDevices == 0)
  724. {
  725. ++wi->NumDevices;
  726. validate_device(&wi->dev[0], 1);
  727. }
  728. copy_setup_init(); // make a copy of config data for change detection
  729. validate_config(1); // make sure port names are setup
  730. if ((func_num & 1) == 0) // normal
  731. {
  732. DoDriverPropPages(GetFocus()); // in nt40.c
  733. // force it to save things off(probably should disable
  734. // cancel button, instead of this kludge).
  735. do_nt50_install();
  736. }
  737. else // quite
  738. {
  739. wi->ip.prompting_off = 1; // turn our_message() prompting off.
  740. do_nt50_install();
  741. }
  742. #endif
  743. break;
  744. case 0x42: // UnInstall RocketPort Device time.
  745. case 0x82: // UnInstall VS Device time.
  746. DbgPrintf(D_Test, (TEXT("uninstall time\n")));
  747. ci = (CLASS_OUR_INFO *) our_info;
  748. setup_init(); // build our main structs
  749. pi = glob_info; // temporary kludge, unless we don't need re-entrantancy
  750. // copy the important port handles
  751. pi->DeviceInfoSet = ci->DeviceInfoSet;
  752. pi->DeviceInfoData = ci->DeviceInfoData;
  753. wi->NumDevices = 1;
  754. // get the name that NT associates with this device, so we can
  755. // store and retrieve config information based on this also.
  756. stat = get_device_name();
  757. if (stat == 0)
  758. {
  759. get_pnp_setup_info();
  760. //get_nt_config(wi); // get configured vslink device settings.
  761. //validate_config();
  762. uninstall_device();
  763. }
  764. break;
  765. default:
  766. return 1; // error, bad func_num
  767. break;
  768. } // switch
  769. return 0;
  770. }
  771. /*-----------------------------------------------------------------------------
  772. | get_pnp_setup_info -
  773. |-----------------------------------------------------------------------------*/
  774. static int get_pnp_setup_info(void)
  775. {
  776. static TCHAR tmpstr[600];
  777. TCHAR *ptr;
  778. int stat;
  779. int Hardware_ID = 0;
  780. // grab the board type information. Tells us what type of
  781. // board we have
  782. stat = get_device_property(tmpstr, 580);
  783. if (stat != 0)
  784. return 1;
  785. DbgPrintf(D_Level, (TEXT("dev_prop:%s\n"), tmpstr) );
  786. // Find out what the PnP manager thinks my NT Hardware ID is
  787. // "CtmPort0000" for RocketPort port,
  788. // "CtmVPort0000" for VS port,
  789. // "CtmRK1002" for isa-board rocketport,
  790. // "CtmRM1002" for isa-board rocketmodem,
  791. // "CtmVS1003" for VS1000
  792. // for pci we are getting a multi-wstring, 400 bytes long with
  793. // "PCI\VEN_11FE&DEV_0003&SUBSYS00000...",0,"PCI\VEN.."
  794. stat = HdwIDStrToID(&Hardware_ID, tmpstr);
  795. if (stat)
  796. {
  797. DbgPrintf(D_Error, (TEXT("Err, Unknown pnpid:%s\n"), tmpstr))
  798. }
  799. stat = id_to_num_ports(Hardware_ID);
  800. if ((Hardware_ID & 0xfff) == 0) // marked as pci
  801. wi->dev[0].IoAddress = 1; // indicate to setup prog it is a PCI board
  802. if (Hardware_ID & 0x1000) // marked as isa
  803. get_pnp_isa_address();
  804. // correct number of ports setting if it doesn't match
  805. //if (wi->dev[0].NumPorts != stat)
  806. //{
  807. // DbgPrintf(D_Level, (TEXT("Correct NumPorts!\n")));
  808. wi->dev[0].NumPorts = stat;
  809. //}
  810. wi->dev[0].HardwareId = Hardware_ID;
  811. // check for HubDevice, ModemDevice, etc.
  812. if (IsHubDevice(Hardware_ID))
  813. wi->dev[0].HubDevice = 1;
  814. if (IsModemDevice(Hardware_ID))
  815. wi->dev[0].ModemDevice = 1;
  816. DbgPrintf(D_Level, (TEXT("Num Ports:%d\n"),stat));
  817. return 0;
  818. }
  819. /*-----------------------------------------------------------------------------
  820. | get_device_property - return "rckt1003", or whatever, see INF file for
  821. selections. For PCI this returns a long multi-sz string.
  822. |-----------------------------------------------------------------------------*/
  823. static int get_device_property(char *ret_name, int max_size)
  824. {
  825. int stat, i,j;
  826. ULONG RegType;
  827. ULONG ReqSize;
  828. ret_name[0] = 0;
  829. stat = SetupDiGetDeviceRegistryProperty(glob_info->DeviceInfoSet,
  830. glob_info->DeviceInfoData,
  831. SPDRP_HARDWAREID,
  832. &RegType, // reg data type
  833. (PBYTE)ret_name,
  834. max_size,
  835. &ReqSize); // size thing
  836. if (stat == FALSE)
  837. {
  838. return 1; // err
  839. }
  840. if ((RegType != REG_MULTI_SZ) && (RegType != REG_SZ))
  841. {
  842. return 2; // err
  843. // error
  844. }
  845. return 0; // ok
  846. }
  847. /*-----------------------------------------------------------------------------
  848. | our_nt50_exit - return 1 if not allowing to exit. return 0 if ok to exit.
  849. |-----------------------------------------------------------------------------*/
  850. int our_nt50_exit(void)
  851. {
  852. int stat;
  853. OUR_INFO *pi;
  854. DWORD DataSize;
  855. DWORD DataType;
  856. DWORD dstat;
  857. DWORD Val;
  858. HKEY hkey;
  859. pi = glob_info; // temporary kludge, unless we don't need re-entrantancy
  860. {
  861. stat = do_nt50_install();
  862. if (wi->NeedReset)
  863. our_message(&wi->ip,RcStr((MSGSTR+4)), MB_OK);
  864. write_config(1); // clear out msports claims
  865. write_config(0); // reclaim any new changed port names
  866. }
  867. return 0;
  868. }
  869. /*-----------------------------------------------------------------------------
  870. | get_device_name - return name in wi->ip.szNt50DevObjName[], ret 0 on success.
  871. Pnp puts config data into a registry node associated with the device.
  872. We put a lot of our config information into a related registry node.
  873. This related node is derived by and index saved and read from the pnp-node.
  874. So the first device added we assign a index of 0, and get a derived name
  875. of "Device0". The 2nd device we add to the system sees the first, and
  876. saves an index value of 1, to get a associated device name of "Device1".
  877. The driver actually writes these index values out to the registry, not
  878. the setup program. This is because the driver fires up before setup
  879. has a chance to run.
  880. |-----------------------------------------------------------------------------*/
  881. int get_device_name(void)
  882. {
  883. int i;
  884. int stat;
  885. i = 0;
  886. stat = nt5_get_pnp_dev_id(&i);
  887. if (stat)
  888. {
  889. DbgPrintf(D_Test,(TEXT("failed to get pnp id\n")))
  890. }
  891. wsprintf(wi->ip.szNt50DevObjName, "Device%d", i);
  892. DbgPrintf(D_Test,(TEXT("pnp idstr:%s\n"), wi->ip.szNt50DevObjName))
  893. return 0; // ok
  894. }
  895. /*-----------------------------------------------------------------------------
  896. | nt5_get_pnp_dev_id - Get pnp device ID. Pnp can have devices come and go
  897. dynamically, so a simple list of devices does not work. This is because
  898. we are no longer in charge of the master list. We just get called
  899. from ths OS, which handles half of the installation. This approximates
  900. a simple list of devices by reading a unique "Device#" number which the
  901. driver creates and stores in the software key:
  902. Driver:
  903. Upon startup, reads Pnp_Software_Reg_Area\CtmNodeID
  904. if (not exist)
  905. {
  906. derive unique device id number by enumerating
  907. Service\Rocketport\Parameters\"Device#" key entries.
  908. Add this key entry and also save number off as CtmNodeID.
  909. }
  910. Read in its device configuration from
  911. Service\Rocketport\Parameters\"Device#" key.
  912. Setup Config Program:
  913. Upon startup, reads Pnp_Software_Reg_Area\CtmNodeID
  914. for its "Device#" to use in reading reg config area:
  915. Service\Rocketport\Parameters\"Device#" key entries.
  916. Note on pnp registr areas:
  917. Hardware key is something like:
  918. HKLM\CurrentControlSet\Enum\Root\MultiPortSerial\0000 ; ISA or net device
  919. or
  920. HKLM\CurrentControlSet\Enum\VEN_11FE&DEV......\0000 ; PCI device
  921. or (vs driver bus enumerated port entry):
  922. HKLM\CurrentControlSet\Enum\CtmvPort\RDevice\10&Port000 ; enumerated port
  923. Software key is something like:
  924. HKLM\CurrentControlSet\Control\Class\{50906CB8-....}\0000 ; MPS
  925. or for a port:
  926. HKLM\CurrentControlSet\Control\Class\{4D36E978-....}\0000 ; PORTS
  927. The hardware key is a reg. tree structure which reflects the hardware
  928. configuration. The software key is more of a flat reg. structure
  929. which reflects the devices in the system. Software area uses GUID
  930. names to catagorize and name types of hardware.
  931. The Hardware keys are hidden by default in the NT5 registry.
  932. Use a tool called PNPREG.EXE /U to Unlock this area, then regedit
  933. will see beyond enum. PNPREG /L will lock(hide) it.
  934. The hardware key contains a link to the software key.
  935. |-----------------------------------------------------------------------------*/
  936. static int nt5_get_pnp_dev_id(int *id)
  937. {
  938. HKEY hkey;
  939. int stat;
  940. DWORD id_dword;
  941. stat = nt5_open_dev_key(&hkey);
  942. if (stat)
  943. {
  944. *id = 0;
  945. return 1;
  946. }
  947. stat = reg_get_dword(hkey, "", "CtmNodeId", &id_dword);
  948. reg_close_key(hkey);
  949. if (stat)
  950. {
  951. // it should have been there, the driver should set this up to
  952. // a unique index value. But if not, we use 0.
  953. *id = 0;
  954. return 2;
  955. }
  956. // return the unique index value which is used to derive the
  957. // registry configuration area "Device#".
  958. *id = (int) id_dword;
  959. return 0;
  960. }
  961. /*-----------------------------------------------------------------------------
  962. | nt5_open_dev_key -
  963. |-----------------------------------------------------------------------------*/
  964. int nt5_open_dev_key(HKEY *hkey)
  965. {
  966. CONFIGRET cr;
  967. cr = CM_Open_DevNode_Key(
  968. glob_info->DeviceInfoData->DevInst,
  969. KEY_ALL_ACCESS,
  970. 0,
  971. RegDisposition_OpenExisting,
  972. hkey,
  973. CM_REGISTRY_SOFTWARE); // _SOFTWARE worked!(under CLASS)
  974. //CM_REGISTRY_HARDWARE); // _HARDWARE no open!
  975. //CM_REGISTRY_CONFIG); // _CONFIG wrote under HardwareConfig
  976. if (cr != CR_SUCCESS)
  977. {
  978. DbgPrintf(D_Error,(TEXT("nt50 pnp reg open fail:%d\n"), GetLastError()));
  979. *hkey = NULL;
  980. return 1;
  981. }
  982. return 0;
  983. }
  984. #if DBG
  985. /*-----------------------------------------------------------------------------
  986. | read_config - Save the config for the device Just a test.
  987. |-----------------------------------------------------------------------------*/
  988. static int read_config(void)
  989. {
  990. int stat;
  991. DWORD DataSize;
  992. DWORD DataType;
  993. DWORD Err;
  994. DWORD Val;
  995. HKEY hkey;
  996. DEVINST devInst;
  997. CONFIGRET cr;
  998. static char *szNumPorts = {"NumPorts"};
  999. static char *szTestVal = {"TestVal"};
  1000. stat = 0;
  1001. DbgPrintf(D_Test,(TEXT("read config\n")));
  1002. if((hkey = SetupDiOpenDevRegKey(glob_info->DeviceInfoSet,
  1003. glob_info->DeviceInfoData,
  1004. DICS_FLAG_GLOBAL,
  1005. 0,
  1006. DIREG_DEV,
  1007. //DIREG_DRV,
  1008. KEY_READ)) == INVALID_HANDLE_VALUE) {
  1009. DbgPrintf(D_Error,(TEXT("DI open fail:%xH\n"), GetLastError()));
  1010. stat = 1;
  1011. }
  1012. if (stat == 0)
  1013. {
  1014. DataSize = sizeof(DWORD); // max size of return str
  1015. Err = RegQueryValueEx(hkey, szNumPorts, NULL, &DataType,
  1016. (BYTE *) &Val, &DataSize);
  1017. if (Err != ERROR_SUCCESS)
  1018. {
  1019. DbgPrintf(D_Error,(TEXT("OpenDevReg fail\n")));
  1020. Val = 0;
  1021. }
  1022. DbgPrintf(D_Test,(TEXT("NumPorts=%d\n"), Val));
  1023. RegCloseKey(hkey);
  1024. }
  1025. DbgPrintf(D_Test,(TEXT("write config\n")));
  1026. stat = 0;
  1027. if((hkey = SetupDiOpenDevRegKey(glob_info->DeviceInfoSet,
  1028. glob_info->DeviceInfoData,
  1029. DICS_FLAG_GLOBAL,
  1030. 0,
  1031. DIREG_DEV,
  1032. //DIREG_DRV,
  1033. //KEY_ALL_ACCESS)) == INVALID_HANDLE_VALUE) {
  1034. KEY_WRITE)) == INVALID_HANDLE_VALUE) {
  1035. DbgPrintf(D_Error,(TEXT("DI write open fail:%xH\n"), GetLastError()));
  1036. stat = 1;
  1037. }
  1038. if (stat == 0)
  1039. {
  1040. stat = reg_set_dword(hkey, "", szTestVal, 0x1234);
  1041. if (stat)
  1042. {
  1043. DbgPrintf(D_Error,(TEXT("write val fail\n")));
  1044. }
  1045. RegCloseKey(hkey);
  1046. }
  1047. devInst = glob_info->DeviceInfoData->DevInst;
  1048. if (devInst == 0)
  1049. {
  1050. DbgPrintf(D_Error,(TEXT("err6g\n")));
  1051. return 1; // err
  1052. }
  1053. cr = CM_Open_DevNode_Key(
  1054. devInst,
  1055. KEY_READ, // IN REGSAM samDesired,
  1056. 0, // IN ULONG ulHardwareProfile,
  1057. RegDisposition_OpenExisting,
  1058. &hkey, //OUT PHKEY phkDevice,
  1059. //CM_REGISTRY_SOFTWARE); // _SOFTWARE worked!(under CLASS)
  1060. CM_REGISTRY_HARDWARE); // _HARDWARE no open!
  1061. //CM_REGISTRY_CONFIG); // _CONFIG wrote under HardwareConfig
  1062. if (cr == CR_SUCCESS)
  1063. {
  1064. DataSize = sizeof(DWORD); // max size of return str
  1065. Err = RegQueryValueEx(hkey, szNumPorts, NULL, &DataType,
  1066. (BYTE *) &Val, &DataSize);
  1067. if (Err != ERROR_SUCCESS)
  1068. {
  1069. DbgPrintf(D_Error,(TEXT("Reg query fail\n")));
  1070. Val = 0;
  1071. }
  1072. DbgPrintf(D_Test,(TEXT("cr NumPorts=%d\n"), Val));
  1073. RegCloseKey(hkey);
  1074. }
  1075. else
  1076. {
  1077. DbgPrintf(D_Error,(TEXT("CM open fail:%d\n"), GetLastError()));
  1078. }
  1079. cr = CM_Open_DevNode_Key(
  1080. devInst,
  1081. //KEY_ALL_ACCESS,
  1082. KEY_WRITE,
  1083. 0,
  1084. RegDisposition_OpenExisting,
  1085. &hkey,
  1086. //CM_REGISTRY_SOFTWARE); // _SOFTWARE worked!(under CLASS)
  1087. CM_REGISTRY_HARDWARE); // _HARDWARE no open!
  1088. //CM_REGISTRY_CONFIG); // _CONFIG wrote under HardwareConfig
  1089. if (cr == CR_SUCCESS)
  1090. {
  1091. stat = reg_set_dword(hkey, "", szTestVal, 0x1234);
  1092. if (stat)
  1093. {
  1094. DbgPrintf(D_Error,(TEXT("write val fail\n")));
  1095. }
  1096. else
  1097. {
  1098. DbgPrintf(D_Test,(TEXT("write val ok\n")));
  1099. }
  1100. RegCloseKey(hkey);
  1101. }
  1102. else
  1103. {
  1104. DbgPrintf(D_Error,(TEXT("CM write open fail:%d\n"), GetLastError()));
  1105. }
  1106. return 0;
  1107. }
  1108. #endif
  1109. /*-----------------------------------------------------------------------------
  1110. | get_pnp_devicedesc -
  1111. |-----------------------------------------------------------------------------*/
  1112. static int get_pnp_devicedesc(TCHAR *name)
  1113. {
  1114. CONFIGRET cr;
  1115. DWORD len;
  1116. // Get the Device name
  1117. len = 60;
  1118. cr = CM_Get_DevNode_Registry_Property(glob_info->DeviceInfoData->DevInst,
  1119. CM_DRP_DEVICEDESC,
  1120. NULL,
  1121. (PBYTE)name,
  1122. &len,
  1123. 0);
  1124. if (cr != CR_SUCCESS)
  1125. {
  1126. DbgPrintf(D_Error,(TEXT("err, no fr.name.\n")));
  1127. return 2; // err
  1128. }
  1129. DbgPrintf(D_Test, (TEXT("get friendlyname:%s\n"), name));
  1130. return 0; // ok
  1131. }
  1132. #if 0
  1133. /*-----------------------------------------------------------------------------
  1134. | set_pnp_devicedesc -
  1135. |-----------------------------------------------------------------------------*/
  1136. static int set_pnp_devicedesc(TCHAR *name)
  1137. {
  1138. CONFIGRET cr;
  1139. // Set the Device name
  1140. cr = CM_Set_DevNode_Registry_Property(
  1141. glob_info->DeviceInfoData->DevInst,
  1142. CM_DRP_DEVICEDESC,
  1143. (PBYTE)name,
  1144. (lstrlen(name) + 1) * sizeof(TCHAR),
  1145. 0);
  1146. if (cr != CR_SUCCESS)
  1147. {
  1148. DbgPrintf(D_Error,(TEXT("err3d\n")));
  1149. return 2; // err
  1150. }
  1151. return 0; // ok
  1152. }
  1153. #endif
  1154. /*-----------------------------------------------------------------------------
  1155. | write_config - Save the config for the device - Set pnp port names so
  1156. they match our configuration. Also, try to keep MSPORTS.DLL com-port
  1157. name database in sync with our stuff by detecting when our pnp comport
  1158. name changes, and calling msports routines to free and claim port names.
  1159. We call this routine once with clear_it SET, then call it again with
  1160. it clear. This is because we must clear ALL port claims from msports.dll
  1161. (which holds a database in services\serial reg area) prior to re-claiming
  1162. new port names. This is because if we overlap, we run into trouble.
  1163. |-----------------------------------------------------------------------------*/
  1164. static int write_config(int clear_it)
  1165. {
  1166. DEVINST devInst;
  1167. Device_Config *dev;
  1168. Port_Config *port;
  1169. int i,pi, str_i, stat;
  1170. CONFIGRET cr;
  1171. ULONG len;
  1172. TCHAR buf[120];
  1173. TCHAR curname[40];
  1174. HKEY hKey;
  1175. int port_index = 0;
  1176. int port_i;
  1177. ULONG val_type;
  1178. HCOMDB hPort = NULL;
  1179. FindPortNodes(); // fill in all port->hPnpNode
  1180. for(i=0; i<wi->NumDevices; i++) // Loop through all possible boards
  1181. {
  1182. dev = &wi->dev[i];
  1183. for(pi=0; pi<dev->NumPorts; pi++) // Loop through all ports
  1184. {
  1185. port = &dev->ports[pi];
  1186. if (port->hPnpNode != 0) // have a DEVINST handle for it.
  1187. {
  1188. devInst = (DEVINST) port->hPnpNode;
  1189. if (!clear_it)
  1190. {
  1191. len = sizeof(buf);
  1192. #ifdef S_RK
  1193. wsprintf(buf, "Comtrol RocketPort %d (%s)", port_index, port->Name);
  1194. #else
  1195. wsprintf(buf, "Comtrol VS Port %d (%s)", port_index, port->Name);
  1196. #endif
  1197. cr = CM_Set_DevNode_Registry_Property(devInst,
  1198. CM_DRP_FRIENDLYNAME,
  1199. (PBYTE)buf,
  1200. (lstrlen(buf) + 1) * sizeof(TCHAR),
  1201. 0);
  1202. if (cr != CR_SUCCESS)
  1203. {
  1204. DbgPrintf(D_Error,(TEXT("err7d\n")));
  1205. }
  1206. }
  1207. cr = CM_Open_DevNode_Key(
  1208. devInst,
  1209. KEY_ALL_ACCESS, // IN REGSAM samDesired,
  1210. 0, // IN ULONG ulHardwareProfile,
  1211. RegDisposition_OpenExisting,
  1212. &hKey, //OUT PHKEY phkDevice,
  1213. CM_REGISTRY_HARDWARE); // IN ULONG ulFlags
  1214. wsprintf(buf, "%s", port->Name);
  1215. if (cr == CR_SUCCESS)
  1216. {
  1217. curname[0] = 0;
  1218. len = sizeof(curname);
  1219. cr = RegQueryValueEx(hKey,
  1220. TEXT("PortName"),
  1221. 0,
  1222. &val_type,
  1223. (PBYTE) curname,
  1224. &len);
  1225. if (cr != CR_SUCCESS)
  1226. {
  1227. DbgPrintf(D_Error,(TEXT("error reading portname\n")));
  1228. }
  1229. if (_tcsicmp(curname, buf) != 0) // it's changed!
  1230. {
  1231. DbgPrintf(D_Test,(TEXT("com name from:%s, to %s\n"), curname, buf));
  1232. if (hPort == NULL)
  1233. cr = ComDBOpen(&hPort);
  1234. if (hPort == NULL)
  1235. {
  1236. DbgPrintf(D_Error,(TEXT("err dbcom 1d\n")));
  1237. }
  1238. else
  1239. {
  1240. if (clear_it)
  1241. {
  1242. // clear out name
  1243. port_i = ExtractNameNum(curname);
  1244. if ((port_i > 0) && (port_i < 256))
  1245. {
  1246. ComDBReleasePort(hPort, port_i);
  1247. DbgPrintf(D_Test,(TEXT("Free Old:%d\n"), port_i));
  1248. }
  1249. }
  1250. else
  1251. {
  1252. port_i = ExtractNameNum(buf);
  1253. if ((port_i > 0) && (port_i < 256))
  1254. {
  1255. ComDBClaimPort(hPort, port_i, 1 /* force*/, NULL);
  1256. DbgPrintf(D_Test,(TEXT("Claim New:%d\n"), port_i));
  1257. }
  1258. }
  1259. }
  1260. if (!clear_it)
  1261. {
  1262. RegSetValueEx(hKey,
  1263. "PortName",
  1264. 0,
  1265. REG_SZ,
  1266. (PBYTE) buf,
  1267. (lstrlen(buf) + 1) * sizeof(TCHAR) );
  1268. }
  1269. } // not matched, com-port name changed
  1270. RegCloseKey(hKey);
  1271. } // opened dev node key
  1272. else {
  1273. DbgPrintf(D_Error,(TEXT("err7e\n")));
  1274. }
  1275. } // if (port->hPnpNode != 0)
  1276. else
  1277. {
  1278. DbgPrintf(D_Level,(TEXT("Bad Pnp Name Find\n")));
  1279. }
  1280. ++port_index;
  1281. } // for(pi=0; pi<dev->NumPorts; pi++)
  1282. } // for(i=0; i<wi->NumDevices; i++)
  1283. if (hPort != NULL)
  1284. ComDBClose(hPort);
  1285. return 0;
  1286. }
  1287. /*------------------------------------------------------------------------
  1288. | uninstall_device -
  1289. |------------------------------------------------------------------------*/
  1290. static void uninstall_device(void)
  1291. {
  1292. #ifdef DO_SHOWIT
  1293. if (MessageBox( GetFocus(), TEXT("UNINSTALL, Want Info?"), TEXT("aclass"), MB_YESNO | MB_ICONINFORMATION ) ==
  1294. IDYES)
  1295. {
  1296. show_install_info(glob_info);
  1297. DumpPnpTree();
  1298. }
  1299. #endif
  1300. clear_nt_device(wi);
  1301. //if (this_is_last_device)
  1302. // remove_driver(1);
  1303. }
  1304. /*-----------------------------------------------------------------------------
  1305. | FindPortNodes - Find the pnp tree devnodes which hold our port names.
  1306. Put the handle into our port config struct for easy access.
  1307. We start the search at our device node.
  1308. |-----------------------------------------------------------------------------*/
  1309. static int FindPortNodes(void)
  1310. {
  1311. DEVINST devInst;
  1312. DEVINST devInstNext;
  1313. CONFIGRET cr;
  1314. ULONG walkDone = 0;
  1315. ULONG len;
  1316. CHAR buf[120];
  1317. HKEY hKey;
  1318. int di,pi;
  1319. int port_index;
  1320. Device_Config *dev;
  1321. Port_Config *port;
  1322. ULONG val_type;
  1323. // clear out all stale pnpnode handles before re-creating this list
  1324. for(di=0; di<wi->NumDevices; di++) // Loop through all possible boards
  1325. {
  1326. dev = &wi->dev[di];
  1327. for(pi=0; pi<dev->NumPorts; pi++) // Loop through all ports
  1328. {
  1329. dev->ports[pi].hPnpNode = 0;
  1330. }
  1331. }
  1332. #if 0
  1333. // Get Root DevNode
  1334. //
  1335. cr = CM_Locate_DevNode(&devInst, NULL, 0);
  1336. if (cr != CR_SUCCESS)
  1337. {
  1338. return 1; // err
  1339. }
  1340. #endif
  1341. devInst = glob_info->DeviceInfoData->DevInst;
  1342. if (devInst == 0)
  1343. {
  1344. DbgPrintf(D_Error,(TEXT("err6g\n")));
  1345. return 1; // err
  1346. }
  1347. DbgPrintf(D_Level, (TEXT("search nodes\n")));
  1348. cr = CM_Get_Child(&devInstNext,
  1349. devInst,
  1350. 0);
  1351. while (cr == CR_SUCCESS)
  1352. {
  1353. devInst = devInstNext;
  1354. // Get the DriverName value
  1355. //
  1356. buf[0] = 0;
  1357. len = sizeof(buf);
  1358. cr = CM_Get_DevNode_Registry_Property(devInst,
  1359. CM_DRP_CLASS, NULL, buf, &len, 0);
  1360. if (cr == CR_SUCCESS && strcmp("Ports", buf) == 0)
  1361. {
  1362. // grab the "MatchingDeviceId"
  1363. cr = CM_Open_DevNode_Key(
  1364. devInst,
  1365. KEY_READ, // IN REGSAM samDesired,
  1366. 0, // IN ULONG ulHardwareProfile,
  1367. RegDisposition_OpenExisting,
  1368. &hKey, //OUT PHKEY phkDevice,
  1369. CM_REGISTRY_SOFTWARE); // IN ULONG ulFlags
  1370. if (cr == CR_SUCCESS)
  1371. {
  1372. buf[0] = 0;
  1373. len = sizeof(buf);
  1374. cr = RegQueryValueEx(hKey,
  1375. TEXT("MatchingDeviceId"),
  1376. 0,
  1377. &val_type,
  1378. (PBYTE) buf,
  1379. &len);
  1380. if (cr != ERROR_SUCCESS)
  1381. {
  1382. buf[0] = 0;
  1383. }
  1384. #ifdef S_RK
  1385. if (strstr(buf, "ctmport") != NULL) // found it
  1386. #else
  1387. if (strstr(buf, "ctmvport") != NULL) // found it
  1388. #endif
  1389. {
  1390. int k, dev_num;
  1391. k = sscanf(&buf[8], "%d", &dev_num);
  1392. if (k==1)
  1393. {
  1394. port_index = 0;
  1395. // found a vs port node, so save a reference to this node
  1396. // in our config struct for simple reference.
  1397. //save_pnp_node(j, devInst);
  1398. for(di=0; di<wi->NumDevices; di++) // Loop through all possible boards
  1399. {
  1400. dev = &wi->dev[di];
  1401. for(pi=0; pi<dev->NumPorts; pi++) // Loop through all ports
  1402. {
  1403. port = &dev->ports[pi];
  1404. if (port_index == dev_num) // found our matching index
  1405. {
  1406. port->hPnpNode = (HANDLE) devInst;
  1407. }
  1408. ++port_index;
  1409. } // for pi
  1410. } // for di
  1411. } // if scanf
  1412. } // if strstr "ctmvport"
  1413. RegCloseKey(hKey);
  1414. } // if openreg
  1415. } // if "Ports"
  1416. // Get next child
  1417. cr = CM_Get_Sibling(&devInstNext,
  1418. devInst,
  1419. 0);
  1420. } // while (!cr_success)
  1421. return 2; // done;
  1422. }
  1423. /*-----------------------------------------------------------------------------
  1424. | do_nt50_install -
  1425. |-----------------------------------------------------------------------------*/
  1426. int do_nt50_install(void)
  1427. {
  1428. int stat = 0;
  1429. int do_remove = 0;
  1430. int do_modem_inf = 0;
  1431. static int in_here = 0;
  1432. if (in_here) // problem hitting OK button twice(sets off two of these)
  1433. return 2;
  1434. in_here = 1;
  1435. if (wi->nt_reg_flags & 4) // initial install, no setupversion string found
  1436. {
  1437. if (setup_utils_exist())
  1438. {
  1439. setup_make_progman_group(1); // 1=with prompt
  1440. }
  1441. wi->nt_reg_flags &= ~4;
  1442. }
  1443. if (!wi->ChangesMade)
  1444. send_to_driver(0); // evaluate if anything changed
  1445. stat = send_to_driver(1);
  1446. stat = set_nt_config(wi);
  1447. in_here = 0;
  1448. if (stat)
  1449. return 1; // error
  1450. return 0; // ok
  1451. }
  1452. /*----------------------------------------------------------------------------
  1453. | get_pnp_isa_address -
  1454. |-----------------------------------------------------------------------------*/
  1455. static int get_pnp_isa_address(void)
  1456. {
  1457. int IoBase;
  1458. LOG_CONF LogConfig;
  1459. RES_DES ResDes;
  1460. IO_RESOURCE IoResource;
  1461. //IRQ_RESOURCE IrqResource;
  1462. CONFIGRET cr;
  1463. int status;
  1464. status = CM_Get_First_Log_Conf(&LogConfig,
  1465. (DEVINST)(glob_info->DeviceInfoData->DevInst),
  1466. ALLOC_LOG_CONF);
  1467. //if (status != CR_SUCCESS)
  1468. // mess(&wi->ip, "No ALLOC lc %xH\n",status);
  1469. if (status != CR_SUCCESS)
  1470. return 1;
  1471. // get the Io base port
  1472. status = CM_Get_Next_Res_Des(&ResDes, LogConfig, ResType_IO, NULL, 0);
  1473. if (status != CR_SUCCESS)
  1474. {
  1475. return 2;
  1476. }
  1477. cr = CM_Get_Res_Des_Data(ResDes, &IoResource, sizeof(IO_RESOURCE), 0);
  1478. CM_Free_Res_Des_Handle(ResDes);
  1479. if(cr != CR_SUCCESS)
  1480. {
  1481. return 3;
  1482. }
  1483. IoBase = (int)IoResource.IO_Header.IOD_Alloc_Base;
  1484. //mess(&wi->ip, "OK 1c, Base:%xH\n", IoBase);
  1485. if ((IoBase < 0x400) && (IoBase >= 0x100))
  1486. wi->dev[0].IoAddress = IoBase;
  1487. else
  1488. wi->dev[0].IoAddress = 0;
  1489. return 0;
  1490. }
  1491. #if 0
  1492. /*----------------------------------------------------------------------------
  1493. | test_config - See what we can do concerning the allocated IO resources.
  1494. |-----------------------------------------------------------------------------*/
  1495. static void test_config(void)
  1496. {
  1497. int IoBase;
  1498. LOG_CONF LogConfig;
  1499. RES_DES ResDes;
  1500. IO_RESOURCE IoResource;
  1501. //IRQ_RESOURCE IrqResource;
  1502. CONFIGRET cr;
  1503. int status;
  1504. //glob_ourstr[0] = 0;
  1505. //lstrcat(glob_ourstr, "Test Config:\n");
  1506. // mess(&wi->ip, "Test Config");
  1507. status = CM_Get_First_Log_Conf(&LogConfig,
  1508. (DEVINST)(glob_info->DeviceInfoData->DevInst),
  1509. BOOT_LOG_CONF);
  1510. if (status != CR_SUCCESS)
  1511. mess(&wi->ip, "No BOOT lc %xH\n",status);
  1512. else
  1513. mess(&wi->ip, "Got BOOT lc\n");
  1514. status = CM_Get_First_Log_Conf(&LogConfig,
  1515. (DEVINST)(glob_info->DeviceInfoData->DevInst),
  1516. FORCED_LOG_CONF);
  1517. if (status != CR_SUCCESS)
  1518. mess(&wi->ip, "No FORCED lc %xH\n",status);
  1519. else
  1520. mess(&wi->ip, "Got FORCED lc\n");
  1521. status = CM_Get_First_Log_Conf(&LogConfig,
  1522. (DEVINST)(glob_info->DeviceInfoData->DevInst),
  1523. BASIC_LOG_CONF);
  1524. if (status != CR_SUCCESS)
  1525. mess(&wi->ip, "No BASIC lc %xH\n",status);
  1526. else
  1527. mess(&wi->ip, "Got BASIC lc\n");
  1528. status = CM_Get_First_Log_Conf(&LogConfig,
  1529. (DEVINST)(glob_info->DeviceInfoData->DevInst),
  1530. FORCED_LOG_CONF);
  1531. if (status != CR_SUCCESS)
  1532. mess(&wi->ip, "No FORCED lc %xH\n",status);
  1533. else
  1534. mess(&wi->ip, "Got FORCED lc\n");
  1535. status = CM_Get_First_Log_Conf(&LogConfig,
  1536. (DEVINST)(glob_info->DeviceInfoData->DevInst),
  1537. ALLOC_LOG_CONF);
  1538. if (status != CR_SUCCESS)
  1539. mess(&wi->ip, "No ALLOC lc %xH\n",status);
  1540. else
  1541. mess(&wi->ip, "Got ALLOC lc\n");
  1542. if (status != CR_SUCCESS)
  1543. return;
  1544. //
  1545. // First, get the Io base port
  1546. //
  1547. status = CM_Get_Next_Res_Des(&ResDes, LogConfig, ResType_IO, NULL, 0);
  1548. if (status != CR_SUCCESS)
  1549. {
  1550. mess(&wi->ip, "Error 1b\n");
  1551. return;
  1552. }
  1553. mess(&wi->ip, "OK 1b\n");
  1554. cr = CM_Get_Res_Des_Data(ResDes, &IoResource, sizeof(IO_RESOURCE), 0);
  1555. CM_Free_Res_Des_Handle(ResDes);
  1556. if(cr != CR_SUCCESS)
  1557. {
  1558. mess(&wi->ip, "Error 1c\n");
  1559. return;
  1560. }
  1561. IoBase = (int)IoResource.IO_Header.IOD_Alloc_Base;
  1562. mess(&wi->ip, "OK 1c, Base:%xH\n", IoBase);
  1563. //OldIrq = IrqResource.IRQ_Header.IRQD_Alloc_Num;
  1564. #if 0
  1565. // We don't want to popup the configuration UI if the 'quiet install' flag is
  1566. // set _and_ we already have a forced config (pre-install support).
  1567. if (CM_Get_First_Log_Conf(&ForcedLogConf, glob_info->DeviceInfoData->DevInst, FORCED_LOG_CONF) == CR_SUCCESS)
  1568. {
  1569. CM_Free_Log_Conf_Handle(ForcedLogConf);
  1570. DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  1571. if (SetupDiGetDeviceInstallParams(DeviceInfoSet, DeviceInfoData, &DeviceInstallParams))
  1572. {
  1573. if(FirstTime && (DeviceInstallParams.Flags & DI_QUIETINSTALL))
  1574. {
  1575. DisplayPropSheet = FALSE;
  1576. }
  1577. }
  1578. }
  1579. #endif
  1580. }
  1581. #endif
  1582. #ifdef TRY_UI
  1583. #define MAX_NUM_CLASS_SHEETS 3
  1584. PROPSHEETPAGE class_psp[MAX_NUM_CLASS_SHEETS];
  1585. int num_class_pages = 0;
  1586. /*------------------------------------------------------------------------
  1587. | DoCLassPropPages -
  1588. |------------------------------------------------------------------------*/
  1589. int DoCLassPropPages(HWND hwndOwner,
  1590. SP_PROPSHEETPAGE_REQUEST *propreq)
  1591. {
  1592. PROPSHEETPAGE *psp;
  1593. PROPSHEETHEADER psh;
  1594. OUR_INFO * our_params;
  1595. INT stat;
  1596. //SP_PROPSHEETPAGE_REQUEST propreq;
  1597. //typedef struct _SP_PROPSHEETPAGE_REQUEST {
  1598. //DWORD cbSize;
  1599. //DWORD PageRequested;
  1600. //HDEVINFO DeviceInfoSet;
  1601. //PSP_DEVINFO_DATA DeviceInfoData;
  1602. //Fill out the PROPSHEETPAGE data structure for the Background Color
  1603. //sheet
  1604. // our_params = glob_info; // temporary kludge, unless we don't need re-entrantancy
  1605. psp = &class_psp[0];
  1606. //Fill out the PROPSHEETPAGE data structure for the Client Area Shape
  1607. //sheet
  1608. FillClassPropertySheets(&psp[0], (LPARAM)our_params);
  1609. ++num_class_pages;
  1610. //Fill out the PROPSHEETHEADER
  1611. //stat = DevicePropPage(
  1612. // (LPVOID) propreq, // points to PROPSHEETPAGE_REQUEST, see setupapi.h
  1613. // (LPFNADDPROPSHEETPAGE) ClassAddPropPage, // add sheet function
  1614. // 0) // add sheet function data handle?
  1615. memset(&psh, 0, sizeof(PROPSHEETHEADER)); // add fix 11-24-98
  1616. psh.dwSize = sizeof(PROPSHEETHEADER);
  1617. //psh.dwFlags = PSH_USEICONID | PSH_PROPSHEETPAGE;
  1618. psh.dwFlags = PSH_PROPSHEETPAGE | PSH_NOAPPLYNOW;
  1619. psh.hwndParent = hwndOwner;
  1620. psh.hInstance = glob_hinst;
  1621. psh.pszIcon = TEXT("");
  1622. psh.nPages = num_class_pages;
  1623. psh.ppsp = (LPCPROPSHEETPAGE) &psp;
  1624. //And finally display the dialog with the two property sheets.
  1625. stat = PropertySheet(&psh);
  1626. //BOOL WINAPI DevicePropPage(
  1627. // LPVOID pinfo, // points to PROPSHEETPAGE_REQUEST, see setupapi.h
  1628. // LPFNADDPROPSHEETPAGE pfnAdd, // add sheet function
  1629. // LPARAM lParam) // add sheet function data handle?
  1630. return 0;
  1631. }
  1632. /*------------------------------------------------------------------------
  1633. | ClassAddPropPage - Call back function to add a prop page.
  1634. |------------------------------------------------------------------------*/
  1635. BOOL WINAPI ClassAddPropPage(HPROPSHEETPAGE hpage, LPARAM lparam)
  1636. {
  1637. PropSheet_AddPage(lparam, hpage);
  1638. }
  1639. /*------------------------------------------------------------------------
  1640. | FillClassPropertySheets - Setup pages for driver level property sheets.
  1641. |------------------------------------------------------------------------*/
  1642. int FillClassPropertySheets(PROPSHEETPAGE *psp, LPARAM our_params)
  1643. {
  1644. INT pi;
  1645. static TCHAR titlestr[40];
  1646. memset(psp, 0, sizeof(*psp) * NUM_CLASS_SHEETS);
  1647. pi = 0;
  1648. psp[pi].dwSize = sizeof(PROPSHEETPAGE);
  1649. psp[pi].dwFlags = PSP_USETITLE | PSP_HASHELP | PSH_NOAPPLYNOW;
  1650. psp[pi].hInstance = glob_hinst;
  1651. // psp[pi].pszTemplate = MAKEINTRESOURCE(IDD_CLASS_DLG);
  1652. psp[pi].pszTemplate = MAKEINTRESOURCE(IDD_DRIVER_OPTIONS);
  1653. psp[pi].pfnDlgProc = ClassSheet;
  1654. load_str( glob_hinst, (TITLESTR+3), titlestr, CharSizeOf(titlestr) );
  1655. psp[pi].pszTitle = TEXT("Setup");
  1656. psp[pi].lParam = (LPARAM)our_params;
  1657. psp[pi].pfnCallback = NULL;
  1658. ++pi;
  1659. return 0;
  1660. }
  1661. /*----------------------------------------------------------
  1662. ClassSheet - Dlg window procedure for add on Advanced sheet.
  1663. |-------------------------------------------------------------*/
  1664. BOOL WINAPI ClassSheet(
  1665. IN HWND hDlg,
  1666. IN UINT uMessage,
  1667. IN WPARAM wParam,
  1668. IN LPARAM lParam)
  1669. {
  1670. ////OUR_INFO *OurProps = (OUR_INFO *)GetWindowLong(hDlg, DWL_USER);
  1671. switch(uMessage)
  1672. {
  1673. case WM_INITDIALOG :
  1674. ////OurProps = (OUR_INFO *)((LPPROPSHEETPAGE)lParam)->lParam;
  1675. ////SetWindowLong(hDlg, DWL_USER, (LONG)OurProps);
  1676. #ifdef NT50
  1677. glob_hwnd = hDlg;
  1678. #endif
  1679. stat = DevicePropPage(
  1680. (LPVOID) propreq, // points to PROPSHEETPAGE_REQUEST, see setupapi.h
  1681. (LPFNADDPROPSHEETPAGE) ClassAddPropPage, // add sheet function
  1682. 0) // add sheet function data handle?
  1683. //set_field(hDlg, IDC_VERBOSE);
  1684. return TRUE; // No need for us to set the focus.
  1685. case WM_COMMAND:
  1686. return FALSE;
  1687. case WM_PAINT:
  1688. return FALSE;
  1689. case WM_CONTEXTMENU: // right-click
  1690. //context_menu();
  1691. break;
  1692. case WM_HELP: // question mark thing
  1693. //our_context_help(lParam);
  1694. return FALSE;
  1695. case WM_NOTIFY :
  1696. switch (((NMHDR *)lParam)->code)
  1697. {
  1698. case PSN_KILLACTIVE :
  1699. // we're losing focus to another page...
  1700. // make sure we update the Global485 variable here.
  1701. //get_field(hDlg, IDC_GLOBAL485);
  1702. SetWindowLong(hDlg, DWL_MSGRESULT, PSNRET_NOERROR);
  1703. return FALSE; // allow focus change
  1704. break;
  1705. case PSN_HELP :
  1706. //our_help(&wi->ip, WIN_NT);
  1707. break;
  1708. case PSN_QUERYCANCEL :
  1709. // the DWL_MSGRESULT field must be *FALSE* to tell QueryCancel
  1710. // that an exit is acceptable. The function result must be
  1711. // *TRUE* to acknowledge that we handled the message.
  1712. SetWindowLong(hDlg, DWL_MSGRESULT, FALSE); // allow cancel
  1713. return TRUE;
  1714. break;
  1715. case PSN_APPLY :
  1716. SetWindowLong(hDlg, DWL_MSGRESULT, PSNRET_NOERROR);
  1717. return TRUE;
  1718. default :
  1719. return FALSE;
  1720. } // switch ->code
  1721. break; // case wmnotify
  1722. default :
  1723. return FALSE;
  1724. } // switch(uMessage)
  1725. }
  1726. #endif