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.

4164 lines
119 KiB

  1. /*++
  2. Copyright (c) 1995-2001 Microsoft Corporation
  3. Module Name:
  4. hwprof.c
  5. Abstract:
  6. This module contains the dialog box procedure for the Hardware Profiles
  7. Dialog Box in the System Applet.
  8. Author:
  9. Paula Tomlinson (paulat) 8-22-1995
  10. Environment:
  11. User mode only.
  12. Revision History:
  13. 22-Aug-1995 paulat
  14. Creation and initial implementation.
  15. 21-Jan-1999 jamesca
  16. Added handling for hardware profile aliases and hardware-detected
  17. profile attributes.
  18. --*/
  19. //
  20. // include files
  21. //
  22. #include "sysdm.h"
  23. #include <stdlib.h>
  24. #include <usp10.h>
  25. #include <dbt.h>
  26. //
  27. // private types and definitions
  28. //
  29. #define MAX_PROFILES 9999
  30. #define MAX_ALIASES 9999
  31. #define MAX_FRIENDLYNAME_LEN 80
  32. #define MAX_PROFILEID_LEN 5
  33. #define MAX_DOCKID_LEN 128
  34. #define MAX_SERIALNUM_LEN 128
  35. #define MAX_USER_WAIT 500
  36. #define MIN_USER_WAIT 0
  37. #define DEFAULT_USER_WAIT 30
  38. #define MAX_GUID_STRING_LEN 39 // 38 chars + terminating null
  39. typedef struct HWPROFILE_s {
  40. HWND hParent;
  41. ULONG ulFromProfileID;
  42. TCHAR szFromFriendlyName[MAX_FRIENDLYNAME_LEN];
  43. ULONG ulToProfileID;
  44. TCHAR szToFriendlyName[MAX_FRIENDLYNAME_LEN];
  45. } HWPROFILE, *PHWPROFILE;
  46. typedef struct HWPROF_VALUES_s {
  47. ULONG ulAction;
  48. ULONG ulProfile;
  49. ULONG ulPreferenceOrder;
  50. ULONG ulDockState;
  51. BOOL bAliasable;
  52. BOOL bCloned;
  53. BOOL bPortable;
  54. ULONG ulCreatedFrom;
  55. WCHAR szDockID[MAX_DOCKID_LEN];
  56. WCHAR szSerialNumber[MAX_SERIALNUM_LEN];
  57. WCHAR szFriendlyName[MAX_FRIENDLYNAME_LEN];
  58. } HWPROF_VALUES, *PHWPROF_VALUES;
  59. typedef struct HWPROF_INFO_s {
  60. ULONG ulNumProfiles;
  61. ULONG ulActiveProfiles;
  62. PHWPROF_VALUES pHwProfValues;
  63. ULONG ulSelectedProfile;
  64. ULONG ulSelectedProfileIndex;
  65. BOOL bPortable;
  66. BOOL bHwDetectedPortable;
  67. ULONG ulUndockedProfileNameCount;
  68. ULONG ulDockedProfileNameCount;
  69. ULONG ulUnknownProfileNameCount;
  70. } HWPROF_INFO, *PHWPROF_INFO;
  71. #define HWP_NO_ACTION 0x00000000
  72. #define HWP_DELETE 0x00000001
  73. #define HWP_CREATE 0x00000002
  74. #define HWP_RENAME 0x00000004
  75. #define HWP_REORDER 0x00000008
  76. #define HWP_PROPERTIES 0x00000010
  77. #define HWP_NEWPROFILE 0x00001000
  78. //
  79. // private prototypes
  80. //
  81. BOOL
  82. GetCurrentProfile(
  83. PULONG pulProfile
  84. );
  85. BOOL
  86. GetRegProfileCount(
  87. PULONG pulProfiles
  88. );
  89. BOOL
  90. FillProfileList(
  91. HWND hDlg
  92. );
  93. BOOL
  94. IsProfileNameInUse(
  95. HWND hDlg,
  96. LPTSTR pszFriendlyName
  97. );
  98. BOOL
  99. CopyHardwareProfile(
  100. HWND hDlg,
  101. ULONG_PTR ulIndex,
  102. ULONG ulProfile,
  103. LPTSTR szNewFriendlyName
  104. );
  105. BOOL
  106. RenameHardwareProfile(
  107. HWND hDlg,
  108. ULONG_PTR ulIndex,
  109. ULONG ulProfile,
  110. LPTSTR szNewFriendlyName
  111. );
  112. BOOL
  113. DeleteHardwareProfile(
  114. HWND hDlg,
  115. ULONG_PTR ulIndex
  116. );
  117. BOOL
  118. GetUserWaitInterval(
  119. PULONG pulWait
  120. );
  121. BOOL
  122. SetUserWaitInterval(
  123. ULONG ulWait
  124. );
  125. BOOL
  126. GetFreeProfileID(
  127. PHWPROF_INFO pInfo,
  128. PULONG pulProfile
  129. );
  130. ULONG
  131. GetOriginalProfile(
  132. PHWPROF_INFO pInfo,
  133. ULONG ulProfile,
  134. ULONG ulBufferIndex
  135. );
  136. BOOL
  137. InsertRank(
  138. PHWPROF_INFO pInfo,
  139. ULONG ulRank
  140. );
  141. BOOL
  142. DeleteRank(
  143. PHWPROF_INFO pInfo,
  144. ULONG ulRank
  145. );
  146. BOOL
  147. FlushProfileChanges(
  148. HWND hDlg,
  149. HWND hList
  150. );
  151. BOOL
  152. WriteProfileInfo(
  153. PHWPROF_VALUES pProfValues
  154. );
  155. BOOL
  156. RemoveNewProfiles(
  157. PHWPROF_INFO pInfo
  158. );
  159. BOOL
  160. SwapPreferenceOrder(
  161. HWND hDlg,
  162. HWND hList,
  163. ULONG_PTR ulIndex1,
  164. ULONG_PTR ulIndex2
  165. );
  166. BOOL
  167. DeleteProfileDependentTree(
  168. ULONG ulProfile
  169. );
  170. BOOL
  171. CopyAliasEntries(
  172. ULONG ulSrcProfile,
  173. ULONG ulDestProfile
  174. );
  175. BOOL
  176. DeleteAliasEntries(
  177. ULONG ulProfile
  178. );
  179. BOOL
  180. CopyAliasEntryType(
  181. ULONG ulSrcProfile,
  182. ULONG ulDestProfile,
  183. LPWSTR szSubKeyName
  184. );
  185. BOOL
  186. DeleteAliasEntryType(
  187. ULONG ulProfile,
  188. LPWSTR szSubKeyName
  189. );
  190. BOOL
  191. CopyRegistryNode(
  192. HKEY hSrcKey,
  193. HKEY hDestKey
  194. );
  195. BOOL
  196. DeleteRegistryNode(
  197. HKEY hNodeKey,
  198. LPTSTR szSubKey
  199. );
  200. VOID
  201. AdjustProfileTypeCounter(
  202. PHWPROF_INFO pInfo,
  203. ULONG ulDockState,
  204. BOOL bIncrement
  205. );
  206. BOOL
  207. StripCurrentTag(
  208. LPTSTR szOriginalName,
  209. ULONG ulProfile,
  210. ULONG ulCurrentProfile
  211. );
  212. BOOL
  213. AppendCurrentTag(
  214. LPTSTR szTaggedName,
  215. LPCTSTR szOriginalName,
  216. ULONG ulProfile,
  217. ULONG ulCurrentProfile
  218. );
  219. VOID
  220. CreateHwProfileFriendlyName(
  221. IN HWND hDlg,
  222. IN ULONG ulDockState,
  223. OUT LPTSTR szFriendlyName
  224. );
  225. VOID
  226. DisplayPrivateMessage(
  227. HWND hDlg,
  228. UINT uiPrivateError
  229. );
  230. VOID
  231. DisplaySystemMessage(
  232. HWND hWnd,
  233. UINT uiSystemError
  234. );
  235. BOOL
  236. UpdateOrderButtonState(
  237. HWND hDlg
  238. );
  239. BOOL
  240. DisplayProperties(
  241. IN HWND hOwnerDlg,
  242. IN PHWPROF_INFO pProfValues
  243. );
  244. typedef BOOL (CALLBACK FAR * LPFNADDPROPSHEETPAGE)(HPROPSHEETPAGE, LPARAM);
  245. //
  246. // global strings
  247. //
  248. WCHAR pszErrorCaption[MAX_PATH];
  249. WCHAR pszRegDefaultFriendlyName[MAX_FRIENDLYNAME_LEN];
  250. WCHAR pszCurrentTag[64];
  251. WCHAR pszUnavailable[64];
  252. WCHAR pszDocked[64];
  253. WCHAR pszUndocked[64];
  254. WCHAR pszUnknown[64];
  255. WCHAR pszRegIDConfigDB[] = TEXT("System\\CurrentControlSet\\Control\\IDConfigDB");
  256. WCHAR pszRegHwProfiles[] = TEXT("System\\CurrentControlSet\\Hardware Profiles");
  257. WCHAR pszRegKnownDockingStates[] = TEXT("Hardware Profiles");
  258. WCHAR pszRegCurrentDockInfo[] = TEXT("CurrentDockInfo");
  259. WCHAR pszRegDockingState[] = TEXT("DockingState");
  260. WCHAR pszRegAlias[] = TEXT("Alias");
  261. WCHAR pszRegAcpiAlias[] = TEXT("AcpiAlias");
  262. WCHAR pszRegProfileNumber[] = TEXT("ProfileNumber");
  263. WCHAR pszRegCurrentConfig[] = TEXT("CurrentConfig");
  264. WCHAR pszRegUserWaitInterval[] = TEXT("UserWaitInterval");
  265. WCHAR pszRegFriendlyName[] = TEXT("FriendlyName");
  266. WCHAR pszRegPristine[] = TEXT("Pristine");
  267. WCHAR pszRegHwProfileGuid[] = TEXT("HwProfileGuid");
  268. WCHAR pszRegPreferenceOrder[] = TEXT("PreferenceOrder");
  269. WCHAR pszRegDockState[] = TEXT("DockState");
  270. WCHAR pszRegAliasable[] = TEXT("Aliasable");
  271. WCHAR pszRegCloned[] = TEXT("Cloned");
  272. WCHAR pszRegIsPortable[] = TEXT("IsPortable");
  273. WCHAR pszRegDockID[] = TEXT("DockID");
  274. WCHAR pszRegSerialNumber[] = TEXT("SerialNumber");
  275. WCHAR pszRegAcpiSerialNumber[] = TEXT("AcpiSerialNumber");
  276. WCHAR pszRegPropertyProviders[] = TEXT("PropertyProviders");
  277. WCHAR pszRegDocked[] = TEXT("Docked");
  278. WCHAR pszRegUndocked[] = TEXT("Undocked");
  279. WCHAR pszRegUnknown[] = TEXT("Unknown");
  280. //
  281. // global mutex for synchronization
  282. //
  283. WCHAR pszNamedMutex[] = TEXT("System-HardwareProfiles-PLT");
  284. HANDLE g_hMutex = NULL;
  285. //
  286. // global info for property sheet extensions
  287. //
  288. #define MAX_EXTENSION_PROVIDERS 32
  289. HMODULE hLibs[MAX_EXTENSION_PROVIDERS];
  290. HPROPSHEETPAGE hPages[MAX_EXTENSION_PROVIDERS];
  291. ULONG ulNumPages = 0;
  292. BOOL bAdmin = FALSE;
  293. static int HwProfileHelpIds[] = {
  294. IDD_HWP_PROFILES, (IDH_HWPROFILE + IDD_HWP_PROFILES),
  295. IDD_HWP_PROPERTIES, (IDH_HWPROFILE + IDD_HWP_PROPERTIES),
  296. IDD_HWP_COPY, (IDH_HWPROFILE + IDD_HWP_COPY),
  297. IDD_HWP_RENAME, (IDH_HWPROFILE + IDD_HWP_RENAME),
  298. IDD_HWP_DELETE, (IDH_HWPROFILE + IDD_HWP_DELETE),
  299. IDD_HWP_ST_MULTIPLE, (IDH_HWPROFILE + IDD_HWP_ST_MULTIPLE),
  300. IDD_HWP_WAITFOREVER, (IDH_HWPROFILE + IDD_HWP_WAITFOREVER),
  301. IDD_HWP_WAITUSER, (IDH_HWPROFILE + IDD_HWP_WAITUSER),
  302. IDD_HWP_SECONDS, (IDH_HWPROFILE + IDD_HWP_SECONDS),
  303. IDD_HWP_SECSCROLL, (IDH_HWPROFILE + IDD_HWP_SECSCROLL),
  304. IDD_HWP_COPYTO, (IDH_HWPROFILE + IDD_HWP_COPYTO),
  305. IDD_HWP_COPYTO_CAPTION, (IDH_HWPROFILE + IDD_HWP_COPYTO),
  306. IDD_HWP_COPYFROM, (IDH_HWPROFILE + IDD_HWP_COPYFROM),
  307. IDD_HWP_ST_DOCKID, (IDH_HWPROFILE + IDD_HWP_ST_DOCKID),
  308. IDD_HWP_ST_SERIALNUM, (IDH_HWPROFILE + IDD_HWP_ST_SERIALNUM),
  309. IDD_HWP_DOCKID, (IDH_HWPROFILE + IDD_HWP_DOCKID),
  310. IDD_HWP_SERIALNUM, (IDH_HWPROFILE + IDD_HWP_SERIALNUM),
  311. IDD_HWP_PORTABLE, (IDH_HWPROFILE + IDD_HWP_PORTABLE),
  312. IDD_HWP_ALIASABLE, IDH_HWP_PROPERTIES_SELECTION_CHECKBOX,
  313. IDD_HWP_UNKNOWN, (IDH_HWPROFILE + IDD_HWP_UNKNOWN),
  314. IDD_HWP_DOCKED, (IDH_HWPROFILE + IDD_HWP_DOCKED),
  315. IDD_HWP_UNDOCKED, (IDH_HWPROFILE + IDD_HWP_UNDOCKED),
  316. IDD_HWP_ST_PROFILE, (IDH_HWPROFILE + IDD_HWP_ST_PROFILE),
  317. IDD_HWP_ORDERUP, (IDH_HWPROFILE + IDD_HWP_ORDERUP),
  318. IDD_HWP_ORDERDOWN, (IDH_HWPROFILE + IDD_HWP_ORDERDOWN),
  319. IDD_HWP_RENAMEFROM, (IDH_HWPROFILE + IDD_HWP_RENAMEFROM),
  320. IDD_HWP_RENAMETO, (IDH_HWPROFILE + IDD_HWP_RENAMETO),
  321. IDD_HWP_RENAMETO_CAPTION,(IDH_HWPROFILE + IDD_HWP_RENAMETO),
  322. IDD_HWP_WAITUSER_TEXT_1, (IDH_HWPROFILE + IDD_HWP_SECSCROLL),
  323. IDD_HWP_UNUSED_1, -1,
  324. IDD_HWP_UNUSED_2, -1,
  325. IDD_HWP_UNUSED_3, -1,
  326. IDD_HWP_UNUSED_4, -1,
  327. IDD_HWP_UNUSED_5, -1,
  328. IDD_HWP_UNUSED_6, -1,
  329. 0, 0
  330. };
  331. /**-------------------------------------------------------------------------**/
  332. INT_PTR
  333. APIENTRY
  334. HardwareProfilesDlg(
  335. HWND hDlg,
  336. UINT uMessage,
  337. WPARAM wParam,
  338. LPARAM lParam
  339. )
  340. {
  341. BOOL Status;
  342. ULONG ulCurrentProfile, ulSelectedProfile,
  343. ulWait, ulBufferIndex = 0;
  344. ULONG_PTR ulIndex;
  345. LONG lValue;
  346. TCHAR szProfileName[MAX_PATH], szName[MAX_PATH];
  347. HWND hList;
  348. int nValue;
  349. HWPROFILE HwSelectedProfile;
  350. LPNM_UPDOWN pUDData;
  351. PHWPROF_INFO pInfo;
  352. HICON hIcon;
  353. switch (uMessage)
  354. {
  355. case WM_INITDIALOG:
  356. bAdmin = IsUserAdmin();
  357. //
  358. // attempt to claim the named mutex and lock other instances of
  359. // this dialog box out
  360. //
  361. g_hMutex = CreateMutex(NULL, TRUE, pszNamedMutex);
  362. if (g_hMutex == NULL) {
  363. if (GetLastError() == ERROR_ALREADY_EXISTS) {
  364. DisplayPrivateMessage(hDlg, HWP_ERROR_IN_USE);
  365. } else {
  366. DisplaySystemMessage(hDlg, GetLastError());
  367. }
  368. EndDialog(hDlg, FALSE);
  369. return FALSE;
  370. }
  371. //
  372. // load some global strings
  373. //
  374. LoadString(hInstance, HWP_CURRENT_TAG, pszCurrentTag, 64);
  375. LoadString(hInstance, HWP_UNAVAILABLE, pszUnavailable, 64);
  376. LoadString(hInstance, HWP_UNKNOWN_PROFILE, pszUnknown, 64);
  377. LoadString(hInstance, HWP_DOCKED_PROFILE, pszDocked, 64);
  378. LoadString(hInstance, HWP_UNDOCKED_PROFILE, pszUndocked, 64);
  379. LoadString(hInstance, HWP_ERROR_CAPTION, pszErrorCaption, MAX_PATH);
  380. LoadString(hInstance, HWP_DEF_FRIENDLYNAME, pszRegDefaultFriendlyName,
  381. MAX_FRIENDLYNAME_LEN);
  382. //
  383. // fill the profiles listbox with all installed profiles,
  384. // this will also select the current profile
  385. //
  386. if (!FillProfileList(hDlg)) {
  387. EndDialog(hDlg, FALSE);
  388. return FALSE;
  389. }
  390. pInfo = (PHWPROF_INFO)GetWindowLongPtr(hDlg, DWLP_USER);
  391. //
  392. // place the icons on the up and down selection buttons
  393. //
  394. SendDlgItemMessage(
  395. hDlg, IDD_HWP_ORDERUP, BM_SETIMAGE, (WPARAM)IMAGE_ICON,
  396. (LPARAM)LoadIcon(hInstance, MAKEINTRESOURCE(UP_ICON)));
  397. SendDlgItemMessage(
  398. hDlg, IDD_HWP_ORDERDOWN, BM_SETIMAGE, (WPARAM)IMAGE_ICON,
  399. (LPARAM)LoadIcon(hInstance, MAKEINTRESOURCE(DOWN_ICON)));
  400. //
  401. // update button enable/disable states
  402. //
  403. UpdateOrderButtonState(hDlg);
  404. //
  405. // disable Delete for the current profile
  406. //
  407. EnableWindow(GetDlgItem(hDlg, IDD_HWP_DELETE), FALSE);
  408. //
  409. // disable copy if we're already at the max number of profiles
  410. // (including the pristine profile)
  411. //
  412. if ((pInfo->ulNumProfiles+1) > MAX_PROFILES) {
  413. EnableWindow(GetDlgItem(hDlg, IDD_HWP_COPY), FALSE);
  414. }
  415. //
  416. // initialize the user wait setting
  417. //
  418. SendDlgItemMessage(hDlg, IDD_HWP_SECSCROLL, UDM_SETBASE, 10, 0);
  419. SendDlgItemMessage(hDlg, IDD_HWP_SECSCROLL, UDM_SETRANGE, 0,
  420. MAKELONG((SHORT)MAX_USER_WAIT, (SHORT)MIN_USER_WAIT));
  421. SendDlgItemMessage(hDlg, IDD_HWP_SECONDS, EM_LIMITTEXT, 3, 0L);
  422. GetUserWaitInterval(&ulWait);
  423. if (ulWait == 0xFFFFFFFF) {
  424. CheckRadioButton(hDlg, IDD_HWP_WAITFOREVER, IDD_HWP_WAITUSER,
  425. IDD_HWP_WAITFOREVER);
  426. SendDlgItemMessage(hDlg, IDD_HWP_SECSCROLL, UDM_SETPOS, 0,
  427. DEFAULT_USER_WAIT);
  428. EnableWindow(GetDlgItem(hDlg, IDD_HWP_SECONDS), FALSE);
  429. EnableWindow(GetDlgItem(hDlg, IDD_HWP_SECSCROLL), FALSE);
  430. }
  431. else {
  432. CheckRadioButton(hDlg, IDD_HWP_WAITFOREVER, IDD_HWP_WAITUSER,
  433. IDD_HWP_WAITUSER);
  434. SendDlgItemMessage(hDlg, IDD_HWP_SECSCROLL, UDM_SETPOS, 0, ulWait);
  435. }
  436. //
  437. // Disable all actions if user not part of administrators local group
  438. //
  439. if (!bAdmin) {
  440. EnableWindow(GetDlgItem(hDlg, IDD_HWP_ORDERUP), FALSE);
  441. EnableWindow(GetDlgItem(hDlg, IDD_HWP_PROPERTIES), FALSE);
  442. EnableWindow(GetDlgItem(hDlg, IDD_HWP_COPY), FALSE);
  443. EnableWindow(GetDlgItem(hDlg, IDD_HWP_RENAME), FALSE);
  444. EnableWindow(GetDlgItem(hDlg, IDD_HWP_DELETE), FALSE);
  445. EnableWindow(GetDlgItem(hDlg, IDD_HWP_ORDERDOWN), FALSE);
  446. EnableWindow(GetDlgItem(hDlg, IDD_HWP_WAITFOREVER),FALSE);
  447. EnableWindow(GetDlgItem(hDlg, IDD_HWP_WAITUSER), FALSE);
  448. EnableWindow(GetDlgItem(hDlg, IDD_HWP_WAITUSER_TEXT_1), FALSE);
  449. EnableWindow(GetDlgItem(hDlg, IDD_HWP_SECONDS), FALSE);
  450. EnableWindow(GetDlgItem(hDlg, IDD_HWP_SECSCROLL), FALSE);
  451. }
  452. return 0;
  453. case WM_HELP:
  454. WinHelp((HWND)((LPHELPINFO)lParam)->hItemHandle, HELP_FILE,
  455. HELP_WM_HELP, (DWORD_PTR)(LPTSTR)HwProfileHelpIds);
  456. break;
  457. case WM_CONTEXTMENU:
  458. WinHelp((HWND)wParam, HELP_FILE, HELP_CONTEXTMENU,
  459. (DWORD_PTR)(LPTSTR)HwProfileHelpIds);
  460. break;
  461. case WM_DESTROY:
  462. //
  463. // only free the buffer if we've already initialized
  464. //
  465. pInfo = (PHWPROF_INFO)GetWindowLongPtr(hDlg, DWLP_USER);
  466. if (pInfo) {
  467. LocalFree((HLOCAL)pInfo->pHwProfValues);
  468. LocalFree((HLOCAL)pInfo);
  469. hIcon = (HICON)SendDlgItemMessage(
  470. hDlg, IDD_HWP_ORDERUP, BM_GETIMAGE, 0, 0);
  471. if (hIcon) {
  472. DeleteObject(hIcon);
  473. }
  474. hIcon = (HICON)SendDlgItemMessage(
  475. hDlg, IDD_HWP_ORDERDOWN, BM_GETIMAGE, 0, 0);
  476. if (hIcon) {
  477. DeleteObject(hIcon);
  478. }
  479. }
  480. break;
  481. case WM_DEVICECHANGE:
  482. //
  483. // If a hardware profile change event takes place while the dialog is
  484. // up, just dismiss the dialog because things have changed.
  485. //
  486. if (wParam == DBT_CONFIGCHANGED) {
  487. EndDialog(hDlg, FALSE);
  488. return FALSE;
  489. }
  490. break;
  491. case WM_COMMAND:
  492. {
  493. switch (LOWORD(wParam))
  494. {
  495. case IDOK:
  496. if (bAdmin) {
  497. //
  498. // save the user wait interval in the registry
  499. //
  500. if (IsDlgButtonChecked(hDlg, IDD_HWP_WAITFOREVER)) {
  501. ulWait = 0xFFFFFFFF;
  502. }
  503. else {
  504. ulWait = GetDlgItemInt(hDlg, IDD_HWP_SECONDS,
  505. &Status, FALSE);
  506. if (!Status || ulWait > MAX_USER_WAIT) {
  507. TCHAR szCaption[MAX_PATH];
  508. TCHAR szMsg[MAX_PATH];
  509. LoadString(hInstance, HWP_ERROR_CAPTION, szCaption, MAX_PATH);
  510. LoadString(hInstance, HWP_INVALID_WAIT, szMsg, MAX_PATH);
  511. MessageBox(hDlg, szMsg, szCaption,
  512. MB_OK | MB_ICONEXCLAMATION);
  513. SetFocus(GetDlgItem(hDlg, IDD_HWP_SECONDS));
  514. return(TRUE);
  515. }
  516. }
  517. SetUserWaitInterval(ulWait);
  518. //
  519. // flush the pending changes in profile buffer
  520. //
  521. hList = GetDlgItem(hDlg, IDD_HWP_PROFILES);
  522. FlushProfileChanges(hDlg, hList);
  523. }
  524. EndDialog(hDlg, 0);
  525. break;
  526. case IDCANCEL:
  527. pInfo = (PHWPROF_INFO)GetWindowLongPtr(hDlg, DWLP_USER);
  528. if (pInfo) {
  529. //
  530. // If profile modifications have already been commited from
  531. // within the Property Sheet, that's okay. But if accessing
  532. // Properties caused any profiles to be created then they
  533. // should be removed now since the user is effectively
  534. // cancelling that creation now by cancelling from the main
  535. // Hardware Profiles dialog.
  536. //
  537. if (bAdmin) {
  538. RemoveNewProfiles(pInfo);
  539. }
  540. }
  541. SetWindowLongPtr (hDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
  542. EndDialog(hDlg, 0);
  543. break;
  544. case IDD_HWP_ORDERUP:
  545. //
  546. // move selected profile "up" in preference order
  547. //
  548. hList = GetDlgItem(hDlg, IDD_HWP_PROFILES);
  549. ulIndex = SendMessage(hList, LB_GETCURSEL, 0, 0);
  550. if (ulIndex == LB_ERR) {
  551. break;
  552. }
  553. pInfo = (PHWPROF_INFO)GetWindowLongPtr(hDlg, DWLP_USER);
  554. //
  555. // if we're not already at the top, swap preferences
  556. //
  557. if (ulIndex > 0) {
  558. SwapPreferenceOrder(hDlg, hList, ulIndex, ulIndex-1);
  559. UpdateOrderButtonState(hDlg);
  560. PropSheet_Changed(GetParent(hDlg), hDlg);
  561. }
  562. break;
  563. case IDD_HWP_ORDERDOWN:
  564. //
  565. // move selected profile "down" in preference order
  566. //
  567. hList = GetDlgItem(hDlg, IDD_HWP_PROFILES);
  568. ulIndex = SendMessage(hList, LB_GETCURSEL, 0, 0);
  569. if (ulIndex == LB_ERR) {
  570. break;
  571. }
  572. pInfo = (PHWPROF_INFO)GetWindowLongPtr(hDlg, DWLP_USER);
  573. //
  574. // if we're not already at the bottom, swap preferences
  575. //
  576. if (ulIndex < pInfo->ulNumProfiles-1) {
  577. SwapPreferenceOrder(hDlg, hList, ulIndex, ulIndex+1);
  578. UpdateOrderButtonState(hDlg);
  579. PropSheet_Changed(GetParent(hDlg), hDlg);
  580. }
  581. break;
  582. case IDD_HWP_PROFILES:
  583. //
  584. // selection changed, enable/disable Delete button based
  585. // on whether it's the current config that is selected
  586. //
  587. if (bAdmin) {
  588. if (HIWORD(wParam) == LBN_DBLCLK) {
  589. SendMessage(hDlg, WM_COMMAND, MAKELONG(IDD_HWP_PROPERTIES,0), 0);
  590. }
  591. else if (HIWORD(wParam) == LBN_SELCHANGE) {
  592. if (!GetCurrentProfile(&ulCurrentProfile)) {
  593. break;
  594. }
  595. if ((ulIndex = SendMessage((HWND)lParam,
  596. LB_GETCURSEL, 0, 0)) == LB_ERR) {
  597. break;
  598. }
  599. if ((lValue = (LONG)SendMessage((HWND)lParam, LB_GETITEMDATA,
  600. ulIndex, 0)) == LB_ERR) {
  601. break;
  602. }
  603. if ((ULONG)lValue == ulCurrentProfile) {
  604. EnableWindow(GetDlgItem(hDlg, IDD_HWP_DELETE), FALSE);
  605. }
  606. else {
  607. EnableWindow(GetDlgItem(hDlg, IDD_HWP_DELETE), TRUE);
  608. }
  609. //
  610. // update button enable/disable states
  611. //
  612. UpdateOrderButtonState(hDlg);
  613. }
  614. }
  615. break;
  616. case IDD_HWP_WAITFOREVER:
  617. //
  618. // if user chooses wait forever, disable the seconds control
  619. //
  620. if (HIWORD(wParam) == BN_CLICKED) {
  621. EnableWindow(GetDlgItem(hDlg, IDD_HWP_SECONDS), FALSE);
  622. EnableWindow(GetDlgItem(hDlg, IDD_HWP_SECSCROLL), FALSE);
  623. PropSheet_Changed(GetParent(hDlg), hDlg);
  624. }
  625. break;
  626. case IDD_HWP_WAITUSER:
  627. //
  628. // if user chooses a wait interval, reenable seconds control
  629. //
  630. if (HIWORD(wParam) == BN_CLICKED) {
  631. EnableWindow(GetDlgItem(hDlg, IDD_HWP_SECONDS), TRUE);
  632. EnableWindow(GetDlgItem(hDlg, IDD_HWP_SECSCROLL), TRUE);
  633. PropSheet_Changed(GetParent(hDlg), hDlg);
  634. }
  635. break;
  636. case IDD_HWP_PROPERTIES:
  637. //
  638. // retrieve the profile buffer
  639. //
  640. pInfo = (PHWPROF_INFO)GetWindowLongPtr(hDlg, DWLP_USER);
  641. //
  642. // get the selected profile
  643. //
  644. hList = GetDlgItem(hDlg, IDD_HWP_PROFILES);
  645. ulIndex = SendMessage(hList, LB_GETCURSEL, 0, 0);
  646. if (ulIndex == LB_ERR) {
  647. break;
  648. }
  649. //
  650. // find the profile entry in the buffer that matches the selection
  651. //
  652. hList = GetDlgItem(hDlg, IDD_HWP_PROFILES);
  653. ulSelectedProfile = (ULONG)SendMessage(hList, LB_GETITEMDATA, ulIndex, 0);
  654. while (ulBufferIndex < pInfo->ulNumProfiles) {
  655. if (pInfo->pHwProfValues[ulBufferIndex].ulProfile == ulSelectedProfile) {
  656. break;
  657. }
  658. ulBufferIndex++;
  659. }
  660. //
  661. // commit the changes for this profile before calling Properties
  662. //
  663. WriteProfileInfo(&pInfo->pHwProfValues[ulBufferIndex]);
  664. //
  665. // pass the HWPROF_VALUES struct for the selected profile
  666. // to the property sheet page when it's created. The
  667. // property sheet may update some of these fields and
  668. // may also commit changes for this profile to the registry.
  669. //
  670. pInfo->ulSelectedProfileIndex = ulBufferIndex;
  671. pInfo->ulSelectedProfile = (ULONG)SendMessage(hList, LB_GETITEMDATA,
  672. ulIndex, 0);
  673. DisplayProperties(hDlg, pInfo);
  674. //DisplayProperties(hDlg, &pInfo->pHwProfValues[ulBufferIndex]);
  675. break;
  676. case IDD_HWP_COPY:
  677. //
  678. // retrieve the profile buffer
  679. //
  680. pInfo = (PHWPROF_INFO)GetWindowLongPtr(hDlg, DWLP_USER);
  681. //
  682. // get the selected profile, this is the "From" selection
  683. //
  684. hList = GetDlgItem(hDlg, IDD_HWP_PROFILES);
  685. ulIndex = SendMessage(hList, LB_GETCURSEL, 0, 0);
  686. if (ulIndex == LB_ERR) {
  687. break;
  688. }
  689. SendMessage(hList, LB_GETTEXT, ulIndex,
  690. (LPARAM)(LPCTSTR)HwSelectedProfile.szFromFriendlyName);
  691. HwSelectedProfile.ulFromProfileID =
  692. (ULONG)SendMessage(hList, LB_GETITEMDATA, ulIndex, 0);
  693. //
  694. // find the profile entry in the buffer that matches the selection
  695. //
  696. ulBufferIndex = 0;
  697. while (ulBufferIndex < pInfo->ulNumProfiles) {
  698. if (pInfo->pHwProfValues[ulBufferIndex].ulProfile == HwSelectedProfile.ulFromProfileID) {
  699. break;
  700. }
  701. ulBufferIndex++;
  702. }
  703. //
  704. // determine the next suggested name for the given profile
  705. //
  706. CreateHwProfileFriendlyName(hDlg,
  707. pInfo->pHwProfValues[ulBufferIndex].ulDockState,
  708. HwSelectedProfile.szToFriendlyName);
  709. //
  710. // pass selected profile info to copy profile dialog box
  711. //
  712. HwSelectedProfile.hParent = hDlg;
  713. if (!DialogBoxParam(hInstance,
  714. MAKEINTRESOURCE(DLG_HWP_COPY), hDlg,
  715. CopyProfileDlg,
  716. (LPARAM)&HwSelectedProfile)) {
  717. //
  718. // if returns FALSE, either user canceled or no work
  719. // required
  720. //
  721. break;
  722. }
  723. //
  724. // clone the profile in the in-memory profile buffer
  725. // and update the display
  726. //
  727. CopyHardwareProfile(
  728. hDlg,
  729. ulIndex,
  730. HwSelectedProfile.ulFromProfileID,
  731. HwSelectedProfile.szToFriendlyName);
  732. UpdateOrderButtonState(hDlg);
  733. PropSheet_Changed(GetParent(hDlg), hDlg);
  734. break;
  735. case IDD_HWP_RENAME:
  736. //
  737. // get the selected profile
  738. //
  739. hList = GetDlgItem(hDlg, IDD_HWP_PROFILES);
  740. ulIndex = SendMessage(hList, LB_GETCURSEL, 0, 0);
  741. if (ulIndex == LB_ERR) {
  742. break;
  743. }
  744. SendMessage(hList, LB_GETTEXT, ulIndex,
  745. (LPARAM)(LPCTSTR)HwSelectedProfile.szFromFriendlyName);
  746. HwSelectedProfile.ulFromProfileID =
  747. (ULONG)SendMessage(hList, LB_GETITEMDATA, ulIndex, 0);
  748. //
  749. // strip off the current tag if it exists "(Current)"
  750. //
  751. GetCurrentProfile(&ulCurrentProfile);
  752. StripCurrentTag(
  753. HwSelectedProfile.szFromFriendlyName,
  754. HwSelectedProfile.ulFromProfileID,
  755. ulCurrentProfile);
  756. // pass selected profile info to rename profile dialog box
  757. //
  758. HwSelectedProfile.hParent = hDlg;
  759. if (!DialogBoxParam(hInstance,
  760. MAKEINTRESOURCE(DLG_HWP_RENAME), hDlg,
  761. RenameProfileDlg,
  762. (LPARAM)&HwSelectedProfile)) {
  763. //
  764. // if returns FASLE, either user canceled or no work
  765. // required (i.e., user chose same name or zero-length
  766. // name)
  767. //
  768. break;
  769. }
  770. //
  771. // rename the profile in the in-memory profile buffer
  772. // and update the display
  773. //
  774. RenameHardwareProfile(
  775. hDlg,
  776. ulIndex,
  777. HwSelectedProfile.ulFromProfileID,
  778. HwSelectedProfile.szToFriendlyName);
  779. PropSheet_Changed(GetParent(hDlg), hDlg);
  780. break;
  781. case IDD_HWP_DELETE: {
  782. TCHAR szCaption[MAX_PATH];
  783. TCHAR szMsg[MAX_PATH];
  784. TCHAR szMsg1[MAX_PATH];
  785. //
  786. // get the selected profile
  787. //
  788. hList = GetDlgItem(hDlg, IDD_HWP_PROFILES);
  789. ulIndex = SendMessage(hList, LB_GETCURSEL, 0, 0);
  790. if (ulIndex == LB_ERR) {
  791. break;
  792. }
  793. //
  794. // confirm that user really wants to delete the profile
  795. // (the confirm message has a substitute symbol for
  796. // profile name)
  797. //
  798. SendMessage(hList, LB_GETTEXT, ulIndex,
  799. (LPARAM)(LPCTSTR)szProfileName);
  800. LoadString(hInstance, HWP_CONFIRM_DELETE_CAP, szCaption, MAX_PATH);
  801. LoadString(hInstance, HWP_CONFIRM_DELETE, szMsg1, MAX_PATH);
  802. wsprintf(szMsg, szMsg1, szProfileName);
  803. if (MessageBox(hDlg, szMsg, szCaption,
  804. MB_YESNO | MB_ICONQUESTION) == IDNO) {
  805. break;
  806. }
  807. //
  808. // mark the profile as deleted in the in-memory buffer
  809. // and update the display
  810. //
  811. DeleteHardwareProfile(
  812. hDlg,
  813. ulIndex);
  814. UpdateOrderButtonState(hDlg);
  815. PropSheet_Changed(GetParent(hDlg), hDlg);
  816. break;
  817. }
  818. case IDD_HWP_SECONDS:
  819. if (HIWORD(wParam) == EN_UPDATE) {
  820. PropSheet_Changed(GetParent(hDlg), hDlg);
  821. }
  822. break;
  823. default:
  824. return FALSE;
  825. }
  826. break;
  827. } // case WM_COMMAND...
  828. default:
  829. return FALSE;
  830. break;
  831. }
  832. return TRUE;
  833. } // HardwareProfilesDlg
  834. /**-------------------------------------------------------------------------**/
  835. INT_PTR
  836. APIENTRY
  837. CopyProfileDlg(
  838. HWND hDlg,
  839. UINT uMessage,
  840. WPARAM wParam,
  841. LPARAM lParam
  842. )
  843. {
  844. PHWPROFILE pHwProfile;
  845. static HIMC himcOrg;
  846. switch (uMessage)
  847. {
  848. case WM_INITDIALOG:
  849. //
  850. // the profile info struct is passed in lparam, save in
  851. // Window word for thread-safe use in later messages
  852. //
  853. SetWindowLongPtr(hDlg, DWLP_USER, lParam);
  854. pHwProfile = (PHWPROFILE)lParam;
  855. //
  856. // initialize "To" and "From" fields
  857. //
  858. SendDlgItemMessage(hDlg, IDD_HWP_COPYTO, EM_LIMITTEXT,
  859. MAX_FRIENDLYNAME_LEN-1, 0L);
  860. SetDlgItemText(hDlg, IDD_HWP_COPYFROM, pHwProfile->szFromFriendlyName);
  861. SetDlgItemText(hDlg, IDD_HWP_COPYTO, pHwProfile->szToFriendlyName);
  862. SendDlgItemMessage(hDlg, IDD_HWP_COPYTO, EM_SETSEL, 0, -1);
  863. SetFocus(GetDlgItem(hDlg, IDD_HWP_COPYTO));
  864. //
  865. // Remove any association the window may have with an input context,
  866. // because we don't allow to use DBCS in H/W profile name.
  867. //
  868. himcOrg = ImmAssociateContext(GetDlgItem(hDlg, IDD_HWP_COPYTO), (HIMC)NULL);
  869. return FALSE;
  870. case WM_DEVICECHANGE:
  871. //
  872. // If a hardware profile change event takes place while the dialog is
  873. // up, just dismiss the dialog because things have changed.
  874. //
  875. if (wParam == DBT_CONFIGCHANGED) {
  876. EndDialog(hDlg, FALSE);
  877. return FALSE;
  878. }
  879. break;
  880. case WM_DESTROY:
  881. if (himcOrg)
  882. ImmAssociateContext(GetDlgItem(hDlg, IDD_HWP_COPYTO), himcOrg);
  883. return FALSE;
  884. case WM_HELP:
  885. WinHelp((HWND)((LPHELPINFO)lParam)->hItemHandle, HELP_FILE,
  886. HELP_WM_HELP, (DWORD_PTR)(LPTSTR)HwProfileHelpIds);
  887. break;
  888. case WM_CONTEXTMENU:
  889. WinHelp((HWND)wParam, HELP_FILE, HELP_CONTEXTMENU,
  890. (DWORD_PTR)(LPTSTR)HwProfileHelpIds);
  891. break;
  892. case WM_COMMAND:
  893. {
  894. switch (LOWORD(wParam))
  895. {
  896. case IDOK:
  897. pHwProfile = (PHWPROFILE)GetWindowLongPtr(hDlg, DWLP_USER);
  898. GetDlgItemText(hDlg, IDD_HWP_COPYTO,
  899. pHwProfile->szToFriendlyName, MAX_FRIENDLYNAME_LEN);
  900. if (pHwProfile->szToFriendlyName == NULL ||
  901. *pHwProfile->szToFriendlyName == '\0') {
  902. //
  903. // accept request to copy to zero-length string but
  904. // do nothing (return FALSE from DialogBox call)
  905. //
  906. EndDialog(hDlg, FALSE);
  907. return TRUE;
  908. }
  909. //
  910. // Check for duplicates
  911. //
  912. if (IsProfileNameInUse(pHwProfile->hParent,
  913. pHwProfile->szToFriendlyName)) {
  914. //
  915. // if name already used by a different profile (including
  916. // the name of this profile), deny the request, but don't
  917. // end the dialog box
  918. //
  919. DisplayPrivateMessage(hDlg, HWP_ERROR_PROFILE_IN_USE);
  920. break;
  921. }
  922. //
  923. // Check for complex script names
  924. //
  925. if (S_OK == ScriptIsComplex(pHwProfile->szToFriendlyName, lstrlen(pHwProfile->szToFriendlyName), SIC_COMPLEX))
  926. {
  927. DisplayPrivateMessage(hDlg, HWP_ERROR_COMPLEX_SCRIPT);
  928. break;
  929. }
  930. //
  931. // otherwise, we'll accept the name
  932. //
  933. EndDialog(hDlg,TRUE);
  934. break;
  935. case IDCANCEL:
  936. EndDialog(hDlg,FALSE);
  937. break;
  938. default:
  939. return FALSE;
  940. }
  941. break;
  942. } // case WM_COMMAND...
  943. default:
  944. return FALSE;
  945. break;
  946. }
  947. return TRUE;
  948. } // CopyProfileDlg
  949. /**-------------------------------------------------------------------------**/
  950. INT_PTR
  951. APIENTRY
  952. RenameProfileDlg(
  953. HWND hDlg,
  954. UINT uMessage,
  955. WPARAM wParam,
  956. LPARAM lParam
  957. )
  958. {
  959. PHWPROFILE pHwProfile;
  960. ULONG ulReturn;
  961. static HIMC himcOrg;
  962. switch (uMessage)
  963. {
  964. case WM_INITDIALOG:
  965. //
  966. // the profile info struct is passed in lparam, save in
  967. // Window word for thread-safe use in later messages
  968. //
  969. SetWindowLongPtr(hDlg, DWLP_USER, lParam);
  970. pHwProfile = (PHWPROFILE)lParam;
  971. //
  972. // initialize "To" and "From" fields
  973. //
  974. SendDlgItemMessage(hDlg, IDD_HWP_RENAMETO, EM_LIMITTEXT,
  975. MAX_FRIENDLYNAME_LEN-1, 0L);
  976. SetDlgItemText(hDlg, IDD_HWP_RENAMEFROM, pHwProfile->szFromFriendlyName);
  977. SetDlgItemText(hDlg, IDD_HWP_RENAMETO, pHwProfile->szFromFriendlyName);
  978. SendDlgItemMessage(hDlg, IDD_HWP_RENAMETO, EM_SETSEL, 0, -1);
  979. SetFocus(GetDlgItem(hDlg, IDD_HWP_RENAMETO));
  980. //
  981. // Remove any association the window may have with an input context,
  982. // because we don't allow to use DBCS in H/W profile name.
  983. //
  984. himcOrg = ImmAssociateContext(GetDlgItem(hDlg, IDD_HWP_RENAMETO), (HIMC)NULL);
  985. return FALSE;
  986. case WM_DESTROY:
  987. if (himcOrg)
  988. ImmAssociateContext(GetDlgItem(hDlg, IDD_HWP_RENAMETO), himcOrg);
  989. return FALSE;
  990. case WM_DEVICECHANGE:
  991. //
  992. // If a hardware profile change event takes place while the dialog is
  993. // up, just dismiss the dialog because things have changed.
  994. //
  995. if (wParam == DBT_CONFIGCHANGED) {
  996. EndDialog(hDlg, FALSE);
  997. return FALSE;
  998. }
  999. break;
  1000. case WM_HELP:
  1001. WinHelp((HWND)((LPHELPINFO)lParam)->hItemHandle, HELP_FILE,
  1002. HELP_WM_HELP, (DWORD_PTR)(LPTSTR)HwProfileHelpIds);
  1003. break;
  1004. case WM_CONTEXTMENU:
  1005. WinHelp((HWND)wParam, HELP_FILE, HELP_CONTEXTMENU,
  1006. (DWORD_PTR)(LPTSTR)HwProfileHelpIds);
  1007. break;
  1008. case WM_COMMAND:
  1009. {
  1010. switch (LOWORD(wParam))
  1011. {
  1012. case IDOK:
  1013. pHwProfile = (PHWPROFILE)GetWindowLongPtr(hDlg, DWLP_USER);
  1014. ulReturn = GetDlgItemText(hDlg, IDD_HWP_RENAMETO,
  1015. pHwProfile->szToFriendlyName, MAX_FRIENDLYNAME_LEN);
  1016. if (pHwProfile->szToFriendlyName == NULL ||
  1017. *pHwProfile->szToFriendlyName == '\0') {
  1018. //
  1019. // accept request to copy to zero-length string but
  1020. // do nothing (return FALSE from DialogBox call)
  1021. //
  1022. EndDialog(hDlg, FALSE);
  1023. return TRUE;
  1024. }
  1025. if (lstrcmpi(pHwProfile->szToFriendlyName,
  1026. pHwProfile->szFromFriendlyName) == 0) {
  1027. //
  1028. // accept request to rename to same name but do
  1029. // nothing (return FALSE from DialogBox call)
  1030. //
  1031. EndDialog(hDlg, FALSE);
  1032. return TRUE;
  1033. }
  1034. //
  1035. // Check for duplicates
  1036. //
  1037. if (IsProfileNameInUse(pHwProfile->hParent,
  1038. pHwProfile->szToFriendlyName)) {
  1039. //
  1040. // if name already used by a different profile, deny
  1041. // the request, but don't end the dialog box
  1042. //
  1043. DisplayPrivateMessage(hDlg, HWP_ERROR_PROFILE_IN_USE);
  1044. break;
  1045. }
  1046. //
  1047. // Check for complex script names
  1048. //
  1049. if (S_OK == ScriptIsComplex(pHwProfile->szToFriendlyName, lstrlen(pHwProfile->szToFriendlyName), SIC_COMPLEX))
  1050. {
  1051. DisplayPrivateMessage(hDlg, HWP_ERROR_COMPLEX_SCRIPT);
  1052. break;
  1053. }
  1054. //
  1055. // otherwise, we'll accept the name
  1056. //
  1057. EndDialog(hDlg,TRUE);
  1058. break;
  1059. case IDCANCEL:
  1060. EndDialog(hDlg,FALSE);
  1061. break;
  1062. default:
  1063. return FALSE;
  1064. }
  1065. break;
  1066. } // case WM_COMMAND...
  1067. default:
  1068. return FALSE;
  1069. break;
  1070. }
  1071. return TRUE;
  1072. } // RenameProfileDlg
  1073. /**-------------------------------------------------------------------------**/
  1074. BOOL
  1075. GetCurrentProfile(
  1076. PULONG pulProfile
  1077. )
  1078. {
  1079. WCHAR RegStr[MAX_PATH];
  1080. ULONG ulSize;
  1081. HKEY hKey;
  1082. //
  1083. // open the IDConfigDB key
  1084. //
  1085. if (RegOpenKeyEx(
  1086. HKEY_LOCAL_MACHINE, pszRegIDConfigDB, 0,
  1087. KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS) {
  1088. DisplaySystemMessage(NULL, ERROR_REGISTRY_CORRUPT);
  1089. return FALSE;
  1090. }
  1091. //
  1092. // retrieve the CurrentConfig value
  1093. //
  1094. ulSize = sizeof(ULONG);
  1095. if (RegQueryValueEx(
  1096. hKey, pszRegCurrentConfig, NULL, NULL,
  1097. (LPBYTE)pulProfile, &ulSize) != ERROR_SUCCESS) {
  1098. RegCloseKey(hKey);
  1099. DisplaySystemMessage(NULL, ERROR_REGISTRY_CORRUPT);
  1100. return FALSE;
  1101. }
  1102. RegCloseKey(hKey);
  1103. return TRUE;
  1104. } // GetCurrentProfile
  1105. /**-------------------------------------------------------------------------**/
  1106. BOOL
  1107. GetRegProfileCount(
  1108. PULONG pulProfiles
  1109. )
  1110. {
  1111. WCHAR RegStr[MAX_PATH];
  1112. HKEY hKey;
  1113. //
  1114. // open the Known Docking States key
  1115. //
  1116. wsprintf(RegStr, TEXT("%s\\%s"),
  1117. pszRegIDConfigDB,
  1118. pszRegKnownDockingStates);
  1119. if (RegOpenKeyEx(
  1120. HKEY_LOCAL_MACHINE, RegStr, 0, KEY_READ,
  1121. &hKey) != ERROR_SUCCESS) {
  1122. *pulProfiles = 0;
  1123. DisplaySystemMessage(NULL, ERROR_REGISTRY_CORRUPT);
  1124. return FALSE;
  1125. }
  1126. //
  1127. // find out the total number of profiles
  1128. //
  1129. if (RegQueryInfoKey(
  1130. hKey, NULL, NULL, NULL, pulProfiles, NULL, NULL, NULL,
  1131. NULL, NULL, NULL, NULL) != ERROR_SUCCESS) {
  1132. *pulProfiles = 0;
  1133. RegCloseKey(hKey);
  1134. DisplaySystemMessage(NULL, ERROR_REGISTRY_CORRUPT);
  1135. return FALSE;
  1136. }
  1137. ASSERT(*pulProfiles > 0); // The key for the pristine profile should be there, at least.
  1138. *pulProfiles-= 1; // Don't count the pristine in the number or working profiles.
  1139. RegCloseKey(hKey);
  1140. return TRUE;
  1141. } // GetRegProfileCount
  1142. /**-------------------------------------------------------------------------**/
  1143. BOOL
  1144. GetSelectedProfile(
  1145. HWND hCtl,
  1146. PULONG pulSelectedProfile
  1147. )
  1148. {
  1149. LONG lSelect;
  1150. // THIS ISN"T BEING CALLED RIGHT NOW, IF IT STARTS GETTING CALLED,
  1151. // THERE SHOULD BE LOGIC FOR REENABLING OR DISABLING THE DELETE
  1152. // BUTTON BASED ON WHETHER THE FIRST INDEX IS THE CURRENT PROFILE
  1153. // (ONLY APPLIES TO THE ERROR CASE WHERE THERE ARE NO CURRENT
  1154. // SELECTIONS)
  1155. lSelect = (LONG)SendMessage(hCtl, LB_GETCURSEL, 0, 0);
  1156. if (lSelect != LB_ERR) {
  1157. *pulSelectedProfile =
  1158. (ULONG)SendMessage(hCtl, LB_GETITEMDATA, lSelect, 0);
  1159. }
  1160. else {
  1161. //
  1162. // no selections, assume first one
  1163. //
  1164. SendMessage(hCtl, LB_SETCURSEL, 0, 0);
  1165. *pulSelectedProfile = (ULONG)SendMessage(hCtl, LB_GETITEMDATA, 0, 0);
  1166. }
  1167. return TRUE;
  1168. } // GetSelectedProfile
  1169. /**-------------------------------------------------------------------------**/
  1170. BOOL
  1171. FillProfileList(
  1172. HWND hDlg
  1173. )
  1174. {
  1175. HWND hList;
  1176. ULONG ulCurrentProfile, ulCurrentIndex;
  1177. ULONG ulIndex=0, ulSize=0;
  1178. ULONG enumIndex = 0, ulProfileID=0;
  1179. ULONG ulCurrentDockingState = 0;
  1180. ULONG ulDockID = 0, ulSerialNumber=0;
  1181. HKEY hKey = NULL, hCfgKey = NULL;
  1182. HKEY hCurrent = NULL;
  1183. WCHAR RegStr[MAX_PATH], szName[MAX_PATH];
  1184. ULONG RegStatus = ERROR_SUCCESS;
  1185. WCHAR szFriendlyName[MAX_FRIENDLYNAME_LEN];
  1186. WCHAR szProfile[MAX_PROFILEID_LEN];
  1187. PHWPROF_INFO pInfo;
  1188. LRESULT lReturn;
  1189. REGSAM sam;
  1190. //
  1191. // retrieve a handle to the listbox window
  1192. //
  1193. hList = GetDlgItem(hDlg, IDD_HWP_PROFILES);
  1194. //
  1195. // retrieve the id of the current profile
  1196. //
  1197. if (!GetCurrentProfile(&ulCurrentProfile)) {
  1198. DisplaySystemMessage(hDlg, ERROR_NOT_ENOUGH_MEMORY);
  1199. return FALSE;
  1200. }
  1201. //
  1202. // allocate a buffer for the main profile info struct
  1203. //
  1204. pInfo = (PHWPROF_INFO) LocalAlloc(LPTR, sizeof(HWPROF_INFO));
  1205. if (pInfo == NULL) {
  1206. DisplaySystemMessage(hDlg, ERROR_NOT_ENOUGH_MEMORY);
  1207. return FALSE;
  1208. }
  1209. //
  1210. // save the number of profiles currently in the registry
  1211. //
  1212. if (!GetRegProfileCount(&(pInfo->ulNumProfiles))) {
  1213. LocalFree((HLOCAL)pInfo);
  1214. return FALSE;
  1215. }
  1216. pInfo->ulActiveProfiles = pInfo->ulNumProfiles;
  1217. //
  1218. // Initialize the hardware detected portable flag
  1219. //
  1220. pInfo->bHwDetectedPortable = FALSE;
  1221. //
  1222. // allocate a buffer to hold all the profile values
  1223. //
  1224. pInfo->pHwProfValues = (PHWPROF_VALUES) LocalAlloc(LPTR, sizeof(HWPROF_VALUES) * pInfo->ulNumProfiles);
  1225. if (pInfo->pHwProfValues == NULL) {
  1226. LocalFree((HLOCAL)pInfo);
  1227. return FALSE;
  1228. }
  1229. SetWindowLongPtr(hDlg, DWLP_USER, (LPARAM)pInfo);
  1230. //
  1231. // clear the listbox and turn redraw off
  1232. //
  1233. SendMessage(hList, LB_RESETCONTENT, 0, 0);
  1234. SendMessage(hList, WM_SETREDRAW, (WPARAM)FALSE, 0);
  1235. //
  1236. // open the Hardware Profiles key
  1237. //
  1238. wsprintf(RegStr, TEXT("%s\\%s"),
  1239. pszRegIDConfigDB,
  1240. pszRegKnownDockingStates);
  1241. if (RegOpenKeyEx(
  1242. HKEY_LOCAL_MACHINE, RegStr, 0,
  1243. KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
  1244. &hKey) != ERROR_SUCCESS) {
  1245. DisplaySystemMessage(hDlg, ERROR_REGISTRY_CORRUPT);
  1246. LocalFree((HLOCAL)pInfo->pHwProfValues);
  1247. LocalFree((HLOCAL)pInfo);
  1248. return FALSE;
  1249. }
  1250. //
  1251. // read the values for the name generating counters
  1252. //
  1253. ulSize = sizeof(DWORD);
  1254. wsprintf(szName, pszRegUndocked);
  1255. if (RegQueryValueEx(hKey, szName, NULL, NULL,
  1256. (LPBYTE)&pInfo->ulUndockedProfileNameCount, &ulSize)) {
  1257. pInfo->ulUnknownProfileNameCount = 0;
  1258. }
  1259. wsprintf(szName, pszRegDocked);
  1260. if (RegQueryValueEx(hKey, szName, NULL, NULL,
  1261. (LPBYTE)&pInfo->ulDockedProfileNameCount, &ulSize)) {
  1262. pInfo->ulUnknownProfileNameCount = 0;
  1263. }
  1264. wsprintf(szName, pszRegUnknown);
  1265. if (RegQueryValueEx(hKey, szName, NULL, NULL,
  1266. (LPBYTE)&pInfo->ulUnknownProfileNameCount, &ulSize)) {
  1267. pInfo->ulUnknownProfileNameCount = 0;
  1268. }
  1269. //
  1270. // pad the list box with a blank entry for each profile
  1271. // (this facilitates adding the profiles in rank order
  1272. //
  1273. for (ulIndex = 0; ulIndex < pInfo->ulNumProfiles; ulIndex++) {
  1274. SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)(LPCTSTR)TEXT(" "));
  1275. }
  1276. //
  1277. // enumerate each of the existing hardware profiles
  1278. //
  1279. ulIndex = 0;
  1280. enumIndex = 0;
  1281. while (RegStatus != ERROR_NO_MORE_ITEMS) {
  1282. //
  1283. // enumerate the profile key
  1284. //
  1285. ulSize = MAX_PROFILEID_LEN;
  1286. RegStatus = RegEnumKeyEx(
  1287. hKey, enumIndex, szProfile, &ulSize, NULL, NULL, NULL, NULL);
  1288. if (RegStatus == ERROR_SUCCESS) {
  1289. //
  1290. // open the enumerated profile key
  1291. //
  1292. if (bAdmin) {
  1293. sam = KEY_QUERY_VALUE | KEY_SET_VALUE;
  1294. } else {
  1295. sam = KEY_QUERY_VALUE;
  1296. }
  1297. if (RegOpenKeyEx(
  1298. hKey, szProfile, 0, sam, &hCfgKey) != ERROR_SUCCESS) {
  1299. RegCloseKey(hKey);
  1300. LocalFree((HLOCAL)pInfo->pHwProfValues);
  1301. LocalFree((HLOCAL)pInfo);
  1302. if (bAdmin) {
  1303. DisplaySystemMessage(hDlg, ERROR_REGISTRY_CORRUPT);
  1304. return FALSE;
  1305. }
  1306. else {
  1307. return TRUE;
  1308. }
  1309. }
  1310. //
  1311. // if this is the Pristine profile, ignore it, and move on to the next.
  1312. //
  1313. ulProfileID = _wtoi(szProfile);
  1314. if (!ulProfileID) {
  1315. enumIndex++;
  1316. RegCloseKey(hCfgKey);
  1317. continue;
  1318. }
  1319. //----------------------------------------------------------
  1320. // retrieve the profile registry info, save in buffer
  1321. //----------------------------------------------------------
  1322. //
  1323. // aliasable
  1324. //
  1325. ulSize = sizeof(DWORD);
  1326. if (RegQueryValueEx(
  1327. hCfgKey, pszRegAliasable, NULL, NULL,
  1328. (LPBYTE)&pInfo->pHwProfValues[ulIndex].bAliasable,
  1329. &ulSize) != ERROR_SUCCESS) {
  1330. pInfo->pHwProfValues[ulIndex].bAliasable = TRUE;
  1331. }
  1332. //
  1333. // cloned
  1334. //
  1335. ulSize = sizeof(DWORD);
  1336. if (RegQueryValueEx(
  1337. hCfgKey, pszRegCloned, NULL, NULL,
  1338. (LPBYTE)&pInfo->pHwProfValues[ulIndex].bCloned,
  1339. &ulSize) != ERROR_SUCCESS) {
  1340. pInfo->pHwProfValues[ulIndex].bCloned = FALSE;
  1341. }
  1342. //
  1343. // friendly name
  1344. //
  1345. ulSize = MAX_FRIENDLYNAME_LEN * sizeof(TCHAR);
  1346. if (RegQueryValueEx(
  1347. hCfgKey, pszRegFriendlyName, NULL, NULL,
  1348. (LPBYTE)&pInfo->pHwProfValues[ulIndex].szFriendlyName,
  1349. &ulSize) != ERROR_SUCCESS) {
  1350. //
  1351. // if no FriendlyName then write out and use a default
  1352. // value name (for compatibility with Win95)
  1353. //
  1354. if (bAdmin) {
  1355. lstrcpy(pInfo->pHwProfValues[ulIndex].szFriendlyName,
  1356. pszRegDefaultFriendlyName);
  1357. RegSetValueEx(
  1358. hCfgKey, pszRegFriendlyName, 0, REG_SZ,
  1359. (LPBYTE)pszRegDefaultFriendlyName,
  1360. (lstrlen(pszRegDefaultFriendlyName)+1) * sizeof(TCHAR));
  1361. }
  1362. }
  1363. //
  1364. // preference order ranking
  1365. //
  1366. ulSize = sizeof(ULONG);
  1367. if (RegQueryValueEx(
  1368. hCfgKey, pszRegPreferenceOrder, NULL, NULL,
  1369. (LPBYTE)&pInfo->pHwProfValues[ulIndex].ulPreferenceOrder,
  1370. &ulSize) != ERROR_SUCCESS) {
  1371. // FEATURE - rerank all profiles if this happens
  1372. }
  1373. //
  1374. // dock state
  1375. //
  1376. ulSize = sizeof(ULONG);
  1377. if (RegQueryValueEx(
  1378. hCfgKey, pszRegDockState, NULL, NULL,
  1379. (LPBYTE)&pInfo->pHwProfValues[ulIndex].ulDockState,
  1380. &ulSize) != ERROR_SUCCESS) {
  1381. pInfo->pHwProfValues[ulIndex].ulDockState =
  1382. DOCKINFO_USER_SUPPLIED | DOCKINFO_DOCKED | DOCKINFO_UNDOCKED;
  1383. }
  1384. //
  1385. // portable computer flag - this is obsolete info, just save the current
  1386. // setting if it exists and then delete it (might need the original
  1387. // setting later)
  1388. //
  1389. ulSize = sizeof(ULONG);
  1390. if (RegQueryValueEx(
  1391. hCfgKey, pszRegIsPortable, NULL, NULL,
  1392. (LPBYTE)&pInfo->pHwProfValues[ulIndex].bPortable,
  1393. &ulSize) != ERROR_SUCCESS) {
  1394. pInfo->pHwProfValues[ulIndex].bPortable = FALSE;
  1395. }
  1396. RegDeleteValue(hCfgKey, pszRegIsPortable);
  1397. pInfo->pHwProfValues[ulIndex].ulProfile = _wtoi(szProfile);
  1398. pInfo->pHwProfValues[ulIndex].ulAction = HWP_NO_ACTION;
  1399. RegCloseKey(hCfgKey);
  1400. //
  1401. // If this is the current profile, open the CurrentDockInfo key
  1402. //
  1403. if (pInfo->pHwProfValues[ulIndex].ulProfile == ulCurrentProfile) {
  1404. wsprintf(RegStr, TEXT("%s\\%s"),
  1405. pszRegIDConfigDB,
  1406. pszRegCurrentDockInfo);
  1407. if (RegOpenKeyEx(
  1408. HKEY_LOCAL_MACHINE, RegStr, 0,
  1409. KEY_QUERY_VALUE, &hCurrent) != ERROR_SUCCESS) {
  1410. //
  1411. // Could not open the CurrentDockInfo key;
  1412. // Dock ID and Serial Number are unavailable
  1413. //
  1414. pInfo->pHwProfValues[ulIndex].szDockID[0] = TEXT('\0');
  1415. pInfo->pHwProfValues[ulIndex].szSerialNumber[0] = TEXT('\0');
  1416. } else {
  1417. //
  1418. // Retrieve the hardware-detected dock state for the current profile
  1419. //
  1420. ulSize = sizeof(DWORD);
  1421. if ((RegQueryValueEx(
  1422. hCurrent, pszRegDockingState, NULL, NULL,
  1423. (LPBYTE)&ulCurrentDockingState,
  1424. &ulSize) == ERROR_SUCCESS) &&
  1425. ulCurrentDockingState &&
  1426. !((ulCurrentDockingState & DOCKINFO_DOCKED) &&
  1427. (ulCurrentDockingState & DOCKINFO_UNDOCKED))) {
  1428. //
  1429. // if the hardware-detected dockstate is present and known,
  1430. // override the user-supplied dockstate
  1431. //
  1432. pInfo->bHwDetectedPortable = TRUE;
  1433. pInfo->pHwProfValues[ulIndex].ulDockState = ulCurrentDockingState;
  1434. } else {
  1435. //
  1436. // keep the user-supplied dockstate
  1437. //
  1438. pInfo->bHwDetectedPortable = FALSE;
  1439. ulCurrentDockingState = pInfo->pHwProfValues[ulIndex].ulDockState;
  1440. }
  1441. if ((ulCurrentDockingState & DOCKINFO_UNDOCKED) &&
  1442. !(ulCurrentDockingState & DOCKINFO_DOCKED) &&
  1443. !(ulCurrentDockingState & DOCKINFO_USER_SUPPLIED)) {
  1444. //
  1445. // The hardware has detected an undocked state; set the global IsPortable flag
  1446. //
  1447. pInfo->bPortable = TRUE;
  1448. } else if ((ulCurrentDockingState & DOCKINFO_DOCKED) &&
  1449. !(ulCurrentDockingState & DOCKINFO_UNDOCKED) &&
  1450. !(ulCurrentDockingState & DOCKINFO_USER_SUPPLIED)) {
  1451. //
  1452. // The hardware has detected a docked state; set the global IsPortable flag
  1453. //
  1454. pInfo->bPortable = TRUE;
  1455. //
  1456. // Serial Number and DockID are only valid for docked Profiles
  1457. //
  1458. //
  1459. // Retrieve the Serial Number for the current Profile.
  1460. //
  1461. // ("AcpiSerialNumber" is preferred because it is updated
  1462. // on Acpi dock events; "SerialNumber" is set only at boot
  1463. // time, from the BIOS, and may be inaccurate across Acpi
  1464. // dock transitions)
  1465. //
  1466. ulSize = MAX_SERIALNUM_LEN * sizeof(TCHAR);
  1467. if (RegQueryValueEx(
  1468. hCurrent, pszRegAcpiSerialNumber, NULL, NULL,
  1469. (LPBYTE)&pInfo->pHwProfValues[ulIndex].szSerialNumber,
  1470. &ulSize) != ERROR_SUCCESS) {
  1471. //
  1472. // No Acpi Serial Number, but we know the machine is
  1473. // docked (based on the DockState from the PnP BIOS
  1474. // info) so check for a PnP BIOS SerialNumber
  1475. //
  1476. ulSize = sizeof(DWORD);
  1477. if (RegQueryValueEx(
  1478. hCurrent, pszRegSerialNumber, NULL, NULL,
  1479. (LPBYTE)&ulSerialNumber,
  1480. &ulSize) != ERROR_SUCCESS) {
  1481. pInfo->pHwProfValues[ulIndex].szSerialNumber[0] = TEXT('\0');
  1482. } else {
  1483. wsprintf(pInfo->pHwProfValues[ulIndex].szSerialNumber,
  1484. L"%X",
  1485. (ULONG)ulSerialNumber);
  1486. }
  1487. }
  1488. //
  1489. // Retrieve the DockID for the current Profile, if available.
  1490. //
  1491. ulSize = sizeof(DWORD);
  1492. if (RegQueryValueEx(
  1493. hCurrent, pszRegDockID, NULL, NULL,
  1494. (LPBYTE)&ulDockID,
  1495. &ulSize) != ERROR_SUCCESS) {
  1496. pInfo->pHwProfValues[ulIndex].szDockID[0] = TEXT('\0');
  1497. } else {
  1498. wsprintf(pInfo->pHwProfValues[ulIndex].szDockID,
  1499. L"%X",
  1500. (ULONG)ulDockID);
  1501. }
  1502. }
  1503. }
  1504. } else {
  1505. //
  1506. // Serial Number and DockID are only valid for the current Profile
  1507. //
  1508. pInfo->pHwProfValues[ulIndex].szSerialNumber[0] = TEXT('\0');
  1509. pInfo->pHwProfValues[ulIndex].szDockID[0] = TEXT('\0');
  1510. }
  1511. //
  1512. // delete the blank string in this spot, add the friendly name
  1513. // (append current tag if necessary)
  1514. //
  1515. SendMessage(hList, LB_DELETESTRING,
  1516. pInfo->pHwProfValues[ulIndex].ulPreferenceOrder, 0);
  1517. AppendCurrentTag(
  1518. szName, // new fixed up name
  1519. pInfo->pHwProfValues[ulIndex].szFriendlyName,
  1520. pInfo->pHwProfValues[ulIndex].ulProfile,
  1521. ulCurrentProfile);
  1522. lReturn = SendMessage(hList, LB_INSERTSTRING,
  1523. pInfo->pHwProfValues[ulIndex].ulPreferenceOrder,
  1524. (LPARAM)(LPCTSTR)szName);
  1525. //
  1526. // store the profile id along with the entry so we
  1527. // can associate the string and the profile id later
  1528. //
  1529. SendMessage(hList, LB_SETITEMDATA,
  1530. (WPARAM)lReturn, pInfo->pHwProfValues[ulIndex].ulProfile);
  1531. //
  1532. // if this is the current profile, save the index
  1533. //
  1534. if (pInfo->pHwProfValues[ulIndex].ulProfile == ulCurrentProfile) {
  1535. ulCurrentIndex = pInfo->pHwProfValues[ulIndex].ulPreferenceOrder;
  1536. }
  1537. }
  1538. ulIndex++;
  1539. enumIndex++;
  1540. } // while
  1541. RegCloseKey(hKey);
  1542. //---------------------------------------------------------------------
  1543. // migrate portable information
  1544. //---------------------------------------------------------------------
  1545. if (bAdmin) {
  1546. sam = KEY_READ | KEY_WRITE;
  1547. } else {
  1548. sam = KEY_READ;
  1549. }
  1550. if (RegOpenKeyEx(
  1551. HKEY_LOCAL_MACHINE, pszRegIDConfigDB, 0,
  1552. sam, &hKey) == ERROR_SUCCESS) {
  1553. if (pInfo->bHwDetectedPortable) {
  1554. if (bAdmin) {
  1555. //
  1556. // Set the global IsPortable setting as identified by the Hardware
  1557. //
  1558. RegSetValueEx(hKey, pszRegIsPortable, 0, REG_DWORD,
  1559. (LPBYTE)&pInfo->bPortable, sizeof(DWORD));
  1560. }
  1561. } else {
  1562. //
  1563. // Is there a global IsPortable setting?
  1564. //
  1565. ulSize = sizeof(DWORD);
  1566. if (RegQueryValueEx(hKey, pszRegIsPortable, NULL, NULL,
  1567. (LPBYTE)&pInfo->bPortable, &ulSize) != ERROR_SUCCESS) {
  1568. //
  1569. // the global IsPortable flag isn't there, and the hardware did
  1570. // not detect this as being a portable machine, so by default, it
  1571. // is not.
  1572. //
  1573. pInfo->bPortable = FALSE;
  1574. }
  1575. }
  1576. RegCloseKey(hKey);
  1577. }
  1578. SendMessage(hList, WM_SETREDRAW, (WPARAM)TRUE, 0);
  1579. SendMessage(hList, LB_SETCURSEL, ulCurrentIndex, 0);
  1580. return TRUE;
  1581. } // FillProfileList
  1582. /**-------------------------------------------------------------------------**/
  1583. BOOL
  1584. IsProfileNameInUse(
  1585. HWND hDlg,
  1586. LPTSTR pszFriendlyName
  1587. )
  1588. {
  1589. ULONG ulBufferIndex=0;
  1590. PHWPROF_INFO pInfo=NULL;
  1591. //
  1592. // retrieve the profile buffer
  1593. //
  1594. pInfo = (PHWPROF_INFO)GetWindowLongPtr(hDlg, DWLP_USER);
  1595. //
  1596. // check each friendly name (that hasn't been deleted) for a
  1597. // match (case-insensitive)
  1598. //
  1599. while (ulBufferIndex < pInfo->ulNumProfiles) {
  1600. if (!(pInfo->pHwProfValues[ulBufferIndex].ulAction & HWP_DELETE)) {
  1601. if (lstrcmpi(pInfo->pHwProfValues[ulBufferIndex].szFriendlyName,
  1602. pszFriendlyName) == 0) {
  1603. return TRUE; // match, name is in use
  1604. }
  1605. }
  1606. ulBufferIndex++;
  1607. }
  1608. return FALSE; // no match found, name not in use
  1609. } // IsProfileNameInUse
  1610. /**-------------------------------------------------------------------------**/
  1611. VOID
  1612. UnicodeToUL(LPWSTR pString, PULONG pulValue)
  1613. {
  1614. ULONG i;
  1615. *pulValue = 0;
  1616. for (i = 0; i < 4; i++) {
  1617. *pulValue *= 10;
  1618. *pulValue += (pString[i] <= '9') ?
  1619. (pString[i] - '0') :
  1620. (pString[i]-'A'+10);
  1621. }
  1622. } // UnicodeToUL
  1623. /**-------------------------------------------------------------------------**/
  1624. BOOL
  1625. CopyHardwareProfile(
  1626. HWND hDlg,
  1627. ULONG_PTR ulIndex,
  1628. ULONG ulProfile,
  1629. LPTSTR szNewFriendlyName
  1630. )
  1631. {
  1632. HWND hList;
  1633. ULONG ulBufferIndex=0, ulNewBufferIndex=0;
  1634. ULONG ulNewProfile=0;
  1635. ULONG_PTR ulNewIndex=0;
  1636. PHWPROF_INFO pInfo=NULL;
  1637. HLOCAL hMem=NULL;
  1638. WCHAR szTemp[MAX_PATH];
  1639. HKEY hKey;
  1640. LONG RegStatus;
  1641. //
  1642. // retrieve the profile buffer
  1643. //
  1644. pInfo = (PHWPROF_INFO)GetWindowLongPtr(hDlg, DWLP_USER);
  1645. //
  1646. // retrieve a handle to the listbox window
  1647. //
  1648. hList = GetDlgItem(hDlg, IDD_HWP_PROFILES);
  1649. //
  1650. // find which entry in the buffer list matches this profile
  1651. //
  1652. while (ulBufferIndex < pInfo->ulNumProfiles) {
  1653. if (pInfo->pHwProfValues[ulBufferIndex].ulProfile == ulProfile) {
  1654. break;
  1655. }
  1656. ulBufferIndex++;
  1657. }
  1658. //
  1659. // reallocate the profile buffer to hold another entry
  1660. //
  1661. pInfo->ulActiveProfiles++;
  1662. pInfo->ulNumProfiles++;
  1663. LocalUnlock(LocalHandle(pInfo->pHwProfValues));
  1664. hMem = (PHWPROF_VALUES)LocalReAlloc(
  1665. LocalHandle(pInfo->pHwProfValues),
  1666. pInfo->ulNumProfiles * sizeof(HWPROF_VALUES),
  1667. LMEM_MOVEABLE | LMEM_ZEROINIT);
  1668. if (hMem == NULL) {
  1669. DisplaySystemMessage(hDlg, ERROR_NOT_ENOUGH_MEMORY);
  1670. return FALSE;
  1671. }
  1672. pInfo->pHwProfValues = (PHWPROF_VALUES)LocalLock(hMem);
  1673. ulNewBufferIndex = pInfo->ulNumProfiles-1;
  1674. //
  1675. // find a free profile id to use
  1676. //
  1677. if (!GetFreeProfileID(pInfo, &ulNewProfile)) {
  1678. return FALSE;
  1679. }
  1680. pInfo->pHwProfValues[ulNewBufferIndex].ulProfile = ulNewProfile;
  1681. //
  1682. // save the friendly name retrieved from the copy dialog box
  1683. //
  1684. lstrcpy(pInfo->pHwProfValues[ulNewBufferIndex].szFriendlyName,
  1685. szNewFriendlyName);
  1686. //
  1687. // assume it's the last in the preference order (zero-based)
  1688. //
  1689. pInfo->pHwProfValues[ulNewBufferIndex].ulPreferenceOrder =
  1690. pInfo->ulActiveProfiles - 1;
  1691. //
  1692. // copy the profile info from the selected profile to the new profile
  1693. //
  1694. pInfo->pHwProfValues[ulNewBufferIndex].ulDockState =
  1695. pInfo->pHwProfValues[ulBufferIndex].ulDockState;
  1696. //
  1697. // new hardware profiles are (by default) not aliasable, unless no alias can
  1698. // be copied for this profile.
  1699. //
  1700. pInfo->pHwProfValues[ulNewBufferIndex].bAliasable = FALSE;
  1701. //
  1702. // copied profiles are not clones of the pristine profile.
  1703. //
  1704. pInfo->pHwProfValues[ulNewBufferIndex].bCloned = FALSE;
  1705. //pInfo->pHwProfValues[ulNewBufferIndex].bPortable =
  1706. // pInfo->pHwProfValues[ulBufferIndex].bPortable;
  1707. lstrcpy(pInfo->pHwProfValues[ulNewBufferIndex].szDockID,
  1708. pInfo->pHwProfValues[ulBufferIndex].szDockID);
  1709. lstrcpy(pInfo->pHwProfValues[ulNewBufferIndex].szSerialNumber,
  1710. pInfo->pHwProfValues[ulBufferIndex].szSerialNumber);
  1711. //
  1712. // save the original profile id this was copied from
  1713. //
  1714. pInfo->pHwProfValues[ulNewBufferIndex].ulCreatedFrom =
  1715. GetOriginalProfile(pInfo, ulProfile, ulBufferIndex);
  1716. //
  1717. // increment the appropriate name-generating counter
  1718. // (note that the counter is NOT symmetrically decreased whenever a profile
  1719. // is deleted -- it increases over the lifetime of the system as new profiles
  1720. // are created; this prevents us from assigning names that incrementally less
  1721. // than names we have already assigned.)
  1722. //
  1723. AdjustProfileTypeCounter(pInfo,
  1724. pInfo->pHwProfValues[ulNewBufferIndex].ulDockState,
  1725. TRUE);
  1726. //
  1727. // set the new profile in the listbox (at the end)
  1728. //
  1729. ulNewIndex = SendMessage(hList, LB_ADDSTRING, 0,
  1730. (LPARAM)(LPTSTR)szNewFriendlyName);
  1731. SendMessage(hList, LB_SETITEMDATA,
  1732. (WPARAM)ulNewIndex,
  1733. pInfo->pHwProfValues[ulNewBufferIndex].ulProfile);
  1734. //
  1735. // select the new profile
  1736. //
  1737. SendMessage(hList, LB_SETCURSEL, ulNewIndex, 0);
  1738. //
  1739. // mark the change
  1740. //
  1741. pInfo->pHwProfValues[ulNewBufferIndex].ulAction |= HWP_CREATE;
  1742. //
  1743. // disable copy if we're now at the max number of profiles
  1744. //
  1745. if ((pInfo->ulNumProfiles+1) >= MAX_PROFILES) {
  1746. EnableWindow(GetDlgItem(hDlg, IDD_HWP_COPY), FALSE);
  1747. }
  1748. //
  1749. // reenable delete since by definition the selection is not on the
  1750. // current profile (whether it was before or not)
  1751. //
  1752. EnableWindow(GetDlgItem(hDlg, IDD_HWP_DELETE), TRUE);
  1753. return TRUE;
  1754. } // CopyHardwareProfile
  1755. /**-------------------------------------------------------------------------**/
  1756. BOOL
  1757. RenameHardwareProfile(
  1758. HWND hDlg,
  1759. ULONG_PTR ulIndex,
  1760. ULONG ulProfile,
  1761. LPTSTR szNewFriendlyName
  1762. )
  1763. {
  1764. HWND hList;
  1765. ULONG ulBufferIndex=0, ulCurrentProfile=0;
  1766. PHWPROF_INFO pInfo=NULL;
  1767. WCHAR szName[MAX_PATH];
  1768. //
  1769. // retrieve the profile buffer
  1770. //
  1771. pInfo = (PHWPROF_INFO)GetWindowLongPtr(hDlg, DWLP_USER);
  1772. //
  1773. // retrieve a handle to the listbox window
  1774. //
  1775. hList = GetDlgItem(hDlg, IDD_HWP_PROFILES);
  1776. //
  1777. // find the profile entry in the buffer that matches the selection
  1778. //
  1779. while (ulBufferIndex < pInfo->ulNumProfiles) {
  1780. if (pInfo->pHwProfValues[ulBufferIndex].ulProfile == ulProfile) {
  1781. break;
  1782. }
  1783. ulBufferIndex++;
  1784. }
  1785. //
  1786. // set the new friendly name in the listbox
  1787. //
  1788. GetCurrentProfile(&ulCurrentProfile);
  1789. AppendCurrentTag(szName, szNewFriendlyName, ulProfile, ulCurrentProfile);
  1790. SendMessage(hList, LB_DELETESTRING, ulIndex, 0);
  1791. SendMessage(hList, LB_INSERTSTRING, ulIndex, (LPARAM)(LPTSTR)szName);
  1792. SendMessage(hList, LB_SETITEMDATA, ulIndex,
  1793. pInfo->pHwProfValues[ulIndex].ulProfile);
  1794. //
  1795. // re-select the index (is this necessary?)
  1796. //
  1797. SendMessage(hList, LB_SETCURSEL, ulIndex, 0);
  1798. //
  1799. // mark the change
  1800. //
  1801. pInfo->pHwProfValues[ulBufferIndex].ulAction |= HWP_RENAME;
  1802. lstrcpy(pInfo->pHwProfValues[ulBufferIndex].szFriendlyName,
  1803. szNewFriendlyName);
  1804. return TRUE;
  1805. } // RenameHardwareProfile
  1806. /**-------------------------------------------------------------------------**/
  1807. BOOL
  1808. DeleteHardwareProfile(
  1809. HWND hDlg,
  1810. ULONG_PTR ulIndex
  1811. )
  1812. {
  1813. HWND hList;
  1814. ULONG ulBufferIndex=0, ulProfile=0, ulCurrentProfile=0;
  1815. PHWPROF_INFO pInfo=NULL;
  1816. //
  1817. // retrieve the profile buffer
  1818. //
  1819. pInfo = (PHWPROF_INFO)GetWindowLongPtr(hDlg, DWLP_USER);
  1820. //
  1821. // retrieve a handle to the listbox window
  1822. //
  1823. hList = GetDlgItem(hDlg, IDD_HWP_PROFILES);
  1824. //
  1825. // find the profile entry in the buffer that matches the selection
  1826. //
  1827. ulProfile = (ULONG)SendMessage(hList, LB_GETITEMDATA, ulIndex, 0);
  1828. while (ulBufferIndex < pInfo->ulNumProfiles) {
  1829. if (pInfo->pHwProfValues[ulBufferIndex].ulProfile == ulProfile) {
  1830. break;
  1831. }
  1832. ulBufferIndex++;
  1833. }
  1834. //
  1835. // readjust all the rankings to be consecutive
  1836. //
  1837. DeleteRank(pInfo, pInfo->pHwProfValues[ulBufferIndex].ulPreferenceOrder);
  1838. //
  1839. // decrement the count of active profiles
  1840. //
  1841. pInfo->ulActiveProfiles--;
  1842. //
  1843. // delete the friendly name in the listbox
  1844. //
  1845. SendMessage(hList, LB_DELETESTRING, ulIndex, 0);
  1846. //
  1847. // re-select the following index (same position)
  1848. //
  1849. if (ulIndex >= pInfo->ulActiveProfiles) {
  1850. ulIndex = pInfo->ulActiveProfiles-1;
  1851. }
  1852. SendMessage(hList, LB_SETCURSEL, ulIndex, 0);
  1853. //
  1854. // mark the change
  1855. //
  1856. pInfo->pHwProfValues[ulBufferIndex].ulAction |= HWP_DELETE;
  1857. //
  1858. // enable copy if less than max number of profiles
  1859. //
  1860. if (pInfo->ulNumProfiles < MAX_PROFILES) {
  1861. EnableWindow(GetDlgItem(hDlg, IDD_HWP_COPY), TRUE);
  1862. }
  1863. //
  1864. // find the profile entry in the buffer that matches the new selection
  1865. //
  1866. ulProfile = (ULONG)SendMessage(hList, LB_GETITEMDATA, ulIndex, 0);
  1867. ulBufferIndex = 0;
  1868. while (ulBufferIndex < pInfo->ulNumProfiles) {
  1869. if (pInfo->pHwProfValues[ulBufferIndex].ulProfile == ulProfile) {
  1870. break;
  1871. }
  1872. ulBufferIndex++;
  1873. }
  1874. GetCurrentProfile(&ulCurrentProfile);
  1875. //
  1876. // if the newly selected entry is the current profile, disable delete
  1877. //
  1878. if (pInfo->pHwProfValues[ulBufferIndex].ulProfile == ulCurrentProfile) {
  1879. EnableWindow(GetDlgItem(hDlg, IDD_HWP_DELETE), FALSE);
  1880. }
  1881. return TRUE;
  1882. } // DeleteHardwareProfiles
  1883. /**-------------------------------------------------------------------------**/
  1884. BOOL
  1885. GetUserWaitInterval(
  1886. PULONG pulWait
  1887. )
  1888. {
  1889. ULONG ulSize;
  1890. HKEY hKey;
  1891. //
  1892. // open the IDConfigDB key
  1893. //
  1894. if(RegOpenKeyEx(
  1895. HKEY_LOCAL_MACHINE, pszRegIDConfigDB, 0,
  1896. KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS) {
  1897. DisplaySystemMessage(NULL, ERROR_REGISTRY_CORRUPT);
  1898. return FALSE;
  1899. }
  1900. //
  1901. // retrieve the UserWaitInterval value
  1902. //
  1903. ulSize = sizeof(ULONG);
  1904. if (RegQueryValueEx(
  1905. hKey, pszRegUserWaitInterval, NULL, NULL,
  1906. (LPBYTE)pulWait, &ulSize) != ERROR_SUCCESS) {
  1907. *pulWait = DEFAULT_USER_WAIT;
  1908. }
  1909. RegCloseKey(hKey);
  1910. return TRUE;
  1911. } // GetUserWaitInterval
  1912. /**-------------------------------------------------------------------------**/
  1913. BOOL
  1914. SetUserWaitInterval(
  1915. ULONG ulWait
  1916. )
  1917. {
  1918. HKEY hKey;
  1919. if (bAdmin) {
  1920. //
  1921. // open the IDConfigDB key
  1922. //
  1923. if(RegOpenKeyEx(
  1924. HKEY_LOCAL_MACHINE, pszRegIDConfigDB, 0,
  1925. KEY_SET_VALUE, &hKey) != ERROR_SUCCESS) {
  1926. DisplaySystemMessage(NULL, ERROR_REGISTRY_CORRUPT);
  1927. return FALSE;
  1928. }
  1929. //
  1930. // set the UserWaitInterval value
  1931. //
  1932. if (RegSetValueEx(
  1933. hKey, pszRegUserWaitInterval, 0, REG_DWORD,
  1934. (LPBYTE)&ulWait, sizeof(ULONG)) != ERROR_SUCCESS) {
  1935. RegCloseKey(hKey);
  1936. return FALSE;
  1937. }
  1938. RegCloseKey(hKey);
  1939. }
  1940. return TRUE;
  1941. } // SetUserWaitInterval
  1942. /**-------------------------------------------------------------------------**/
  1943. BOOL
  1944. GetFreeProfileID(
  1945. PHWPROF_INFO pInfo,
  1946. PULONG pulProfile
  1947. )
  1948. {
  1949. ULONG ulProfileID = 0, ulBufferIndex = 0;
  1950. BOOL bHit;
  1951. //
  1952. // find a profile id that isn't used
  1953. //
  1954. while (ulProfileID < MAX_PROFILES) {
  1955. ulBufferIndex = 0;
  1956. bHit = FALSE;
  1957. while (ulBufferIndex < pInfo->ulNumProfiles) {
  1958. if (ulProfileID == pInfo->pHwProfValues[ulBufferIndex].ulProfile) {
  1959. bHit = TRUE;
  1960. break;
  1961. }
  1962. ulBufferIndex++;
  1963. }
  1964. //
  1965. // if I got all the way through the list without a hit, then this
  1966. // profile id is free
  1967. //
  1968. if (!bHit) {
  1969. *pulProfile = ulProfileID;
  1970. return TRUE;
  1971. }
  1972. ulProfileID++;
  1973. }
  1974. *pulProfile = 0xFFFFFFFF;
  1975. return FALSE;
  1976. } // GetFreeProfileID
  1977. /**-------------------------------------------------------------------------**/
  1978. ULONG
  1979. GetOriginalProfile(
  1980. PHWPROF_INFO pInfo,
  1981. ULONG ulProfile,
  1982. ULONG ulBufferIndex
  1983. )
  1984. {
  1985. ULONG ulIndex, ulIndexCreatedFrom;
  1986. //
  1987. // if the specified profile is a newly created profile, then it is
  1988. // by definition the first in the copy chain
  1989. //
  1990. if (!(pInfo->pHwProfValues[ulBufferIndex].ulAction & HWP_CREATE)) {
  1991. return ulProfile;
  1992. }
  1993. ulIndex = ulBufferIndex;
  1994. while (pInfo->pHwProfValues[ulIndex].ulAction & HWP_CREATE) {
  1995. //
  1996. // find which entry in the buffer list matches the "CopiedFrom" profile
  1997. //
  1998. ulIndexCreatedFrom = 0;
  1999. while (ulIndexCreatedFrom < pInfo->ulNumProfiles) {
  2000. if (pInfo->pHwProfValues[ulIndexCreatedFrom].ulProfile ==
  2001. pInfo->pHwProfValues[ulIndex].ulCreatedFrom) {
  2002. break;
  2003. }
  2004. ulIndexCreatedFrom++;
  2005. }
  2006. ulIndex = ulIndexCreatedFrom;
  2007. }
  2008. return pInfo->pHwProfValues[ulIndex].ulProfile;
  2009. } // GetOriginalProfile
  2010. /**-------------------------------------------------------------------------**/
  2011. BOOL
  2012. InsertRank(
  2013. PHWPROF_INFO pInfo,
  2014. ULONG ulRank
  2015. )
  2016. {
  2017. ULONG ulIndex;
  2018. //
  2019. // for inserting a rank and readjusting the other ranks, just
  2020. // scan through the list and for any rank that is greater than
  2021. // or equal to the inserted rank, increment the rank value
  2022. //
  2023. for (ulIndex = 0; ulIndex < pInfo->ulNumProfiles; ulIndex++) {
  2024. //
  2025. // if it's marked for delete, don't bother with it
  2026. //
  2027. if (!(pInfo->pHwProfValues[ulIndex].ulAction & HWP_DELETE)) {
  2028. if (pInfo->pHwProfValues[ulIndex].ulPreferenceOrder >= ulRank) {
  2029. pInfo->pHwProfValues[ulIndex].ulPreferenceOrder++;
  2030. pInfo->pHwProfValues[ulIndex].ulAction |= HWP_REORDER;
  2031. }
  2032. }
  2033. }
  2034. return TRUE;
  2035. } // InsertRank
  2036. /**-------------------------------------------------------------------------**/
  2037. BOOL
  2038. DeleteRank(
  2039. PHWPROF_INFO pInfo,
  2040. ULONG ulRank
  2041. )
  2042. {
  2043. ULONG ulIndex;
  2044. //
  2045. // for deleting a rank and readjusting the other ranks, just
  2046. // scan through the list and for any rank that is greater than
  2047. // the deleted rank, subtract one from the rank value
  2048. //
  2049. for (ulIndex = 0; ulIndex < pInfo->ulNumProfiles; ulIndex++) {
  2050. //
  2051. // if it's marked for delete, don't bother with it
  2052. //
  2053. if (!(pInfo->pHwProfValues[ulIndex].ulAction & HWP_DELETE)) {
  2054. if (pInfo->pHwProfValues[ulIndex].ulPreferenceOrder > ulRank) {
  2055. pInfo->pHwProfValues[ulIndex].ulPreferenceOrder--;
  2056. pInfo->pHwProfValues[ulIndex].ulAction |= HWP_REORDER;
  2057. }
  2058. }
  2059. }
  2060. return TRUE;
  2061. } // DeleteRank
  2062. /**-------------------------------------------------------------------------**/
  2063. BOOL
  2064. FlushProfileChanges(
  2065. HWND hDlg,
  2066. HWND hList
  2067. )
  2068. {
  2069. ULONG ulIndex=0;
  2070. HKEY hKey = NULL, hDestKey = NULL, hSrcKey = NULL, hHwProf = NULL;
  2071. WCHAR RegStr[MAX_PATH];
  2072. PHWPROF_INFO pInfo=NULL;
  2073. //
  2074. // retrieve the profile buffer
  2075. //
  2076. pInfo = (PHWPROF_INFO)GetWindowLongPtr(hDlg, DWLP_USER);
  2077. //
  2078. // First pass, process the changes for each profile (except delete)
  2079. //
  2080. while (ulIndex < pInfo->ulNumProfiles) {
  2081. //
  2082. // were any changes made to this profile?
  2083. //
  2084. if (pInfo->pHwProfValues[ulIndex].ulAction == HWP_NO_ACTION) {
  2085. goto NextProfile;
  2086. }
  2087. //
  2088. // save deleting for the second pass
  2089. //
  2090. if (pInfo->pHwProfValues[ulIndex].ulAction & HWP_DELETE) {
  2091. goto NextProfile;
  2092. }
  2093. //
  2094. // commit the changes for this profile
  2095. //
  2096. WriteProfileInfo(&pInfo->pHwProfValues[ulIndex]);
  2097. NextProfile:
  2098. ulIndex++;
  2099. }
  2100. //
  2101. // Second pass, process the delete requests
  2102. //
  2103. ulIndex = 0;
  2104. while (ulIndex < pInfo->ulNumProfiles) {
  2105. if (pInfo->pHwProfValues[ulIndex].ulAction & HWP_DELETE) {
  2106. //
  2107. // we only need to delete the key if it exists (if this
  2108. // isn't a delete of a profile that was also just created)
  2109. //
  2110. if (!(pInfo->pHwProfValues[ulIndex].ulAction & HWP_CREATE)) {
  2111. wsprintf(RegStr, TEXT("%s\\%s"),
  2112. pszRegIDConfigDB,
  2113. pszRegKnownDockingStates);
  2114. if (RegOpenKeyEx(
  2115. HKEY_LOCAL_MACHINE, RegStr, 0, KEY_ALL_ACCESS,
  2116. &hKey) != ERROR_SUCCESS) {
  2117. DisplaySystemMessage(hDlg, ERROR_REGISTRY_CORRUPT);
  2118. return FALSE;
  2119. }
  2120. wsprintf(RegStr, TEXT("%04u"),
  2121. pInfo->pHwProfValues[ulIndex].ulProfile);
  2122. RegDeleteKey(hKey, RegStr);
  2123. RegCloseKey(hKey);
  2124. //
  2125. // also delete the profile specific enum tree
  2126. //
  2127. DeleteProfileDependentTree(pInfo->pHwProfValues[ulIndex].ulProfile);
  2128. //
  2129. // also delete the aliases to this profile
  2130. //
  2131. DeleteAliasEntries(pInfo->pHwProfValues[ulIndex].ulProfile);
  2132. } else {
  2133. //
  2134. // decrement the name-generating counter for profiles we are
  2135. // deleting that we created this session (only if registry keys
  2136. // were never created for this new profile)
  2137. //
  2138. AdjustProfileTypeCounter(pInfo,
  2139. pInfo->pHwProfValues[ulIndex].ulDockState,
  2140. FALSE);
  2141. }
  2142. }
  2143. ulIndex++;
  2144. }
  2145. //
  2146. // commit global settings
  2147. //
  2148. if(RegOpenKeyEx(
  2149. HKEY_LOCAL_MACHINE, pszRegIDConfigDB, 0,
  2150. KEY_SET_VALUE, &hKey) == ERROR_SUCCESS) {
  2151. RegSetValueEx(hKey, pszRegIsPortable, 0, REG_DWORD,
  2152. (LPBYTE)&pInfo->bPortable, sizeof(DWORD));
  2153. if (RegOpenKeyEx(
  2154. hKey, pszRegKnownDockingStates, 0,
  2155. KEY_SET_VALUE, &hHwProf) == ERROR_SUCCESS) {
  2156. if (pInfo->ulUndockedProfileNameCount > 0) {
  2157. RegSetValueEx(hHwProf, pszRegUndocked, 0, REG_DWORD,
  2158. (LPBYTE)&pInfo->ulUndockedProfileNameCount, sizeof(ULONG));
  2159. } else {
  2160. RegDeleteValue(hHwProf, pszRegUndocked);
  2161. }
  2162. if (pInfo->ulDockedProfileNameCount > 0) {
  2163. RegSetValueEx(hHwProf, pszRegDocked, 0, REG_DWORD,
  2164. (LPBYTE)&pInfo->ulDockedProfileNameCount, sizeof(ULONG));
  2165. } else {
  2166. RegDeleteValue(hHwProf, pszRegDocked);
  2167. }
  2168. if (pInfo->ulUnknownProfileNameCount > 0) {
  2169. RegSetValueEx(hHwProf, pszRegUnknown, 0, REG_DWORD,
  2170. (LPBYTE)&pInfo->ulUnknownProfileNameCount, sizeof(ULONG));
  2171. } else {
  2172. RegDeleteValue(hHwProf, pszRegUnknown);
  2173. }
  2174. RegCloseKey(hHwProf);
  2175. }
  2176. RegCloseKey(hKey);
  2177. }
  2178. return TRUE;
  2179. } // FlushProfileChanges
  2180. /**-------------------------------------------------------------------------**/
  2181. BOOL
  2182. WriteProfileInfo(
  2183. PHWPROF_VALUES pProfValues
  2184. )
  2185. {
  2186. HKEY hKey = NULL, hDestKey = NULL, hSrcKey = NULL;
  2187. WCHAR RegStr[MAX_PATH];
  2188. UUID NewGuid;
  2189. LPTSTR UuidString;
  2190. TCHAR szGuid[MAX_GUID_STRING_LEN];
  2191. if (pProfValues->ulAction & HWP_DELETE) {
  2192. return TRUE; // skip it
  2193. }
  2194. //
  2195. // form the registry key string
  2196. //
  2197. wsprintf(RegStr, TEXT("%s\\%s\\%04u"),
  2198. pszRegIDConfigDB,
  2199. pszRegKnownDockingStates,
  2200. pProfValues->ulProfile);
  2201. //
  2202. // create the profile key if it's a new profile. Don't
  2203. // worry about security because the profile subkey always
  2204. // inherits the security of the parent Hardware Profiles key.
  2205. //
  2206. if (pProfValues->ulAction & HWP_CREATE) {
  2207. if (RegCreateKeyEx(
  2208. HKEY_LOCAL_MACHINE, RegStr, 0, NULL,
  2209. REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
  2210. NULL, &hKey, NULL) != ERROR_SUCCESS) {
  2211. return FALSE;
  2212. }
  2213. //
  2214. // create a HwProfileGuid if its a new profile
  2215. //
  2216. if ((UuidCreate(&NewGuid) == RPC_S_OK) &&
  2217. (UuidToString(&NewGuid, &UuidString) == RPC_S_OK)) {
  2218. //
  2219. // put curly braces around the guid
  2220. //
  2221. lstrcpy(szGuid, TEXT("{"));
  2222. lstrcat(szGuid, UuidString);
  2223. lstrcat(szGuid, TEXT("}"));
  2224. RpcStringFree(&UuidString);
  2225. //
  2226. // save the new HwProfileGuid in the registry
  2227. //
  2228. RegSetValueEx(
  2229. hKey, pszRegHwProfileGuid, 0, REG_SZ,
  2230. (LPBYTE)szGuid,
  2231. (lstrlen(szGuid)+1) * sizeof(TCHAR) );
  2232. }
  2233. } else {
  2234. //
  2235. // if not a create, just open the existing key
  2236. //
  2237. if (RegOpenKeyEx(
  2238. HKEY_LOCAL_MACHINE, RegStr, 0, KEY_SET_VALUE,
  2239. &hKey) != ERROR_SUCCESS) {
  2240. return FALSE;
  2241. }
  2242. }
  2243. //
  2244. // update preference order if modified
  2245. //
  2246. if ((pProfValues->ulAction & HWP_REORDER) ||
  2247. (pProfValues->ulAction & HWP_CREATE)) {
  2248. RegSetValueEx(
  2249. hKey, pszRegPreferenceOrder, 0, REG_DWORD,
  2250. (LPBYTE)&pProfValues->ulPreferenceOrder, sizeof(ULONG));
  2251. pProfValues->ulAction &= ~HWP_REORDER; // clear action
  2252. }
  2253. //
  2254. // update friendly name if modified
  2255. //
  2256. if ((pProfValues->ulAction & HWP_RENAME) ||
  2257. (pProfValues->ulAction & HWP_CREATE)) {
  2258. RegSetValueEx(
  2259. hKey, pszRegFriendlyName, 0, REG_SZ,
  2260. (LPBYTE)pProfValues->szFriendlyName,
  2261. (lstrlen(pProfValues->szFriendlyName)+1) * sizeof(TCHAR));
  2262. pProfValues->ulAction &= ~HWP_RENAME; // clear action
  2263. }
  2264. //
  2265. // update property values if modified
  2266. //
  2267. if ((pProfValues->ulAction & HWP_PROPERTIES) ||
  2268. (pProfValues->ulAction & HWP_CREATE)) {
  2269. RegSetValueEx(
  2270. hKey, pszRegDockState, 0, REG_DWORD,
  2271. (LPBYTE)&pProfValues->ulDockState, sizeof(ULONG));
  2272. RegSetValueEx(
  2273. hKey, pszRegAliasable, 0, REG_DWORD,
  2274. (LPBYTE)&pProfValues->bAliasable, sizeof(DWORD));
  2275. pProfValues->ulAction &= ~HWP_PROPERTIES; // clear action
  2276. }
  2277. if (pProfValues->ulAction & HWP_CREATE) {
  2278. //
  2279. // copy the profile enum info. Don't worry about security on
  2280. // this createkey because the profile key always inherits the
  2281. // security of the parent Hardware Profiles key.
  2282. //
  2283. wsprintf(RegStr, TEXT("%s\\%04u"),
  2284. pszRegHwProfiles,
  2285. pProfValues->ulProfile);
  2286. RegCreateKeyEx(
  2287. HKEY_LOCAL_MACHINE, RegStr, 0, NULL, REG_OPTION_NON_VOLATILE,
  2288. KEY_ALL_ACCESS, NULL, &hDestKey, NULL);
  2289. wsprintf(RegStr, TEXT("%s\\%04u"),
  2290. pszRegHwProfiles,
  2291. pProfValues->ulCreatedFrom);
  2292. RegOpenKeyEx(
  2293. HKEY_LOCAL_MACHINE, RegStr, 0, KEY_ALL_ACCESS, &hSrcKey);
  2294. CopyRegistryNode(hSrcKey, hDestKey);
  2295. //
  2296. // copy all aliases for the source profile to the destination as well.
  2297. //
  2298. if (CopyAliasEntries(pProfValues->ulCreatedFrom,
  2299. pProfValues->ulProfile) == FALSE) {
  2300. //
  2301. // We didn't actually copy any aliases, so make sure this profile gets
  2302. // marked as "Aliasable" so that it shows up as a profile option at
  2303. // boot time.
  2304. //
  2305. pProfValues->bAliasable = TRUE;
  2306. RegSetValueEx(
  2307. hKey, pszRegAliasable, 0, REG_DWORD,
  2308. (LPBYTE)&pProfValues->bAliasable, sizeof(DWORD));
  2309. }
  2310. if (hDestKey != NULL) RegCloseKey(hDestKey);
  2311. if (hSrcKey != NULL) RegCloseKey(hSrcKey);
  2312. pProfValues->ulAction &= ~HWP_CREATE; // clear action
  2313. pProfValues->ulAction |= HWP_NEWPROFILE; // created during this session
  2314. }
  2315. RegCloseKey(hKey);
  2316. return TRUE;
  2317. } // WriteProfileInfo
  2318. /**-------------------------------------------------------------------------**/
  2319. BOOL
  2320. RemoveNewProfiles(
  2321. PHWPROF_INFO pInfo
  2322. )
  2323. {
  2324. ULONG ulIndex=0;
  2325. HKEY hKey = NULL;
  2326. WCHAR RegStr[MAX_PATH];
  2327. //
  2328. // check each profile for any HWP_NEWPROFILE flags
  2329. //
  2330. while (ulIndex < pInfo->ulNumProfiles) {
  2331. if (pInfo->pHwProfValues[ulIndex].ulAction & HWP_NEWPROFILE) {
  2332. wsprintf(RegStr, TEXT("%s\\%s"),
  2333. pszRegIDConfigDB,
  2334. pszRegKnownDockingStates);
  2335. if (RegOpenKeyEx(
  2336. HKEY_LOCAL_MACHINE, RegStr, 0, KEY_ALL_ACCESS,
  2337. &hKey) == ERROR_SUCCESS) {
  2338. wsprintf(RegStr, TEXT("%04u"),
  2339. pInfo->pHwProfValues[ulIndex].ulProfile);
  2340. RegDeleteKey(hKey, RegStr);
  2341. RegCloseKey(hKey);
  2342. }
  2343. //
  2344. // also delete the profile specific enum tree
  2345. //
  2346. DeleteProfileDependentTree(pInfo->pHwProfValues[ulIndex].ulProfile);
  2347. //
  2348. // also delete aliases to this profile
  2349. //
  2350. DeleteAliasEntries(pInfo->pHwProfValues[ulIndex].ulProfile);
  2351. //
  2352. // decrement the appropriate name-generating counter
  2353. // (note that the counter is only deleted for new profiles that are
  2354. // never fully commited; we don't make an attempt to decerement the
  2355. // counter when any profile is deleted, else we may get into a case
  2356. // where we assign a name to a new profile that in incrementally less
  2357. // than a name we had previously assigned.)
  2358. //
  2359. AdjustProfileTypeCounter(pInfo,
  2360. pInfo->pHwProfValues[ulIndex].ulDockState,
  2361. FALSE);
  2362. }
  2363. ulIndex++;
  2364. }
  2365. return TRUE;
  2366. } // RemoveNewProfiles
  2367. /**-------------------------------------------------------------------------**/
  2368. BOOL
  2369. SwapPreferenceOrder(
  2370. HWND hDlg,
  2371. HWND hList,
  2372. ULONG_PTR ulIndex1,
  2373. ULONG_PTR ulIndex2
  2374. )
  2375. {
  2376. ULONG ulProfile1=0, ulProfile2=0;
  2377. ULONG ulBufferIndex1=0, ulBufferIndex2=0;
  2378. WCHAR szFriendlyName1[MAX_FRIENDLYNAME_LEN];
  2379. WCHAR szFriendlyName2[MAX_FRIENDLYNAME_LEN];
  2380. ULONG ulTemp=0;
  2381. PHWPROF_INFO pInfo=NULL;
  2382. //
  2383. // retrieve the profile buffer
  2384. //
  2385. pInfo = (PHWPROF_INFO)GetWindowLongPtr(hDlg, DWLP_USER);
  2386. //
  2387. // retrieve the profile id for the two selected profile entries
  2388. //
  2389. ulProfile1 = (ULONG)SendMessage(hList, LB_GETITEMDATA, ulIndex1, 0);
  2390. ulProfile2 = (ULONG)SendMessage(hList, LB_GETITEMDATA, ulIndex2, 0);
  2391. //
  2392. // find the profile entry in the buffer that matches these selections
  2393. //
  2394. while (ulBufferIndex1 < pInfo->ulNumProfiles) {
  2395. if (pInfo->pHwProfValues[ulBufferIndex1].ulProfile == ulProfile1) {
  2396. break;
  2397. }
  2398. ulBufferIndex1++;
  2399. }
  2400. while (ulBufferIndex2 < pInfo->ulNumProfiles) {
  2401. if (pInfo->pHwProfValues[ulBufferIndex2].ulProfile == ulProfile2) {
  2402. break;
  2403. }
  2404. ulBufferIndex2++;
  2405. }
  2406. //
  2407. // swap the order values of the profiles in the in-memory buffer
  2408. //
  2409. ulTemp = pInfo->pHwProfValues[ulBufferIndex1].ulPreferenceOrder;
  2410. pInfo->pHwProfValues[ulBufferIndex1].ulPreferenceOrder =
  2411. pInfo->pHwProfValues[ulBufferIndex2].ulPreferenceOrder;
  2412. pInfo->pHwProfValues[ulBufferIndex2].ulPreferenceOrder = ulTemp;
  2413. //
  2414. // mark both profiles as having been reordered
  2415. //
  2416. pInfo->pHwProfValues[ulBufferIndex1].ulAction |= HWP_REORDER;
  2417. pInfo->pHwProfValues[ulBufferIndex2].ulAction |= HWP_REORDER;
  2418. //
  2419. // swap the positions in the list box
  2420. //
  2421. SendMessage(hList, LB_GETTEXT, ulIndex1, (LPARAM)(LPTSTR)szFriendlyName1);
  2422. SendMessage(hList, LB_GETTEXT, ulIndex2, (LPARAM)(LPTSTR)szFriendlyName2);
  2423. SendMessage(hList, LB_DELETESTRING, ulIndex1, 0);
  2424. SendMessage(hList, LB_INSERTSTRING, ulIndex1,
  2425. (LPARAM)(LPTSTR)szFriendlyName2);
  2426. SendMessage(hList, LB_DELETESTRING, ulIndex2, 0);
  2427. SendMessage(hList, LB_INSERTSTRING, ulIndex2,
  2428. (LPARAM)(LPTSTR)szFriendlyName1);
  2429. SendMessage(hList, LB_SETITEMDATA, ulIndex1, ulProfile2);
  2430. SendMessage(hList, LB_SETITEMDATA, ulIndex2, ulProfile1);
  2431. //
  2432. // finally, select the second index (the second index is the rank
  2433. // position we're moving to)
  2434. //
  2435. SendMessage(hList, LB_SETCURSEL, ulIndex2, 0);
  2436. return TRUE;
  2437. } // SwapPreferenceOrder
  2438. /**-------------------------------------------------------------------------**/
  2439. BOOL
  2440. DeleteProfileDependentTree(
  2441. ULONG ulProfile
  2442. )
  2443. {
  2444. TCHAR szProfile[5], szKey[MAX_PATH];
  2445. LONG RegStatus = ERROR_SUCCESS;
  2446. HKEY hHwProfKey, hCfgKey;
  2447. ULONG ulIndex = 0, ulSize = 0;
  2448. //
  2449. // form the registry key string
  2450. //
  2451. if (RegOpenKeyEx(
  2452. HKEY_LOCAL_MACHINE, pszRegHwProfiles, 0, KEY_ALL_ACCESS,
  2453. &hHwProfKey) != ERROR_SUCCESS) {
  2454. DisplaySystemMessage(NULL, ERROR_REGISTRY_CORRUPT);
  2455. return FALSE;
  2456. }
  2457. wsprintf(szProfile, TEXT("%04u"),
  2458. ulProfile);
  2459. DeleteRegistryNode(hHwProfKey, szProfile);
  2460. RegCloseKey(hHwProfKey);
  2461. return TRUE;
  2462. } // DeleteProfileDependentTree
  2463. /**-------------------------------------------------------------------------**/
  2464. BOOL
  2465. CopyAliasEntries(
  2466. ULONG ulSrcProfile,
  2467. ULONG ulDestProfile
  2468. )
  2469. {
  2470. BOOL bNewAliasCreated = FALSE;
  2471. bNewAliasCreated |= CopyAliasEntryType(ulSrcProfile, ulDestProfile, pszRegAlias);
  2472. bNewAliasCreated |= CopyAliasEntryType(ulSrcProfile, ulDestProfile, pszRegAcpiAlias);
  2473. return bNewAliasCreated;
  2474. } // CopyAliasEntries
  2475. /**-------------------------------------------------------------------------**/
  2476. BOOL
  2477. DeleteAliasEntries(
  2478. ULONG ulProfile
  2479. )
  2480. {
  2481. BOOL bResult = TRUE;
  2482. bResult |= DeleteAliasEntryType(ulProfile, pszRegAlias);
  2483. bResult |= DeleteAliasEntryType(ulProfile, pszRegAcpiAlias);
  2484. return bResult;
  2485. } // CopyAliasEntries
  2486. /**-------------------------------------------------------------------------**/
  2487. BOOL
  2488. CopyAliasEntryType(
  2489. ULONG ulSrcProfile,
  2490. ULONG ulDestProfile,
  2491. LPWSTR szSubKeyName
  2492. )
  2493. {
  2494. LONG RegStatus = ERROR_SUCCESS;
  2495. HKEY hAliasRoot, hSrcKey, hDestKey;
  2496. WCHAR RegStr[MAX_PATH];
  2497. WCHAR szString[MAX_PATH];
  2498. ULONG ulAliasProfileNumber, ulNewAlias, ulSize, i;
  2499. BOOL bNewAliasCreated=FALSE;
  2500. //
  2501. // check all aliases under the "Alias" key
  2502. //
  2503. wsprintf(RegStr, TEXT("%s\\%s"),
  2504. pszRegIDConfigDB,
  2505. szSubKeyName);
  2506. RegStatus = RegOpenKeyEx(
  2507. HKEY_LOCAL_MACHINE, RegStr, 0, KEY_ALL_ACCESS,
  2508. &hAliasRoot);
  2509. if (RegStatus == ERROR_FILE_NOT_FOUND) {
  2510. //
  2511. // No Alias subkey, this could be ok if we have the other type.
  2512. //
  2513. RegStatus = ERROR_SUCCESS;
  2514. return bNewAliasCreated;
  2515. } else if (RegStatus != ERROR_SUCCESS) {
  2516. //
  2517. // Some other registry error occurred.
  2518. //
  2519. DisplaySystemMessage(NULL, ERROR_REGISTRY_CORRUPT);
  2520. return FALSE;
  2521. } else {
  2522. //
  2523. // enumerate all Alias subkeys
  2524. //
  2525. for (i=0; RegStatus == ERROR_SUCCESS; i++) {
  2526. ulSize = MAX_PATH;
  2527. RegStatus = RegEnumKey(hAliasRoot, i, szString, ulSize);
  2528. if (RegStatus == ERROR_SUCCESS) {
  2529. if (RegOpenKey(hAliasRoot, szString, &hSrcKey) == ERROR_SUCCESS) {
  2530. ulSize = sizeof(ULONG);
  2531. if (RegQueryValueEx(
  2532. hSrcKey, pszRegProfileNumber, NULL, NULL,
  2533. (LPBYTE)&ulAliasProfileNumber,
  2534. &ulSize) == ERROR_SUCCESS) {
  2535. //
  2536. // Check if we need to copy this one
  2537. //
  2538. if (ulSrcProfile == ulAliasProfileNumber) {
  2539. //
  2540. // Find an unused Alias subkey name
  2541. //
  2542. ulNewAlias = 0;
  2543. while (ulNewAlias < MAX_ALIASES) {
  2544. ulNewAlias++;
  2545. wsprintf(RegStr, TEXT("%s\\%s\\%04u"),
  2546. pszRegIDConfigDB,
  2547. szSubKeyName,
  2548. ulNewAlias);
  2549. RegStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  2550. RegStr, 0, KEY_ALL_ACCESS,
  2551. &hDestKey);
  2552. if (RegStatus == ERROR_SUCCESS) {
  2553. RegCloseKey(hDestKey);
  2554. continue;
  2555. } else if (RegStatus == ERROR_FILE_NOT_FOUND) {
  2556. RegStatus = ERROR_SUCCESS;
  2557. break;
  2558. } else {
  2559. break;
  2560. }
  2561. }
  2562. if ((RegStatus != ERROR_SUCCESS) || (ulNewAlias >= MAX_ALIASES)) {
  2563. RegCloseKey(hSrcKey);
  2564. break;
  2565. }
  2566. wsprintf(RegStr, TEXT("%s\\%s\\%04u"),
  2567. pszRegIDConfigDB,
  2568. szSubKeyName,
  2569. ulNewAlias);
  2570. RegCreateKeyEx(
  2571. HKEY_LOCAL_MACHINE, RegStr, 0, NULL, REG_OPTION_NON_VOLATILE,
  2572. KEY_ALL_ACCESS, NULL, &hDestKey, NULL);
  2573. //
  2574. // copy this alias entry
  2575. //
  2576. CopyRegistryNode(hSrcKey, hDestKey);
  2577. RegSetValueEx(
  2578. hDestKey, pszRegProfileNumber, 0, REG_DWORD,
  2579. (LPBYTE)&ulDestProfile, sizeof(ULONG));
  2580. bNewAliasCreated = TRUE;
  2581. if (ulNewAlias < (ULONG)_wtoi(szString)) {
  2582. // kick the enumeration index up one, else we'll
  2583. // find the key we just copied again.
  2584. i++;
  2585. }
  2586. if (hDestKey != NULL) {
  2587. RegCloseKey(hDestKey);
  2588. hDestKey = NULL;
  2589. }
  2590. }
  2591. }
  2592. if (hSrcKey != NULL) {
  2593. RegCloseKey(hSrcKey);
  2594. hSrcKey = NULL;
  2595. }
  2596. }
  2597. }
  2598. }
  2599. RegCloseKey(hAliasRoot);
  2600. hAliasRoot = NULL;
  2601. }
  2602. return bNewAliasCreated;
  2603. } // CopyAliasEntryType
  2604. /**-------------------------------------------------------------------------**/
  2605. BOOL
  2606. DeleteAliasEntryType(
  2607. ULONG ulProfile,
  2608. LPWSTR szSubKeyName
  2609. )
  2610. {
  2611. LONG RegStatus = ERROR_SUCCESS;
  2612. HKEY hAliasRoot;
  2613. HKEY hAliasSubKey;
  2614. WCHAR RegStr[MAX_PATH];
  2615. WCHAR szString[MAX_PATH];
  2616. ULONG ulAliasProfileNumber, ulSize, i;
  2617. BOOL bDeleted = FALSE;
  2618. //
  2619. // check all aliases under the "Alias" key
  2620. //
  2621. wsprintf(RegStr, TEXT("%s\\%s"),
  2622. pszRegIDConfigDB,
  2623. szSubKeyName);
  2624. RegStatus = RegOpenKeyEx(
  2625. HKEY_LOCAL_MACHINE, RegStr, 0, KEY_ALL_ACCESS,
  2626. &hAliasRoot);
  2627. if (RegStatus == ERROR_FILE_NOT_FOUND) {
  2628. return TRUE;
  2629. } else if (RegStatus != ERROR_SUCCESS) {
  2630. DisplaySystemMessage(NULL, ERROR_REGISTRY_CORRUPT);
  2631. return FALSE;
  2632. }
  2633. //
  2634. // enumerate all subkeys
  2635. //
  2636. RegStatus = ERROR_SUCCESS;
  2637. for (i=0; RegStatus == ERROR_SUCCESS; ) {
  2638. ulSize = MAX_PATH;
  2639. RegStatus = RegEnumKey(hAliasRoot, i, szString, ulSize);
  2640. bDeleted = FALSE;
  2641. if (RegStatus == ERROR_SUCCESS) {
  2642. if (RegOpenKey(hAliasRoot, szString, &hAliasSubKey) == ERROR_SUCCESS) {
  2643. ulSize = sizeof(ULONG);
  2644. if (RegQueryValueEx(
  2645. hAliasSubKey, pszRegProfileNumber, NULL, NULL,
  2646. (LPBYTE)&ulAliasProfileNumber,
  2647. &ulSize) == ERROR_SUCCESS) {
  2648. if (ulProfile == ulAliasProfileNumber) {
  2649. //
  2650. // delete this alias entry
  2651. //
  2652. RegCloseKey(hAliasSubKey);
  2653. hAliasSubKey = NULL;
  2654. RegDeleteKey(hAliasRoot, szString);
  2655. bDeleted = TRUE;
  2656. }
  2657. }
  2658. if (hAliasSubKey) RegCloseKey(hAliasSubKey);
  2659. }
  2660. }
  2661. if (!bDeleted) i++;
  2662. }
  2663. RegCloseKey(hAliasRoot);
  2664. return TRUE;
  2665. } // DeleteAliasEntryType
  2666. /**-------------------------------------------------------------------------**/
  2667. BOOL
  2668. CopyRegistryNode(
  2669. HKEY hSrcKey,
  2670. HKEY hDestKey
  2671. )
  2672. {
  2673. LONG RegStatus = ERROR_SUCCESS;
  2674. HKEY hSrcSubKey, hDestSubKey;
  2675. WCHAR szString[MAX_PATH];
  2676. ULONG ulDataSize, ulLength, ulType, i;
  2677. BYTE Data[MAX_PATH * 2]; // biggest value data??
  2678. PSECURITY_DESCRIPTOR pSecDesc;
  2679. // copy all values for this key
  2680. for (i=0; RegStatus == ERROR_SUCCESS; i++)
  2681. {
  2682. ulLength = MAX_PATH;
  2683. ulDataSize = sizeof(Data);
  2684. RegStatus = RegEnumValue(hSrcKey, i, szString, &ulLength, NULL,
  2685. &ulType, Data, &ulDataSize);
  2686. if (RegStatus == ERROR_SUCCESS)
  2687. {
  2688. RegSetValueEx(hDestKey, szString, 0, ulType, Data, ulDataSize);
  2689. }
  2690. }
  2691. // recursively call CopyRegistryNode to copy all subkeys
  2692. RegStatus = ERROR_SUCCESS;
  2693. for (i=0; RegStatus == ERROR_SUCCESS; i++)
  2694. {
  2695. ulLength = MAX_PATH;
  2696. RegStatus = RegEnumKey(hSrcKey, i, szString, ulLength);
  2697. if (RegStatus == ERROR_SUCCESS)
  2698. {
  2699. if (RegOpenKey(hSrcKey, szString, &hSrcSubKey) == ERROR_SUCCESS)
  2700. {
  2701. if (RegCreateKey(hDestKey, szString, &hDestSubKey) == ERROR_SUCCESS)
  2702. {
  2703. RegGetKeySecurity(hSrcSubKey, DACL_SECURITY_INFORMATION, NULL, &ulDataSize);
  2704. pSecDesc = LocalAlloc(LPTR, ulDataSize);
  2705. RegGetKeySecurity(hSrcSubKey, DACL_SECURITY_INFORMATION, pSecDesc, &ulDataSize);
  2706. CopyRegistryNode(hSrcSubKey, hDestSubKey);
  2707. RegSetKeySecurity(hDestSubKey, DACL_SECURITY_INFORMATION, pSecDesc);
  2708. LocalFree(pSecDesc);
  2709. RegCloseKey(hDestSubKey);
  2710. }
  2711. RegCloseKey(hSrcSubKey);
  2712. }
  2713. }
  2714. }
  2715. return TRUE;
  2716. } // CopyRegistryNode
  2717. /**-------------------------------------------------------------------------**/
  2718. BOOL
  2719. DeleteRegistryNode(
  2720. HKEY hParentKey,
  2721. LPTSTR szKey
  2722. )
  2723. {
  2724. ULONG ulSize = 0;
  2725. LONG RegStatus = ERROR_SUCCESS;
  2726. HKEY hKey = NULL;
  2727. WCHAR szSubKey[MAX_PATH];
  2728. //
  2729. // attempt to delete the key
  2730. //
  2731. if (RegDeleteKey(hParentKey, szKey) != ERROR_SUCCESS) {
  2732. if (RegOpenKeyEx(
  2733. hParentKey, szKey, 0, KEY_ENUMERATE_SUB_KEYS | KEY_WRITE,
  2734. &hKey) != ERROR_SUCCESS) {
  2735. return FALSE;
  2736. }
  2737. //
  2738. // enumerate subkeys and delete those nodes
  2739. //
  2740. while (RegStatus == ERROR_SUCCESS) {
  2741. //
  2742. // enumerate the first level children under the profile key
  2743. //
  2744. ulSize = MAX_PATH;
  2745. RegStatus = RegEnumKeyEx(
  2746. hKey, 0, szSubKey, &ulSize,
  2747. NULL, NULL, NULL, NULL);
  2748. if (RegStatus == ERROR_SUCCESS) {
  2749. if (!DeleteRegistryNode(hKey, szSubKey)) {
  2750. RegCloseKey(hKey);
  2751. return FALSE;
  2752. }
  2753. }
  2754. }
  2755. //
  2756. // subkeys have been deleted, try deleting this key again
  2757. //
  2758. RegCloseKey(hKey);
  2759. RegDeleteKey(hParentKey, szKey);
  2760. }
  2761. return TRUE;
  2762. } // DeleteRegistryNode
  2763. /**-------------------------------------------------------------------------**/
  2764. VOID
  2765. AdjustProfileTypeCounter(
  2766. PHWPROF_INFO pInfo,
  2767. ULONG ulDockState,
  2768. BOOL bIncrement
  2769. )
  2770. {
  2771. PULONG pCounter;
  2772. //
  2773. // use the counter corresponding to the given DockState.
  2774. //
  2775. if ((ulDockState & DOCKINFO_DOCKED) &&
  2776. (ulDockState & DOCKINFO_UNDOCKED)) {
  2777. pCounter = &pInfo->ulUnknownProfileNameCount;
  2778. } else if (ulDockState & DOCKINFO_DOCKED) {
  2779. pCounter = &pInfo->ulDockedProfileNameCount;
  2780. } else if (ulDockState & DOCKINFO_UNDOCKED) {
  2781. pCounter = &pInfo->ulUndockedProfileNameCount;
  2782. } else {
  2783. pCounter = &pInfo->ulUnknownProfileNameCount;
  2784. }
  2785. //
  2786. // increment or decrement the counter, as requested.
  2787. //
  2788. if (bIncrement) {
  2789. *pCounter += 1;
  2790. } else if (!bIncrement && (*pCounter > 0)) {
  2791. *pCounter -= 1;
  2792. } else {
  2793. *pCounter = 0;
  2794. }
  2795. }
  2796. /**-------------------------------------------------------------------------**/
  2797. BOOL
  2798. StripCurrentTag(
  2799. LPTSTR szFriendlyName,
  2800. ULONG ulProfile,
  2801. ULONG ulCurrentProfile
  2802. )
  2803. {
  2804. ULONG ulTagLen, ulNameLen;
  2805. if (ulProfile == ulCurrentProfile) {
  2806. ulTagLen = lstrlen(pszCurrentTag);
  2807. ulNameLen = lstrlen(szFriendlyName);
  2808. if (ulNameLen < ulTagLen) {
  2809. return TRUE; // nothing to do
  2810. }
  2811. if (lstrcmpi(&szFriendlyName[ulNameLen - ulTagLen], pszCurrentTag) == 0) {
  2812. //
  2813. // truncate the string before the current tag
  2814. //
  2815. szFriendlyName[ulNameLen - ulTagLen - 1] = '\0';
  2816. }
  2817. }
  2818. return TRUE;
  2819. } // StripCurrentTag
  2820. /**-------------------------------------------------------------------------**/
  2821. BOOL
  2822. AppendCurrentTag(
  2823. LPTSTR szTaggedName,
  2824. LPCTSTR szOriginalName,
  2825. ULONG ulProfile,
  2826. ULONG ulCurrentProfile
  2827. )
  2828. {
  2829. lstrcpy(szTaggedName, szOriginalName);
  2830. //
  2831. // if the profile is the current profile, then append the tag
  2832. // (let's user easily identify it as current)
  2833. //
  2834. if (ulProfile == ulCurrentProfile) {
  2835. lstrcat(szTaggedName, TEXT(" "));
  2836. lstrcat(szTaggedName, pszCurrentTag);
  2837. }
  2838. return TRUE;
  2839. } // AppendCurrentTag
  2840. /**-------------------------------------------------------------------------**/
  2841. VOID
  2842. CreateHwProfileFriendlyName(
  2843. IN HWND hDlg,
  2844. IN ULONG ulDockState,
  2845. OUT LPTSTR szFriendlyName
  2846. )
  2847. {
  2848. PHWPROF_INFO pInfo;
  2849. LPTSTR szPrefix;
  2850. PULONG pulIndex;
  2851. BOOL bUnknown=FALSE, bUniqueFriendlyName=FALSE;
  2852. //
  2853. // retrieve the profile buffer
  2854. //
  2855. pInfo = (PHWPROF_INFO)GetWindowLongPtr(hDlg, DWLP_USER);
  2856. //
  2857. // based on the DockState, determine the appropriate label to use and get a
  2858. // pointer to its counter index
  2859. //
  2860. if ((ulDockState & DOCKINFO_DOCKED) &&
  2861. (ulDockState & DOCKINFO_UNDOCKED)) {
  2862. szPrefix = pszUnknown;
  2863. pulIndex = &pInfo->ulUnknownProfileNameCount;
  2864. bUnknown = TRUE;
  2865. }
  2866. else if (ulDockState & DOCKINFO_DOCKED) {
  2867. szPrefix = pszDocked;
  2868. pulIndex = &pInfo->ulDockedProfileNameCount;
  2869. }
  2870. else if (ulDockState & DOCKINFO_UNDOCKED) {
  2871. szPrefix = pszUndocked;
  2872. pulIndex = &pInfo->ulUndockedProfileNameCount;
  2873. }
  2874. else {
  2875. szPrefix = pszUnknown;
  2876. pulIndex = &pInfo->ulUnknownProfileNameCount;
  2877. bUnknown = TRUE;
  2878. }
  2879. while ((!bUniqueFriendlyName) && (*pulIndex < MAX_PROFILES)) {
  2880. //
  2881. // as long as we don't have a unique name, build a FriendlyName based on
  2882. // the DockState and counter index
  2883. //
  2884. if (bUnknown || (*pulIndex > 0)) {
  2885. wsprintf(szFriendlyName, TEXT("%s %u"),
  2886. szPrefix,
  2887. *pulIndex + 1);
  2888. } else {
  2889. lstrcpy(szFriendlyName, szPrefix);
  2890. }
  2891. if (IsProfileNameInUse(hDlg,szFriendlyName)) {
  2892. //
  2893. // if this friendly name is in use, increment the counter to reflect this
  2894. //
  2895. *pulIndex += 1;
  2896. } else {
  2897. //
  2898. // a unique friendly name has been generated
  2899. //
  2900. bUniqueFriendlyName = TRUE;
  2901. }
  2902. }
  2903. if (!bUniqueFriendlyName) {
  2904. //
  2905. // if unable to generate a unique friendly name, just use some default.
  2906. // the user may have to deal with any errors arising from duplicate names
  2907. // is this name is already taken
  2908. //
  2909. lstrcpy(szFriendlyName, pszRegDefaultFriendlyName);
  2910. }
  2911. return;
  2912. } // CreateHwProfileFriendlyName
  2913. /**-------------------------------------------------------------------------**/
  2914. VOID
  2915. DisplayPrivateMessage(
  2916. HWND hWnd,
  2917. UINT uiPrivateError
  2918. )
  2919. {
  2920. WCHAR szMessage[MAX_PATH];
  2921. LoadString(hInstance, uiPrivateError, szMessage, MAX_PATH);
  2922. MessageBox(hWnd, szMessage, pszErrorCaption, MB_OK | MB_ICONSTOP);
  2923. return;
  2924. }
  2925. /**-------------------------------------------------------------------------**/
  2926. VOID
  2927. DisplaySystemMessage(
  2928. HWND hWnd,
  2929. UINT uiSystemError
  2930. )
  2931. {
  2932. WCHAR szMessage[MAX_PATH];
  2933. //
  2934. // retrieve the string matching the Win32 system error
  2935. //
  2936. FormatMessage(
  2937. FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
  2938. NULL,
  2939. uiSystemError,
  2940. MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
  2941. szMessage,
  2942. MAX_PATH,
  2943. NULL);
  2944. //
  2945. // display a message box with this error
  2946. //
  2947. MessageBox(
  2948. hWnd,
  2949. szMessage,
  2950. pszErrorCaption,
  2951. MB_OK | MB_ICONSTOP);
  2952. return;
  2953. } // DisplaySystemMessage
  2954. /**--------------------------------------------------------------------------**/
  2955. BOOL
  2956. UpdateOrderButtonState(
  2957. HWND hDlg
  2958. )
  2959. {
  2960. PHWPROF_INFO pInfo;
  2961. ULONG_PTR ulIndex = 0;
  2962. HWND hList;
  2963. pInfo = (PHWPROF_INFO)GetWindowLongPtr(hDlg, DWLP_USER);
  2964. hList = GetDlgItem(hDlg, IDD_HWP_PROFILES);
  2965. if ((ulIndex = SendMessage(hList,
  2966. LB_GETCURSEL, 0, 0)) == LB_ERR) {
  2967. return FALSE;
  2968. }
  2969. if (ulIndex == 0) {
  2970. //
  2971. // if focus currently on the button we're about to disable,
  2972. // change focus first or focus will be lost.
  2973. //
  2974. if (GetFocus() == GetDlgItem(hDlg, IDD_HWP_ORDERUP)) {
  2975. SendMessage(hDlg, DM_SETDEFID, IDD_HWP_ORDERDOWN, 0L);
  2976. SetFocus(GetDlgItem(hDlg, IDD_HWP_ORDERDOWN));
  2977. }
  2978. EnableWindow(GetDlgItem(hDlg, IDD_HWP_ORDERUP), FALSE);
  2979. } else {
  2980. EnableWindow(GetDlgItem(hDlg, IDD_HWP_ORDERUP), TRUE);
  2981. }
  2982. if (ulIndex < pInfo->ulActiveProfiles-1) {
  2983. EnableWindow(GetDlgItem(hDlg, IDD_HWP_ORDERDOWN), TRUE);
  2984. } else {
  2985. //
  2986. // if focus currently on the button we're about to disable,
  2987. // change focus first or focus will be lost.
  2988. //
  2989. if (GetFocus() == GetDlgItem(hDlg, IDD_HWP_ORDERDOWN)) {
  2990. SendMessage(hDlg, DM_SETDEFID, IDD_HWP_PROPERTIES, 0L);
  2991. SetFocus(GetDlgItem(hDlg, IDD_HWP_PROPERTIES));
  2992. }
  2993. EnableWindow(GetDlgItem(hDlg, IDD_HWP_ORDERDOWN), FALSE);
  2994. }
  2995. return TRUE;
  2996. }
  2997. /**-------------------------------------------------------------------------**/
  2998. BOOL CALLBACK AddPropSheetPageProc(
  2999. HPROPSHEETPAGE hpage,
  3000. LPARAM lParam
  3001. )
  3002. {
  3003. hPages[ulNumPages] = hpage;
  3004. return TRUE;
  3005. } // AddPropSheetPageProc
  3006. /**--------------------------------------------------------------------------**/
  3007. BOOL
  3008. DisplayProperties(
  3009. IN HWND hOwnerDlg,
  3010. IN PHWPROF_INFO pInfo
  3011. )
  3012. {
  3013. BOOL bStatus;
  3014. LPTSTR pszProviderList = NULL, pszProvider = NULL;
  3015. PROPSHEETPAGE PropPage;
  3016. PROPSHEETHEADER PropHeader;
  3017. FARPROC lpProc;
  3018. ULONG i, ulSize = 0;
  3019. HKEY hKey = NULL;
  3020. //
  3021. // create the first page (General)
  3022. //
  3023. ulNumPages = 0;
  3024. PropPage.dwSize = sizeof(PROPSHEETPAGE);
  3025. PropPage.dwFlags = PSP_DEFAULT;
  3026. PropPage.hInstance = hInstance;
  3027. PropPage.pszTemplate = MAKEINTRESOURCE(DLG_HWP_GENERAL);
  3028. PropPage.pszIcon = NULL;
  3029. PropPage.pszTitle = NULL;
  3030. PropPage.pfnDlgProc = GeneralProfileDlg;
  3031. PropPage.lParam = (LPARAM)pInfo;
  3032. PropPage.pfnCallback = NULL;
  3033. hPages[0] = CreatePropertySheetPage(&PropPage);
  3034. if (hPages[0] == NULL) {
  3035. return FALSE;
  3036. }
  3037. ulNumPages++;
  3038. //
  3039. // open the IDConfigDB key
  3040. //
  3041. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, pszRegIDConfigDB, 0,
  3042. KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS) {
  3043. return FALSE;
  3044. }
  3045. //---------------------------------------------------------------
  3046. // Are there any other property pages?
  3047. //---------------------------------------------------------------
  3048. if (RegQueryValueEx(hKey, pszRegPropertyProviders, NULL, NULL,
  3049. NULL, &ulSize) == ERROR_SUCCESS) {
  3050. pszProviderList = LocalAlloc(LPTR, ulSize);
  3051. if (pszProviderList != NULL) {
  3052. //
  3053. // read list of providers
  3054. //
  3055. if (RegQueryValueEx(hKey, pszRegPropertyProviders, NULL, NULL,
  3056. (LPBYTE)pszProviderList, &ulSize) == ERROR_SUCCESS) {
  3057. //
  3058. // Ask each provider to create and register it's property page
  3059. //
  3060. for (pszProvider = pszProviderList;
  3061. *pszProvider;
  3062. pszProvider += lstrlen(pszProvider) + 1) {
  3063. if (ulNumPages >= MAX_EXTENSION_PROVIDERS) {
  3064. break; // stop at max number of pages
  3065. }
  3066. //
  3067. // load the provider DLL
  3068. //
  3069. hLibs[ulNumPages] = LoadLibrary(pszProvider);
  3070. if (hLibs[ulNumPages] != NULL) {
  3071. lpProc = GetProcAddress(hLibs[ulNumPages],
  3072. "ExtensionPropSheetPageProc");
  3073. if (lpProc != NULL) {
  3074. //
  3075. // pass the profile ID to the provider as the lParam value
  3076. //
  3077. if ((lpProc)(NULL,
  3078. &AddPropSheetPageProc,
  3079. pInfo->ulSelectedProfile)) {
  3080. ulNumPages++;
  3081. }
  3082. }
  3083. }
  3084. }
  3085. }
  3086. LocalFree(pszProviderList);
  3087. }
  3088. }
  3089. RegCloseKey(hKey);
  3090. //
  3091. // create the property sheet
  3092. //
  3093. PropHeader.dwSize = sizeof(PROPSHEETHEADER);
  3094. PropHeader.dwFlags = PSH_PROPTITLE | PSH_NOAPPLYNOW;
  3095. PropHeader.hwndParent = hOwnerDlg;
  3096. PropHeader.hInstance = hInstance;
  3097. PropHeader.pszIcon = NULL; //MAKEINTRESOURCE(DOCK_ICON);
  3098. PropHeader.pszCaption =
  3099. pInfo->pHwProfValues[pInfo->ulSelectedProfileIndex].szFriendlyName;
  3100. PropHeader.nPages = ulNumPages;
  3101. PropHeader.phpage = hPages;
  3102. PropHeader.nStartPage = 0;
  3103. PropHeader.pfnCallback = NULL;
  3104. if (PropertySheet(&PropHeader) == 1) {
  3105. bStatus = FALSE;
  3106. } else {
  3107. bStatus = TRUE;
  3108. }
  3109. //
  3110. // cleanup extension page info
  3111. //
  3112. for (i = 1; i < ulNumPages; i++) {
  3113. FreeLibrary(hLibs[i]);
  3114. }
  3115. return bStatus;
  3116. } // DisplayProperties
  3117. /**-------------------------------------------------------------------------**/
  3118. INT_PTR
  3119. APIENTRY
  3120. GeneralProfileDlg(
  3121. HWND hDlg,
  3122. UINT uMessage,
  3123. WPARAM wParam,
  3124. LPARAM lParam
  3125. )
  3126. {
  3127. PHWPROF_INFO pInfo = NULL;
  3128. PHWPROF_VALUES pProfInfo = NULL;
  3129. ULONG ulReturn, ulIndex;
  3130. switch (uMessage)
  3131. {
  3132. case WM_INITDIALOG:
  3133. if (!lParam) {
  3134. break;
  3135. }
  3136. //
  3137. // on WM_INITDIALOG call, lParam points to the property sheet page.
  3138. // The lParam field in the property sheet page struct is set by,
  3139. // caller. When I created the property sheet, I passed in a pointer
  3140. // to a HWPROF_INFO struct. Save this in the user window long so I
  3141. // can access it on later messages.
  3142. //
  3143. pInfo = (PHWPROF_INFO)((LPPROPSHEETPAGE)lParam)->lParam;
  3144. SetWindowLongPtr(hDlg, DWLP_USER, (LPARAM)pInfo);
  3145. pProfInfo = (PHWPROF_VALUES)(&(pInfo->pHwProfValues[pInfo->ulSelectedProfileIndex]));
  3146. SetDlgItemText(hDlg, IDD_HWP_ST_PROFILE, pProfInfo->szFriendlyName);
  3147. //
  3148. // for pre-beta hwprofile code, the dockstate might have originally
  3149. // been set to zero which is invalid, use 0x111 instead
  3150. //
  3151. if (pProfInfo->ulDockState == 0) {
  3152. pProfInfo->ulDockState =
  3153. DOCKINFO_USER_SUPPLIED | DOCKINFO_DOCKED | DOCKINFO_UNDOCKED;
  3154. }
  3155. //
  3156. // initialize the dock state radio buttons
  3157. //
  3158. if ((pProfInfo->ulDockState & DOCKINFO_DOCKED) &&
  3159. (pProfInfo->ulDockState & DOCKINFO_UNDOCKED)) {
  3160. CheckRadioButton(hDlg, IDD_HWP_UNKNOWN, IDD_HWP_UNDOCKED, IDD_HWP_UNKNOWN);
  3161. }
  3162. else if (pProfInfo->ulDockState & DOCKINFO_DOCKED) {
  3163. CheckRadioButton(hDlg, IDD_HWP_UNKNOWN, IDD_HWP_UNDOCKED, IDD_HWP_DOCKED);
  3164. }
  3165. else if (pProfInfo->ulDockState & DOCKINFO_UNDOCKED) {
  3166. CheckRadioButton(hDlg, IDD_HWP_UNKNOWN, IDD_HWP_UNDOCKED, IDD_HWP_UNDOCKED);
  3167. }
  3168. else {
  3169. CheckRadioButton(hDlg, IDD_HWP_UNKNOWN, IDD_HWP_UNDOCKED, IDD_HWP_UNKNOWN);
  3170. }
  3171. //
  3172. // if the user-specified bit is not set then the dock state
  3173. // was determined from the hardware so don't allow changing it
  3174. //
  3175. if (pProfInfo->ulDockState & DOCKINFO_USER_SUPPLIED) {
  3176. }
  3177. else {
  3178. EnableWindow(GetDlgItem(hDlg, IDD_HWP_PORTABLE), FALSE);
  3179. EnableWindow(GetDlgItem(hDlg, IDD_HWP_DOCKED), FALSE);
  3180. EnableWindow(GetDlgItem(hDlg, IDD_HWP_UNDOCKED), FALSE);
  3181. EnableWindow(GetDlgItem(hDlg, IDD_HWP_UNKNOWN), FALSE);
  3182. }
  3183. //
  3184. // initialize the dock id and serial # static control
  3185. //
  3186. if (pProfInfo->szSerialNumber[0] &&
  3187. (pProfInfo->szSerialNumber[0] != TEXT('0'))) {
  3188. SetDlgItemText(hDlg, IDD_HWP_SERIALNUM, pProfInfo->szSerialNumber);
  3189. }
  3190. else {
  3191. SetDlgItemText(hDlg, IDD_HWP_SERIALNUM, pszUnavailable);
  3192. }
  3193. if (pProfInfo->szDockID[0] &&
  3194. (pProfInfo->szDockID[0] != TEXT('0'))) {
  3195. SetDlgItemText(hDlg, IDD_HWP_DOCKID, pProfInfo->szDockID);
  3196. //
  3197. // if dock id is available then docking state is known
  3198. // and cannot be over-ridden (this is a redundant check,
  3199. // the dock state should be accurate)
  3200. //
  3201. EnableWindow(GetDlgItem(hDlg, IDD_HWP_PORTABLE), FALSE);
  3202. EnableWindow(GetDlgItem(hDlg, IDD_HWP_DOCKED), FALSE);
  3203. EnableWindow(GetDlgItem(hDlg, IDD_HWP_UNDOCKED), FALSE);
  3204. EnableWindow(GetDlgItem(hDlg, IDD_HWP_UNKNOWN), FALSE);
  3205. }
  3206. else {
  3207. SetDlgItemText(hDlg, IDD_HWP_DOCKID, pszUnavailable);
  3208. }
  3209. //
  3210. // initialize the portable checkbox-groupbox
  3211. //
  3212. if (pInfo->bPortable) {
  3213. CheckDlgButton(hDlg, IDD_HWP_PORTABLE, BST_CHECKED);
  3214. }
  3215. else {
  3216. EnableWindow(GetDlgItem(hDlg, IDD_HWP_DOCKED), FALSE);
  3217. EnableWindow(GetDlgItem(hDlg, IDD_HWP_UNDOCKED), FALSE);
  3218. EnableWindow(GetDlgItem(hDlg, IDD_HWP_UNKNOWN), FALSE);
  3219. }
  3220. //
  3221. // Don't allow changing the global IsPortable Flag if it was determined
  3222. // from the hardware
  3223. //
  3224. if (pInfo->bHwDetectedPortable) {
  3225. EnableWindow(GetDlgItem(hDlg, IDD_HWP_PORTABLE), FALSE);
  3226. }
  3227. //
  3228. // initialize the aliasable checkbox
  3229. //
  3230. if (pProfInfo->bAliasable) {
  3231. CheckDlgButton(hDlg, IDD_HWP_ALIASABLE, BST_CHECKED);
  3232. }
  3233. else {
  3234. CheckDlgButton(hDlg, IDD_HWP_ALIASABLE, BST_UNCHECKED);
  3235. }
  3236. SetFocus(GetDlgItem(hDlg, IDD_HWP_PORTABLE));
  3237. return FALSE;
  3238. case WM_DEVICECHANGE:
  3239. //
  3240. // If a hardware profile change event takes place while the dialog is
  3241. // up, just dismiss the dialog because things have changed.
  3242. //
  3243. if (wParam == DBT_CONFIGCHANGED) {
  3244. PropSheet_PressButton(GetParent(hDlg), PSBTN_CANCEL);
  3245. return TRUE;
  3246. }
  3247. break;
  3248. case WM_NOTIFY:
  3249. if (!lParam) {
  3250. break;
  3251. }
  3252. switch (((NMHDR *)lParam)->code) {
  3253. case PSN_APPLY:
  3254. pInfo = (PHWPROF_INFO)GetWindowLongPtr(hDlg, DWLP_USER);
  3255. pProfInfo = (PHWPROF_VALUES)(&(pInfo->pHwProfValues[pInfo->ulSelectedProfileIndex]));
  3256. //
  3257. // unchecked --> checked case
  3258. //
  3259. if (!pInfo->bPortable && IsDlgButtonChecked(hDlg, IDD_HWP_PORTABLE)) {
  3260. pInfo->bPortable = TRUE;
  3261. }
  3262. //
  3263. // checked --> unchecked case
  3264. //
  3265. else if (pInfo->bPortable && !IsDlgButtonChecked(hDlg, IDD_HWP_PORTABLE)) {
  3266. TCHAR szCaption[MAX_PATH];
  3267. TCHAR szMsg[MAX_PATH];
  3268. LoadString(hInstance, HWP_ERROR_CAPTION, szCaption, MAX_PATH);
  3269. LoadString(hInstance, HWP_CONFIRM_NOT_PORTABLE, szMsg, MAX_PATH);
  3270. //
  3271. // confirm with user that other profiles will be set to unknown
  3272. //
  3273. if (MessageBox(hDlg, szMsg, szCaption,
  3274. MB_OKCANCEL | MB_ICONQUESTION) == IDCANCEL) {
  3275. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, TRUE); // don't apply
  3276. return TRUE;
  3277. }
  3278. for (ulIndex = 0; ulIndex < pInfo->ulNumProfiles; ulIndex++) {
  3279. if (pInfo->pHwProfValues[ulIndex].ulDockState &
  3280. DOCKINFO_USER_SUPPLIED) {
  3281. //
  3282. // only user-specified dock states will be changed
  3283. //
  3284. pInfo->pHwProfValues[ulIndex].ulDockState =
  3285. DOCKINFO_USER_SUPPLIED | DOCKINFO_DOCKED | DOCKINFO_UNDOCKED;
  3286. pInfo->pHwProfValues[ulIndex].ulAction = HWP_PROPERTIES;
  3287. }
  3288. }
  3289. pInfo->bPortable = FALSE;
  3290. }
  3291. //
  3292. // if user-specified dock state, then update the profile values
  3293. // with current ui settings
  3294. //
  3295. if (pProfInfo->ulDockState & DOCKINFO_USER_SUPPLIED) {
  3296. if (IsDlgButtonChecked(hDlg, IDD_HWP_DOCKED)) {
  3297. pProfInfo->ulDockState |= DOCKINFO_DOCKED;
  3298. pProfInfo->ulDockState &= ~DOCKINFO_UNDOCKED;
  3299. }
  3300. else if (IsDlgButtonChecked(hDlg, IDD_HWP_UNDOCKED)) {
  3301. pProfInfo->ulDockState |= DOCKINFO_UNDOCKED;
  3302. pProfInfo->ulDockState &= ~DOCKINFO_DOCKED;
  3303. }
  3304. else {
  3305. pProfInfo->ulDockState |= (DOCKINFO_UNDOCKED | DOCKINFO_DOCKED);
  3306. }
  3307. }
  3308. //
  3309. // aliasable unchecked --> checked case
  3310. //
  3311. if (!pProfInfo->bAliasable && IsDlgButtonChecked(hDlg, IDD_HWP_ALIASABLE)) {
  3312. pProfInfo->bAliasable = TRUE;
  3313. }
  3314. //
  3315. // aliasable checked --> unchecked case
  3316. //
  3317. else if (pProfInfo->bAliasable && !IsDlgButtonChecked(hDlg, IDD_HWP_ALIASABLE)) {
  3318. pProfInfo->bAliasable = FALSE;
  3319. }
  3320. //
  3321. // commit the changes for this profile
  3322. //
  3323. pProfInfo->ulAction |= HWP_PROPERTIES;
  3324. WriteProfileInfo(pProfInfo);
  3325. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, FALSE); // TRUE if error
  3326. break;
  3327. case PSN_RESET:
  3328. //
  3329. // user canceled the property sheet
  3330. //
  3331. break;
  3332. }
  3333. break;
  3334. case WM_HELP:
  3335. WinHelp((HWND)((LPHELPINFO)lParam)->hItemHandle, HELP_FILE,
  3336. HELP_WM_HELP, (DWORD_PTR)(LPTSTR)HwProfileHelpIds);
  3337. break;
  3338. case WM_CONTEXTMENU:
  3339. WinHelp((HWND)wParam, HELP_FILE, HELP_CONTEXTMENU,
  3340. (DWORD_PTR)(LPTSTR)HwProfileHelpIds);
  3341. break;
  3342. case WM_COMMAND:
  3343. {
  3344. switch (LOWORD(wParam))
  3345. {
  3346. case IDD_HWP_PORTABLE:
  3347. //
  3348. // if user chooses portable
  3349. //
  3350. if (!IsDlgButtonChecked(hDlg, IDD_HWP_PORTABLE)) {
  3351. CheckRadioButton(hDlg, IDD_HWP_UNKNOWN, IDD_HWP_UNDOCKED, IDD_HWP_UNKNOWN);
  3352. EnableWindow(GetDlgItem(hDlg, IDD_HWP_DOCKED), FALSE);
  3353. EnableWindow(GetDlgItem(hDlg, IDD_HWP_UNDOCKED), FALSE);
  3354. EnableWindow(GetDlgItem(hDlg, IDD_HWP_UNKNOWN), FALSE);
  3355. }
  3356. else {
  3357. EnableWindow(GetDlgItem(hDlg, IDD_HWP_DOCKED), TRUE);
  3358. EnableWindow(GetDlgItem(hDlg, IDD_HWP_UNDOCKED), TRUE);
  3359. EnableWindow(GetDlgItem(hDlg, IDD_HWP_UNKNOWN), TRUE);
  3360. }
  3361. break;
  3362. default:
  3363. return FALSE;
  3364. }
  3365. break;
  3366. } // case WM_COMMAND...
  3367. default:
  3368. return FALSE;
  3369. break;
  3370. }
  3371. return TRUE;
  3372. } // GeneralProfileDlg