Source code of Windows XP (NT5)
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.

1984 lines
57 KiB

  1. /*****************************************************************************
  2. *
  3. * Copyright (c) 1998-1999 Microsoft Corporation
  4. *
  5. * @doc
  6. * @module IRCLASS.C
  7. * @comm
  8. *
  9. *-----------------------------------------------------------------------------
  10. *
  11. * Date: 1/26/1998 (created)
  12. *
  13. * Contents: CoClassInstaller and Property Pages for IRSIR
  14. *
  15. *****************************************************************************/
  16. #include <objbase.h>
  17. #include <windows.h>
  18. #include <tchar.h>
  19. #include <cfgmgr32.h>
  20. #include <setupapi.h>
  21. #include <regstr.h>
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include <malloc.h>
  26. #include <stddef.h>
  27. #include <stdarg.h>
  28. #include "irclass.h"
  29. //
  30. // Instantiate device class GUIDs (we need infrared class GUID).
  31. //
  32. #include <initguid.h>
  33. #include <devguid.h>
  34. HANDLE ghDllInst = NULL;
  35. TCHAR gszTitle[40];
  36. TCHAR gszOutOfMemory[512];
  37. TCHAR gszHelpFile[40];
  38. TCHAR *BaudTable[] = {
  39. TEXT("2400"),
  40. TEXT("9600"),
  41. TEXT("19200"),
  42. TEXT("38400"),
  43. TEXT("57600"),
  44. TEXT("115200")
  45. };
  46. #define NUM_BAUD_RATES (sizeof(BaudTable)/sizeof(TCHAR*))
  47. #define DEFAULT_MAX_CONNECT_RATE BaudTable[NUM_BAUD_RATES-1]
  48. TCHAR szHelpFile[] = TEXT("INFRARED.HLP");
  49. #define IDH_DEVICE_MAXIMUM_CONNECT_RATE 1201
  50. #define IDH_DEVICE_COMMUNICATIONS_PORT 1202
  51. const DWORD HelpIDs[] =
  52. {
  53. IDC_MAX_CONNECT, IDH_DEVICE_MAXIMUM_CONNECT_RATE,
  54. IDC_RATE_TEXT, IDH_DEVICE_MAXIMUM_CONNECT_RATE,
  55. IDC_PORT, IDH_DEVICE_COMMUNICATIONS_PORT,
  56. IDC_SELECT_PORT_TEXT, IDH_DEVICE_COMMUNICATIONS_PORT,
  57. IDC_PORT_TEXT, IDH_DEVICE_COMMUNICATIONS_PORT,
  58. IDC_DEVICE_DESC, -1,
  59. IDC_PORT_BOX, -1,
  60. IDC_IRDA_ICON, -1,
  61. 0, 0
  62. };
  63. void InitStrings(HINSTANCE hInst)
  64. /*++
  65. Routine Description: InitStrings
  66. Loads default strings from resource table
  67. Arguments:
  68. hInst - DLL Instance
  69. Return Value: NONE
  70. --*/
  71. {
  72. LoadString(hInst, IDS_TITLE, gszTitle, sizeof(gszTitle)/sizeof(gszTitle[0]));
  73. LoadString(hInst, IDS_MEM_ERROR, gszOutOfMemory, sizeof(gszOutOfMemory)/sizeof(gszOutOfMemory[0]));
  74. }
  75. //==========================================================================
  76. // Dll Entry Point
  77. //==========================================================================
  78. BOOL APIENTRY LibMain( HANDLE hDll, DWORD dwReason, LPVOID lpReserved )
  79. {
  80. switch ( dwReason )
  81. {
  82. case DLL_PROCESS_ATTACH:
  83. ghDllInst = hDll;
  84. InitStrings(ghDllInst);
  85. DisableThreadLibraryCalls(ghDllInst);
  86. break;
  87. case DLL_PROCESS_DETACH:
  88. break;
  89. case DLL_THREAD_DETACH:
  90. break;
  91. case DLL_THREAD_ATTACH:
  92. break;
  93. default:
  94. break;
  95. }
  96. return TRUE;
  97. }
  98. int MyLoadString(HINSTANCE hInst, UINT uID, LPTSTR *ppBuffer)
  99. /*++
  100. Routine Description: MyLoadString
  101. LoadString wrapper which allocs properly sized buffer and loads
  102. string from resource table
  103. Arguments:
  104. hInst - DLL Instanace
  105. uID - Resource ID
  106. ppBuffer - returns allocated buffer containing string.
  107. Return Value:
  108. ERROR_SUCCESS on success
  109. ERROR_* on failure.
  110. --*/
  111. {
  112. UINT Length = 8;
  113. int LoadResult = 0;
  114. HLOCAL hLocal = NULL;
  115. do
  116. {
  117. Length <<= 1;
  118. if (hLocal)
  119. {
  120. LocalFree(hLocal);
  121. }
  122. hLocal = LocalAlloc(LMEM_FIXED, Length*sizeof(TCHAR));
  123. if (hLocal)
  124. {
  125. LoadResult = LoadString(hInst, uID, (LPTSTR)hLocal, Length);
  126. }
  127. else
  128. {
  129. MessageBox(GetFocus(), OUT_OF_MEMORY_MB);
  130. }
  131. } while ( (UINT)LoadResult==Length-1 && Length<4096 && hLocal);
  132. if (LoadResult==0 && hLocal)
  133. {
  134. LocalFree(hLocal);
  135. hLocal = NULL;
  136. }
  137. *ppBuffer = (LPTSTR)hLocal;
  138. return LoadResult;
  139. }
  140. int MyMessageBox(HWND hWnd, UINT uText, UINT uCaption, UINT uType)
  141. /*++
  142. Routine Description: MyMessageBox
  143. MessageBox wrapper which takes string resource IDs as parameters
  144. Arguments:
  145. hWnd - Parent window
  146. uText - Message box body text ID
  147. uCaption - Message box caption ID
  148. uType - As in MessageBox()
  149. Return Value:
  150. Result of MessageBox call
  151. --*/
  152. {
  153. LPTSTR szText=NULL, szCaption=NULL;
  154. int Result = 0;
  155. MyLoadString(ghDllInst, uText, &szText);
  156. if (szText != NULL) {
  157. MyLoadString(ghDllInst, uCaption, &szCaption);
  158. if (szCaption != NULL) {
  159. Result = MessageBox(hWnd, szText, szCaption, uType);
  160. LocalFree(szCaption);
  161. }
  162. LocalFree(szText);
  163. }
  164. return Result;
  165. }
  166. LONG
  167. MyRegQueryValueEx(
  168. IN HKEY hKey,
  169. IN LPCTSTR Value,
  170. IN LPDWORD lpdwReserved,
  171. IN LPDWORD lpdwType,
  172. OUT LPBYTE *lpbpData,
  173. OUT LPDWORD lpcbLength)
  174. /*++
  175. Routine Description:
  176. RegQueryValueEx wrapper which automatically queries data size and
  177. LocalAllocs a buffer.
  178. Arguments:
  179. hKey - handle of open key
  180. Value - text name of value
  181. lpdwReserved - Must be NULL
  182. lpdwType - Returns type of value queried
  183. lpbpData - Returns alloced buffer containing query data
  184. lpcbLength - Returns length of data returned/size of buffer alloced.
  185. Return Value:
  186. ERROR_SUCCESS
  187. ERROR_OUTOFMEMORY on failure to alloc buffer
  188. result of RegQueryValueEx call
  189. --*/
  190. {
  191. LONG Result;
  192. *lpcbLength = 0;
  193. Result = RegQueryValueEx(hKey,
  194. Value,
  195. lpdwReserved,
  196. lpdwType,
  197. NULL,
  198. lpcbLength);
  199. if (Result==ERROR_SUCCESS)
  200. {
  201. *lpbpData = LocalAlloc(LMEM_FIXED, *lpcbLength);
  202. if (!*lpbpData)
  203. {
  204. Result = ERROR_OUTOFMEMORY;
  205. }
  206. else
  207. {
  208. Result = RegQueryValueEx(hKey,
  209. Value,
  210. lpdwReserved,
  211. lpdwType,
  212. *lpbpData,
  213. lpcbLength);
  214. }
  215. }
  216. return Result;
  217. }
  218. LPTSTR GetDIFString(IN DI_FUNCTION Func)
  219. /*++
  220. Routine Description:
  221. Given a DI_FUNCTION value, returns a text representation.
  222. Arguments:
  223. Func - DI_FUNCTON value
  224. Return Value:
  225. Text string if value is known. Hex representation if not.
  226. --*/
  227. {
  228. static TCHAR buf[32];
  229. #define MakeCase(d) case d: return TEXT(#d)
  230. switch (Func)
  231. {
  232. MakeCase(DIF_SELECTDEVICE);
  233. MakeCase(DIF_INSTALLDEVICE);
  234. MakeCase(DIF_ASSIGNRESOURCES);
  235. MakeCase(DIF_PROPERTIES);
  236. MakeCase(DIF_REMOVE);
  237. MakeCase(DIF_FIRSTTIMESETUP);
  238. MakeCase(DIF_FOUNDDEVICE);
  239. MakeCase(DIF_SELECTCLASSDRIVERS);
  240. MakeCase(DIF_VALIDATECLASSDRIVERS);
  241. MakeCase(DIF_INSTALLCLASSDRIVERS);
  242. MakeCase(DIF_CALCDISKSPACE);
  243. MakeCase(DIF_DESTROYPRIVATEDATA);
  244. MakeCase(DIF_VALIDATEDRIVER);
  245. MakeCase(DIF_MOVEDEVICE);
  246. MakeCase(DIF_DETECT);
  247. MakeCase(DIF_INSTALLWIZARD);
  248. MakeCase(DIF_DESTROYWIZARDDATA);
  249. MakeCase(DIF_PROPERTYCHANGE);
  250. MakeCase(DIF_ENABLECLASS);
  251. MakeCase(DIF_DETECTVERIFY);
  252. MakeCase(DIF_INSTALLDEVICEFILES);
  253. MakeCase(DIF_UNREMOVE);
  254. MakeCase(DIF_SELECTBESTCOMPATDRV);
  255. MakeCase(DIF_ALLOW_INSTALL);
  256. MakeCase(DIF_REGISTERDEVICE);
  257. MakeCase(DIF_INSTALLINTERFACES);
  258. MakeCase(DIF_DETECTCANCEL);
  259. MakeCase(DIF_REGISTER_COINSTALLERS);
  260. MakeCase(DIF_NEWDEVICEWIZARD_FINISHINSTALL);
  261. default:
  262. wsprintf(buf, TEXT("%x"), Func);
  263. return buf;
  264. }
  265. }
  266. void EnumValues(
  267. IN HDEVINFO DeviceInfoSet,
  268. IN PSP_DEVINFO_DATA DeviceInfoData
  269. )
  270. /*++
  271. Routine Description:
  272. Function mainly for debugging purposes which will print to debugger
  273. a list of values found in the device's Class/{GUID}/Instance key.
  274. Arguments:
  275. DeviceInfoSet - As passed in to IrSIRClassCoInstaller
  276. DeviceInfoData - As passed in to IrSIRClassCoInstaller
  277. Return Value:
  278. NONE
  279. --*/
  280. {
  281. HKEY hKey;
  282. DWORD i, dwReserved = 0, dwType;
  283. TCHAR Value[MAX_PATH];
  284. TCHAR Data[MAX_PATH];
  285. DWORD ValueLength = sizeof(Value)/sizeof(TCHAR);
  286. DWORD DataLength = sizeof(Data);
  287. TCHAR buf[100];
  288. hKey = SetupDiOpenDevRegKey(DeviceInfoSet,
  289. DeviceInfoData,
  290. DICS_FLAG_GLOBAL,
  291. 0,
  292. DIREG_DEV,
  293. KEY_READ);
  294. if (hKey == INVALID_HANDLE_VALUE)
  295. {
  296. #if DBG
  297. OutputDebugString(TEXT("IrSIRCoClassInstaller:EnumValues:SetupDiOpenDevRegKey failed\n"));
  298. #endif
  299. return;
  300. }
  301. for (i=0,
  302. dwType=REG_SZ;
  303. RegEnumValue(hKey,
  304. i,
  305. Value,
  306. &ValueLength,
  307. NULL,
  308. &dwType,
  309. (LPBYTE)Data,
  310. &DataLength
  311. )==ERROR_SUCCESS;
  312. i++, dwType=REG_SZ
  313. )
  314. {
  315. #if DBG
  316. if (dwType==REG_SZ)
  317. {
  318. wsprintf(buf, TEXT("Value(%d):%s Data:%s\n"), i, Value, Data);
  319. OutputDebugString(buf);
  320. }
  321. #endif
  322. ValueLength = sizeof(Value)/sizeof(TCHAR);
  323. DataLength = sizeof(Data);
  324. }
  325. RegCloseKey(hKey);
  326. }
  327. LONG
  328. EnumSerialDevices(
  329. IN PPROPPAGEPARAMS pPropParams,
  330. IN HWND hDlg,
  331. OUT PULONG pNumFound
  332. )
  333. /*++
  334. Routine Description:
  335. Function which fills in the IDC_PORT control of the dialiog box with
  336. valid COM names.
  337. Arguments:
  338. pPropParams - Context data
  339. hDlg - Dialog box containing IDC_PORT
  340. pNumFound - Count of COM names added to IDC_PORT
  341. Return Value:
  342. ERROR_SUCCESS or failure code
  343. --*/
  344. {
  345. LRESULT lResult;
  346. LONG Result = ERROR_SUCCESS, tmpResult;
  347. HKEY hKey = INVALID_HANDLE_VALUE;
  348. HKEY hkSerialComm = INVALID_HANDLE_VALUE;
  349. TCHAR Buf[100];
  350. LPTSTR CurrentPort = NULL;
  351. DWORD dwLength, dwType, dwDisposition;
  352. HDEVINFO hPorts;
  353. SP_DEVINFO_DATA PortData;
  354. *pNumFound = 0;
  355. hKey = SetupDiOpenDevRegKey(pPropParams->DeviceInfoSet,
  356. pPropParams->DeviceInfoData,
  357. DICS_FLAG_GLOBAL,
  358. 0,
  359. DIREG_DRV,
  360. KEY_ALL_ACCESS);
  361. if (hKey == INVALID_HANDLE_VALUE)
  362. {
  363. #if DBG
  364. OutputDebugString(TEXT("IrSIRCoClassInstaller:EnumSerial:SetupDiOpenDevRegKey failed\n"));
  365. #endif
  366. Result = GetLastError();
  367. }
  368. else
  369. {
  370. // Read the current port. If it's empty, we'll start with an empty value.
  371. // Failure is ok.
  372. (void)MyRegQueryValueEx(hKey,
  373. TEXT("Port"),
  374. NULL,
  375. NULL,
  376. (LPBYTE*)&CurrentPort,
  377. &dwLength);
  378. Result = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  379. TEXT("HARDWARE\\DEVICEMAP\\SERIALCOMM"),
  380. 0,
  381. KEY_ALL_ACCESS,
  382. &hkSerialComm);
  383. }
  384. if (Result != ERROR_SUCCESS)
  385. {
  386. #if DBG
  387. OutputDebugString(TEXT("IrSIRCoClassInstaller:RegOpenKeyEx on SERIALCOMM failed\n"));
  388. #endif
  389. }
  390. else
  391. {
  392. DWORD i, dwReserved = 0, dwType;
  393. TCHAR Value[MAX_PATH];
  394. TCHAR Data[MAX_PATH];
  395. DWORD ValueLength = sizeof(Value)/sizeof(TCHAR);
  396. DWORD DataLength = sizeof(Data);
  397. for (i=0,
  398. dwType=REG_SZ;
  399. RegEnumValue(hkSerialComm,
  400. i,
  401. Value,
  402. &ValueLength,
  403. NULL,
  404. &dwType,
  405. (LPBYTE)Data,
  406. &DataLength
  407. )==ERROR_SUCCESS;
  408. i++, dwType=REG_SZ
  409. )
  410. {
  411. if (dwType==REG_SZ)
  412. {
  413. (*pNumFound)++;
  414. SendDlgItemMessage(hDlg,
  415. IDC_PORT,
  416. LB_ADDSTRING,
  417. 0,
  418. (LPARAM)Data);
  419. }
  420. ValueLength = sizeof(Value)/sizeof(TCHAR);
  421. DataLength = sizeof(Data);
  422. }
  423. lResult = SendDlgItemMessage(hDlg,
  424. IDC_PORT,
  425. LB_FINDSTRINGEXACT,
  426. 0,
  427. (LPARAM)CurrentPort);
  428. if (lResult==LB_ERR)
  429. {
  430. i = 0;
  431. pPropParams->PortInitialValue = -1;
  432. }
  433. else
  434. {
  435. i = (DWORD)lResult;
  436. pPropParams->PortInitialValue = i;
  437. }
  438. SendDlgItemMessage(hDlg,
  439. IDC_PORT,
  440. LB_SETCURSEL,
  441. i,
  442. 0);
  443. }
  444. if (CurrentPort)
  445. {
  446. LocalFree(CurrentPort);
  447. }
  448. if (hkSerialComm!=INVALID_HANDLE_VALUE)
  449. {
  450. RegCloseKey(hkSerialComm);
  451. }
  452. if (hKey!=INVALID_HANDLE_VALUE)
  453. {
  454. RegCloseKey(hKey);
  455. }
  456. return Result;
  457. }
  458. BOOL
  459. IsPortValueSet(
  460. IN HDEVINFO DeviceInfoSet,
  461. IN PSP_DEVINFO_DATA DeviceInfoData
  462. )
  463. {
  464. HKEY hKey = INVALID_HANDLE_VALUE;
  465. BOOL bResult = FALSE;
  466. LPTSTR CurrentPort = NULL;
  467. DWORD dwLength;
  468. LONG Result;
  469. hKey = SetupDiOpenDevRegKey(DeviceInfoSet,
  470. DeviceInfoData,
  471. DICS_FLAG_GLOBAL,
  472. 0,
  473. DIREG_DRV,
  474. KEY_ALL_ACCESS);
  475. if (hKey != INVALID_HANDLE_VALUE)
  476. {
  477. // Read the current port. If it's empty, we'll start with an empty value.
  478. // Failure is ok.
  479. Result = MyRegQueryValueEx(hKey,
  480. TEXT("Port"),
  481. NULL,
  482. NULL,
  483. (LPBYTE*)&CurrentPort,
  484. &dwLength);
  485. if (Result == ERROR_SUCCESS && CurrentPort!=NULL)
  486. {
  487. bResult = TRUE;
  488. LocalFree(CurrentPort);
  489. }
  490. RegCloseKey(hKey);
  491. }
  492. return bResult;
  493. }
  494. LONG
  495. InitMaxConnect(
  496. IN PPROPPAGEPARAMS pPropParams,
  497. IN HWND hDlg
  498. )
  499. /*++
  500. Routine Description:
  501. Function which fills in the IDC_MAX_CONNECT control of the dialiog box with
  502. valid baud rates for this device.
  503. Arguments:
  504. pPropParams - Context data
  505. hDlg - Dialog box containing IDC_MAX_CONNECT
  506. Return Value:
  507. ERROR_SUCCESS or failure code
  508. --*/
  509. {
  510. LRESULT lResult;
  511. LONG Result = ERROR_SUCCESS;
  512. HKEY hKey = INVALID_HANDLE_VALUE;
  513. TCHAR Buf[100];
  514. LPTSTR CurrentMaxConnectRate = NULL;
  515. LPTSTR MaxConnectList = NULL;
  516. DWORD dwLength;
  517. LONG i;
  518. hKey = SetupDiOpenDevRegKey(pPropParams->DeviceInfoSet,
  519. pPropParams->DeviceInfoData,
  520. DICS_FLAG_GLOBAL,
  521. 0,
  522. DIREG_DRV,
  523. KEY_ALL_ACCESS);
  524. if (hKey == INVALID_HANDLE_VALUE)
  525. {
  526. #if DBG
  527. OutputDebugString(TEXT("IrSIRCoClassInstaller:InitMaxConnect:SetupDiOpenDevRegKey failed\n"));
  528. #endif
  529. Result = GetLastError();
  530. }
  531. else
  532. {
  533. LONG TmpResult;
  534. // Read the MaxConnectRate. If it doesn't exist, we'll use the BaudTable instead.
  535. TmpResult = MyRegQueryValueEx(
  536. hKey,
  537. TEXT("MaxConnectList"),
  538. NULL,
  539. NULL,
  540. (LPBYTE*)&MaxConnectList,
  541. &dwLength);
  542. if (TmpResult == ERROR_SUCCESS)
  543. {
  544. i = 0;
  545. // Parse the MULTI_SZ, and add each string to IDC_MAX_CONNECT
  546. // We assume the values are ordered.
  547. while (MaxConnectList[i])
  548. {
  549. SendDlgItemMessage(hDlg,
  550. IDC_MAX_CONNECT,
  551. LB_ADDSTRING,
  552. 0,
  553. (LPARAM)&MaxConnectList[i]);
  554. while (MaxConnectList[i]) i++;
  555. i++; // advance past the null
  556. if ((unsigned)i>=dwLength)
  557. {
  558. break;
  559. }
  560. }
  561. }
  562. else
  563. {
  564. // Key not found, use default baud table.
  565. for (i=NUM_BAUD_RATES-1; i>=0; i--)
  566. {
  567. SendDlgItemMessage(hDlg,
  568. IDC_MAX_CONNECT,
  569. LB_ADDSTRING,
  570. 0,
  571. (LPARAM)BaudTable[i]);
  572. }
  573. }
  574. TmpResult = MyRegQueryValueEx(
  575. hKey,
  576. TEXT("MaxConnectRate"),
  577. NULL,
  578. NULL,
  579. (LPBYTE*)&CurrentMaxConnectRate,
  580. &dwLength);
  581. lResult = SendDlgItemMessage(
  582. hDlg,
  583. IDC_MAX_CONNECT,
  584. LB_FINDSTRINGEXACT,
  585. 0,
  586. (LPARAM)CurrentMaxConnectRate);
  587. if (lResult==LB_ERR)
  588. {
  589. i = 0;
  590. pPropParams->MaxConnectInitialValue = -1;
  591. }
  592. else
  593. {
  594. i = (LONG)lResult;
  595. pPropParams->MaxConnectInitialValue = i;
  596. }
  597. SendDlgItemMessage(hDlg,
  598. IDC_MAX_CONNECT,
  599. LB_SETCURSEL,
  600. i,
  601. 0);
  602. }
  603. if (CurrentMaxConnectRate)
  604. {
  605. LocalFree(CurrentMaxConnectRate);
  606. }
  607. if (MaxConnectList)
  608. {
  609. LocalFree(MaxConnectList);
  610. }
  611. if (hKey!=INVALID_HANDLE_VALUE)
  612. {
  613. RegCloseKey(hKey);
  614. }
  615. return Result;
  616. }
  617. BOOL
  618. EnablePortSelection(
  619. IN HDEVINFO DeviceInfoSet,
  620. IN PSP_DEVINFO_DATA DeviceInfoData,
  621. IN HWND hDlg
  622. )
  623. /*++
  624. Routine Description:
  625. This function determines whether the dialog box should have a port
  626. selection entry, and if so enables the appropriate controls:
  627. IDC_PORT_BOX, IDC_PORT_TEXT, IDC_PORT.
  628. Arguments:
  629. DeviceInfoSet - As passed in to IrSIRClassCoInstaller
  630. DeviceInfoData - As passed in to IrSIRClassCoInstaller
  631. hDlg - Dialog box containing IDC_PORT and associated controls
  632. Return Value:
  633. TRUE if PortSelection was enabled.
  634. --*/
  635. {
  636. LONG Result = ERROR_SUCCESS;
  637. HKEY hKey = INVALID_HANDLE_VALUE;
  638. TCHAR Buf[100];
  639. TCHAR SerialBased[16] = TEXT("");
  640. DWORD dwLength;
  641. LONG i;
  642. BOOL bSerialBased = FALSE;
  643. hKey = SetupDiOpenDevRegKey(DeviceInfoSet,
  644. DeviceInfoData,
  645. DICS_FLAG_GLOBAL,
  646. 0,
  647. DIREG_DRV,
  648. KEY_ALL_ACCESS);
  649. if (hKey == INVALID_HANDLE_VALUE)
  650. {
  651. #if DBG
  652. OutputDebugString(TEXT("IrSIRCoClassInstaller:EnablePortSelection:SetupDiOpenDevRegKey failed\n"));
  653. #endif
  654. }
  655. else
  656. {
  657. // Read the MaxConnectRate. If it's empty, we'll start with an empty value.
  658. dwLength = sizeof(SerialBased);
  659. Result = RegQueryValueEx(hKey,
  660. TEXT("SerialBased"),
  661. NULL,
  662. NULL,
  663. (LPBYTE)SerialBased,
  664. &dwLength);
  665. bSerialBased = (Result==ERROR_SUCCESS) ? _ttol(SerialBased) : TRUE;
  666. if (bSerialBased)
  667. {
  668. DWORD ControlsToShow[] = { IDC_PORT_BOX, IDC_PORT_TEXT, IDC_PORT };
  669. for (i=0; i<sizeof(ControlsToShow)/sizeof(ControlsToShow[0]); i++)
  670. {
  671. ShowWindow(GetDlgItem(hDlg, ControlsToShow[i]),
  672. SW_SHOWNA);
  673. }
  674. }
  675. }
  676. if (hKey!=INVALID_HANDLE_VALUE)
  677. {
  678. RegCloseKey(hKey);
  679. }
  680. return bSerialBased;
  681. }
  682. LONG
  683. InitDescription(
  684. IN HDEVINFO DeviceInfoSet,
  685. IN PSP_DEVINFO_DATA DeviceInfoData,
  686. IN HWND hDlg
  687. )
  688. /*++
  689. Routine Description:
  690. Function to fill the IDC_DEVICE_DESC box with an appropriate description
  691. of the device being configured.
  692. Arguments:
  693. DeviceInfoSet - As passed in to IrSIRClassCoInstaller
  694. DeviceInfoData - As passed in to IrSIRClassCoInstaller
  695. hDlg - Dialog box containing IDC_DEVICE_DESC
  696. Return Value:
  697. ERROR_SUCCESS or failure code
  698. --*/
  699. {
  700. LONG Result = ERROR_SUCCESS;
  701. TCHAR Description[LINE_LEN] = TEXT("Failed to retrive description");
  702. DWORD dwLength;
  703. if (!SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
  704. DeviceInfoData,
  705. SPDRP_DEVICEDESC,
  706. NULL,
  707. (LPBYTE)Description,
  708. sizeof(Description),
  709. &dwLength))
  710. {
  711. Result = GetLastError();
  712. #if DBG
  713. {
  714. TCHAR buf[100];
  715. wsprintf(buf, TEXT("IrSIRCoClassInstaller:InitDescription:SetupDiGetDeviceRegistryProperty failed (0x%08x)\n"), Result);
  716. OutputDebugString(buf);
  717. }
  718. #endif
  719. }
  720. // Display it
  721. SetDlgItemText(hDlg, IDC_DEVICE_DESC, Description);
  722. return Result;
  723. }
  724. LONG
  725. WriteRegistrySettings(
  726. IN HWND hDlg,
  727. IN PPROPPAGEPARAMS pPropParams
  728. )
  729. /*++
  730. Routine Description:
  731. Function to write Port and MaxConnectRate values to the devnode key.
  732. This also ensures that the miniport is restarted to pick up these changes.
  733. It usually means someone has changed a value in the device manager.
  734. Arguments:
  735. hDlg - Dialog box containing IDC_PORT and associated controls
  736. pPropParams - Local context data for this devnode
  737. Return Value:
  738. ERROR_SUCCESS or failure code
  739. --*/
  740. {
  741. TCHAR szPort[16], szMaxConnectRate[16];
  742. HKEY hKey;
  743. LRESULT lResult;
  744. DWORD i;
  745. LONG Result = ERROR_SUCCESS;
  746. BOOL PropertiesChanged = FALSE;
  747. TCHAR buf[100];
  748. #if DBG
  749. OutputDebugString(TEXT("IrSIRCoClassInstaller:WriteRegistrySettings\n"));
  750. #endif
  751. //
  752. // Write out the com port options to the registry. These options
  753. // are read by the NDIS miniport via NdisReadConfiguration()
  754. //
  755. if (pPropParams->SerialBased)
  756. {
  757. lResult = SendDlgItemMessage(hDlg,
  758. IDC_PORT,
  759. LB_GETCURSEL,
  760. 0, 0);
  761. SendDlgItemMessage(hDlg,
  762. IDC_PORT,
  763. LB_GETTEXT,
  764. (UINT)lResult, (LPARAM)szPort);
  765. if ((unsigned)lResult!=pPropParams->PortInitialValue)
  766. {
  767. PropertiesChanged = TRUE;
  768. }
  769. }
  770. if (pPropParams->FirstTimeInstall)
  771. {
  772. lstrcpy(szMaxConnectRate, DEFAULT_MAX_CONNECT_RATE);
  773. }
  774. else
  775. {
  776. lResult = SendDlgItemMessage(hDlg,
  777. IDC_MAX_CONNECT,
  778. LB_GETCURSEL,
  779. 0, 0);
  780. SendDlgItemMessage(hDlg,
  781. IDC_MAX_CONNECT,
  782. LB_GETTEXT,
  783. (UINT)lResult, (LPARAM)szMaxConnectRate);
  784. if ((unsigned)lResult!=pPropParams->MaxConnectInitialValue)
  785. {
  786. PropertiesChanged = TRUE;
  787. }
  788. }
  789. hKey = SetupDiOpenDevRegKey(pPropParams->DeviceInfoSet,
  790. pPropParams->DeviceInfoData,
  791. DICS_FLAG_GLOBAL,
  792. 0,
  793. DIREG_DRV,
  794. KEY_ALL_ACCESS);
  795. if (hKey == INVALID_HANDLE_VALUE)
  796. {
  797. #if DBG
  798. OutputDebugString(TEXT("IrSIRCoClassInstaller:WriteRegistrySettings:SetupDiOpenDevRegKey failed\n"));
  799. #endif
  800. }
  801. else
  802. {
  803. if (pPropParams->SerialBased)
  804. {
  805. TCHAR szLocation[128], *pszLocationFmt;
  806. Result = RegSetValueEx(hKey,
  807. TEXT("Port"),
  808. 0,
  809. REG_SZ,
  810. (LPBYTE)szPort,
  811. lstrlen(szPort)*sizeof(szPort[0]));
  812. #if 0
  813. if(MyLoadString(ghDllInst, IDS_LOCATION_FORMAT, &pszLocationFmt))
  814. {
  815. wsprintf(szLocation, pszLocationFmt, szPort);
  816. LocalFree(pszLocationFmt);
  817. }
  818. else
  819. {
  820. szLocation[0] = 0;
  821. }
  822. #else
  823. lstrcpy(szLocation,szPort);
  824. #endif
  825. SetupDiSetDeviceRegistryProperty(pPropParams->DeviceInfoSet,
  826. pPropParams->DeviceInfoData,
  827. SPDRP_LOCATION_INFORMATION,
  828. (LPBYTE)szLocation,
  829. (lstrlen(szLocation)+1)*sizeof(TCHAR));
  830. }
  831. if (Result==ERROR_SUCCESS)
  832. {
  833. Result = RegSetValueEx(hKey,
  834. TEXT("MaxConnectRate"),
  835. 0,
  836. REG_SZ,
  837. (LPBYTE)szMaxConnectRate,
  838. lstrlen(szMaxConnectRate)*sizeof(szMaxConnectRate[0]));
  839. }
  840. RegCloseKey(hKey);
  841. }
  842. if (Result==ERROR_SUCCESS && PropertiesChanged)
  843. {
  844. if (pPropParams->FirstTimeInstall)
  845. {
  846. // On a first time install, NT may not look for the PROPCHANGE_PENDING bit.
  847. // Instead we will notify that the driver needs to be restarted ourselves,
  848. // so that the changes we're writing get picked up.
  849. SP_DEVINSTALL_PARAMS DevInstallParams;
  850. SP_PROPCHANGE_PARAMS PropChangeParams;
  851. ZeroMemory(&PropChangeParams, sizeof(SP_PROPCHANGE_PARAMS));
  852. PropChangeParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
  853. PropChangeParams.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
  854. PropChangeParams.StateChange = DICS_PROPCHANGE;
  855. PropChangeParams.Scope = DICS_FLAG_GLOBAL;
  856. if (SetupDiSetClassInstallParams(pPropParams->DeviceInfoSet,
  857. pPropParams->DeviceInfoData,
  858. (PSP_CLASSINSTALL_HEADER)&PropChangeParams,
  859. sizeof(SP_PROPCHANGE_PARAMS))
  860. )
  861. {
  862. DevInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  863. if(SetupDiGetDeviceInstallParams(pPropParams->DeviceInfoSet,
  864. pPropParams->DeviceInfoData,
  865. &DevInstallParams))
  866. {
  867. DevInstallParams.Flags |= DI_CLASSINSTALLPARAMS;
  868. SetupDiSetDeviceInstallParams(pPropParams->DeviceInfoSet,
  869. pPropParams->DeviceInfoData,
  870. &DevInstallParams);
  871. }
  872. else
  873. {
  874. #if DBG
  875. OutputDebugString(TEXT("IrSIRCoClassInstaller:WriteRegistrySettings:SetupDiGetDeviceInstallParams failed 1\n"));
  876. #endif
  877. }
  878. SetupDiCallClassInstaller(DIF_PROPERTYCHANGE,
  879. pPropParams->DeviceInfoSet,
  880. pPropParams->DeviceInfoData);
  881. if(SetupDiGetDeviceInstallParams(pPropParams->DeviceInfoSet,
  882. pPropParams->DeviceInfoData,
  883. &DevInstallParams))
  884. {
  885. DevInstallParams.Flags |= DI_PROPERTIES_CHANGE;
  886. SetupDiSetDeviceInstallParams(pPropParams->DeviceInfoSet,
  887. pPropParams->DeviceInfoData,
  888. &DevInstallParams);
  889. }
  890. else
  891. {
  892. #if DBG
  893. OutputDebugString(TEXT("IrSIRCoClassInstaller:WriteRegistrySettings:SetupDiGetDeviceInstallParams failed 2\n"));
  894. #endif
  895. }
  896. }
  897. else
  898. {
  899. #if DBG
  900. OutputDebugString(TEXT("IrSIRCoClassInstaller:WriteRegistrySettings:SetupDiSetClassInstallParams failed \n"));
  901. #endif
  902. }
  903. }
  904. else
  905. {
  906. // This is the case where the user has changed settings in the property
  907. // sheet. Life is much easier.
  908. SP_DEVINSTALL_PARAMS DevInstallParams;
  909. //
  910. // The changes are written, notify the world to reset the driver.
  911. //
  912. DevInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  913. if(SetupDiGetDeviceInstallParams(pPropParams->DeviceInfoSet,
  914. pPropParams->DeviceInfoData,
  915. &DevInstallParams))
  916. {
  917. LONG ChangeResult;
  918. DevInstallParams.FlagsEx |= DI_FLAGSEX_PROPCHANGE_PENDING;
  919. ChangeResult =
  920. SetupDiSetDeviceInstallParams(pPropParams->DeviceInfoSet,
  921. pPropParams->DeviceInfoData,
  922. &DevInstallParams);
  923. #if DBG
  924. {
  925. wsprintf(buf, TEXT("SetupDiSetDeviceInstallParams(DI_FLAGSEX_PROPCHANGE_PENDING)==%d %x\n"), ChangeResult, GetLastError());
  926. OutputDebugString(buf);
  927. }
  928. #endif
  929. }
  930. else
  931. {
  932. #if DBG
  933. OutputDebugString(TEXT("IrSIRCoClassInstaller:WriteRegistrySettings:SetupDiGetDeviceInstallParams failed 2\n"));
  934. #endif
  935. }
  936. }
  937. }
  938. #if DBG
  939. {
  940. wsprintf(buf, TEXT("IrSIRCoClassInstaller:Result==%x FirstTimeInstall==%d Changed==%d\n"),
  941. Result, pPropParams->FirstTimeInstall, PropertiesChanged);
  942. OutputDebugString(buf);
  943. }
  944. #endif
  945. return Result;
  946. }
  947. INT_PTR APIENTRY PortDlgProc(IN HWND hDlg,
  948. IN UINT uMessage,
  949. IN WPARAM wParam,
  950. IN LPARAM lParam)
  951. /*++
  952. Routine Description:
  953. The windows control function for the IrDA Settings properties window
  954. Arguments:
  955. hDlg, uMessage, wParam, lParam: standard windows DlgProc parameters
  956. Return Value:
  957. BOOL: FALSE if function fails, TRUE if function passes
  958. --*/
  959. {
  960. ULONG i;
  961. TCHAR CharBuffer[LINE_LEN];
  962. PPROPPAGEPARAMS pPropParams;
  963. TCHAR buf[100];
  964. pPropParams = (PPROPPAGEPARAMS)GetWindowLongPtr(hDlg, DWLP_USER);
  965. switch (uMessage)
  966. {
  967. case WM_INITDIALOG:
  968. //
  969. // lParam points to one of two possible objects. If we're a property
  970. // page, it points to the PropSheetPage structure. If we're a regular
  971. // dialog box, it points to the PROPPAGEPARAMS structure. We can
  972. // verify which because the first field of PROPPAGEPARAMS is a signature.
  973. //
  974. // In either case, once we figure out which, we store the value into
  975. // DWL_USER so we only have to do this once.
  976. //
  977. pPropParams = (PPROPPAGEPARAMS)lParam;
  978. if (pPropParams->Signature!=PPParamsSignature)
  979. {
  980. pPropParams = (PPROPPAGEPARAMS)((LPPROPSHEETPAGE)lParam)->lParam;
  981. if (pPropParams->Signature!=PPParamsSignature)
  982. {
  983. #if DBG
  984. OutputDebugString(TEXT("IRCLASS.DLL: PortDlgProc Signature not found!\n"));
  985. #endif
  986. return FALSE;
  987. }
  988. }
  989. SetWindowLongPtr(hDlg, DWLP_USER, (LPARAM)pPropParams);
  990. if (!pPropParams->FirstTimeInstall)
  991. {
  992. InitMaxConnect(pPropParams, hDlg);
  993. pPropParams->SerialBased = EnablePortSelection(pPropParams->DeviceInfoSet,
  994. pPropParams->DeviceInfoData,
  995. hDlg);
  996. if (pPropParams->SerialBased)
  997. {
  998. EnumSerialDevices(pPropParams, hDlg, &i);
  999. }
  1000. InitDescription(pPropParams->DeviceInfoSet,
  1001. pPropParams->DeviceInfoData,
  1002. hDlg);
  1003. }
  1004. else
  1005. {
  1006. pPropParams->SerialBased = TRUE;
  1007. EnumSerialDevices(pPropParams, hDlg, &i);
  1008. if (i > 0) {
  1009. //
  1010. // there were some port availible
  1011. //
  1012. // Enable next and cancel wizard buttons. BACK is not valid here,
  1013. // since the device is already installed at this point. Cancel
  1014. // will cause the device to be removed.
  1015. //
  1016. PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_NEXT);
  1017. }
  1018. EnableWindow(GetDlgItem(GetParent(hDlg), IDCANCEL), TRUE);
  1019. }
  1020. return TRUE; // No need for us to set the focus.
  1021. case WM_COMMAND:
  1022. switch (HIWORD(wParam))
  1023. {
  1024. case LBN_SELCHANGE:
  1025. {
  1026. #if DBG
  1027. OutputDebugString(TEXT("IrSIRCoClassInstaller:PropertySheet Changed\n"));
  1028. #endif
  1029. PropSheet_Changed(GetParent(hDlg), hDlg);
  1030. }
  1031. return TRUE;
  1032. default:
  1033. break;
  1034. }
  1035. switch (LOWORD(wParam))
  1036. {
  1037. //
  1038. // Because this is a prop sheet, we should never get this.
  1039. // All notifications for ctrols outside of the sheet come through
  1040. // WM_NOTIFY
  1041. //
  1042. case IDCANCEL:
  1043. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
  1044. EndDialog(hDlg, uMessage);
  1045. return TRUE;
  1046. case IDOK:
  1047. {
  1048. WriteRegistrySettings(hDlg, pPropParams);
  1049. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
  1050. EndDialog(hDlg, uMessage);
  1051. return TRUE;
  1052. }
  1053. default:
  1054. return FALSE;
  1055. }
  1056. case WM_NOTIFY:
  1057. switch (((NMHDR *)lParam)->code)
  1058. {
  1059. //
  1060. // Sent when the user clicks on Apply OR OK !!
  1061. //
  1062. case PSN_WIZNEXT:
  1063. if (!pPropParams->FirstTimeInstall)
  1064. {
  1065. break;
  1066. }
  1067. case PSN_APPLY:
  1068. {
  1069. WriteRegistrySettings(hDlg, pPropParams);
  1070. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
  1071. return TRUE;
  1072. }
  1073. default:
  1074. return FALSE;
  1075. }
  1076. case WM_DESTROY:
  1077. //
  1078. // free the description of the com ports. If any msgs are processed
  1079. // after WM_DESTROY, do not reference pPropParams!!! To enforce this,
  1080. // set the DWL_USER stored long to 0
  1081. //
  1082. LocalFree(pPropParams);
  1083. SetWindowLongPtr(hDlg, DWLP_USER, 0);
  1084. case WM_HELP:
  1085. if (lParam)
  1086. {
  1087. return WinHelp((HWND)((LPHELPINFO)lParam)->hItemHandle,
  1088. (LPCTSTR)szHelpFile,
  1089. HELP_WM_HELP,
  1090. (ULONG_PTR)HelpIDs);
  1091. }
  1092. else
  1093. {
  1094. return FALSE;
  1095. }
  1096. case WM_CONTEXTMENU:
  1097. return WinHelp((HWND)wParam,
  1098. (LPCTSTR)szHelpFile,
  1099. HELP_CONTEXTMENU,
  1100. (ULONG_PTR)HelpIDs);
  1101. default:
  1102. return FALSE;
  1103. }
  1104. } /* PortDialogProc */
  1105. void PortSelectionDlg(
  1106. HDEVINFO DeviceInfoSet,
  1107. PSP_DEVINFO_DATA DeviceInfoData
  1108. )
  1109. /*++
  1110. Routine Description:
  1111. PropSheet setup for devnode configuration.
  1112. Arguments:
  1113. DeviceInfoSet - As passed in to IrSIRClassCoInstaller
  1114. DeviceInfoData - As passed in to IrSIRClassCoInstaller
  1115. Return Value:
  1116. --*/
  1117. {
  1118. HKEY hKey = 0;
  1119. PPROPPAGEPARAMS pPropParams = NULL;
  1120. PROPSHEETHEADER PropHeader;
  1121. PROPSHEETPAGE PropSheetPage;
  1122. TCHAR buf[100];
  1123. LPTSTR Title=NULL;
  1124. LPTSTR SubTitle=NULL;
  1125. SP_NEWDEVICEWIZARD_DATA WizData;
  1126. WizData.ClassInstallHeader.cbSize = sizeof(WizData.ClassInstallHeader);
  1127. if (!SetupDiGetClassInstallParams(DeviceInfoSet,
  1128. DeviceInfoData,
  1129. (PSP_CLASSINSTALL_HEADER)&WizData,
  1130. sizeof(WizData),
  1131. NULL)
  1132. || WizData.ClassInstallHeader.InstallFunction!=DIF_NEWDEVICEWIZARD_FINISHINSTALL)
  1133. {
  1134. #if DBG
  1135. OutputDebugString(TEXT("IrSIRCoClassInstaller: Failed to get ClassInstall params\n"));
  1136. #endif
  1137. return;
  1138. }
  1139. #if DBG
  1140. OutputDebugString(TEXT("IrSIRCoClassInstaller: PortSelectionDlg\n"));
  1141. #endif
  1142. pPropParams = LocalAlloc(LMEM_FIXED, sizeof(PROPPAGEPARAMS));
  1143. if (!pPropParams)
  1144. {
  1145. return;
  1146. }
  1147. pPropParams->Signature = PPParamsSignature;
  1148. pPropParams->DeviceInfoSet = DeviceInfoSet;
  1149. pPropParams->DeviceInfoData = DeviceInfoData;
  1150. pPropParams->FirstTimeInstall = TRUE;
  1151. if (WizData.NumDynamicPages < MAX_INSTALLWIZARD_DYNAPAGES)
  1152. {
  1153. //
  1154. // Setup the advanced properties window information
  1155. //
  1156. BOOLEAN bResult;
  1157. DWORD RequiredSize = 0;
  1158. DWORD dwTotalSize = 0;
  1159. LONG lResult;
  1160. memset(&PropSheetPage, 0, sizeof(PropSheetPage));
  1161. //
  1162. // Add the Port Settings property page
  1163. //
  1164. PropSheetPage.dwSize = sizeof(PROPSHEETPAGE);
  1165. PropSheetPage.dwFlags = PSP_DEFAULT; //PSP_USECALLBACK; // | PSP_HASHELP;
  1166. PropSheetPage.hInstance = ghDllInst;
  1167. PropSheetPage.pszTemplate = MAKEINTRESOURCE(IDD_INSTALL_PORT_SELECT);
  1168. //
  1169. // following points to the dlg window proc
  1170. //
  1171. PropSheetPage.hIcon = NULL;
  1172. PropSheetPage.pfnDlgProc = PortDlgProc;
  1173. PropSheetPage.lParam = (LPARAM)pPropParams;
  1174. //
  1175. // following points to some control callback of the dlg window proc
  1176. //
  1177. PropSheetPage.pfnCallback = NULL;
  1178. PropSheetPage.pcRefParent = NULL;
  1179. if ( 0 != MyLoadString(ghDllInst, IDS_SELECT_PORT_TITLE, &Title)) {
  1180. // We don't use these, but if we wanted to...
  1181. PropSheetPage.dwFlags |= PSP_USEHEADERTITLE;
  1182. PropSheetPage.pszHeaderTitle = Title;
  1183. }
  1184. if (0 != MyLoadString(ghDllInst, IDS_SELECT_PORT_SUBTITLE, &SubTitle)) {
  1185. PropSheetPage.dwFlags |= PSP_USEHEADERSUBTITLE;
  1186. PropSheetPage.pszHeaderSubTitle = SubTitle;
  1187. }
  1188. WizData.DynamicPages[WizData.NumDynamicPages] = CreatePropertySheetPage(&PropSheetPage);
  1189. if (WizData.DynamicPages[WizData.NumDynamicPages])
  1190. {
  1191. WizData.NumDynamicPages++;
  1192. }
  1193. SetupDiSetClassInstallParams(DeviceInfoSet,
  1194. DeviceInfoData,
  1195. (PSP_CLASSINSTALL_HEADER)&WizData,
  1196. sizeof(WizData));
  1197. if (Title != NULL) {
  1198. LocalFree(Title);
  1199. }
  1200. if (SubTitle != NULL) {
  1201. LocalFree(SubTitle);
  1202. }
  1203. }
  1204. else
  1205. {
  1206. LocalFree(pPropParams);
  1207. }
  1208. } /* PortSelectionDlg */
  1209. VOID
  1210. DestroyPrivateData(PCOINSTALLER_PRIVATE_DATA pPrivateData)
  1211. /*++
  1212. Routine Description:
  1213. Function to dealloc/destroy context data
  1214. Arguments:
  1215. pPrivateData - Context buffer to dealloc/destroy
  1216. Return Value:
  1217. none
  1218. --*/
  1219. {
  1220. if (pPrivateData)
  1221. {
  1222. if (pPrivateData->hInf!=INVALID_HANDLE_VALUE)
  1223. {
  1224. SetupCloseInfFile(pPrivateData->hInf);
  1225. }
  1226. LocalFree(pPrivateData);
  1227. pPrivateData = NULL;
  1228. }
  1229. }
  1230. PCOINSTALLER_PRIVATE_DATA
  1231. CreatePrivateData(
  1232. IN HDEVINFO DeviceInfoSet,
  1233. IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
  1234. )
  1235. /*++
  1236. Routine Description:
  1237. Allocs and initailizes private context data buffer
  1238. Arguments:
  1239. DeviceInfoSet - As passed in to IrSIRClassCoInstaller
  1240. DeviceInfoData - As passed in to IrSIRClassCoInstaller
  1241. Return Value:
  1242. Pointer to alloced context data, or NULL if failure. Call GetLastError()
  1243. for extended error information.
  1244. --*/
  1245. {
  1246. PCOINSTALLER_PRIVATE_DATA pPrivateData;
  1247. BOOL Status = TRUE;
  1248. UINT ErrorLine;
  1249. TCHAR buf[100];
  1250. pPrivateData = LocalAlloc(LPTR, sizeof(COINSTALLER_PRIVATE_DATA));
  1251. if (!pPrivateData)
  1252. {
  1253. #if DBG
  1254. OutputDebugString(TEXT("IrSIRCoClassInstaller: Insufficient Memory\n"));
  1255. #endif
  1256. Status = FALSE;
  1257. }
  1258. else
  1259. {
  1260. pPrivateData->DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
  1261. Status = SetupDiGetSelectedDriver(DeviceInfoSet,
  1262. DeviceInfoData,
  1263. &pPrivateData->DriverInfoData);
  1264. if (!Status)
  1265. {
  1266. #if DBG
  1267. wsprintf(buf, TEXT("IrSIRCoClassInstaller:SetupDiGetSelectedDriver failed (%d)\n"), GetLastError());
  1268. OutputDebugString(buf);
  1269. #endif
  1270. }
  1271. }
  1272. if (Status)
  1273. {
  1274. pPrivateData->DriverInfoDetailData.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
  1275. Status = SetupDiGetDriverInfoDetail(DeviceInfoSet,
  1276. DeviceInfoData,
  1277. &pPrivateData->DriverInfoData,
  1278. &pPrivateData->DriverInfoDetailData,
  1279. sizeof(SP_DRVINFO_DETAIL_DATA),
  1280. NULL);
  1281. if (!Status)
  1282. {
  1283. if (GetLastError()==ERROR_INSUFFICIENT_BUFFER)
  1284. {
  1285. // We don't need the extended information. Ignore.
  1286. Status = TRUE;
  1287. }
  1288. else
  1289. {
  1290. #if DBG
  1291. wsprintf(buf, TEXT("IrSIRCoClassInstaller:SetupDiGetDriverInfoDetail failed (%d)\n"), GetLastError());
  1292. OutputDebugString(buf);
  1293. #endif
  1294. }
  1295. }
  1296. }
  1297. if (Status)
  1298. {
  1299. pPrivateData->hInf = SetupOpenInfFile(pPrivateData->DriverInfoDetailData.InfFileName,
  1300. NULL,
  1301. INF_STYLE_WIN4,
  1302. &ErrorLine);
  1303. if (pPrivateData->hInf==INVALID_HANDLE_VALUE)
  1304. {
  1305. Status = FALSE;
  1306. #if DBG
  1307. wsprintf(buf, TEXT("IrSIRCoClassInstaller:SetupOpenInfFile failed (%d) ErrorLine==%d\n"), GetLastError(), ErrorLine);
  1308. OutputDebugString(buf);
  1309. #endif
  1310. }
  1311. }
  1312. if (Status)
  1313. {
  1314. // Translate to the .NT name, if present.
  1315. Status = SetupDiGetActualSectionToInstall(pPrivateData->hInf,
  1316. pPrivateData->DriverInfoDetailData.SectionName,
  1317. pPrivateData->InfSectionWithExt,
  1318. LINE_LEN,
  1319. NULL,
  1320. NULL);
  1321. if (!Status)
  1322. {
  1323. #if DBG
  1324. OutputDebugString(TEXT("IrSIRCoClassInstaller:SetupDiGetActualSectionToInstall failed\n"));
  1325. #endif
  1326. }
  1327. }
  1328. if (!Status)
  1329. {
  1330. // We experienced some failure. Cleanup.
  1331. DestroyPrivateData(pPrivateData);
  1332. pPrivateData = NULL;
  1333. }
  1334. return pPrivateData;
  1335. }
  1336. DWORD
  1337. IrSIRClassCoInstaller(
  1338. IN DI_FUNCTION InstallFunction,
  1339. IN HDEVINFO DeviceInfoSet,
  1340. IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
  1341. IN OUT PCOINSTALLER_CONTEXT_DATA pContext
  1342. )
  1343. /*++
  1344. Routine Description:
  1345. This routine acts as the class coinstaller for SIR devices. This is set up
  1346. to be called by the INF:
  1347. [MS_Devices]
  1348. ; DisplayName Section DeviceID
  1349. ; ----------- ------- --------
  1350. %*PNP0510.DevDesc% = PNP, *PNP0510
  1351. [PNP.NT.CoInstallers]
  1352. AddReg = IRSIR.CoInstallers.reg
  1353. [IRSIR.CoInstallers.reg]
  1354. HKR,,CoInstallers32,0x00010000,"IRCLASS.dll,IrSIRClassCoInstaller"
  1355. Arguments:
  1356. InstallFunction - Specifies the device installer function code indicating
  1357. the action being performed.
  1358. DeviceInfoSet - Supplies a handle to the device information set being
  1359. acted upon by this install action.
  1360. DeviceInfoData - Optionally, supplies the address of a device information
  1361. element being acted upon by this install action.
  1362. Return Value:
  1363. ERROR_DI_DO_DEFAULT, ERROR_DI_POSTPROCESSING_REQUIRED, or error code
  1364. --*/
  1365. {
  1366. TCHAR buf[100];
  1367. DWORD Result = ERROR_SUCCESS;
  1368. LONG lResult;
  1369. PCOINSTALLER_PRIVATE_DATA pPrivateData;
  1370. INFCONTEXT InfContext;
  1371. #if DBG
  1372. wsprintf(buf, TEXT("IrSIRCoClassInstaller:InstallFunction(%s) PostProcessing:%d\n"), GetDIFString(InstallFunction), pContext->PostProcessing);
  1373. OutputDebugString(buf);
  1374. #endif
  1375. switch (InstallFunction)
  1376. {
  1377. case DIF_INSTALLDEVICE:
  1378. {
  1379. UINT ErrorLine;
  1380. // Private data for coinstallers is only kept across a single call,
  1381. // pre and post processing. The private data that we create here
  1382. // is not any good for any other DIF_ call.
  1383. pContext->PrivateData = CreatePrivateData(DeviceInfoSet,
  1384. DeviceInfoData);
  1385. if (!pContext->PrivateData)
  1386. {
  1387. return GetLastError();
  1388. }
  1389. pPrivateData = pContext->PrivateData;
  1390. {
  1391. // NOTE on the use of UPPERFILTERS and LOWERFILTERS
  1392. // A filter driver is a driver that is loaded as a shim above
  1393. // or below another driver, in this case SERIAL below IRSIR.
  1394. // It does special processing on IRPs and can give added
  1395. // functionality or is a means to avoid duplicate functionality
  1396. // in multiple drivers. UPPERFILTERS and LOWERFILTERS values
  1397. // are used by the PnP system to identify and load filter
  1398. // drivers. These values could be set via the INF in a .HW
  1399. // section, but setting them via the coinstaller may give you
  1400. // more control, i.e. you could remove one of several filter
  1401. // drivers from a list.
  1402. //
  1403. // If your driver isn't a filter driver, or doesn't use filter
  1404. // drivers, you won't need to clear these values as is done
  1405. // here.
  1406. // Always clear UpperFilters. If this is an upgrade from
  1407. // a post-1671, the IrDA device could have been installed as
  1408. // a serial port, with a serenum upper filter. This will
  1409. // blow up NDIS, so clear it.
  1410. //
  1411. // This is atypical behavior for a class coinstaller. Normally
  1412. // the upperfilter/lowerfilter values do not need to be touched.
  1413. // Note that it is possible to do this from the INF. This
  1414. // is here more for demo purpose.
  1415. SetupDiSetDeviceRegistryProperty(DeviceInfoSet,
  1416. DeviceInfoData,
  1417. SPDRP_UPPERFILTERS,
  1418. NULL,
  1419. 0);
  1420. }
  1421. if (SetupFindFirstLine(pPrivateData->hInf,
  1422. pPrivateData->InfSectionWithExt,
  1423. TEXT("LowerFilters"),
  1424. &InfContext))
  1425. {
  1426. TCHAR LowerFilters[LINE_LEN];
  1427. DWORD BytesNeeded;
  1428. if (!SetupGetMultiSzField(&InfContext, 1, LowerFilters, LINE_LEN, &BytesNeeded))
  1429. {
  1430. // Lowerfilters value was not found in the inf.
  1431. // This means we do not want a lowerfilters value in
  1432. // the registry. (Unique to IRSIR.SYS and NETIRSIR.INF)
  1433. // Setting lowerfilters here for demo purpose only.
  1434. // Normally done from INF, if necessary at all.
  1435. if (!SetupDiSetDeviceRegistryProperty(DeviceInfoSet,
  1436. DeviceInfoData,
  1437. SPDRP_LOWERFILTERS,
  1438. NULL,
  1439. 0)
  1440. )
  1441. {
  1442. #if DBG
  1443. OutputDebugString(TEXT("IrSIRCoClassInstaller: Failed to set lowerfilter\n"));
  1444. #endif
  1445. }
  1446. }
  1447. else
  1448. {
  1449. // Setting lowerfilters here for demo purpose only.
  1450. // Normally done from INF, if necessary at all.
  1451. if (!SetupDiSetDeviceRegistryProperty(DeviceInfoSet,
  1452. DeviceInfoData,
  1453. SPDRP_LOWERFILTERS,
  1454. (LPBYTE)LowerFilters,
  1455. ((BytesNeeded<LINE_LEN) ?
  1456. BytesNeeded : LINE_LEN)*sizeof(TCHAR))
  1457. )
  1458. {
  1459. #if DBG
  1460. OutputDebugString(TEXT("IrSIRCoClassInstaller: Failed to set lowerfilter\n"));
  1461. #endif
  1462. }
  1463. }
  1464. }
  1465. else
  1466. {
  1467. // No lowerfilters value present. Clear it.
  1468. // Setting lowerfilters here for demo purpose only.
  1469. // Normally done from INF, if necessary at all.
  1470. if (!SetupDiSetDeviceRegistryProperty(DeviceInfoSet,
  1471. DeviceInfoData,
  1472. SPDRP_LOWERFILTERS,
  1473. NULL,
  1474. 0)
  1475. )
  1476. {
  1477. #if DBG
  1478. OutputDebugString(TEXT("IrSIRCoClassInstaller: Failed to set lowerfilter\n"));
  1479. #endif
  1480. }
  1481. }
  1482. DestroyPrivateData(pContext->PrivateData);
  1483. pContext->PrivateData = NULL;
  1484. break;
  1485. }
  1486. case DIF_NEWDEVICEWIZARD_FINISHINSTALL:
  1487. {
  1488. pContext->PrivateData = CreatePrivateData(DeviceInfoSet,
  1489. DeviceInfoData);
  1490. if (!pContext->PrivateData)
  1491. {
  1492. return GetLastError();
  1493. }
  1494. pPrivateData = pContext->PrivateData;
  1495. if (!SetupFindFirstLine(pPrivateData->hInf,
  1496. pPrivateData->InfSectionWithExt,
  1497. TEXT("PromptForPort"),
  1498. &InfContext))
  1499. {
  1500. #if DBG
  1501. OutputDebugString(TEXT("IrSIRCoClassInstaller:failed to find PromptForPort in .INF\n"));
  1502. #endif
  1503. }
  1504. else
  1505. {
  1506. if (!SetupGetIntField(&InfContext, 1, &pPrivateData->PromptForPort))
  1507. {
  1508. #if DBG
  1509. OutputDebugString(TEXT("IrSIRCoClassInstaller:failed to read PromptForPort in .INF\n"));
  1510. #endif
  1511. // Default to true
  1512. pPrivateData->PromptForPort = TRUE;
  1513. }
  1514. // If we have a COM port we need to query the user, UNLESS
  1515. // this is an upgrade.
  1516. if (pPrivateData->PromptForPort && !IsPortValueSet(DeviceInfoSet, DeviceInfoData))
  1517. {
  1518. PortSelectionDlg(DeviceInfoSet, DeviceInfoData);
  1519. }
  1520. }
  1521. if (!pPrivateData->PromptForPort)
  1522. {
  1523. TCHAR *pszLocation;
  1524. if (MyLoadString(ghDllInst, IDS_INTERNAL_PORT, &pszLocation))
  1525. {
  1526. SetupDiSetDeviceRegistryProperty(DeviceInfoSet,
  1527. DeviceInfoData,
  1528. SPDRP_LOCATION_INFORMATION,
  1529. (LPBYTE)pszLocation,
  1530. (1+lstrlen(pszLocation))*sizeof(TCHAR));
  1531. LocalFree(pszLocation);
  1532. }
  1533. }
  1534. DestroyPrivateData(pContext->PrivateData);
  1535. pContext->PrivateData = NULL;
  1536. break;
  1537. }
  1538. default:
  1539. {
  1540. break;
  1541. }
  1542. }
  1543. #if DBG
  1544. wsprintf(buf, TEXT("IrSIRCoClassInstaller:returning:0x%08x\n"), Result);
  1545. OutputDebugString(buf);
  1546. #endif
  1547. return Result;
  1548. }
  1549. BOOL APIENTRY IrSIRPortPropPageProvider(LPVOID pinfo,
  1550. LPFNADDPROPSHEETPAGE pfnAdd,
  1551. LPARAM lParam
  1552. )
  1553. /*++
  1554. Routine Description:
  1555. Entry-point for adding additional device manager property
  1556. sheet pages. This entry-point gets called only when the Device
  1557. Manager asks for additional property pages. The INF associated with
  1558. this causes it to be called by specifying it in an AddReg section:
  1559. [IRSIR.reg]
  1560. HKR, , EnumPropPages32, , "IRCLASS.dll,IrSIRPortPropPageProvider"
  1561. Arguments:
  1562. pinfo - points to PROPSHEETPAGE_REQUEST, see setupapi.h
  1563. pfnAdd - function ptr to call to add sheet.
  1564. lParam - add sheet functions private data handle.
  1565. Return Value:
  1566. BOOL: FALSE if pages could not be added, TRUE on success
  1567. --*/
  1568. {
  1569. PSP_PROPSHEETPAGE_REQUEST pprPropPageRequest;
  1570. HKEY hKey = 0;
  1571. PROPSHEETPAGE PropSheetPage;
  1572. HPROPSHEETPAGE hspPropSheetPage;
  1573. PPROPPAGEPARAMS pPropParams = NULL;
  1574. pPropParams = LocalAlloc(LMEM_FIXED, sizeof(PROPPAGEPARAMS));
  1575. if (!pPropParams)
  1576. {
  1577. return FALSE;
  1578. }
  1579. pprPropPageRequest = (PSP_PROPSHEETPAGE_REQUEST) pinfo;
  1580. pPropParams->Signature = PPParamsSignature;
  1581. pPropParams->DeviceInfoSet = pprPropPageRequest->DeviceInfoSet;
  1582. pPropParams->DeviceInfoData = pprPropPageRequest->DeviceInfoData;
  1583. pPropParams->FirstTimeInstall = FALSE;
  1584. if (pprPropPageRequest->PageRequested == SPPSR_ENUM_ADV_DEVICE_PROPERTIES)
  1585. {
  1586. //
  1587. // Setup the advanced properties window information
  1588. //
  1589. BOOLEAN bResult;
  1590. DWORD RequiredSize = 0;
  1591. DWORD dwTotalSize = 0;
  1592. memset(&PropSheetPage, 0, sizeof(PropSheetPage));
  1593. //
  1594. // Add the Port Settings property page
  1595. //
  1596. PropSheetPage.dwSize = sizeof(PROPSHEETPAGE);
  1597. PropSheetPage.dwFlags = PSP_USECALLBACK; // | PSP_HASHELP;
  1598. PropSheetPage.hInstance = ghDllInst;
  1599. PropSheetPage.pszTemplate = MAKEINTRESOURCE(IDD_PP_IRDA_SETTINGS);
  1600. //
  1601. // following points to the dlg window proc
  1602. //
  1603. PropSheetPage.pfnDlgProc = PortDlgProc;
  1604. PropSheetPage.lParam = (LPARAM)pPropParams;
  1605. //
  1606. // following points to some control callback of the dlg window proc
  1607. //
  1608. PropSheetPage.pfnCallback = NULL;
  1609. //
  1610. // allocate our "Ports Setting" sheet
  1611. //
  1612. hspPropSheetPage = CreatePropertySheetPage(&PropSheetPage);
  1613. if (!hspPropSheetPage)
  1614. {
  1615. return FALSE;
  1616. }
  1617. //
  1618. // add the thing in.
  1619. //
  1620. if (!pfnAdd(hspPropSheetPage, lParam))
  1621. {
  1622. DestroyPropertySheetPage(hspPropSheetPage);
  1623. return FALSE;
  1624. }
  1625. }
  1626. else
  1627. {
  1628. LocalFree(pPropParams);
  1629. }
  1630. return TRUE;
  1631. } /* IrSIRPortPropPageProvider */