Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1776 lines
41 KiB

  1. /*==========================================================================;
  2. *
  3. * Copyright (C) 1999 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: retrocfg.cpp
  6. * Content: Implement the RetroConfigProcess function, and supporting functions
  7. * History:
  8. * Date By Reason
  9. * ============
  10. * 10/13/99 pnewson created
  11. * 10/27/99 pnewson Fix: Bug #113692 & #113943 - support for new dplay app flags
  12. * 11/04/99 pnewson Bug #115279 - added HWND to check audio setup calls
  13. * - call audio setup automatically when retrofit enabled
  14. * 12/03/99 scottle Merged into joy.cpl, and handed to pnewson to bug fix.
  15. * 01/25/2000 pnewson Removed "unlisted games" checkbox
  16. * 02/15/2000 pnewson Assorted bug fixes:
  17. * millen 131837
  18. * millen 131794
  19. * millen 131889
  20. * 03/23/2000 rodtoll Changed include dsound.x --> dsprv.h
  21. * 04/05/2000 pnewson Changed format of "More Information" dialog box.
  22. * 04/10/2000 pnewson changes to make 64bit builds work.
  23. * 06/21/2000 rodtoll Bug #36213 - DX8 options panel should only appear on Millenium
  24. * Panel will not load on any other OS.
  25. * rodtoll Bug #30776 - Game options control panel gives Unexpected error if no device is present
  26. * 09/28/2000 rodtoll Bug #46003 - DPVOICE: Memory leak when joy.cpl closed without clicking voice tab
  27. *
  28. ***************************************************************************/
  29. #include <windows.h>
  30. #include <tchar.h>
  31. #include <initguid.h>
  32. #include <mmsystem.h>
  33. #include <dsound.h>
  34. #include <dsprv.h> // need for GUID instances
  35. #include "dvoice.h"
  36. #include "resource.h"
  37. #include "retrocfg.h"
  38. #include "dndbg.h"
  39. #include "creg.h"
  40. #include "dvosal.h"
  41. #include <commctrl.h>
  42. #include <shellapi.h>
  43. #include <windowsx.h>
  44. #include "joyarray.h"
  45. #include "..\\..\\..\\dplay\\dplobby\\dplobby\\dplobby.h"
  46. INT_PTR CALLBACK RetrofitProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  47. INT_PTR RetrofitInitDialogHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  48. INT_PTR RetrofitSetActiveHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  49. INT_PTR RetrofitApplyHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  50. INT_PTR RetrofitResetHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  51. INT_PTR RetrofitDetailsHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  52. INT_PTR RetrofitDestroyHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  53. INT_PTR CALLBACK WizardCancelProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  54. INT_PTR CALLBACK WizardLaunchProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  55. INT_PTR CALLBACK ConfirmHalfDuplexProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  56. INT_PTR CALLBACK SoundInitFailureProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  57. INT_PTR CALLBACK WizardErrorProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  58. INT_PTR CALLBACK VoiceEnabledProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  59. INT_PTR CALLBACK DetailsProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  60. INT_PTR CALLBACK PrevHalfDuplexProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  61. INT_PTR CALLBACK ListViewSubclassProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
  62. INT_PTR ListViewLButtonDownHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  63. INT_PTR ListViewLButtonDblClkHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  64. INT_PTR ListViewKeydownHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  65. void ClearAllCheckboxes(HWND hDlg, HWND hwndListView, LONG lNumItems);
  66. void MySetCheckState(HWND hwnd, int iItem, BOOL bChecked);
  67. BOOL MyGetCheckState(HWND hwnd, int iItem);
  68. BOOL MyToggleCheckState(HWND hwnd, int iItem);
  69. static void RetrofitOnAdvHelp (LPARAM);
  70. static void RetrofitOnContextMenu (WPARAM wParam, LPARAM lParam);
  71. // These defines have been repeated here instead of inclucing dplobpr.h
  72. // because it causes build problems.
  73. #define DPLAY_REGISTRY_APPS L"Software\\Microsoft\\DirectPlay\\Applications"
  74. #define REGSTR_VAL_FLAGS L"dwFlags"
  75. #define REGSTR_VAL_FILE L"File"
  76. #define REGSTR_VAL_PATH L"Path"
  77. #define MAX_ICONS 2048
  78. // Gasp! globals!
  79. HIMAGELIST g_himagelist = NULL;
  80. int g_iCheckboxEmptyIndex;
  81. int g_iCheckboxFullIndex;
  82. HINSTANCE g_hResDLLInstance;
  83. LPDIRECTPLAYVOICETEST g_IDirectPlayVoiceSetup = NULL;
  84. #define COLUMN_HEADER_SIZE 32
  85. TCHAR g_tstrColumnHeader1[COLUMN_HEADER_SIZE];
  86. TCHAR g_tstrColumnHeader2[COLUMN_HEADER_SIZE];
  87. WNDPROC g_ListViewProc;
  88. #define MESSAGE_BOX_SCRATCH_SIZE 128
  89. // From Main.cpp
  90. extern HINSTANCE ghInstance;
  91. // externals for context help
  92. extern const DWORD gaHelpIDs[];
  93. typedef HRESULT (* PFGETDEVICEID)(LPCGUID, LPGUID);
  94. #undef DPF_MODNAME
  95. #define DPF_MODNAME "DPVoiceCheckForDefaultDevices"
  96. // DPVoiceCheckForDefaultDevices
  97. //
  98. // This function returns DV_OK if this system has at least a single playback
  99. // and recording device.
  100. //
  101. HRESULT DPVoiceCheckForDefaultDevices()
  102. {
  103. HRESULT hr = DV_OK;
  104. HMODULE hModule = NULL;
  105. PFGETDEVICEID pfGetDeviceID = NULL;
  106. GUID guidTmp;
  107. hModule = LoadLibraryA("dsound.dll");
  108. if (!hModule)
  109. {
  110. hr = GetLastError();
  111. DPF(DVF_ERRORLEVEL, "Error loading dsound.dll - 0x%x", hr);
  112. goto CHECKDEVICE_ERROR;
  113. }
  114. // attempt to get a pointer to the GetDeviceId function
  115. pfGetDeviceID = (PFGETDEVICEID)GetProcAddress(hModule, "GetDeviceID");
  116. if( !pfGetDeviceID )
  117. {
  118. hr = GetLastError();
  119. DPF(DVF_ERRORLEVEL, "Error getting default devices - 0x%x", hr );
  120. hr = DVERR_GENERIC;
  121. goto CHECKDEVICE_ERROR;
  122. }
  123. hr = (*pfGetDeviceID)( &DSDEVID_DefaultPlayback, &guidTmp );
  124. if( FAILED( hr ) )
  125. {
  126. DPF( DVF_ERRORLEVEL, "Error getting default playback device hr=0x%x", hr );
  127. goto CHECKDEVICE_ERROR;
  128. }
  129. hr = (*pfGetDeviceID)( &DSDEVID_DefaultCapture, &guidTmp );
  130. if( FAILED( hr ) )
  131. {
  132. DPF( DVF_ERRORLEVEL, "Error getting default capture device hr=0x%x", hr );
  133. goto CHECKDEVICE_ERROR;
  134. }
  135. CHECKDEVICE_ERROR:
  136. if( hModule )
  137. FreeLibrary( hModule );
  138. DPF_EXIT();
  139. return hr;
  140. }
  141. #undef DPF_MODNAME
  142. #define DPF_MODNAME "DPVoiceCheckOS"
  143. // DPVoiceCheckOS
  144. //
  145. // This function returns DV_OK if this is a platform the retrofit runs on.
  146. //
  147. // This function will return DVERR_GENERIC if this is a platform the retrofit does not
  148. // run on.
  149. //
  150. HRESULT DPVoiceCheckOS()
  151. {
  152. OSVERSIONINFO osVerInfo;
  153. LONG lLastError;
  154. osVerInfo.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
  155. if( GetVersionEx( &osVerInfo ) )
  156. {
  157. // Win2K
  158. if( osVerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT )
  159. {
  160. // NOTE: If we enable Whistler support we have to ensure that this returns an error
  161. // if we're booting in safe-mode!
  162. /*
  163. // Whistler -- Major Version = 5 & Build # > 2195
  164. if( osVerInfo.dwMajorVersion == 5 && osVerInfo.dwBuildNumber > 2195 )
  165. {
  166. return DV_OK;
  167. }*/
  168. return DVERR_GENERIC;
  169. }
  170. // Win9X
  171. else
  172. {
  173. // Millenium Major = 4, Minor = 90
  174. if( (HIBYTE(HIWORD(osVerInfo.dwBuildNumber)) == 4) &&
  175. (LOBYTE(HIWORD(osVerInfo.dwBuildNumber)) == 90) )
  176. {
  177. return DV_OK;
  178. }
  179. return DVERR_GENERIC;
  180. }
  181. }
  182. else
  183. {
  184. lLastError = GetLastError();
  185. DPF( 0, "Error getting version info: 0x%x", lLastError );
  186. return DVERR_GENERIC;
  187. }
  188. }
  189. #undef DPF_MODNAME
  190. #define DPF_MODNAME "DVoiceCPLInit"
  191. HRESULT DVoiceCPLInit(void)
  192. {
  193. DPF_ENTER();
  194. HRESULT hr = S_OK;
  195. GUID guidTmp;
  196. g_hResDLLInstance = ghInstance;
  197. // Check to ensure we're on Millenium or Whistler. If we aren't we want to hide this
  198. // control panel.
  199. //
  200. hr = DPVoiceCheckOS();
  201. if( FAILED( hr ) )
  202. {
  203. DPF( DVF_ERRORLEVEL, "Error checking OS. Not a supported OS hr=0x%x", hr );
  204. return hr;
  205. }
  206. // Check to ensure there is at least a default playback and default capture device in the
  207. // system. If there is not we want to hide the control panel.
  208. //
  209. hr = DPVoiceCheckForDefaultDevices();
  210. if( FAILED( hr ) )
  211. {
  212. DPF( DVF_ERRORLEVEL, "Error checking for play/cap device hr=0x%x", hr );
  213. return hr;
  214. }
  215. if (FAILED(CoInitialize(NULL)))
  216. {
  217. DPF_EXIT();
  218. return E_FAIL;
  219. }
  220. hr = CoCreateInstance(CLSID_DirectPlayVoiceTest,
  221. NULL,
  222. CLSCTX_INPROC_SERVER,
  223. IID_IDirectPlayVoiceTest,
  224. (LPVOID *) &g_IDirectPlayVoiceSetup);
  225. if( FAILED( hr ) )
  226. {
  227. DPF( DVF_ERRORLEVEL, "Failed to create test interface hr=0x%x", hr );
  228. DPF_EXIT();
  229. return hr;
  230. }
  231. DPF_EXIT();
  232. return hr;
  233. } // End DVoiceCPLInit();
  234. #undef DPF_MODNAME
  235. #define DPF_MODNAME "RetrofitProc"
  236. INT_PTR CALLBACK RetrofitProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  237. {
  238. DPF_ENTER();
  239. INT_PTR fRet;
  240. fRet = FALSE;
  241. switch (message)
  242. {
  243. case WM_INITDIALOG :
  244. fRet = RetrofitInitDialogHandler(hDlg, message, wParam, lParam);
  245. break;
  246. case WM_NOTIFY :
  247. {
  248. LPNMHDR lpnm = (LPNMHDR) lParam;
  249. switch (lpnm->code)
  250. {
  251. case PSN_SETACTIVE :
  252. fRet = RetrofitSetActiveHandler(hDlg, message, wParam, lParam);
  253. break;
  254. case PSN_APPLY :
  255. fRet = RetrofitApplyHandler(hDlg, message, wParam, lParam);
  256. break;
  257. case PSN_RESET :
  258. fRet = RetrofitResetHandler(hDlg, message, wParam, lParam);
  259. break;
  260. case LVN_ITEMCHANGED :
  261. PropSheet_Changed(GetParent(hDlg), hDlg);
  262. fRet = TRUE;
  263. break;
  264. default :
  265. break;
  266. }
  267. }
  268. break;
  269. case WM_COMMAND:
  270. switch (LOWORD(wParam))
  271. {
  272. case IDC_DETAILS:
  273. fRet = RetrofitDetailsHandler(hDlg, message, wParam, lParam);
  274. break;
  275. }
  276. break;
  277. case WM_DESTROY:
  278. fRet = RetrofitDestroyHandler(hDlg, message, wParam, lParam);
  279. break;
  280. case WM_HELP:
  281. RetrofitOnAdvHelp(lParam);
  282. return(TRUE);
  283. case WM_CONTEXTMENU:
  284. RetrofitOnContextMenu(wParam, lParam);
  285. return(TRUE);
  286. default:
  287. break;
  288. }
  289. DPF_EXIT();
  290. return fRet;
  291. }
  292. #undef DPF_MODNAME
  293. #define DPF_MODNAME "RetrofitInitDialogHandler"
  294. INT_PTR RetrofitInitDialogHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  295. {
  296. DPF_ENTER();
  297. CRegistry cregApps;
  298. CRegistry cregApp;
  299. DWORD dwIndex;
  300. DWORD dwListViewIndex;
  301. WCHAR swzBuffer[MAX_REGISTRY_STRING_SIZE];
  302. TCHAR tszBuffer[MAX_REGISTRY_STRING_SIZE];
  303. WCHAR swzFilename[MAX_REGISTRY_STRING_SIZE];
  304. WCHAR swzPath[MAX_REGISTRY_STRING_SIZE];
  305. TCHAR tszFilename[MAX_REGISTRY_STRING_SIZE];
  306. TCHAR tszPathAndFile[MAX_REGISTRY_STRING_SIZE * 2 + 1];
  307. DWORD dwStrLen;
  308. HKEY hkApps;
  309. LONG lRet;
  310. HRESULT hr;
  311. LVITEM lvitem;
  312. LVCOLUMN lvcolumn;
  313. RECT rect;
  314. HWND hwndListView;
  315. HICON hiLarge;
  316. HICON hiSmall;
  317. int iIconXSize;
  318. int iIconYSize;
  319. int iIconIndex;
  320. int iScrollWidth;
  321. DWORD dwGlobalFlags;
  322. HICON hiconDefault;
  323. HDC hdc;
  324. TEXTMETRIC tm;
  325. int iChars;
  326. // create the image list for the icons
  327. iIconXSize = GetSystemMetrics(SM_CXSMICON);
  328. if (iIconXSize == 0)
  329. {
  330. lRet = GetLastError();
  331. DPF(DVF_ERRORLEVEL, "GetSystemMetrics failed, code: %i", lRet);
  332. goto error_level_0;
  333. }
  334. iIconYSize = GetSystemMetrics(SM_CYSMICON);
  335. if (iIconYSize == 0)
  336. {
  337. lRet = GetLastError();
  338. DPF(DVF_ERRORLEVEL, "GetSystemMetrics failed, code: %i", lRet);
  339. goto error_level_0;
  340. }
  341. g_himagelist = ImageList_Create(iIconXSize, iIconYSize, ILC_MASK, 0, MAX_ICONS);
  342. if (g_himagelist == NULL)
  343. {
  344. lRet = GetLastError();
  345. DPF(DVF_ERRORLEVEL, "ImageList_Create failed, code: %i", lRet);
  346. goto error_level_0;
  347. }
  348. // Load the default icon for the image list
  349. hiconDefault = LoadIcon(g_hResDLLInstance, MAKEINTRESOURCE(IDI_LIST_DEFAULT));
  350. if (hiconDefault == NULL)
  351. {
  352. lRet = GetLastError();
  353. DPF(DVF_ERRORLEVEL, "LoadIcon failed, code: %i", lRet);
  354. goto error_level_0;
  355. }
  356. // get a handle to the list view control
  357. hwndListView = GetDlgItem(hDlg, IDC_LIST_GAMES);
  358. if (hwndListView == NULL)
  359. {
  360. lRet = GetLastError();
  361. DPF(DVF_ERRORLEVEL, "GetDlgItem failed, code: %i", lRet);
  362. goto error_level_0;
  363. }
  364. // subclass the list view
  365. g_ListViewProc = (WNDPROC)SetWindowLongPtr(hwndListView, GWLP_WNDPROC, (INT_PTR)ListViewSubclassProc);
  366. if (g_ListViewProc == NULL)
  367. {
  368. lRet = GetLastError();
  369. DPF(DVF_ERRORLEVEL, "SetWindowLong failed, code: %i", lRet);
  370. goto error_level_0;
  371. }
  372. // add the enable column to the list view control
  373. hdc = GetDC(hDlg);
  374. if (hdc == NULL)
  375. {
  376. DPF(DVF_ERRORLEVEL, "GetDC failed");
  377. goto error_level_0;
  378. }
  379. if (GetTextMetrics(hdc, &tm) == 0)
  380. {
  381. DPF(DVF_ERRORLEVEL, "GetTextMetrics failed");
  382. goto error_level_0;
  383. }
  384. ZeroMemory(&lvcolumn, sizeof(lvcolumn));
  385. lvcolumn.mask = LVCF_ORDER|LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM;
  386. lvcolumn.iOrder = 1;
  387. lvcolumn.iSubItem = 1;
  388. ZeroMemory(g_tstrColumnHeader2, COLUMN_HEADER_SIZE*sizeof(TCHAR));
  389. iChars = LoadString(g_hResDLLInstance,
  390. IDS_ENABLED_COLUMN_HEADER,
  391. g_tstrColumnHeader2,
  392. COLUMN_HEADER_SIZE);
  393. if (iChars == 0)
  394. {
  395. DPF(DVF_ERRORLEVEL, "LoadString failed");
  396. goto error_level_0;
  397. }
  398. lvcolumn.pszText = g_tstrColumnHeader2;
  399. lvcolumn.cx = tm.tmAveCharWidth * iChars;
  400. if (ListView_InsertColumn(hwndListView, 1, &lvcolumn) == -1)
  401. {
  402. DPF(DVF_ERRORLEVEL, "ListView_InsertColumn failed");
  403. goto error_level_0;
  404. }
  405. // add the game column to the list view control
  406. ZeroMemory(&lvcolumn, sizeof(lvcolumn));
  407. lvcolumn.mask = LVCF_ORDER|LVCF_WIDTH|LVCF_TEXT;
  408. lvcolumn.iOrder = 0;
  409. if (!GetClientRect(hwndListView, &rect))
  410. {
  411. lRet = GetLastError();
  412. DPF(DVF_ERRORLEVEL, "GetClientRect failed, code: %i", lRet);
  413. goto error_level_0;
  414. }
  415. iScrollWidth = GetSystemMetrics(SM_CXVSCROLL);
  416. if (iScrollWidth == 0)
  417. {
  418. DPF(DVF_ERRORLEVEL, "GetSystemMetrics failed");
  419. goto error_level_0;
  420. }
  421. lvcolumn.cx = rect.right - rect.left - iScrollWidth - (iChars * tm.tmAveCharWidth);
  422. ZeroMemory(g_tstrColumnHeader1, COLUMN_HEADER_SIZE*sizeof(TCHAR));
  423. iChars = LoadString(g_hResDLLInstance,
  424. IDS_GAMES_COLUMN_HEADER,
  425. g_tstrColumnHeader1,
  426. COLUMN_HEADER_SIZE);
  427. if (iChars == 0)
  428. {
  429. DPF(DVF_ERRORLEVEL, "LoadString failed");
  430. goto error_level_0;
  431. }
  432. lvcolumn.pszText = g_tstrColumnHeader1;
  433. if (ListView_InsertColumn(hwndListView, 0, &lvcolumn) == -1)
  434. {
  435. DPF(DVF_ERRORLEVEL, "ListView_InsertColumn failed");
  436. goto error_level_0;
  437. }
  438. // put checkboxes into the list view control
  439. //ListView_SetExtendedListViewStyle(hwndListView, LVS_EX_CHECKBOXES);
  440. ListView_SetExtendedListViewStyle(hwndListView, LVS_EX_SUBITEMIMAGES);
  441. // add the small image list to the list view control
  442. ListView_SetImageList(hwndListView, g_himagelist, LVSIL_SMALL);
  443. // add icons to the image list for selected and cleared checkboxes
  444. hiSmall = (HICON)LoadImage(
  445. g_hResDLLInstance,
  446. MAKEINTRESOURCE(IDI_CHECKBOX_EMPTY),
  447. IMAGE_ICON,
  448. iIconXSize,
  449. iIconYSize,
  450. LR_SHARED);
  451. if (hiSmall == NULL)
  452. {
  453. DPF(DVF_ERRORLEVEL, "Unable to load empty checkbox icon resource");
  454. goto error_level_0;
  455. }
  456. g_iCheckboxEmptyIndex = ImageList_AddIcon(g_himagelist, hiSmall);
  457. if (g_iCheckboxEmptyIndex == -1)
  458. {
  459. DPF(DVF_ERRORLEVEL, "Unable to add empty checkbox icon to image list");
  460. goto error_level_0;
  461. }
  462. hiSmall = (HICON)LoadImage(
  463. g_hResDLLInstance,
  464. MAKEINTRESOURCE(IDI_CHECKBOX_FULL),
  465. IMAGE_ICON,
  466. iIconXSize,
  467. iIconYSize,
  468. LR_SHARED);
  469. if (hiSmall == NULL)
  470. {
  471. DPF(DVF_ERRORLEVEL, "Unable to load full checkbox icon resource");
  472. goto error_level_0;
  473. }
  474. g_iCheckboxFullIndex = ImageList_AddIcon(g_himagelist, hiSmall);
  475. if (g_iCheckboxFullIndex == -1)
  476. {
  477. DPF(DVF_ERRORLEVEL, "Unable to add full checkbox icon to image list");
  478. goto error_level_0;
  479. }
  480. // open the applications area of the registry
  481. if (!cregApps.Open(HKEY_LOCAL_MACHINE, DPLAY_REGISTRY_APPS, FALSE))
  482. {
  483. DPF(DVF_ERRORLEVEL, "Unable to open DirectPlay applications registry key");
  484. goto error_level_0;
  485. }
  486. hkApps = cregApps.GetHandle();
  487. // default the global checkbox to off
  488. /*
  489. if (!CheckDlgButton(hDlg, IDC_UNLISTEDCHECK, FALSE))
  490. {
  491. DPF(DVF_ERRORLEVEL, "Unable to clear unlisted games enable checkbox");
  492. // don't bail, continue
  493. }
  494. */
  495. // get the dwFlags value from the root of the applications area
  496. if (cregApps.ReadDWORD(REGSTR_VAL_FLAGS, dwGlobalFlags))
  497. {
  498. // set the checkbox if indicated
  499. /*
  500. if (dwGlobalFlags & DPLAPP_AUTOVOICE)
  501. {
  502. if (!CheckDlgButton(hDlg, IDC_UNLISTEDCHECK, TRUE))
  503. {
  504. DPF(DVF_ERRORLEVEL, "Unable to clear unlisted games enable checkbox");
  505. // don't bail, continue
  506. }
  507. }
  508. */
  509. }
  510. else
  511. {
  512. DPF(DVF_ERRORLEVEL, "Unable to read flags DirectPlay applications registry key");
  513. // don't bail, continue
  514. }
  515. // enum the apps and add them to the list box
  516. dwIndex = 0;
  517. dwListViewIndex = 0;
  518. while(1)
  519. {
  520. dwStrLen = MAX_REGISTRY_STRING_SIZE;
  521. if (!cregApps.EnumKeys(swzBuffer, &dwStrLen, dwIndex))
  522. {
  523. // that's all, we're done.
  524. break;
  525. }
  526. if (!cregApp.Open(hkApps, swzBuffer, FALSE))
  527. {
  528. DPF(DVF_ERRORLEVEL, "Unable to open application registry key");
  529. continue;
  530. }
  531. // get the app flags so we know if we want
  532. // to add this item to the list.
  533. DWORD dwFlags;
  534. if (!cregApp.ReadDWORD(REGSTR_VAL_FLAGS, dwFlags))
  535. {
  536. DPF(DVF_ERRORLEVEL, "CRegistry::ReadDWORD failed");
  537. // forgive this error, since apps registered with
  538. // older versions of DirectPlay will not have
  539. // flags entries, set dwFlags to zero.
  540. dwFlags = 0;
  541. }
  542. if (dwFlags & DPLAPP_NOENUM || dwFlags & DPLAPP_SELFVOICE)
  543. {
  544. // This app is either hidden, or implements it's own
  545. // voice comms. We don't want to add it to the list,
  546. // so continuue with the next iteration.
  547. ++dwIndex;
  548. cregApp.Close();
  549. continue;
  550. }
  551. // get the name of the key in a TCHAR
  552. if (!OSAL_WideToTChar(tszBuffer, swzBuffer, MAX_REGISTRY_STRING_SIZE))
  553. {
  554. DPF(DVF_ERRORLEVEL, "OSAL_WideToAnsi failed");
  555. ++dwIndex;
  556. cregApp.Close();
  557. continue;
  558. }
  559. // get the application's icon
  560. dwStrLen = MAX_REGISTRY_STRING_SIZE;
  561. if (!cregApp.ReadString(REGSTR_VAL_FILE, swzFilename, &dwStrLen))
  562. {
  563. DPF(DVF_ERRORLEVEL, "CRegistry::ReadString failed");
  564. ++dwIndex;
  565. cregApp.Close();
  566. continue;
  567. }
  568. hr = OSAL_WideToTChar(tszFilename, swzFilename, dwStrLen);
  569. if (FAILED(hr))
  570. {
  571. DPF(DVF_ERRORLEVEL, "OSAL_WidToAnsi failed, code: %i", hr);
  572. ++dwIndex;
  573. cregApp.Close();
  574. continue;
  575. }
  576. dwStrLen = MAX_REGISTRY_STRING_SIZE;
  577. if (!cregApp.ReadString(REGSTR_VAL_PATH, swzPath, &dwStrLen))
  578. {
  579. DPF(DVF_ERRORLEVEL, "CRegistry::ReadString failed");
  580. ++dwIndex;
  581. cregApp.Close();
  582. continue;
  583. }
  584. if (!cregApp.Close())
  585. {
  586. DPF(DVF_ERRORLEVEL, "CRegistry::Close failed");
  587. ++dwIndex;
  588. continue;
  589. }
  590. hr = OSAL_WideToTChar(tszPathAndFile, swzPath, MAX_REGISTRY_STRING_SIZE);
  591. if (FAILED(hr))
  592. {
  593. DPF(DVF_ERRORLEVEL, "OSAL_AllocAndConvertToANSI failed, code: %i", hr);
  594. ++dwIndex;
  595. continue;
  596. }
  597. if (tszPathAndFile[_tcslen(tszPathAndFile)-1] != '\\')
  598. {
  599. // since there isn't one there, tack on the trailing backslash
  600. _tcscat(tszPathAndFile, _T("\\"));
  601. }
  602. _tcscat(tszPathAndFile, tszFilename);
  603. ExtractIconEx(tszPathAndFile, 0, &hiLarge, &hiSmall, 1);
  604. // don't need the large icon.
  605. if (hiLarge != NULL)
  606. {
  607. DestroyIcon(hiLarge);
  608. }
  609. // add the small icon to the image list if it is valid
  610. if (hiSmall != NULL)
  611. {
  612. iIconIndex = ImageList_AddIcon(g_himagelist, hiSmall);
  613. }
  614. else
  615. {
  616. iIconIndex = ImageList_AddIcon(g_himagelist, hiconDefault);
  617. }
  618. if (iIconIndex == -1)
  619. {
  620. lRet = GetLastError();
  621. DPF(DVF_ERRORLEVEL, "ImageList_AddIcon failed, code: %i", lRet);
  622. ++dwIndex;
  623. continue;
  624. }
  625. lvitem.mask = LVIF_TEXT|LVIF_PARAM|LVIF_IMAGE;
  626. lvitem.iImage = iIconIndex;
  627. if (hiSmall != NULL)
  628. {
  629. DestroyIcon(hiSmall);
  630. }
  631. lvitem.iItem = dwListViewIndex;
  632. lvitem.iSubItem = 0;
  633. lvitem.state = 0;
  634. lvitem.stateMask = 0;
  635. lvitem.pszText = tszBuffer;
  636. lvitem.cchTextMax = 0;
  637. lvitem.lParam = dwFlags;
  638. lvitem.iIndent = 0;
  639. if (ListView_InsertItem(hwndListView, &lvitem) == -1)
  640. {
  641. DPF(DVF_ERRORLEVEL, "ListView_InsertItem failed");
  642. ++dwIndex;
  643. continue;
  644. }
  645. lvitem.mask = LVIF_IMAGE;
  646. lvitem.iItem = dwListViewIndex;
  647. lvitem.iSubItem = 1;
  648. // check the flags to see if this item should be initially selected
  649. if (dwFlags & DPLAPP_AUTOVOICE)
  650. {
  651. // select this item in the list
  652. lvitem.iImage = g_iCheckboxFullIndex;
  653. }
  654. else
  655. {
  656. lvitem.iImage = g_iCheckboxEmptyIndex;
  657. }
  658. if (ListView_SetItem(hwndListView, &lvitem) == -1)
  659. {
  660. DPF(DVF_ERRORLEVEL, "ListView_SetItem failed");
  661. ListView_DeleteItem(hwndListView, dwListViewIndex);
  662. ++dwIndex;
  663. continue;
  664. }
  665. ++dwIndex;
  666. ++dwListViewIndex;
  667. }
  668. if (!cregApps.Close())
  669. {
  670. DPF(DVF_ERRORLEVEL, "Unable to close DirectPlay applications registry key");
  671. }
  672. // If there is at least one item in the list, set the focus to the first item
  673. // in the list so it will be marked when the user first comes to this tab.
  674. if (dwListViewIndex > 0)
  675. {
  676. ListView_SetItemState(hwndListView, 0, LVIS_FOCUSED, LVIS_FOCUSED);
  677. }
  678. DPF_EXIT();
  679. return TRUE;
  680. error_level_0:
  681. DPF_EXIT();
  682. return TRUE;
  683. }
  684. #undef DPF_MODNAME
  685. #define DPF_MODNAME "RetrofitSetActiveHandler"
  686. INT_PTR RetrofitSetActiveHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  687. {
  688. DPF_ENTER();
  689. DPF_EXIT();
  690. return FALSE;
  691. }
  692. #undef DPF_MODNAME
  693. #define DPF_MODNAME "RetrofitApplyHandler"
  694. INT_PTR RetrofitApplyHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  695. {
  696. DPF_ENTER();
  697. LONG lRet;
  698. LONG lNumItems;
  699. LONG lIndex;
  700. TCHAR tszItemText[MAX_REGISTRY_STRING_SIZE];
  701. WCHAR swzItemText[MAX_REGISTRY_STRING_SIZE];
  702. CRegistry cregApps;
  703. CRegistry cregApp;
  704. HKEY hkApps;
  705. HWND hwndListView;
  706. LVITEM lvitem;
  707. DWORD dwFlags;
  708. HRESULT hr1;
  709. HRESULT hr2;
  710. BOOL fItemsSelected;
  711. INT_PTR intptr;
  712. BOOL fTestRun = FALSE;
  713. // Get a handle to the list view
  714. hwndListView = GetDlgItem(hDlg, IDC_LIST_GAMES);
  715. if (hwndListView == NULL)
  716. {
  717. lRet = GetLastError();
  718. DPF(DVF_ERRORLEVEL, "GetDlgItem failed, code: %i", lRet);
  719. goto error_level_0;
  720. }
  721. // Get the number of items in the list view
  722. lNumItems = ListView_GetItemCount(hwndListView);
  723. // Prescan the list to see if any items have been
  724. // checked off.
  725. fItemsSelected = FALSE;
  726. lvitem.mask = LVIF_IMAGE;
  727. lvitem.iSubItem = 1;
  728. for (lIndex = 0; lIndex < lNumItems; ++lIndex)
  729. {
  730. lvitem.iItem = lIndex;
  731. if (!ListView_GetItem(hwndListView, &lvitem))
  732. {
  733. DPF(DVF_ERRORLEVEL, "ListView_GetItem failed");
  734. goto error_level_0;
  735. }
  736. if (lvitem.iImage == g_iCheckboxFullIndex)
  737. {
  738. fItemsSelected = TRUE;
  739. }
  740. }
  741. // look at the checkbox for unlisted games as well
  742. /*
  743. if (IsDlgButtonChecked(hDlg, IDC_UNLISTEDCHECK) == BST_CHECKED)
  744. {
  745. fItemsSelected = TRUE;
  746. }
  747. */
  748. if (fItemsSelected)
  749. {
  750. // Before we allow the user to enable the retrofit, we are going
  751. // to make sure that setup has been run on the default
  752. // devices, and run it forcibly if required.
  753. hr1 = g_IDirectPlayVoiceSetup->CheckAudioSetup(&DSDEVID_DefaultVoicePlayback, &DSDEVID_DefaultVoiceCapture, NULL, DVFLAGS_QUERYONLY);
  754. switch (hr1)
  755. {
  756. case DV_FULLDUPLEX:
  757. // The sound hardware is fine, do nothing special.
  758. break;
  759. case DV_HALFDUPLEX:
  760. // The wizard has been run before, but the result was half duplex.
  761. // Give the user the option to run the wizard again, or continue
  762. // with the half duplex limitation.
  763. intptr = DialogBox(g_hResDLLInstance, MAKEINTRESOURCE(IDD_PREV_HALFDUPLEX),
  764. hDlg, PrevHalfDuplexProc);
  765. switch (intptr)
  766. {
  767. case IDOK:
  768. // the user has accepted half duplex mode, exit the control panel
  769. break;
  770. case IDCANCEL:
  771. // the use hit the X or esc. Escape back to the control panel, and
  772. // do not exit it
  773. goto error_level_1;
  774. case IDC_RUNTEST:
  775. default:
  776. // default should not occur, but treat as a run test
  777. fTestRun = TRUE;
  778. hr2 = g_IDirectPlayVoiceSetup->CheckAudioSetup(&DSDEVID_DefaultVoicePlayback, &DSDEVID_DefaultVoiceCapture, hDlg, 0);
  779. break;
  780. }
  781. break;
  782. default:
  783. // With any other result, either the wizard hasn't been run, or it failed
  784. // really badly. Run it again, but warn the user we're about to run the wizard,
  785. // and give them the chance to bail.
  786. if (DialogBox(g_hResDLLInstance, MAKEINTRESOURCE(IDD_WIZARD_LAUNCH),
  787. hDlg, WizardLaunchProc) != IDOK)
  788. {
  789. // treat this as if they bailed out of the wizard itself.
  790. fTestRun = TRUE;
  791. hr2 = DVERR_USERCANCEL;
  792. }
  793. else
  794. {
  795. fTestRun = TRUE;
  796. hr2 = g_IDirectPlayVoiceSetup->CheckAudioSetup(&DSDEVID_DefaultVoicePlayback, &DSDEVID_DefaultVoiceCapture, hDlg, 0);
  797. }
  798. break;
  799. }
  800. // if the test was run, deal with the results
  801. if (fTestRun)
  802. {
  803. switch (hr2)
  804. {
  805. case DV_FULLDUPLEX:
  806. // The user just exited from the wizard, so we don't want to
  807. // kick them completely out of the control panel. They should
  808. // have to hit OK again in the control panel.
  809. goto error_level_1;
  810. break;
  811. case DV_HALFDUPLEX:
  812. // the user is only getting half duplex, confirm that they want
  813. // to use voice chat anyway. If they don't, clear all checkboxes
  814. // and don't exit the control panel.
  815. if (DialogBox(g_hResDLLInstance, MAKEINTRESOURCE(IDD_CONFIRM_HALFDUPLEX),
  816. hDlg, ConfirmHalfDuplexProc) != IDOK)
  817. {
  818. ClearAllCheckboxes(hDlg, hwndListView, lNumItems);
  819. }
  820. // The user just exited from the wizard, so we don't want to
  821. // kick them completely out of the control panel. They should
  822. // have to hit OK again in the control panel.
  823. goto error_level_1;
  824. case DVERR_SOUNDINITFAILURE:
  825. // The sound test failed miserably. Let the user know they cannot use
  826. // voice chat, clear all the checkboxes and exit the control panel
  827. ClearAllCheckboxes(hDlg, hwndListView, lNumItems);
  828. DialogBox(g_hResDLLInstance, MAKEINTRESOURCE(IDD_CONFIRM_SOUNDINITFAILURE),
  829. hDlg, SoundInitFailureProc);
  830. goto error_level_1;
  831. case DVERR_USERCANCEL:
  832. // The user canceled the wizard, inform them they cannot use
  833. // voice chat and clear all the checkboxes. Don't exit the property sheet.
  834. ClearAllCheckboxes(hDlg, hwndListView, lNumItems);
  835. DialogBox(g_hResDLLInstance, MAKEINTRESOURCE(IDD_WIZARD_CANCELED),
  836. hDlg, WizardCancelProc);
  837. goto error_level_1;
  838. default:
  839. // Anything else is unexpect and should be treated as an error.
  840. // Display an error message, clear the checkboxes, and DO exit the propery sheet
  841. ClearAllCheckboxes(hDlg, hwndListView, lNumItems);
  842. DialogBox(g_hResDLLInstance, MAKEINTRESOURCE(IDD_WIZARD_ERROR),
  843. hDlg, WizardErrorProc);
  844. goto error_level_1;
  845. }
  846. }
  847. }
  848. // If we get here, the test was already run on the default
  849. // devices, and it returned either halfduplex or fullduplex,
  850. // so we can set the bits as we please.
  851. // Open the applications registry key
  852. if (!cregApps.Open(HKEY_LOCAL_MACHINE, DPLAY_REGISTRY_APPS, FALSE))
  853. {
  854. DPF(DVF_ERRORLEVEL, "CRegistry::Open failed");
  855. goto error_level_1;
  856. }
  857. hkApps = cregApps.GetHandle();
  858. // set the autovoice bit - maintaint the state of the rest of the bits
  859. // in case we add more global flags later
  860. /*
  861. if (!cregApps.ReadDWORD(REGSTR_VAL_FLAGS, dwGlobalFlags))
  862. {
  863. DPF(DVF_ERRORLEVEL, "Error reading default flags from applications key");
  864. dwGlobalFlags = 0;
  865. // continue anyway
  866. }
  867. if (IsDlgButtonChecked(hDlg, IDC_UNLISTEDCHECK) == BST_CHECKED)
  868. {
  869. dwGlobalFlags |= DPLAPP_AUTOVOICE;
  870. }
  871. else
  872. {
  873. dwGlobalFlags &= ~DPLAPP_AUTOVOICE;
  874. }
  875. if (cregApps.WriteDWORD(REGSTR_VAL_FLAGS, dwGlobalFlags))
  876. {
  877. DPF(DVF_ERRORLEVEL, "Error writing default flags to application key");
  878. // continue anyway
  879. }
  880. */
  881. // loop through the items and set the app's flags according to
  882. // the selected state of the list view
  883. for (lIndex = 0; lIndex < lNumItems; ++lIndex)
  884. {
  885. // get the item info
  886. lvitem.mask = LVIF_TEXT|LVIF_PARAM;
  887. lvitem.iItem = lIndex;
  888. lvitem.iSubItem = 0;
  889. lvitem.state = 0;
  890. lvitem.stateMask = 0;
  891. lvitem.pszText = tszItemText;
  892. lvitem.cchTextMax = MAX_REGISTRY_STRING_SIZE;
  893. lvitem.iImage = 0;
  894. lvitem.lParam = 0;
  895. lvitem.iIndent = 0;
  896. if (!ListView_GetItem(hwndListView, &lvitem))
  897. {
  898. DPF(DVF_ERRORLEVEL, "ListView_GetItem failed");
  899. goto error_level_1;
  900. }
  901. dwFlags = (DWORD)lvitem.lParam;
  902. if (!OSAL_TCharToWide(swzItemText, tszItemText, MAX_REGISTRY_STRING_SIZE))
  903. {
  904. DPF(DVF_ERRORLEVEL, "OSAL_AnsiToWide failed");
  905. goto error_level_1;
  906. }
  907. lvitem.mask = LVIF_IMAGE;
  908. lvitem.iItem = lIndex;
  909. lvitem.iSubItem = 1;
  910. if (!ListView_GetItem(hwndListView, &lvitem))
  911. {
  912. DPF(DVF_ERRORLEVEL, "ListView_GetItem failed");
  913. goto error_level_1;
  914. }
  915. if (lvitem.iImage == g_iCheckboxFullIndex)
  916. {
  917. dwFlags |= DPLAPP_AUTOVOICE;
  918. }
  919. else
  920. {
  921. dwFlags &= ~DPLAPP_AUTOVOICE;
  922. }
  923. if (!cregApp.Open(hkApps, swzItemText, FALSE))
  924. {
  925. DPF(DVF_ERRORLEVEL, "CRegistry::Open failed");
  926. goto error_level_1;
  927. }
  928. if (!cregApp.WriteDWORD(REGSTR_VAL_FLAGS, dwFlags))
  929. {
  930. DPF(DVF_ERRORLEVEL, "CRegistry::WriteDWORD failed");
  931. goto error_level_1;
  932. }
  933. if (!cregApp.Close())
  934. {
  935. DPF(DVF_ERRORLEVEL, "CRegistry::Close failed");
  936. goto error_level_1;
  937. }
  938. }
  939. if (!cregApps.Close())
  940. {
  941. DPF(DVF_ERRORLEVEL, "CRegistry::Close failed");
  942. goto error_level_1;
  943. }
  944. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
  945. DPF_EXIT();
  946. return TRUE;
  947. error_level_1:
  948. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE);
  949. error_level_0:
  950. DPF_EXIT();
  951. return TRUE;
  952. }
  953. #undef DPF_MODNAME
  954. #define DPF_MODNAME "RetrofitResetHandler"
  955. INT_PTR RetrofitResetHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  956. {
  957. DPF_ENTER();
  958. DPF_EXIT();
  959. return FALSE;
  960. }
  961. #undef DPF_MODNAME
  962. #define DPF_MODNAME "RetrofitDetailsHandler"
  963. INT_PTR RetrofitDetailsHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  964. {
  965. DPF_ENTER();
  966. DialogBox(g_hResDLLInstance, MAKEINTRESOURCE(IDD_MOREINFO),
  967. hDlg, DetailsProc);
  968. DPF_EXIT();
  969. return FALSE;
  970. }
  971. #undef DPF_MODNAME
  972. #define DPF_MODNAME "RetrofitDestroyHandler"
  973. INT_PTR RetrofitDestroyHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  974. {
  975. DPF_ENTER();
  976. if( g_himagelist )
  977. {
  978. // clean up the image list
  979. ImageList_Destroy(g_himagelist);
  980. g_himagelist = NULL;
  981. }
  982. if( g_IDirectPlayVoiceSetup )
  983. {
  984. // release the IDirectPlayVoiceSetup interface
  985. g_IDirectPlayVoiceSetup->Release();
  986. g_IDirectPlayVoiceSetup = NULL;
  987. }
  988. DPF_EXIT();
  989. return FALSE;
  990. }
  991. #undef DPF_MODNAME
  992. #define DPF_MODNAME "WizardCancelProc"
  993. INT_PTR CALLBACK WizardCancelProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  994. {
  995. DPF_ENTER();
  996. BOOL fRet;
  997. HICON hIcon;
  998. fRet = FALSE;
  999. switch (message)
  1000. {
  1001. case WM_INITDIALOG:
  1002. hIcon = LoadIcon(NULL, IDI_WARNING);
  1003. SendDlgItemMessage(hDlg, IDC_ICON_NOTCOMPLETE, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
  1004. break;
  1005. case WM_COMMAND:
  1006. switch (LOWORD(wParam))
  1007. {
  1008. case IDOK:
  1009. case IDCANCEL:
  1010. EndDialog(hDlg, LOWORD(wParam));
  1011. fRet = TRUE;
  1012. break;
  1013. default:
  1014. break;
  1015. }
  1016. break;
  1017. default:
  1018. break;
  1019. }
  1020. DPF_EXIT();
  1021. return fRet;
  1022. }
  1023. #undef DPF_MODNAME
  1024. #define DPF_MODNAME "WizardLaunchProc"
  1025. INT_PTR CALLBACK WizardLaunchProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  1026. {
  1027. DPF_ENTER();
  1028. BOOL fRet;
  1029. HICON hIcon;
  1030. fRet = FALSE;
  1031. switch (message)
  1032. {
  1033. case WM_INITDIALOG:
  1034. hIcon = LoadIcon(NULL, IDI_INFORMATION);
  1035. SendDlgItemMessage(hDlg, IDC_ICON_INFORMATION, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
  1036. break;
  1037. case WM_COMMAND:
  1038. switch (LOWORD(wParam))
  1039. {
  1040. case IDOK:
  1041. case IDCANCEL:
  1042. EndDialog(hDlg, LOWORD(wParam));
  1043. fRet = TRUE;
  1044. break;
  1045. default:
  1046. break;
  1047. }
  1048. break;
  1049. default:
  1050. break;
  1051. }
  1052. DPF_EXIT();
  1053. return fRet;
  1054. }
  1055. #undef DPF_MODNAME
  1056. #define DPF_MODNAME "PrevHalfDuplexProc"
  1057. INT_PTR CALLBACK PrevHalfDuplexProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  1058. {
  1059. DPF_ENTER();
  1060. BOOL fRet;
  1061. HICON hIcon;
  1062. fRet = FALSE;
  1063. switch (message)
  1064. {
  1065. case WM_INITDIALOG:
  1066. hIcon = LoadIcon(NULL, IDI_WARNING);
  1067. SendDlgItemMessage(hDlg, IDC_WARNING_ICON, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
  1068. break;
  1069. case WM_COMMAND:
  1070. switch (LOWORD(wParam))
  1071. {
  1072. case IDOK:
  1073. case IDCANCEL:
  1074. case IDC_RUNTEST:
  1075. EndDialog(hDlg, LOWORD(wParam));
  1076. fRet = TRUE;
  1077. break;
  1078. default:
  1079. break;
  1080. }
  1081. break;
  1082. default:
  1083. break;
  1084. }
  1085. DPF_EXIT();
  1086. return fRet;
  1087. }
  1088. #undef DPF_MODNAME
  1089. #define DPF_MODNAME "ConfirmHalfDuplexProc"
  1090. INT_PTR CALLBACK ConfirmHalfDuplexProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  1091. {
  1092. DPF_ENTER();
  1093. BOOL fRet;
  1094. HICON hIcon;
  1095. fRet = FALSE;
  1096. switch (message)
  1097. {
  1098. case WM_INITDIALOG:
  1099. hIcon = LoadIcon(NULL, IDI_WARNING);
  1100. SendDlgItemMessage(hDlg, IDC_ICON_WARNING, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
  1101. break;
  1102. case WM_COMMAND:
  1103. switch (LOWORD(wParam))
  1104. {
  1105. case IDOK:
  1106. case IDCANCEL:
  1107. EndDialog(hDlg, LOWORD(wParam));
  1108. fRet = TRUE;
  1109. break;
  1110. default:
  1111. break;
  1112. }
  1113. break;
  1114. default:
  1115. break;
  1116. }
  1117. DPF_EXIT();
  1118. return fRet;
  1119. }
  1120. #undef DPF_MODNAME
  1121. #define DPF_MODNAME "SoundInitFailureProc"
  1122. INT_PTR CALLBACK SoundInitFailureProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  1123. {
  1124. DPF_ENTER();
  1125. BOOL fRet;
  1126. HICON hIcon;
  1127. fRet = FALSE;
  1128. switch (message)
  1129. {
  1130. case WM_INITDIALOG:
  1131. hIcon = LoadIcon(NULL, IDI_ERROR);
  1132. SendDlgItemMessage(hDlg, IDC_ICON_ERROR, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
  1133. break;
  1134. case WM_COMMAND:
  1135. switch (LOWORD(wParam))
  1136. {
  1137. case IDOK:
  1138. case IDCANCEL:
  1139. EndDialog(hDlg, LOWORD(wParam));
  1140. fRet = TRUE;
  1141. break;
  1142. default:
  1143. break;
  1144. }
  1145. break;
  1146. default:
  1147. break;
  1148. }
  1149. DPF_EXIT();
  1150. return fRet;
  1151. }
  1152. #undef DPF_MODNAME
  1153. #define DPF_MODNAME "WizardErrorProc"
  1154. INT_PTR CALLBACK WizardErrorProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  1155. {
  1156. DPF_ENTER();
  1157. BOOL fRet;
  1158. HICON hIcon;
  1159. fRet = FALSE;
  1160. switch (message)
  1161. {
  1162. case WM_INITDIALOG:
  1163. hIcon = LoadIcon(NULL, IDI_ERROR);
  1164. SendDlgItemMessage(hDlg, IDC_ICON_ERROR, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
  1165. break;
  1166. case WM_COMMAND:
  1167. switch (LOWORD(wParam))
  1168. {
  1169. case IDOK:
  1170. case IDCANCEL:
  1171. EndDialog(hDlg, LOWORD(wParam));
  1172. fRet = TRUE;
  1173. break;
  1174. default:
  1175. break;
  1176. }
  1177. break;
  1178. default:
  1179. break;
  1180. }
  1181. DPF_EXIT();
  1182. return fRet;
  1183. }
  1184. #undef DPF_MODNAME
  1185. #define DPF_MODNAME "VoiceEnabledProc"
  1186. INT_PTR CALLBACK VoiceEnabledProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  1187. {
  1188. DPF_ENTER();
  1189. BOOL fRet;
  1190. HICON hIcon;
  1191. fRet = FALSE;
  1192. switch (message)
  1193. {
  1194. case WM_INITDIALOG:
  1195. hIcon = LoadIcon(NULL, IDI_INFORMATION);
  1196. SendDlgItemMessage(hDlg, IDC_INFO_ICON, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
  1197. break;
  1198. case WM_COMMAND:
  1199. switch (LOWORD(wParam))
  1200. {
  1201. case IDOK:
  1202. case IDCANCEL:
  1203. EndDialog(hDlg, LOWORD(wParam));
  1204. fRet = TRUE;
  1205. break;
  1206. default:
  1207. break;
  1208. }
  1209. break;
  1210. default:
  1211. break;
  1212. }
  1213. DPF_EXIT();
  1214. return fRet;
  1215. }
  1216. #undef DPF_MODNAME
  1217. #define DPF_MODNAME "DetailsProc"
  1218. INT_PTR CALLBACK DetailsProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  1219. {
  1220. DPF_ENTER();
  1221. BOOL fRet;
  1222. static TCHAR *szMoreInfo = NULL;
  1223. static const int c_iMoreInfoStrLen = 2048;
  1224. fRet = FALSE;
  1225. switch (message)
  1226. {
  1227. case WM_INITDIALOG:
  1228. /*
  1229. hIcon = LoadIcon(NULL, IDI_INFORMATION);
  1230. SendDlgItemMessage(hDlg, IDC_INFO_ICON, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
  1231. hIcon = LoadIcon(NULL, IDI_WARNING);
  1232. SendDlgItemMessage(hDlg, IDC_WARNING_ICON, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
  1233. */
  1234. szMoreInfo = (TCHAR*)malloc((c_iMoreInfoStrLen-1)*sizeof(TCHAR));
  1235. if (szMoreInfo != NULL)
  1236. {
  1237. if (LoadString(g_hResDLLInstance, IDS_VOICEMOREINFO, szMoreInfo, c_iMoreInfoStrLen) != 0)
  1238. {
  1239. SetDlgItemText(hDlg, IDC_MOREINFO, szMoreInfo);
  1240. }
  1241. }
  1242. break;
  1243. case WM_COMMAND:
  1244. switch (LOWORD(wParam))
  1245. {
  1246. case IDOK:
  1247. case IDCANCEL:
  1248. EndDialog(hDlg, LOWORD(wParam));
  1249. fRet = TRUE;
  1250. break;
  1251. default:
  1252. break;
  1253. }
  1254. break;
  1255. default:
  1256. break;
  1257. }
  1258. DPF_EXIT();
  1259. return fRet;
  1260. }
  1261. #undef DPF_MODNAME
  1262. #define DPF_MODNAME "ClearAllCheckboxes"
  1263. void ClearAllCheckboxes(HWND hDlg, HWND hwndListView, LONG lNumItems)
  1264. {
  1265. LONG lIndex;
  1266. // get a handle to the list view control
  1267. HWND hwnd = GetDlgItem(hDlg, IDC_LIST_GAMES);
  1268. if (hwnd == NULL)
  1269. {
  1270. LONG lRet = GetLastError();
  1271. DPF(DVF_ERRORLEVEL, "GetDlgItem failed, code: %i", lRet);
  1272. return;
  1273. }
  1274. for (lIndex = 0; lIndex < lNumItems; ++lIndex)
  1275. {
  1276. MySetCheckState(hwnd, lIndex, FALSE);
  1277. }
  1278. /*
  1279. if (!CheckDlgButton(hDlg, IDC_UNLISTEDCHECK, FALSE))
  1280. {
  1281. DPF(DVF_ERRORLEVEL, "Unable to clear unlisted games enable checkbox");
  1282. }
  1283. */
  1284. InvalidateRect(hwnd, NULL, TRUE);
  1285. UpdateWindow(hwnd);
  1286. return;
  1287. }
  1288. #undef DPF_MODNAME
  1289. #define DPF_MODNAME "ListViewSubclassProc"
  1290. INT_PTR CALLBACK ListViewSubclassProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  1291. {
  1292. DPF_ENTER();
  1293. LRESULT lResult;
  1294. switch (message)
  1295. {
  1296. case WM_LBUTTONDOWN:
  1297. ListViewLButtonDownHandler(hwnd, message, wParam, lParam);
  1298. break;
  1299. case WM_LBUTTONDBLCLK:
  1300. ListViewLButtonDblClkHandler(hwnd, message, wParam, lParam);
  1301. break;
  1302. case WM_KEYDOWN:
  1303. ListViewKeydownHandler(hwnd, message, wParam, lParam);
  1304. break;
  1305. default:
  1306. break;
  1307. }
  1308. lResult = CallWindowProc(g_ListViewProc, hwnd, message, wParam, lParam);
  1309. DPF_EXIT();
  1310. return lResult;
  1311. }
  1312. #undef DPF_MODNAME
  1313. #define DPF_MODNAME "ListViewLButtonDownHandler"
  1314. INT_PTR ListViewLButtonDownHandler(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  1315. {
  1316. DPF_ENTER();
  1317. LVHITTESTINFO lvHitTestInfo;
  1318. lvHitTestInfo.pt.x = GET_X_LPARAM(lParam);
  1319. lvHitTestInfo.pt.y = GET_Y_LPARAM(lParam);
  1320. ListView_SubItemHitTest(hwnd, &lvHitTestInfo);
  1321. if (lvHitTestInfo.flags & LVHT_ONITEMICON && lvHitTestInfo.iSubItem == 1)
  1322. {
  1323. MyToggleCheckState(hwnd, lvHitTestInfo.iItem);
  1324. }
  1325. DPF_EXIT();
  1326. return FALSE;
  1327. }
  1328. #undef DPF_MODNAME
  1329. #define DPF_MODNAME "ListViewLButtonDblClkHandler"
  1330. INT_PTR ListViewLButtonDblClkHandler(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  1331. {
  1332. DPF_ENTER();
  1333. LVHITTESTINFO lvHitTestInfo;
  1334. lvHitTestInfo.pt.x = GET_X_LPARAM(lParam);
  1335. lvHitTestInfo.pt.y = GET_Y_LPARAM(lParam);
  1336. ListView_HitTest(hwnd, &lvHitTestInfo);
  1337. if (lvHitTestInfo.flags & LVHT_ONITEMICON|LVHT_ONITEMLABEL)
  1338. {
  1339. LVITEM lvitem;
  1340. lvitem.mask = LVIF_IMAGE;
  1341. lvitem.iItem = lvHitTestInfo.iItem;
  1342. lvitem.iSubItem = 1;
  1343. if (ListView_GetItem(hwnd, &lvitem))
  1344. {
  1345. // we got the image, toggle the state
  1346. if (lvitem.iImage == g_iCheckboxEmptyIndex)
  1347. {
  1348. lvitem.iImage = g_iCheckboxFullIndex;
  1349. }
  1350. else
  1351. {
  1352. lvitem.iImage = g_iCheckboxEmptyIndex;
  1353. }
  1354. ListView_SetItem(hwnd, &lvitem);
  1355. InvalidateRect(hwnd, NULL, TRUE);
  1356. UpdateWindow(hwnd);
  1357. }
  1358. }
  1359. DPF_EXIT();
  1360. return FALSE;
  1361. }
  1362. #undef DPF_MODNAME
  1363. #define DPF_MODNAME "ListViewKeydownHandler"
  1364. INT_PTR ListViewKeydownHandler(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  1365. {
  1366. DPF_ENTER();
  1367. int iItem;
  1368. switch (wParam)
  1369. {
  1370. case VK_SPACE:
  1371. // The space bar was hit. Figure out if one of the
  1372. // list view items has focus and if so, toggle the
  1373. // checkbox state
  1374. iItem = ListView_GetNextItem(hwnd, -1, LVNI_FOCUSED|LVNI_SELECTED);
  1375. if (iItem != -1)
  1376. {
  1377. MyToggleCheckState(hwnd, iItem);
  1378. }
  1379. break;
  1380. default:
  1381. break;
  1382. }
  1383. DPF_EXIT();
  1384. return FALSE;
  1385. }
  1386. #undef DPF_MODNAME
  1387. #define DPF_MODNAME "MySetCheckState"
  1388. void MySetCheckState(HWND hwnd, int iItem, BOOL bChecked)
  1389. {
  1390. LVITEM lvitem;
  1391. lvitem.mask = LVIF_IMAGE;
  1392. lvitem.iItem = iItem;
  1393. lvitem.iSubItem = 1;
  1394. if (ListView_GetItem(hwnd, &lvitem))
  1395. {
  1396. // we got the image, set the check state
  1397. if (bChecked)
  1398. {
  1399. lvitem.iImage = g_iCheckboxFullIndex;
  1400. }
  1401. else
  1402. {
  1403. lvitem.iImage = g_iCheckboxEmptyIndex;
  1404. }
  1405. ListView_SetItem(hwnd, &lvitem);
  1406. InvalidateRect(hwnd, NULL, TRUE);
  1407. UpdateWindow(hwnd);
  1408. }
  1409. }
  1410. #undef DPF_MODNAME
  1411. #define DPF_MODNAME "MyGetCheckState"
  1412. BOOL MyGetCheckState(HWND hwnd, int iItem)
  1413. {
  1414. LVITEM lvitem;
  1415. lvitem.mask = LVIF_IMAGE;
  1416. lvitem.iItem = iItem;
  1417. lvitem.iSubItem = 1;
  1418. if (ListView_GetItem(hwnd, &lvitem))
  1419. {
  1420. // we got the image, return the state
  1421. if (lvitem.iImage == g_iCheckboxEmptyIndex)
  1422. {
  1423. return FALSE;
  1424. }
  1425. else
  1426. {
  1427. return TRUE;
  1428. }
  1429. }
  1430. return FALSE;
  1431. }
  1432. #undef DPF_MODNAME
  1433. #define DPF_MODNAME "MyToggleCheckState"
  1434. BOOL MyToggleCheckState(HWND hwnd, int iItem)
  1435. {
  1436. LVITEM lvitem;
  1437. lvitem.mask = LVIF_IMAGE;
  1438. lvitem.iItem = iItem;
  1439. lvitem.iSubItem = 1;
  1440. BOOL fRet = FALSE;
  1441. if (ListView_GetItem(hwnd, &lvitem))
  1442. {
  1443. // we got the image, toggle the state
  1444. if (lvitem.iImage == g_iCheckboxEmptyIndex)
  1445. {
  1446. lvitem.iImage = g_iCheckboxFullIndex;
  1447. fRet = FALSE;
  1448. }
  1449. else
  1450. {
  1451. lvitem.iImage = g_iCheckboxEmptyIndex;
  1452. fRet = TRUE;
  1453. }
  1454. ListView_SetItem(hwnd, &lvitem);
  1455. InvalidateRect(hwnd, NULL, TRUE);
  1456. UpdateWindow(hwnd);
  1457. }
  1458. return fRet;
  1459. }
  1460. ////////////////////////////////////
  1461. // copied verbatim from appman.cpp
  1462. ////////////////////////////////////
  1463. #define STR_LEN_32 32 // used by these functions...
  1464. static void RetrofitOnAdvHelp(LPARAM lParam)
  1465. {
  1466. DNASSERT (lParam);
  1467. // point to help file
  1468. LPTSTR pszHelpFileName = new TCHAR[STR_LEN_32];
  1469. DNASSERT (pszHelpFileName);
  1470. if( LoadString(ghInstance, IDS_HELPFILENAME, pszHelpFileName, STR_LEN_32) )
  1471. {
  1472. if( ((LPHELPINFO)lParam)->iContextType == HELPINFO_WINDOW )
  1473. WinHelp((HWND)((LPHELPINFO)lParam)->hItemHandle, pszHelpFileName, HELP_WM_HELP, (ULONG_PTR)gaHelpIDs);
  1474. }
  1475. #ifdef _DEBUG
  1476. else OutputDebugString(TEXT("JOY.CPL: AppMan.cpp: OnAdvHelp: LoadString Failed to find IDS_HELPFILENAME!\n"));
  1477. #endif // _DEBUG
  1478. if( pszHelpFileName )
  1479. delete[] (pszHelpFileName);
  1480. }
  1481. ////////////////////////////////////
  1482. // copied verbatim from appman.cpp
  1483. ////////////////////////////////////
  1484. static void RetrofitOnContextMenu(WPARAM wParam, LPARAM lParam)
  1485. {
  1486. // HWND hListCtrl = NULL
  1487. DNASSERT (wParam);
  1488. #if 0
  1489. hListCtrl = GetDlgItem((HWND) wParam, IDC_APPMAN_DRIVE_LIST);
  1490. // If you are on the ListCtrl...
  1491. if( (HWND)wParam == hListCtrl )
  1492. {
  1493. SetFocus(hListCtrl);
  1494. // Don't attempt if nothing selected
  1495. if( iItem != NO_ITEM )
  1496. OnListviewContextMenu(hListCtrl,lParam);
  1497. } else
  1498. #endif
  1499. {
  1500. // point to help file
  1501. LPTSTR pszHelpFileName = new TCHAR[STR_LEN_32];
  1502. DNASSERT (pszHelpFileName);
  1503. if( LoadString(ghInstance, IDS_HELPFILENAME, pszHelpFileName, STR_LEN_32) )
  1504. WinHelp((HWND)wParam, pszHelpFileName, HELP_CONTEXTMENU, (ULONG_PTR)gaHelpIDs);
  1505. #ifdef _DEBUG
  1506. else OutputDebugString(TEXT("JOY.CPL: appman.cpp: OnContextMenu: LoadString Failed to find IDS_HELPFILENAME!\n"));
  1507. #endif // _DEBUG
  1508. if( pszHelpFileName )
  1509. delete[] (pszHelpFileName);
  1510. }
  1511. }