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.

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