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.

1176 lines
34 KiB

  1. /** FILE: pp_lpt.c ********** Module Header *******************************
  2. *
  3. * Control panel applet for configuring LPT ports. This file contains
  4. * the dialog and utility functions for managing the UI for setting LPT
  5. * port parameters
  6. *
  7. @@BEGIN_DDKSPLIT
  8. * History:
  9. * jsenior - 7/10/98 - created
  10. @@END_DDKSPLIT
  11. *
  12. * Copyright (C) 1990-1995 Microsoft Corporation
  13. *
  14. *************************************************************************/
  15. //==========================================================================
  16. // Include files
  17. //==========================================================================
  18. #include "ports.h"
  19. #include "pp_lpt.h"
  20. #include <windowsx.h>
  21. TCHAR m_szFilterResourceMethod[] = TEXT("FilterResourceMethod");
  22. TCHAR m_szParEnableLegacyZip[] = TEXT("ParEnableLegacyZip");
  23. TCHAR m_szParEnableLegacyZipRegPath[] = TEXT("SYSTEM\\CurrentControlSet\\Services\\Parport\\Parameters");
  24. const DWORD LptHelpIDs[]=
  25. {
  26. IDC_STATIC, IDH_NOHELP, //Filter resource method text - help not needed
  27. IDC_FILTERMETHOD_TRYNOT, idh_devmgr_portset_trynot, //first radio button
  28. IDC_FILTERMETHOD_NEVER, idh_devmgr_portset_never, //second radio button
  29. IDC_FILTERMETHOD_ACCEPTANY, idh_devmgr_portset_acceptany, //third radio button
  30. IDC_LPTNUMTEXT, idh_devmgr_portset_portnum, //Port number text
  31. PP_LPT_PORT_NUMBER, idh_devmgr_portset_LPTchoice, //the list box for port number
  32. IDC_LPT_ENABLE_LEGACY, idh_devmgr_enable_legacy, //Enable legacy detection checkbox
  33. 0, 0
  34. };
  35. #define NUM_FILTER_RESOURCE_METHODS 3
  36. DWORD FilterResourceMethods[NUM_FILTER_RESOURCE_METHODS] = {
  37. 0, // Try not to use an interrupt
  38. 1, // Never use an interrupt
  39. 2 // Accept any interrupt given to the port
  40. };
  41. // C Runtime
  42. // @@BEGIN_DDKSPLIT
  43. //
  44. // Prototype for IsUserAdmin (in pp.c)
  45. //
  46. BOOL
  47. IsUserAdmin(VOID);
  48. // @@END_DDKSPLIT
  49. void
  50. InformDriverOfChanges(BOOL NeedReboot,
  51. IN PLPT_PROP_PARAMS LptPropParams);
  52. void
  53. LptPortOnHelp(HWND ParentHwnd,
  54. LPHELPINFO HelpInfo);
  55. BOOL
  56. LptPortOnContextMenu(HWND HwndControl,
  57. WORD Xpos,
  58. WORD Ypos);
  59. BOOL
  60. LptPortOnInitDialog(
  61. HWND ParentHwnd,
  62. HWND FocusHwnd,
  63. LPARAM Lparam);
  64. ULONG
  65. LptFillPortSettings(
  66. IN HWND ParentHwnd,
  67. IN PLPT_PROP_PARAMS LptPropPageData);
  68. ULONG
  69. LptFillPortNameCb(
  70. HWND ParentHwnd,
  71. PLPT_PROP_PARAMS LptPropPageData);
  72. void LptInitializeControls(
  73. IN HWND ParentHwnd,
  74. IN PLPT_PROP_PARAMS LptPropPageData);
  75. ULONG
  76. LptSetFilterResourceMethod(
  77. HWND ParentHwnd,
  78. PLPT_PROP_PARAMS LptPropPageData);
  79. ULONG
  80. LptSavePortSettings(
  81. IN HWND ParentHwnd,
  82. IN PLPT_PROP_PARAMS LptPropParams);
  83. BOOL
  84. LptPortOnNotify(
  85. HWND ParentHwnd,
  86. LPNMHDR NmHdr);
  87. void
  88. LptPortOnCommand(
  89. HWND ParentHwnd,
  90. int ControlId,
  91. HWND ControlHwnd,
  92. UINT NotifyCode);
  93. UINT
  94. LptEnactPortNameChanges(
  95. IN HWND ParentHwnd,
  96. IN PLPT_PROP_PARAMS LptPropParams,
  97. IN HKEY hDeviceKey,
  98. IN UINT NewLptNum);
  99. void
  100. LptEnumerateUsedPorts(
  101. IN HWND ParentHwnd,
  102. IN PBYTE Buffer,
  103. IN DWORD BufferSize);
  104. void
  105. LptInitPropParams(IN OUT PLPT_PROP_PARAMS Params,
  106. IN HDEVINFO DeviceInfoSet,
  107. IN PSP_DEVINFO_DATA DeviceInfoData);
  108. HPROPSHEETPAGE
  109. LptInitSettingsPage(PROPSHEETPAGE * psp,
  110. OUT PLPT_PROP_PARAMS Params);
  111. INT_PTR
  112. APIENTRY
  113. LptPortSettingsDlgProc(IN HWND hDlg,
  114. IN UINT uMessage,
  115. IN WPARAM wParam,
  116. IN LPARAM lParam);
  117. UINT
  118. CALLBACK
  119. LptPortSettingsDlgCallback(HWND hwnd,
  120. UINT uMsg,
  121. LPPROPSHEETPAGE ppsp);
  122. /*++
  123. Routine Description: ParallelPortPropPageProvider
  124. Entry-point for adding additional device manager property
  125. sheet pages. Registry specifies this routine under
  126. Control\Class\PortNode::EnumPropPage32="msports.dll,thisproc"
  127. entry. This entry-point gets called only when the Device
  128. Manager asks for additional property pages.
  129. Arguments:
  130. Info - points to PROPSHEETPAGE_REQUEST, see setupapi.h
  131. AddFunc - function ptr to call to add sheet.
  132. Lparam - add sheet functions private data handle.
  133. Return Value:
  134. BOOL: FALSE if pages could not be added, TRUE on success
  135. --*/
  136. BOOL
  137. APIENTRY
  138. ParallelPortPropPageProvider(LPVOID Info,
  139. LPFNADDPROPSHEETPAGE AddFunc,
  140. LPARAM Lparam)
  141. {
  142. PSP_PROPSHEETPAGE_REQUEST pprPropPageRequest;
  143. PROPSHEETPAGE psp;
  144. HPROPSHEETPAGE hpsp;
  145. PLPT_PROP_PARAMS params = NULL;
  146. pprPropPageRequest = (PSP_PROPSHEETPAGE_REQUEST) Info;
  147. // @@BEGIN_DDKSPLIT
  148. //
  149. // Only administrators are allowed to see this page
  150. //
  151. if (!IsUserAdmin()) {
  152. return FALSE;
  153. }
  154. // @@END_DDKSPLIT
  155. //
  156. // Allocate and zero out memory for the struct that will contain
  157. // page specific data
  158. //
  159. params = (PLPT_PROP_PARAMS) LocalAlloc(LPTR, sizeof(LPT_PROP_PARAMS));
  160. if (!params) {
  161. ErrMemDlg(GetFocus());
  162. return FALSE;
  163. }
  164. if (pprPropPageRequest->PageRequested == SPPSR_ENUM_ADV_DEVICE_PROPERTIES) {
  165. LptInitPropParams(params,
  166. pprPropPageRequest->DeviceInfoSet,
  167. pprPropPageRequest->DeviceInfoData);
  168. hpsp = LptInitSettingsPage(&psp, params);
  169. if (!hpsp) {
  170. return FALSE;
  171. }
  172. if (!(*AddFunc)(hpsp, Lparam)) {
  173. DestroyPropertySheetPage(hpsp);
  174. return FALSE;
  175. }
  176. }
  177. return TRUE;
  178. } // ParallelPortPropPageProvider
  179. /*++
  180. Routine Description: LptPortSettingsDlgProc
  181. The windows control function for the Port Settings properties window
  182. Arguments:
  183. hDlg, uMessage, wParam, lParam: standard windows DlgProc parameters
  184. Return Value:
  185. BOOL: FALSE if function fails, TRUE if function passes
  186. --*/
  187. INT_PTR
  188. APIENTRY
  189. LptPortSettingsDlgProc(IN HWND hDlg,
  190. IN UINT uMessage,
  191. IN WPARAM wParam,
  192. IN LPARAM lParam)
  193. {
  194. switch(uMessage) {
  195. case WM_COMMAND:
  196. LptPortOnCommand(hDlg, (int) LOWORD(wParam), (HWND)lParam, (UINT)HIWORD(wParam));
  197. break;
  198. case WM_CONTEXTMENU:
  199. return LptPortOnContextMenu((HWND)wParam, LOWORD(lParam), HIWORD(lParam));
  200. case WM_HELP:
  201. LptPortOnHelp(hDlg, (LPHELPINFO) lParam);
  202. break;
  203. case WM_INITDIALOG:
  204. return LptPortOnInitDialog(hDlg, (HWND)wParam, lParam);
  205. case WM_NOTIFY:
  206. return LptPortOnNotify(hDlg, (NMHDR *)lParam);
  207. }
  208. return FALSE;
  209. } // PortSettingsDialogProc
  210. void
  211. LptInitPropParams(IN OUT PLPT_PROP_PARAMS Params,
  212. IN HDEVINFO DeviceInfoSet,
  213. IN PSP_DEVINFO_DATA DeviceInfoData)
  214. {
  215. BOOL bResult;
  216. DWORD requiredSize = 0;
  217. SP_DEVINFO_LIST_DETAIL_DATA detailData;
  218. ZeroMemory(Params, sizeof(LPT_PROP_PARAMS));
  219. Params->DeviceInfoSet = DeviceInfoSet;
  220. Params->DeviceInfoData = DeviceInfoData;
  221. Params->ChangesEnabled = TRUE;
  222. //
  223. // Get the device ID first: if the device path is larger then
  224. // MAX_PATH, we will try again with a bigger buffer
  225. //
  226. bResult = SetupDiGetDeviceInstanceId(DeviceInfoSet,
  227. DeviceInfoData,
  228. NULL,
  229. MAX_PATH,
  230. &requiredSize);
  231. //
  232. // See if we are being invoked locally or over the network. If over the net,
  233. // then disable all possible changes.
  234. //
  235. detailData.cbSize = sizeof(SP_DEVINFO_LIST_DETAIL_DATA);
  236. if (SetupDiGetDeviceInfoListDetail(DeviceInfoSet, &detailData) &&
  237. detailData.RemoteMachineHandle != NULL) {
  238. Params->ChangesEnabled = FALSE;
  239. }
  240. } // LptInitPropParams
  241. HPROPSHEETPAGE LptInitSettingsPage(PROPSHEETPAGE * psp,
  242. OUT PLPT_PROP_PARAMS Params)
  243. {
  244. //
  245. // Add the Port Settings property page
  246. //
  247. psp->dwSize = sizeof(PROPSHEETPAGE);
  248. psp->dwFlags = PSP_USECALLBACK; // | PSP_HASHELP;
  249. psp->hInstance = g_hInst;
  250. psp->pszTemplate = MAKEINTRESOURCE(DLG_PP_LPT_PORTSETTINGS);
  251. //
  252. // following points to the dlg window proc
  253. //
  254. psp->pfnDlgProc = LptPortSettingsDlgProc;
  255. psp->lParam = (LPARAM) Params;
  256. //
  257. // following points to some control callback of the dlg window proc
  258. //
  259. psp->pfnCallback = LptPortSettingsDlgCallback;
  260. //
  261. // allocate our "Ports Setting" sheet
  262. //
  263. return CreatePropertySheetPage(psp);
  264. }
  265. UINT
  266. CALLBACK
  267. LptPortSettingsDlgCallback(HWND hwnd,
  268. UINT uMsg,
  269. LPPROPSHEETPAGE ppsp)
  270. {
  271. PLPT_PROP_PARAMS params;
  272. switch (uMsg) {
  273. case PSPCB_CREATE:
  274. return TRUE; // return TRUE to continue with creation of page
  275. case PSPCB_RELEASE:
  276. params = (PLPT_PROP_PARAMS) ppsp->lParam;
  277. LocalFree(params);
  278. return 0; // return value ignored
  279. default:
  280. break;
  281. }
  282. return TRUE;
  283. }
  284. BOOL
  285. LptPortOnInitDialog(
  286. HWND ParentHwnd,
  287. HWND FocusHwnd,
  288. LPARAM Lparam
  289. )
  290. {
  291. PLPT_PROP_PARAMS lptPropParams;
  292. lptPropParams = (PLPT_PROP_PARAMS) ((LPPROPSHEETPAGE)Lparam)->lParam;
  293. //
  294. // Save value away
  295. SetWindowLongPtr(ParentHwnd, DWLP_USER, (ULONG_PTR) lptPropParams);
  296. //
  297. // Initialize the dialog box parameters
  298. //
  299. LptFillPortSettings(ParentHwnd, lptPropParams);
  300. //
  301. // Set up the dialog box with these initialized parameters
  302. //
  303. LptInitializeControls(ParentHwnd, lptPropParams);
  304. return TRUE;
  305. }
  306. /*++
  307. Routine Description: LptFillPortSettings
  308. Gets the settings out of the registry ready for initializing the dialog box
  309. with.
  310. Arguments:
  311. LptPropPageData: the data to fill in
  312. ParentHwnd: address of the window
  313. Return Value:
  314. ULONG: returns error messages
  315. --*/
  316. ULONG
  317. LptFillPortSettings(
  318. IN HWND ParentHwnd,
  319. IN PLPT_PROP_PARAMS LptPropPageData
  320. )
  321. {
  322. HKEY hKey;
  323. DWORD dwPortNameSize, dwError;
  324. TCHAR szCharBuffer[81];
  325. DWORD dwSize, dwData, dwMethod;
  326. //
  327. // Open the device key for the source device instance, and retrieve its
  328. // "PortName" value.
  329. //
  330. hKey = SetupDiOpenDevRegKey(LptPropPageData->DeviceInfoSet,
  331. LptPropPageData->DeviceInfoData,
  332. DICS_FLAG_GLOBAL,
  333. 0,
  334. DIREG_DEV,
  335. KEY_ALL_ACCESS);
  336. if (INVALID_HANDLE_VALUE == hKey) {
  337. return GetLastError();
  338. }
  339. dwPortNameSize = sizeof(LptPropPageData->szLptName);
  340. dwError = RegQueryValueEx(hKey,
  341. m_szPortName, // "PortName"
  342. NULL,
  343. NULL,
  344. (PBYTE)LptPropPageData->szLptName,
  345. &dwPortNameSize);
  346. if(ERROR_SUCCESS != dwError) {
  347. RegCloseKey(hKey);
  348. return dwError;
  349. }
  350. //
  351. // create "lpt#:"
  352. //
  353. lstrcpy(szCharBuffer, LptPropPageData->szLptName);
  354. lstrcat(szCharBuffer, m_szColon);
  355. dwSize = sizeof(LptPropPageData->FilterResourceMethod);
  356. dwError = RegQueryValueEx(hKey,
  357. m_szFilterResourceMethod,
  358. NULL,
  359. NULL,
  360. (LPBYTE)(&LptPropPageData->FilterResourceMethod),
  361. &dwSize);
  362. if (dwError != ERROR_SUCCESS) {
  363. //
  364. // value does not exist. Create our own:
  365. // Get Filter Resource Method information
  366. //
  367. LptPropPageData->FilterResourceMethod =
  368. FilterResourceMethods[RESOURCE_METHOD_DEFAULT_IDX];
  369. dwError = RegSetValueEx(hKey,
  370. m_szFilterResourceMethod,
  371. 0,
  372. REG_DWORD,
  373. (LPBYTE)(&LptPropPageData->FilterResourceMethod),
  374. sizeof(LptPropPageData->FilterResourceMethod));
  375. }
  376. RegCloseKey(hKey);
  377. dwError = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  378. m_szParEnableLegacyZipRegPath,
  379. 0,
  380. KEY_ALL_ACCESS,
  381. &hKey);
  382. if (dwError != ERROR_SUCCESS) {
  383. //
  384. // Don't have access maybe?
  385. //
  386. LptPropPageData->ParEnableLegacyZip = ENABLELEGACYZIPDEFAULT;
  387. return dwError;
  388. }
  389. dwSize = sizeof(LptPropPageData->ParEnableLegacyZip);
  390. dwError = RegQueryValueEx(hKey,
  391. TEXT("ParEnableLegacyZip"),
  392. NULL,
  393. NULL,
  394. (LPBYTE)(&LptPropPageData->ParEnableLegacyZip),
  395. &dwSize);
  396. if (dwError != ERROR_SUCCESS) {
  397. //
  398. // value does not exist. Create our own
  399. //
  400. LptPropPageData->ParEnableLegacyZip = ENABLELEGACYZIPDEFAULT;
  401. dwError = RegSetValueEx(hKey,
  402. m_szParEnableLegacyZip,
  403. 0,
  404. REG_DWORD,
  405. (LPBYTE)(&LptPropPageData->ParEnableLegacyZip),
  406. sizeof(LptPropPageData->ParEnableLegacyZip));
  407. }
  408. RegCloseKey(hKey);
  409. return dwError;
  410. } // LptFillPortSettings
  411. /*++
  412. Routine Description: LptInitializeControls
  413. Initializes all of the controls that represent Fifo
  414. Arguments:
  415. ParentHwnd - handle to the dialog
  416. LptPropPageData - Contains all of the initial values
  417. Return Value:
  418. None
  419. --*/
  420. void LptInitializeControls(
  421. IN HWND ParentHwnd,
  422. IN PLPT_PROP_PARAMS LptPropPageData
  423. )
  424. {
  425. TCHAR szCurrentValue[40];
  426. HWND hwnd;
  427. int i, periodIdx;
  428. LptFillPortNameCb(ParentHwnd, LptPropPageData);
  429. LptSetFilterResourceMethod(ParentHwnd, LptPropPageData);
  430. //
  431. // Set the state of the Enable Legacy Detection checkbox
  432. //
  433. if (LptPropPageData->ParEnableLegacyZip) {
  434. CheckDlgButton(ParentHwnd,
  435. IDC_LPT_ENABLE_LEGACY,
  436. BST_CHECKED);
  437. } else {
  438. CheckDlgButton(ParentHwnd,
  439. IDC_LPT_ENABLE_LEGACY,
  440. BST_UNCHECKED);
  441. }
  442. if (!LptPropPageData->ChangesEnabled) {
  443. // EnableWindow(GetDlgItem(ParentHwnd, IDC_FIFO), FALSE);
  444. }
  445. } // LptInitializeControls
  446. /*++
  447. Routine Description: LptSetFilterResourceMethod
  448. Checks the appropriate resource method to use
  449. Arguments:
  450. LptPropPageData: where to get the data from
  451. ParentHwnd: address of the window
  452. Return Value:
  453. ULONG: returns error messages
  454. --*/
  455. ULONG
  456. LptSetFilterResourceMethod(
  457. HWND ParentHwnd,
  458. PLPT_PROP_PARAMS LptPropPageData
  459. )
  460. {
  461. switch (LptPropPageData->FilterResourceMethod) {
  462. case FILTERMETHOD_TRYNOT:
  463. CheckRadioButton( ParentHwnd, // handle to dialog box
  464. IDC_FILTERMETHOD_TRYNOT, // first button in group
  465. IDC_FILTERMETHOD_ACCEPTANY, // last button in group
  466. IDC_FILTERMETHOD_TRYNOT // selected
  467. );
  468. break;
  469. case FILTERMETHOD_ACCEPTANY:
  470. CheckRadioButton( ParentHwnd, // handle to dialog box
  471. IDC_FILTERMETHOD_TRYNOT, // first button in group
  472. IDC_FILTERMETHOD_ACCEPTANY, // last button in group
  473. IDC_FILTERMETHOD_ACCEPTANY // selected
  474. );
  475. break;
  476. case FILTERMETHOD_NEVER:
  477. CheckRadioButton( ParentHwnd, // handle to dialog box
  478. IDC_FILTERMETHOD_TRYNOT, // first button in group
  479. IDC_FILTERMETHOD_ACCEPTANY, // last button in group
  480. IDC_FILTERMETHOD_NEVER // selected
  481. );
  482. break;
  483. default:
  484. CheckRadioButton( ParentHwnd, // handle to dialog box
  485. IDC_FILTERMETHOD_TRYNOT, // first button in group
  486. IDC_FILTERMETHOD_ACCEPTANY, // last button in group
  487. IDC_FILTERMETHOD_NEVER // selected
  488. );
  489. break;
  490. }
  491. return 0;
  492. }
  493. /*++
  494. Routine Description: LptFillPortNameCb
  495. fill in the Port Name combo box selection with a list
  496. of possible un-used portnames
  497. Arguments:
  498. LptPropPageData: where to get the data from
  499. hDlg: address of the window
  500. Return Value:
  501. ULONG: returns error messages
  502. --*/
  503. ULONG
  504. LptFillPortNameCb(
  505. HWND ParentHwnd,
  506. PLPT_PROP_PARAMS LptPropPageData
  507. )
  508. {
  509. BYTE portUsage[MAX_LPT_PORT];
  510. DWORD tmp, portsReported;
  511. int i, nEntries;
  512. int nCurPortNum;
  513. TCHAR szLpt[40];
  514. TCHAR szInUse[40];
  515. HWND portHwnd;
  516. portHwnd = GetDlgItem(ParentHwnd, PP_LPT_PORT_NUMBER);
  517. //
  518. // Check if our LptName is blank. If it is, disable the lpt port selector
  519. //
  520. if (_tcscmp(LptPropPageData->szLptName, TEXT("")) == 0) {
  521. EnableWindow(portHwnd, FALSE);
  522. EnableWindow(GetDlgItem(ParentHwnd, IDC_LPTNUMTEXT), FALSE);
  523. return 0;
  524. }
  525. //
  526. // assumes szLptPort filled in...
  527. //
  528. nCurPortNum = myatoi(&LptPropPageData->szLptName[3]);
  529. if (!LoadString(g_hInst, IDS_IN_USE, szInUse, CharSizeOf(szInUse))) {
  530. wcscpy(szInUse, _T(" (in use)"));
  531. }
  532. //
  533. // first tally up which ports NOT to offer in list box
  534. //
  535. ZeroMemory(portUsage, MAX_LPT_PORT);
  536. // Find out which ports not to offer
  537. LptEnumerateUsedPorts(ParentHwnd,
  538. portUsage,
  539. MAX_LPT_PORT);
  540. for(i = MIN_LPT-1; i < MAX_LPT_PORT; i++) {
  541. wsprintf(szLpt, TEXT("LPT%d"), i+1);
  542. if (portUsage[i] &&
  543. _tcscmp(szLpt, LptPropPageData->szLptName)) {
  544. wcscat(szLpt, szInUse);
  545. }
  546. ComboBox_AddString(portHwnd, szLpt);
  547. }
  548. ComboBox_SetCurSel(portHwnd, nCurPortNum-1);
  549. return 0;
  550. } // FillPortNamesCb
  551. void
  552. LptPortOnCommand(
  553. HWND ParentHwnd,
  554. int ControlId,
  555. HWND ControlHwnd,
  556. UINT NotifyCode
  557. )
  558. {
  559. PLPT_PROP_PARAMS params =
  560. (PLPT_PROP_PARAMS) GetWindowLongPtr(ParentHwnd, DWLP_USER);
  561. if (NotifyCode == CBN_SELCHANGE) {
  562. PropSheet_Changed(GetParent(ParentHwnd), ParentHwnd);
  563. }
  564. else {
  565. switch (ControlId) {
  566. //
  567. // Because this is a prop sheet, we should never get this.
  568. // All notifications for ctrols outside of the sheet come through
  569. // WM_NOTIFY
  570. //
  571. case IDOK:
  572. case IDCANCEL:
  573. EndDialog(ParentHwnd, 0);
  574. return;
  575. }
  576. }
  577. } // LptPortOnCommand
  578. BOOL
  579. LptPortOnNotify(
  580. HWND ParentHwnd,
  581. LPNMHDR NmHdr
  582. )
  583. {
  584. PLPT_PROP_PARAMS params =
  585. (PLPT_PROP_PARAMS) GetWindowLongPtr(ParentHwnd, DWLP_USER);
  586. switch (NmHdr->code) {
  587. //
  588. // Sent when the user clicks on Apply OR OK !!
  589. //
  590. case PSN_APPLY:
  591. //
  592. // Write out the lpt port options to the registry
  593. //
  594. LptSavePortSettings(ParentHwnd, params);
  595. SetWindowLongPtr(ParentHwnd, DWLP_MSGRESULT, PSNRET_NOERROR);
  596. return TRUE;
  597. default:
  598. return FALSE;
  599. }
  600. } // LptPortOnNotify
  601. /*++
  602. Routine Description: LptSavePortSettings
  603. saves the advanced box settings back to the registry, if any were
  604. changed
  605. Arguments:
  606. AdvancedData: holds the current settings and the location of of
  607. the device in the registry
  608. ParentHwnd: address of the window
  609. Return Value:
  610. ULONG: returns error messages
  611. --*/
  612. ULONG
  613. LptSavePortSettings(
  614. IN HWND ParentHwnd,
  615. IN PLPT_PROP_PARAMS LptPropParams
  616. )
  617. {
  618. HKEY hKey;
  619. DWORD dwSize, dwData;
  620. UINT i = CB_ERR, curLptNum, newLptNum = CB_ERR;
  621. UINT uiTryNotChecked, uiNeverChecked, uiAcceptAnyChecked;
  622. DWORD curFilterResourceMethod;
  623. DWORD newFilterResourceMethod = 0;
  624. DWORD curParEnableLegacyZip, newParEnableLegacyZip;
  625. ULONG error = ERROR_SUCCESS;
  626. SP_DEVINSTALL_PARAMS spDevInstall;
  627. //
  628. // Grab all of the new settings
  629. //
  630. // Filter resource method
  631. curFilterResourceMethod = newFilterResourceMethod = LptPropParams->FilterResourceMethod;
  632. if (BST_CHECKED ==
  633. IsDlgButtonChecked(ParentHwnd, IDC_FILTERMETHOD_TRYNOT))
  634. newFilterResourceMethod = 0;
  635. else if (BST_CHECKED ==
  636. IsDlgButtonChecked(ParentHwnd, IDC_FILTERMETHOD_NEVER))
  637. newFilterResourceMethod = 1;
  638. else if (BST_CHECKED ==
  639. IsDlgButtonChecked(ParentHwnd, IDC_FILTERMETHOD_ACCEPTANY))
  640. newFilterResourceMethod = 2;
  641. // LPT port number
  642. curLptNum = myatoi(LptPropParams->szLptName + wcslen(m_szLPT));
  643. newLptNum = ComboBox_GetCurSel(GetDlgItem(ParentHwnd, PP_LPT_PORT_NUMBER));
  644. if (newLptNum == CB_ERR) {
  645. newLptNum = curLptNum;
  646. } else {
  647. newLptNum++;
  648. }
  649. // Legacy device detection
  650. curParEnableLegacyZip = LptPropParams->ParEnableLegacyZip;
  651. if (BST_CHECKED == IsDlgButtonChecked(ParentHwnd, IDC_LPT_ENABLE_LEGACY)) {
  652. newParEnableLegacyZip = 0x1;
  653. } else {
  654. newParEnableLegacyZip = 0x0;
  655. }
  656. //
  657. // See if they changed anything
  658. //
  659. if ((curLptNum == newLptNum) &&
  660. (curFilterResourceMethod == newFilterResourceMethod) &&
  661. (curParEnableLegacyZip == newParEnableLegacyZip)) {
  662. //
  663. // They didn't change anything. Just exit.
  664. //
  665. return ERROR_SUCCESS;
  666. }
  667. //
  668. // Open the device key for the source device instance
  669. //
  670. hKey = SetupDiOpenDevRegKey(LptPropParams->DeviceInfoSet,
  671. LptPropParams->DeviceInfoData,
  672. DICS_FLAG_GLOBAL,
  673. 0,
  674. DIREG_DEV,
  675. KEY_ALL_ACCESS);
  676. if (INVALID_HANDLE_VALUE == hKey) {
  677. //
  678. // Not much we can do, just exit gracefully
  679. //
  680. return ERROR_SUCCESS;
  681. }
  682. // Check the LPT port name for changes
  683. if (newLptNum != curLptNum) {
  684. LptEnactPortNameChanges(ParentHwnd,
  685. LptPropParams,
  686. hKey,
  687. newLptNum);
  688. }
  689. // Check the Filter resource method for changes
  690. if (curFilterResourceMethod != newFilterResourceMethod) {
  691. //
  692. // They changed the Filter Resource Method
  693. //
  694. dwData = newFilterResourceMethod;
  695. dwSize = sizeof(dwData);
  696. RegSetValueEx(hKey,
  697. m_szFilterResourceMethod,
  698. 0,
  699. REG_DWORD,
  700. (CONST BYTE *)(&dwData),
  701. dwSize);
  702. }
  703. RegCloseKey(hKey);
  704. if (curParEnableLegacyZip != newParEnableLegacyZip) {
  705. //
  706. // Open the services path and set the new value for Legacy Parallel device
  707. // detection.
  708. //
  709. DWORD disposition = 0;
  710. error = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  711. m_szParEnableLegacyZipRegPath,
  712. 0,
  713. (TCHAR *) NULL,
  714. REG_OPTION_NON_VOLATILE,
  715. KEY_ALL_ACCESS,
  716. (LPSECURITY_ATTRIBUTES) NULL,
  717. &hKey,
  718. &disposition);
  719. if (error == ERROR_SUCCESS) {
  720. error = RegSetValueEx(hKey,
  721. m_szParEnableLegacyZip,
  722. 0,
  723. REG_DWORD,
  724. (LPBYTE)(&newParEnableLegacyZip),
  725. sizeof(newParEnableLegacyZip));
  726. RegCloseKey(hKey);
  727. if (error != ERROR_SUCCESS) {
  728. goto ParEnableLegacyZipSetParamFailed;
  729. }
  730. if (newParEnableLegacyZip == 0) {
  731. //
  732. // We want a reboot when disabling this thing, because the parallel
  733. // enumerator won't get rid of legacy devices.
  734. //
  735. InformDriverOfChanges(TRUE, LptPropParams);
  736. } else {
  737. InformDriverOfChanges(FALSE, LptPropParams);
  738. }
  739. } else {
  740. ParEnableLegacyZipSetParamFailed:
  741. MyMessageBox(ParentHwnd,
  742. IDS_LPT_LEGACY_FAILED,
  743. IDS_LPT_PROPERTIES,
  744. MB_OK);
  745. //
  746. // Don't want to overload the user by telling them they have to
  747. // reboot. Since we were unable to set things correctly, just
  748. // rebuild the stack.
  749. //
  750. InformDriverOfChanges(FALSE, LptPropParams);
  751. }
  752. } else {
  753. InformDriverOfChanges(FALSE, LptPropParams);
  754. }
  755. return error;
  756. } // LptSaveAdvancedSettings
  757. UINT
  758. LptEnactPortNameChanges(
  759. IN HWND ParentHwnd,
  760. IN PLPT_PROP_PARAMS LptPropParams,
  761. IN HKEY hDeviceKey,
  762. IN UINT NewLptNum)
  763. {
  764. HANDLE hLpt;
  765. DWORD dwError, dwNewLptNameLen;
  766. UINT curLptNum;
  767. BYTE portUsage[MAX_LPT_PORT];
  768. TCHAR charBuffer[LINE_LEN],
  769. friendlyNameFormat[LINE_LEN],
  770. deviceDesc[LINE_LEN],
  771. buffer[BUFFER_SIZE],
  772. szNewLptName[20];
  773. //
  774. // Check if we're trying to rename the port to the same name.
  775. //
  776. wsprintf(szNewLptName,_T("\\DosDevices\\LPT%d"),NewLptNum);
  777. if (wcscmp(szNewLptName, LptPropParams->szLptName) == 0) {
  778. return ERROR_SUCCESS;
  779. }
  780. //
  781. // Check if a valid port number has been passed in
  782. //
  783. if (MAX_LPT_PORT < NewLptNum) {
  784. //
  785. // Get out of here - exceeding array bounds
  786. // This should never happen in the property page since it is a hardcoded
  787. // selection box. The user can't simply type a number.
  788. //
  789. MyMessageBox(ParentHwnd, IDS_LPT_NUM_ERROR, IDS_LPT_PROPERTIES,
  790. MB_OK | MB_ICONINFORMATION);
  791. return ERROR_SUCCESS;
  792. }
  793. //
  794. // Get an array of used ports
  795. //
  796. LptEnumerateUsedPorts(ParentHwnd,
  797. portUsage,
  798. MAX_LPT_PORT);
  799. if (portUsage[NewLptNum-1]) {
  800. //
  801. // Port name is taken by another port. Check if user wants system to
  802. // get into inconsistent state.
  803. //
  804. if (IDNO == MyMessageBox(ParentHwnd, IDS_LPT_PORT_INUSE,
  805. IDS_LPT_PROPERTIES, MB_YESNO |
  806. MB_ICONINFORMATION)) {
  807. return ERROR_SUCCESS;
  808. }
  809. }
  810. curLptNum = myatoi(LptPropParams->szLptName + wcslen(m_szLPT));
  811. //
  812. // Make sure that the port has not been opened by another application
  813. //
  814. wsprintf(buffer, L"\\\\.\\%ws", LptPropParams->szLptName);
  815. hLpt = CreateFile(buffer, GENERIC_READ, 0, NULL, OPEN_EXISTING,
  816. FILE_ATTRIBUTE_NORMAL, NULL);
  817. //
  818. // If the file handle is invalid, then the Lpt port is open, warn the user
  819. //
  820. if (hLpt == INVALID_HANDLE_VALUE &&
  821. MyMessageBox(ParentHwnd, IDS_PORT_OPEN, IDS_LPT_PROPERTIES,
  822. MB_YESNO | MB_ICONINFORMATION) == IDNO) {
  823. return GetLastError();
  824. }
  825. CloseHandle(hLpt);
  826. wsprintf(szNewLptName, _T("LPT%d"), NewLptNum);
  827. //
  828. // Open the device key for the source device instance, and write its
  829. // new "PortName" value.
  830. //
  831. hDeviceKey = SetupDiOpenDevRegKey(LptPropParams->DeviceInfoSet,
  832. LptPropParams->DeviceInfoData,
  833. DICS_FLAG_GLOBAL,
  834. 0,
  835. DIREG_DEV,
  836. KEY_ALL_ACCESS);
  837. if (INVALID_HANDLE_VALUE == hDeviceKey) {
  838. return GetLastError();
  839. }
  840. dwNewLptNameLen = ByteCountOf(wcslen(szNewLptName) + 1);
  841. dwError = RegSetValueEx(hDeviceKey,
  842. m_szPortName,
  843. 0,
  844. REG_SZ,
  845. (PBYTE) szNewLptName,
  846. dwNewLptNameLen);
  847. if (ERROR_SUCCESS == dwError) {
  848. wcscpy(LptPropParams->szLptName, szNewLptName);
  849. } else {
  850. return dwError;
  851. }
  852. // Now generate a string, to be used for the device's friendly name, that
  853. // incorporates both the INF-specified device description, and the port
  854. // name. For example,
  855. //
  856. // ECP Printer Port (LPT1)
  857. //
  858. if (LoadString(g_hInst,
  859. IDS_FRIENDLY_FORMAT,
  860. friendlyNameFormat,
  861. CharSizeOf(friendlyNameFormat)) &&
  862. SetupDiGetDeviceRegistryProperty(LptPropParams->DeviceInfoSet,
  863. LptPropParams->DeviceInfoData,
  864. SPDRP_DEVICEDESC,
  865. NULL,
  866. (PBYTE)deviceDesc,
  867. sizeof(deviceDesc),
  868. NULL)) {
  869. wsprintf(charBuffer, friendlyNameFormat, deviceDesc, szNewLptName);
  870. }
  871. else {
  872. //
  873. // Simply use LPT port name.
  874. //
  875. lstrcpy(charBuffer, szNewLptName);
  876. }
  877. SetupDiSetDeviceRegistryProperty(LptPropParams->DeviceInfoSet,
  878. LptPropParams->DeviceInfoData,
  879. SPDRP_FRIENDLYNAME,
  880. (PBYTE)charBuffer,
  881. ByteCountOf(lstrlen(charBuffer) + 1)
  882. );
  883. return ERROR_SUCCESS;
  884. } // LptEnactPortNameChanges
  885. void
  886. InformDriverOfChanges(BOOL NeedReboot,
  887. IN PLPT_PROP_PARAMS LptPropParams)
  888. {
  889. SP_DEVINSTALL_PARAMS spDevInstall;
  890. //
  891. // Now broadcast this change to the device manager
  892. //
  893. ZeroMemory(&spDevInstall, sizeof(SP_DEVINSTALL_PARAMS));
  894. spDevInstall.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  895. if (SetupDiGetDeviceInstallParams(LptPropParams->DeviceInfoSet,
  896. LptPropParams->DeviceInfoData,
  897. &spDevInstall)) {
  898. if (NeedReboot) {
  899. spDevInstall.Flags |= DI_PROPERTIES_CHANGE | DI_NEEDREBOOT;
  900. } else {
  901. spDevInstall.FlagsEx |= DI_FLAGSEX_PROPCHANGE_PENDING;
  902. }
  903. SetupDiSetDeviceInstallParams(LptPropParams->DeviceInfoSet,
  904. LptPropParams->DeviceInfoData,
  905. &spDevInstall);
  906. }
  907. }
  908. //
  909. // Takes a Buffer of bytes and marks out which port names are taken
  910. //
  911. void
  912. LptEnumerateUsedPorts(
  913. IN HWND ParentHwnd,
  914. IN PBYTE Buffer,
  915. IN DWORD BufferSize)
  916. {
  917. HKEY hParallelMap;
  918. TCHAR szParallel[BUFFER_SIZE];
  919. DWORD dwParallelSize, dwLptSize, dwEnum, dwType, dwResult, dwPortNum;
  920. TCHAR szLpt[BUFFER_SIZE];
  921. PTCHAR szParPortNum;
  922. ZeroMemory(Buffer, BufferSize);
  923. //
  924. //
  925. //
  926. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  927. m_szRegParallelMap,
  928. 0,
  929. KEY_ALL_ACCESS,
  930. &hParallelMap) == ERROR_SUCCESS) {
  931. dwEnum = 0;
  932. do {
  933. dwParallelSize = CharSizeOf(szParallel);
  934. dwLptSize = sizeof(szLpt);
  935. dwResult = RegEnumValue(hParallelMap,
  936. dwEnum++,
  937. szParallel,
  938. &dwParallelSize,
  939. NULL,
  940. &dwType,
  941. (LPBYTE)szLpt,
  942. &dwLptSize);
  943. if (dwResult != ERROR_SUCCESS ||
  944. dwType != REG_SZ) {
  945. continue;
  946. }
  947. szParPortNum = _tcsspnp(szLpt,_T("\\DosDevices\\LPT"));
  948. if (szParPortNum) {
  949. //
  950. // Find out if this is an actual port and not simply a
  951. // device attached to the port
  952. //
  953. if (_tcscspn(szParPortNum,_T(".")) ==
  954. _tcslen(szParPortNum)) {
  955. dwPortNum = myatoi(szParPortNum);
  956. if (dwPortNum-1 < BufferSize) {
  957. Buffer[dwPortNum-1] = TRUE;
  958. }
  959. }
  960. }
  961. } while (dwResult == ERROR_SUCCESS);
  962. RegCloseKey(hParallelMap);
  963. }
  964. } // LptEnumerateUsedPorts
  965. BOOL
  966. LptPortOnContextMenu(HWND HwndControl,
  967. WORD Xpos,
  968. WORD Ypos)
  969. {
  970. WinHelp(HwndControl,
  971. _T("devmgr.hlp"),
  972. HELP_CONTEXTMENU,
  973. (ULONG_PTR) LptHelpIDs);
  974. return FALSE;
  975. }
  976. void
  977. LptPortOnHelp(HWND ParentHwnd,
  978. LPHELPINFO HelpInfo)
  979. {
  980. if (HelpInfo->iContextType == HELPINFO_WINDOW) {
  981. WinHelp((HWND) HelpInfo->hItemHandle,
  982. _T("devmgr.hlp"),
  983. HELP_WM_HELP,
  984. (ULONG_PTR) LptHelpIDs);
  985. }
  986. }