Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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