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.

2171 lines
63 KiB

  1. //****************************************************************************
  2. //
  3. // File: joycpl.c
  4. // Content: Joystick configuration and testing
  5. // History:
  6. // Date By Reason
  7. // ==== == ======
  8. // 03-oct-94 craige initial implementation
  9. // 05-nov-94 craige generalized 4 axis joysticks and other improvements
  10. // 11-nov-94 craige allow multiple copies of tab to run
  11. // 22-nov-94 craige tweaks to calibration code
  12. // 29-nov-94 craige small bugs
  13. // 08-dec-94 craige generalized second joystick
  14. // 11-dec-94 craige split into component parts
  15. // 15-dec-94 craige allow N joysticks
  16. // 18-dec-94 craige process UV
  17. // 05-jan-95 craige external rudder bug
  18. // 05-mar-95 craige Bug 9998: pass id -1 to get base dev caps
  19. // Bug 15334: allow reset of user values for compatiblity
  20. // 06-mar-95 craige Bug 7608: deleting VxD name if joystick not present
  21. // caused unplugged joystick to never come back
  22. //
  23. // Copyright (c) Microsoft Corporation 1994
  24. //
  25. //****************************************************************************
  26. #pragma pack (8)
  27. #include "stdafx.h"
  28. #include "assert.h"
  29. #include "joycpl.h"
  30. #include "resource.h"
  31. #include "baseids.h"
  32. #include "pov.h"
  33. #include "pinfo.h"
  34. #include "comstr.h"
  35. #include "joyarray.h" // Help array
  36. extern USHORT gnID; // ID as sent from Client via SetID
  37. extern BOOL fIsSideWinder;
  38. static BOOL fIsLoaded = 0;
  39. // Context sensitive help stuff!
  40. static void OnContextMenu(WPARAM wParam);
  41. extern const DWORD gaHelpIDs[];
  42. #ifdef DEBUG
  43. void cdecl MBOX(LPSTR szFormat, ...)
  44. {
  45. char ach[256];
  46. wvsprintf( ach,szFormat,(LPSTR)(&szFormat+1));
  47. MessageBox( NULL, ach, "JOYCPL", MB_OK | MB_SYSTEMMODAL );
  48. }
  49. #endif
  50. extern "C" WINMMAPI MMRESULT WINAPI joyConfigChanged(DWORD);
  51. /***************************************************************************
  52. MEMORY MANAGEMENT ROUTINES FOLLOW
  53. ***************************************************************************/
  54. #ifdef DEBUG
  55. DWORD allocCount;
  56. #endif
  57. // DoAlloc - allocate memory
  58. LPVOID DoAlloc( DWORD size )
  59. {
  60. LPVOID res;
  61. res = LocalAlloc( LPTR, size );
  62. #ifdef DEBUG
  63. allocCount++;
  64. #endif
  65. return(res);
  66. } /* DoAlloc */
  67. /*
  68. * DoFree - free allocated memory
  69. */
  70. void DoFree( LPVOID ptr )
  71. {
  72. if( ptr != NULL )
  73. {
  74. LocalFree( ptr );
  75. #ifdef DEBUG
  76. allocCount--;
  77. if( allocCount < 0 )
  78. {
  79. DPF( "JOYCPL: Too many frees, allocCount=%d\r\n", allocCount );
  80. }
  81. #endif
  82. }
  83. } /* DoFree */
  84. /***************************************************************************
  85. REGISTRY RELATED ROUTINES FOLLOW
  86. ***************************************************************************/
  87. // getDevCaps - get the joystick device caps
  88. static void getDevCaps( LPGLOBALVARS pgv )
  89. {
  90. JOYCAPS jc;
  91. if( joyGetDevCaps( pgv->iJoyId, &jc, sizeof( jc ) ) == JOYERR_NOERROR )
  92. {
  93. pgv->joyRange.jpMin.dwX = jc.wXmin;
  94. pgv->joyRange.jpMax.dwX = jc.wXmax;
  95. pgv->joyRange.jpMin.dwY = jc.wYmin;
  96. pgv->joyRange.jpMax.dwY = jc.wYmax;
  97. pgv->joyRange.jpMin.dwZ = jc.wZmin;
  98. pgv->joyRange.jpMax.dwZ = jc.wZmax;
  99. pgv->joyRange.jpMin.dwR = jc.wRmin;
  100. pgv->joyRange.jpMax.dwR = jc.wRmax;
  101. pgv->joyRange.jpMin.dwU = jc.wUmin;
  102. pgv->joyRange.jpMax.dwU = jc.wUmax;
  103. pgv->joyRange.jpMin.dwV = jc.wVmin;
  104. pgv->joyRange.jpMax.dwV = jc.wVmax;
  105. pgv->dwMaxAxes = (DWORD) jc.wMaxAxes;
  106. }
  107. } /* getDevCaps */
  108. /*
  109. * RegistryUpdated - notify the driver that the registry is updated
  110. */
  111. void RegistryUpdated( LPGLOBALVARS pgv )
  112. {
  113. // joyConfigChanged( 0 );
  114. if( pgv != NULL )
  115. getDevCaps( pgv ); // devcaps could change
  116. } /* RegistryUpdated */
  117. /*
  118. * createSettingsKeyFromCurr - create a settings key for a specific joystick
  119. */
  120. static void createSettingsKeyFromCurr( LPGLOBALVARS pgv, LPSTR str )
  121. {
  122. assert(pgv);
  123. char tmp[MAX_STR];
  124. int type;
  125. LPJOYDATA pjd;
  126. pjd = pgv->pjd;
  127. assert(pjd);
  128. if( pgv->joyHWCurr.dwUsageSettings & JOY_US_ISOEM )
  129. {
  130. type = pgv->joyHWCurr.dwType - JOY_HW_LASTENTRY;
  131. if( type < 0 || type >= pjd->oemCount )
  132. tmp[0] = 0;
  133. else
  134. lstrcpy( tmp, pjd->oemList[type].keyname );
  135. } else wsprintf( tmp, "predef%d", pgv->joyHWCurr.dwType );
  136. wsprintf( str, "%s\\%s", pjd->regSettingsCfgKey, tmp );
  137. } /* createSettingsKeyFromCurr */
  138. static CListBox ChangeListCtrl;
  139. // regSaveSpecificJoyHW - save specific joystick hardware config. to the registry
  140. static void regSaveSpecificJoyHW( LPGLOBALVARS pgv )
  141. {
  142. assert(pgv);
  143. char str[MAX_STR];
  144. HKEY hkey;
  145. char jcfg[MAX_STR];
  146. if( pgv->joyHWCurr.dwType == JOY_HW_NONE ) return;
  147. createSettingsKeyFromCurr( pgv, str );
  148. if( !RegCreateKey( HKEY_LOCAL_MACHINE, str, &hkey ) )
  149. {
  150. GETKEYNAME( pgv, jcfg, REGSTR_VAL_JOYNCONFIG );
  151. RegSetValueEx( hkey, jcfg, 0, REG_BINARY, (CONST LPBYTE)&pgv->joyHWCurr, sizeof( pgv->joyHWCurr ));
  152. RegCloseKey( hkey );
  153. }
  154. } /* regSaveSpecificJoyHW */
  155. /*
  156. * regCreateCurrKey - create the current joystick settings key
  157. */
  158. static HKEY regCreateCurrKey( LPGLOBALVARS pgv )
  159. {
  160. assert(pgv);
  161. HKEY hkey;
  162. if( !RegCreateKey( HKEY_LOCAL_MACHINE, pgv->pjd->regCurrCfgKey, &hkey ) )
  163. return(hkey);
  164. else
  165. return(NULL);
  166. } /* regCreateCurrKey */
  167. // RegSaveCurrentJoyHW - save the joystick info to the current entry in the registry
  168. void RegSaveCurrentJoyHW( LPGLOBALVARS pgv )
  169. {
  170. HKEY hkey;
  171. LPSTR sptr;
  172. char vname[MAX_STR];
  173. char oname[MAX_STR];
  174. char coname[MAX_STR];
  175. int type;
  176. LPJOYDATA pjd;
  177. assert(pgv);
  178. hkey = regCreateCurrKey( pgv );
  179. assert(hkey);
  180. if( hkey == NULL )
  181. {
  182. DPF( "Could not save current joystick settings!\r\n" );
  183. return;
  184. }
  185. pjd = pgv->pjd;
  186. assert(pjd);
  187. if( pgv->joyHWCurr.dwUsageSettings & JOY_US_ISOEM )
  188. sptr = pjd->oemList[ pgv->joyHWCurr.dwType - JOY_HW_LASTENTRY ].keyname;
  189. GETKEYNAME( pgv, vname, REGSTR_VAL_JOYNCONFIG );
  190. GETKEYNAME( pgv, oname, REGSTR_VAL_JOYNOEMNAME );
  191. GETKEYNAME( pgv, coname, REGSTR_VAL_JOYNOEMCALLOUT );
  192. RegSetValueEx( hkey, vname, 0, REG_BINARY, (CONST LPBYTE)&pgv->joyHWCurr, sizeof( pgv->joyHWCurr ) );
  193. if( pgv->joyHWCurr.dwUsageSettings & JOY_US_ISOEM )
  194. {
  195. RegSetValueEx( hkey, oname, 0, REG_SZ,(const unsigned char *) sptr, strlen( sptr ) + 1 );
  196. // set up VxD name for this joystick
  197. type = pgv->joyHWCurr.dwType - JOY_HW_LASTENTRY;
  198. if( (pjd->oemList[type].vxd_name[0] != 0) )
  199. {
  200. RegSetValueEx( hkey, coname, 0, REG_SZ, (const unsigned char *) pjd->oemList[type].vxd_name,
  201. lstrlen( pjd->oemList[type].vxd_name )+1 );
  202. } else RegDeleteValue( hkey, coname );
  203. } else
  204. {
  205. RegDeleteValue( hkey, oname );
  206. RegDeleteValue( hkey, coname );
  207. }
  208. RegCloseKey( hkey );
  209. } /* RegSaveCurrentJoyHW */
  210. // regPermSaveAllInfo - save joystick data to the registry for good
  211. static void regPermSaveAllInfo( LPGLOBALVARS pgv )
  212. {
  213. assert(pgv);
  214. // save specific hardware settings to the registry
  215. regSaveSpecificJoyHW( pgv );
  216. // save current current hardware to the registry
  217. RegSaveCurrentJoyHW( pgv );
  218. RegistryUpdated( pgv );
  219. } /* regPermSaveAllInfo */
  220. // setHWCurrType - set the current hardware type (check for OEM type)
  221. static BOOL setHWCurrType( LPGLOBALVARS pgv, HKEY hkey, LPJOYREGHWCONFIG pcfg )
  222. {
  223. assert(pgv);
  224. assert(hkey);
  225. assert(pcfg);
  226. char str[MAX_STR];
  227. char pname[MAX_STR];
  228. int i;
  229. DWORD regtype;
  230. DWORD cb;
  231. LPJOYDATA pjd;
  232. if( !(pcfg->dwUsageSettings & JOY_US_ISOEM) )
  233. return(TRUE);
  234. GETKEYNAME( pgv, pname, REGSTR_VAL_JOYNOEMNAME );
  235. cb = sizeof( str );
  236. if( RegQueryValueEx( hkey, pname, NULL, &regtype, (CONST LPBYTE)str, &cb) )
  237. return(FALSE);
  238. if( regtype != REG_SZ )
  239. return(FALSE);
  240. pjd = pgv->pjd;
  241. assert(pjd);
  242. for( i=0;i<pjd->oemCount;i++ )
  243. {
  244. if( !lstrcmpi( str, pjd->oemList[i].keyname ) )
  245. {
  246. pcfg->dwType = i + JOY_HW_LASTENTRY;
  247. return(TRUE);
  248. }
  249. }
  250. return(FALSE);
  251. } /* setHWCurrType */
  252. // regGetCurrHW - get the information about the current configuration from the registry
  253. static void regGetCurrHW( LPGLOBALVARS pgv )
  254. {
  255. assert(pgv);
  256. DWORD regtype;
  257. DWORD cb;
  258. JOYREGHWCONFIG config;
  259. HKEY hkey;
  260. char str[MAX_STR];
  261. if( hkey = regCreateCurrKey( pgv ) )
  262. {
  263. cb = sizeof( config );
  264. GETKEYNAME( pgv, str, REGSTR_VAL_JOYNCONFIG );
  265. if( !RegQueryValueEx( hkey, str, NULL, &regtype, (CONST LPBYTE)&config, &cb) )
  266. {
  267. if( regtype == REG_BINARY && cb == sizeof( config ) )
  268. {
  269. if( setHWCurrType( pgv, hkey, &config ) )
  270. pgv->joyHWCurr = config;
  271. }
  272. }
  273. }
  274. cb = sizeof( config );
  275. RegCloseKey( hkey );
  276. } /* regGetCurrHW */
  277. // regGetOEMStr - get an OEM string
  278. static BOOL regGetOEMStr( HKEY hkey, LPSTR keyname, LPSTR buff, int size, LPSTR *res )
  279. {
  280. assert(hkey);
  281. assert(keyname);
  282. DWORD cb;
  283. DWORD type;
  284. LPSTR str;
  285. int slen;
  286. cb = size;
  287. slen = 1;
  288. if( !RegQueryValueEx( hkey, keyname, NULL, &type, (CONST LPBYTE)buff, &cb ) )
  289. {
  290. if( type == REG_SZ )
  291. slen = strlen( buff ) + 1;
  292. }
  293. str = (char *) DoAlloc( slen );
  294. assert(str);
  295. if( str != NULL )
  296. {
  297. if( slen == 1 )
  298. str[0] = 0;
  299. else
  300. lstrcpy( str, buff );
  301. }
  302. *res = str;
  303. if( str == NULL )
  304. return(TRUE);
  305. return(FALSE);
  306. } /* regGetOEMStr */
  307. #define RANGE_MIN 0
  308. #define RANGE_MAX 65535
  309. /*
  310. * checkNonStandardUserVals
  311. */
  312. static BOOL checkNonStandardUserVals( LPJOYREGUSERVALUES puv )
  313. {
  314. assert(puv);
  315. if( (puv->jrvRanges.jpMin.dwX != RANGE_MIN) ||
  316. (puv->jrvRanges.jpMin.dwY != RANGE_MIN) ||
  317. (puv->jrvRanges.jpMin.dwZ != RANGE_MIN) ||
  318. (puv->jrvRanges.jpMin.dwR != RANGE_MIN) ||
  319. (puv->jrvRanges.jpMin.dwU != RANGE_MIN) ||
  320. (puv->jrvRanges.jpMin.dwV != RANGE_MIN) ||
  321. (puv->jrvRanges.jpMax.dwX != RANGE_MAX) ||
  322. (puv->jrvRanges.jpMax.dwY != RANGE_MAX) ||
  323. (puv->jrvRanges.jpMax.dwZ != RANGE_MAX) ||
  324. (puv->jrvRanges.jpMax.dwR != RANGE_MAX) ||
  325. (puv->jrvRanges.jpMax.dwU != RANGE_MAX) ||
  326. (puv->jrvRanges.jpMax.dwV != RANGE_MAX) ||
  327. (puv->dwTimeOut != 0x1000) ||
  328. (puv->jpDeadZone.dwX != 0) ||
  329. (puv->jpDeadZone.dwY != 0) )
  330. {
  331. return(TRUE);
  332. }
  333. return(FALSE);
  334. } /* checkNonStandardUserVals */
  335. // regSetUserVals - set user values to our defaults
  336. static void regSetUserVals( LPJOYDATA pjd, BOOL retest )
  337. {
  338. assert(pjd);
  339. JOYREGUSERVALUES uv;
  340. JOYREGUSERVALUES ouv;
  341. HKEY hkey;
  342. DWORD regtype;
  343. DWORD cb;
  344. if( !RegOpenKey( HKEY_LOCAL_MACHINE, pjd->regCfgKey, &hkey ) )
  345. {
  346. /*
  347. * build the default settings
  348. */
  349. memset( &uv, 0, sizeof( uv ) );
  350. // fix #2245, take the Greater of the two timeout values.
  351. uv.dwTimeOut = (pjd->userVals.dwTimeOut > 0x1000) ? pjd->userVals.dwTimeOut : 0x1000;
  352. uv.jpDeadZone.dwX = 0;
  353. uv.jpDeadZone.dwY = 0;
  354. uv.jrvRanges.jpMin.dwX = RANGE_MIN;
  355. uv.jrvRanges.jpMin.dwY = RANGE_MIN;
  356. uv.jrvRanges.jpMin.dwZ = RANGE_MIN;
  357. uv.jrvRanges.jpMin.dwR = RANGE_MIN;
  358. uv.jrvRanges.jpMin.dwU = RANGE_MIN;
  359. uv.jrvRanges.jpMin.dwV = RANGE_MIN;
  360. uv.jrvRanges.jpMax.dwX = RANGE_MAX;
  361. uv.jrvRanges.jpMax.dwY = RANGE_MAX;
  362. uv.jrvRanges.jpMax.dwZ = RANGE_MAX;
  363. uv.jrvRanges.jpMax.dwR = RANGE_MAX;
  364. uv.jrvRanges.jpMax.dwU = RANGE_MAX;
  365. uv.jrvRanges.jpMax.dwV = RANGE_MAX;
  366. if( retest )
  367. {
  368. /*
  369. * see if the values have changed since we last set them:
  370. * if yes, then we need to reset our remembered values
  371. */
  372. DPF( "Looking for USER entries\r\n" );
  373. cb = sizeof( ouv );
  374. if( !RegQueryValueEx( hkey, REGSTR_VAL_JOYUSERVALUES, NULL,
  375. &regtype, (CONST LPBYTE)&ouv, &cb) )
  376. {
  377. DPF( "found REGSTR_VAL_JOYUSERVALUES\r\n" );
  378. if( regtype == REG_BINARY && cb == sizeof( ouv ) )
  379. {
  380. if( memcmp( &uv, &ouv, sizeof( uv ) ) )
  381. {
  382. DPF( "USER entries changed!\r\n" );
  383. pjd->bHasUserVals = TRUE;
  384. pjd->bDeleteUserVals = FALSE;
  385. pjd->userVals = ouv;
  386. }
  387. }
  388. } else
  389. {
  390. if( pjd->bHasUserVals )
  391. {
  392. DPF( "USER entries changed, no longer exist!\r\n" );
  393. pjd->bHasUserVals = FALSE;
  394. pjd->bDeleteUserVals = TRUE;
  395. }
  396. }
  397. }
  398. /*
  399. * set our new values
  400. */
  401. RegSetValueEx( hkey, REGSTR_VAL_JOYUSERVALUES, 0, REG_BINARY,
  402. (CONST LPBYTE)&uv, sizeof( uv ) );
  403. RegCloseKey( hkey );
  404. }
  405. } /* regSetUserVals */
  406. // regUserValsInit - save old user values, and init to ones we like
  407. static void regUserValsInit( LPJOYDATA pjd )
  408. {
  409. assert(pjd);
  410. HKEY hkey;
  411. DWORD regtype;
  412. DWORD cb;
  413. pjd->bHasUserVals = FALSE;
  414. pjd->bDeleteUserVals = FALSE;
  415. if( !RegOpenKey( HKEY_LOCAL_MACHINE, pjd->regCfgKey, &hkey ) )
  416. {
  417. cb = sizeof( pjd->userVals );
  418. if( !RegQueryValueEx( hkey, REGSTR_VAL_JOYUSERVALUES, NULL,
  419. &regtype, (CONST LPBYTE)&pjd->userVals, &cb) )
  420. {
  421. if( regtype == REG_BINARY && cb == sizeof( pjd->userVals ) )
  422. {
  423. pjd->bHasUserVals = TRUE;
  424. DPF( "USER entries exist!\r\n" );
  425. }
  426. pjd->bHasNonStandardUserVals = checkNonStandardUserVals( &pjd->userVals );
  427. } else
  428. {
  429. pjd->bDeleteUserVals = TRUE;
  430. pjd->bHasNonStandardUserVals = FALSE;
  431. DPF( "USER entries don't exist!\r\n" );
  432. }
  433. RegCloseKey( hkey );
  434. }
  435. regSetUserVals( pjd, FALSE );
  436. } /* regUserValsInit */
  437. // regUserValsFini - restore old user values
  438. static void regUserValsFini( LPJOYDATA pjd )
  439. {
  440. assert(pjd);
  441. HKEY hkey = 0;
  442. if( pjd->bHasUserVals || pjd->bDeleteUserVals )
  443. {
  444. if( !RegOpenKey( HKEY_LOCAL_MACHINE, pjd->regCfgKey, &hkey ) )
  445. {
  446. if( pjd->bHasUserVals )
  447. {
  448. DPF( "resetting USER entries!\r\n" );
  449. RegSetValueEx( hkey, REGSTR_VAL_JOYUSERVALUES, 0, REG_BINARY,
  450. (CONST LPBYTE)&pjd->userVals, sizeof( pjd->userVals ) );
  451. } else
  452. {
  453. DPF( "deleting USER entries!\r\n" );
  454. RegDeleteValue( hkey, REGSTR_VAL_JOYUSERVALUES );
  455. }
  456. RegistryUpdated( NULL );
  457. }
  458. pjd->bHasUserVals = FALSE;
  459. pjd->bDeleteUserVals = FALSE;
  460. }
  461. } /* regUserValsFini */
  462. /***************************************************************************
  463. CUSTOM JOYSTICK SELECTION FUNCTIONS FOLLOW
  464. ***************************************************************************/
  465. /*
  466. * custom joystick variables
  467. */
  468. typedef struct
  469. {
  470. LPGLOBALVARS pgv;
  471. BOOL bHasZ;
  472. BOOL bHasR;
  473. BOOL bHasPOV;
  474. BOOL bIsYoke;
  475. BOOL bIsGamePad;
  476. BOOL bIsCarCtrl;
  477. BOOL bHas2Buttons;
  478. } cust_vars, *LPCUSTVARS;
  479. // enableCustomSpecial - enable the special section of the custom dialog box
  480. static void enableCustomSpecial( HWND hwnd, BOOL on )
  481. {
  482. ASSERT (::IsWindow(hwnd));
  483. HWND hCtrl = GetDlgItem( hwnd, IDC_JOYISYOKE );
  484. ASSERT (::IsWindow(hCtrl));
  485. EnableWindow( hCtrl, on );
  486. hCtrl = GetDlgItem( hwnd, IDC_JOYISGAMEPAD );
  487. ASSERT (::IsWindow(hCtrl));
  488. EnableWindow( hCtrl, on );
  489. hCtrl = GetDlgItem( hwnd, IDC_JOYISCARCTRL );
  490. ASSERT (::IsWindow(hCtrl));
  491. EnableWindow( hCtrl, on );
  492. CheckDlgButton( hwnd, IDC_JOYUSESPECIAL, on );
  493. if( !on )
  494. {
  495. CheckDlgButton( hwnd, IDC_JOYISYOKE, FALSE );
  496. CheckDlgButton( hwnd, IDC_JOYISGAMEPAD, FALSE );
  497. CheckDlgButton( hwnd, IDC_JOYISCARCTRL, FALSE );
  498. }
  499. } /* enableCustomSpecial */
  500. // CustomProc - callback procedure for custom joystick setup
  501. BOOL CALLBACK CustomProc( HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam)
  502. {
  503. int id;
  504. LPGLOBALVARS pgv;
  505. LPCUSTVARS pcv;
  506. switch( umsg )
  507. {
  508. case WM_DESTROY:
  509. /*
  510. * don't free the dialog's variables here, they are returned to the
  511. * creator; the creator will free them
  512. */
  513. break;
  514. case WM_INITDIALOG:
  515. // create variables for the custom dialog
  516. pcv = (cust_vars *) DoAlloc( sizeof( cust_vars ) );
  517. assert(pcv);
  518. SetWindowLong( hwnd, DWL_USER, (LONG) pcv );
  519. if( pcv == NULL )
  520. {
  521. EndDialog( hwnd, 0 );
  522. return(FALSE);
  523. }
  524. pgv = (LPGLOBALVARS) lParam;
  525. assert(pgv);
  526. pcv->pgv = pgv;
  527. // set up initial dialog state
  528. pcv->bHasZ = (pgv->joyHWCurr.hws.dwFlags & JOY_HWS_HASZ);
  529. pcv->bHasR = (pgv->joyHWCurr.hws.dwFlags & JOY_HWS_HASR);
  530. pcv->bHas2Buttons = (pgv->joyHWCurr.hws.dwNumButtons == 2);
  531. pcv->bHasPOV = (pgv->joyHWCurr.hws.dwFlags & JOY_HWS_HASPOV);
  532. pcv->bIsYoke = (pgv->joyHWCurr.hws.dwFlags & JOY_HWS_ISYOKE);
  533. pcv->bIsGamePad = (pgv->joyHWCurr.hws.dwFlags & JOY_HWS_ISGAMEPAD);
  534. pcv->bIsCarCtrl = (pgv->joyHWCurr.hws.dwFlags & JOY_HWS_ISCARCTRL);
  535. if( pcv->bHasZ && pcv->bHasR )
  536. {
  537. CheckRadioButton( hwnd, IDC_JOY2AXIS, IDC_JOY4AXIS, IDC_JOY4AXIS );
  538. } else if( pcv->bHasZ )
  539. {
  540. CheckRadioButton( hwnd, IDC_JOY2AXIS, IDC_JOY4AXIS, IDC_JOY3AXIS );
  541. } else
  542. {
  543. CheckRadioButton( hwnd, IDC_JOY2AXIS, IDC_JOY4AXIS, IDC_JOY2AXIS );
  544. }
  545. if( pcv->bHas2Buttons )
  546. {
  547. CheckRadioButton( hwnd, IDC_JOY2BUTTON, IDC_JOY4BUTTON, IDC_JOY2BUTTON );
  548. } else
  549. {
  550. CheckRadioButton( hwnd, IDC_JOY2BUTTON, IDC_JOY4BUTTON, IDC_JOY4BUTTON );
  551. }
  552. CheckDlgButton( hwnd, IDC_JOYHASPOV, pcv->bHasPOV );
  553. id = -1;
  554. if( pcv->bIsYoke )
  555. {
  556. id = IDC_JOYISYOKE;
  557. } else if( pcv->bIsGamePad )
  558. {
  559. id = IDC_JOYISGAMEPAD;
  560. } else if( pcv->bIsCarCtrl )
  561. {
  562. id = IDC_JOYISCARCTRL;
  563. }
  564. if( id != -1 )
  565. {
  566. enableCustomSpecial( hwnd, TRUE );
  567. CheckRadioButton( hwnd, IDC_JOYISYOKE, IDC_JOYISCARCTRL, id );
  568. } else
  569. {
  570. enableCustomSpecial( hwnd, FALSE );
  571. }
  572. return(FALSE);
  573. case WM_COMMAND:
  574. pcv = (LPCUSTVARS) GetWindowLong( hwnd, DWL_USER );
  575. id = GET_WM_COMMAND_ID(wParam, lParam);
  576. switch( id )
  577. {
  578. case IDC_JOY2AXIS:
  579. case IDC_JOY3AXIS:
  580. case IDC_JOY4AXIS:
  581. CheckRadioButton( hwnd, IDC_JOY2AXIS, IDC_JOY4AXIS, id );
  582. pcv->bHasZ = FALSE;
  583. pcv->bHasR = FALSE;
  584. if( id == IDC_JOY3AXIS )
  585. {
  586. pcv->bHasZ = TRUE;
  587. } else if( id == IDC_JOY4AXIS )
  588. {
  589. pcv->bHasZ = TRUE;
  590. pcv->bHasR = TRUE;
  591. }
  592. break;
  593. case IDC_JOY2BUTTON:
  594. case IDC_JOY4BUTTON:
  595. CheckRadioButton( hwnd, IDC_JOY2BUTTON, IDC_JOY4BUTTON, id );
  596. pcv->bHas2Buttons = (id == IDC_JOY2BUTTON);
  597. break;
  598. case IDC_JOYUSESPECIAL:
  599. enableCustomSpecial( hwnd, IsDlgButtonChecked( hwnd, IDC_JOYUSESPECIAL ) );
  600. pcv->bIsYoke = FALSE;
  601. pcv->bIsGamePad = FALSE;
  602. pcv->bIsCarCtrl = FALSE;
  603. break;
  604. case IDC_JOYHASPOV:
  605. pcv->bHasPOV = !pcv->bHasPOV;
  606. break;
  607. case IDC_JOYISYOKE:
  608. case IDC_JOYISGAMEPAD:
  609. case IDC_JOYISCARCTRL:
  610. pcv->bIsYoke = (id == IDC_JOYISYOKE);
  611. pcv->bIsGamePad = (id == IDC_JOYISGAMEPAD);
  612. pcv->bIsCarCtrl = (id == IDC_JOYISCARCTRL);
  613. CheckRadioButton( hwnd, IDC_JOYISYOKE, IDC_JOYISCARCTRL, id );
  614. break;
  615. case IDCANCEL:
  616. EndDialog( hwnd, 0 );
  617. break;
  618. case IDOK:
  619. pcv = (LPCUSTVARS) GetWindowLong( hwnd, DWL_USER );
  620. EndDialog(hwnd, (int) pcv );
  621. break;
  622. }
  623. break;
  624. default:
  625. break;
  626. }
  627. return(FALSE);
  628. } /* CustomProc */
  629. /***************************************************************************
  630. MAIN DIALOG FUNCTIONS FOLLOW
  631. ***************************************************************************/
  632. // variables used by joystick tab dialog
  633. typedef struct
  634. {
  635. LPGLOBALVARS pgv;
  636. } JTVARS, *LPJTVARS;
  637. // numJoyAxes - get number of axes on a joystick
  638. static int numJoyAxes( LPGLOBALVARS pgv )
  639. {
  640. assert(pgv);
  641. DWORD flags;
  642. int axis_count;
  643. flags = pgv->joyHWCurr.hws.dwFlags;
  644. axis_count = 2;
  645. if( flags & JOY_HWS_HASZ )
  646. {
  647. axis_count++;
  648. }
  649. if( flags & JOY_HWS_HASR )
  650. {
  651. axis_count++;
  652. }
  653. if( (flags & JOY_HWS_HASPOV) && (flags & JOY_HWS_POVISPOLL) )
  654. {
  655. axis_count++;
  656. }
  657. return(axis_count);
  658. } /* numJoyAxes */
  659. // saveHWSettings - save the current hardware settings
  660. static void saveHWSettings( LPGLOBALVARS pgv )
  661. {
  662. assert(pgv);
  663. pgv->joyHWOrig = pgv->joyHWCurr;
  664. } /* saveHWSettings */
  665. // restoreHWSettings - restore current hw settings to saved values
  666. static void restoreHWSettings( LPGLOBALVARS pgv )
  667. {
  668. assert(pgv);
  669. pgv->joyHWCurr = pgv->joyHWOrig;
  670. RegSaveCurrentJoyHW( pgv );
  671. } /* restoreHWSettings */
  672. // getActiveFlags - poll and test which joysticks are currently plugged in
  673. static unsigned getActiveFlags( LPGLOBALVARS pgv )
  674. {
  675. JOYINFOEX ji;
  676. MMRESULT rc;
  677. unsigned val;
  678. assert(pgv);
  679. // check for presense of joystick 1 and joystick 2
  680. val = 0;
  681. ji.dwSize = sizeof( ji );
  682. ji.dwFlags = JOY_RETURNX|JOY_RETURNY|JOY_CAL_READXYONLY|JOY_CAL_READALWAYS;
  683. rc = joyGetPosEx( pgv->iJoyId, &ji );
  684. DPF( "joyGetPosEx = %d\r\n", rc );
  685. if( rc == JOYERR_NOERROR )
  686. {
  687. val = HASJOY;
  688. }
  689. // check if either could have a rudder attached.
  690. ji.dwFlags = JOY_RETURNR | JOY_CAL_READRONLY;
  691. if( (numJoyAxes( pgv ) < 4) &&
  692. !(pgv->joyHWCurr.hws.dwFlags & JOY_HWS_HASR ) )
  693. {
  694. rc = joyGetPosEx( pgv->iJoyId, &ji );
  695. if( rc ==JOYERR_NOERROR )
  696. {
  697. val |= HASRUDDERMAYBE;
  698. }
  699. }
  700. return(val);
  701. } /* getActiveFlags */
  702. // enableTestCal - enable/disable test and calibrate buttons
  703. static void enableTestCal( HWND hwnd, int hw_type )
  704. {
  705. ASSERT(::IsWindow(hwnd));
  706. BOOL enable = (hw_type != JOY_HW_NONE);
  707. HWND hCtrl = GetDlgItem( hwnd, IDC_JOYCALIBRATE );
  708. ASSERT (::IsWindow(hCtrl));
  709. EnableWindow( hCtrl, enable );
  710. } /* enableTestCal */
  711. // cleanUpJoyDlg - clean up allocated stuff
  712. static void cleanUpJoyDlg( HWND hwnd )
  713. {
  714. assert(hwnd);
  715. LPGLOBALVARS pgv;
  716. pgv = (LPGLOBALVARS) GetWindowLong( hwnd, DWL_USER );
  717. if( pgv == NULL )
  718. return;
  719. // ditch timer
  720. if( pgv->pjd->bHasTimer )
  721. {
  722. KillTimer( hwnd, TIMER_ID );
  723. pgv->pjd->bHasTimer = FALSE;
  724. }
  725. // done with our variables
  726. #if defined( WANT_SHEETS )
  727. DoFree( pgv );
  728. #endif
  729. } /* cleanUpJoyDlg */
  730. // enableJoyWindows - enable controls for a joystick
  731. static void enableJoyWindows( LPGLOBALVARS pgv, HWND hwnd, BOOL enable )
  732. {
  733. HWND hCtrl = GetDlgItem(hwnd,IDC_JOYCALIBRATE);
  734. ASSERT (::IsWindow(hCtrl));
  735. EnableWindow( hCtrl, enable );
  736. } /* enableJoyWindows */
  737. // enableActiveJoystick - enable dialog controls based on presence of joysticks
  738. static void enableActiveJoystick( LPGLOBALVARS pgv, HWND hwnd )
  739. {
  740. assert(pgv);
  741. assert(hwnd);
  742. BOOL allowj;
  743. char str[MAX_STR];
  744. unsigned joys;
  745. LPSTR text;
  746. // check what joysticks are active; if it hasn't changed, just return
  747. joys = getActiveFlags( pgv );
  748. if( pgv->joyActiveFlags == joys )
  749. return;
  750. pgv->joyActiveFlags = joys;
  751. // turn off the rudder if it is gone
  752. if( !(joys & HASRUDDERMAYBE) )
  753. {
  754. pgv->joyHWCurr.dwUsageSettings &= ~JOY_US_HASRUDDER;
  755. CheckDlgButton( hwnd, IDC_JOY1HASRUDDER, FALSE );
  756. }
  757. // enable the appropriate windows
  758. allowj = ((joys & HASJOY) != 0);
  759. enableJoyWindows( pgv, hwnd, allowj );
  760. HWND hCtrl = GetDlgItem( hwnd, IDC_JOY1HASRUDDER );
  761. ASSERT (::IsWindow(hCtrl));
  762. EnableWindow( hCtrl, allowj && (joys & HASRUDDERMAYBE) );
  763. // set message for the user if there is no joystick plugged in, or if there is no joystick driver present
  764. if( allowj )
  765. {
  766. text = "";
  767. } else
  768. {
  769. text = str;
  770. LoadString( GetResourceInstance(), (joyGetNumDevs()) ? IDS_JOYUNPLUGGED : IDS_JOYNOTPRESENT, str, sizeof( str ) );
  771. }
  772. if( allowj )
  773. enableTestCal( hwnd, pgv->joyHWCurr.dwType );
  774. if( allowj )
  775. pgv->joyHWCurr.dwUsageSettings |= JOY_US_PRESENT;
  776. else
  777. pgv->joyHWCurr.dwUsageSettings &= ~JOY_US_PRESENT;
  778. RegSaveCurrentJoyHW( pgv );
  779. RegistryUpdated( pgv );
  780. } /* enableActiveJoystick */
  781. #ifdef DEAD_CODE
  782. /*
  783. * getNewJoyInfo - get information from the registry about a new joystick.
  784. * If no info, default to joyHWDefault settings
  785. */
  786. static void getNewJoyInfo( LPGLOBALVARS pgv, HWND hwnd )
  787. {
  788. assert(pgv);
  789. assert(hwnd);
  790. DWORD hw_type;
  791. HKEY hkey;
  792. char str[MAX_STR];
  793. char jcfg[MAX_STR];
  794. DWORD regtype;
  795. JOYREGHWCONFIG config;
  796. DWORD cb;
  797. BOOL same;
  798. int rc;
  799. GETKEYNAME( pgv, jcfg, REGSTR_VAL_JOYNCONFIG );
  800. // get the hardware type
  801. hw_type = SendDlgItemMessage( hwnd, IDC_JOYSELECT, CB_GETCURSEL, 0, 0L );
  802. same = (hw_type == pgv->joyHWCurr.dwType);
  803. // read the info from the registry if a new hardware type selected
  804. if( !same )
  805. {
  806. pgv->joyHWCurr = pgv->pjd->joyHWDefaults[ hw_type ];
  807. createSettingsKeyFromCurr( pgv, str );
  808. if( !RegOpenKey( HKEY_LOCAL_MACHINE, str, &hkey ) )
  809. {
  810. cb = sizeof( pgv->joyHWCurr );
  811. if( !RegQueryValueEx( hkey, jcfg, NULL, &regtype,
  812. (CONST LPBYTE)&config, &cb) )
  813. {
  814. if( regtype == REG_BINARY && cb == sizeof( config ) )
  815. {
  816. pgv->joyHWCurr.hws = config.hws;
  817. pgv->joyHWCurr.hwv = config.hwv;
  818. pgv->joyHWCurr.dwUsageSettings = config.dwUsageSettings;
  819. }
  820. }
  821. RegCloseKey( hkey );
  822. }
  823. // set up the rudder bit
  824. if( pgv->joyHWCurr.dwUsageSettings & JOY_US_HASRUDDER )
  825. {
  826. CheckDlgButton( hwnd, IDC_JOY1HASRUDDER, TRUE );
  827. } else
  828. {
  829. if( IsDlgButtonChecked( hwnd, IDC_JOY1HASRUDDER ) )
  830. {
  831. pgv->joyHWCurr.dwUsageSettings |= JOY_US_HASRUDDER;
  832. } else
  833. {
  834. pgv->joyHWCurr.dwUsageSettings &= ~JOY_US_HASRUDDER;
  835. }
  836. }
  837. }
  838. // disable test/calibrate buttons based on hardware picked
  839. enableTestCal( hwnd, hw_type );
  840. // if custom selected, go get the data from the user
  841. if( hw_type == JOY_HW_CUSTOM )
  842. {
  843. //ISSUE-2001/03/29-timgill Old code issue
  844. //HINSTANCE hInst = (HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE);
  845. HINSTANCE hInst = (HINSTANCE)GetResourceInstance();
  846. assert(hInst);
  847. rc = DialogBoxParam(hInst,
  848. MAKEINTRESOURCE(IDD_JOYCUSTOM), hwnd,
  849. (int (__stdcall *)(struct HWND__ *,unsigned int,unsigned int,long))CustomProc, (LONG) pgv );
  850. if( rc )
  851. {
  852. LPCUSTVARS pcv;
  853. pcv = (LPCUSTVARS) rc;
  854. pgv->joyHWCurr.dwUsageSettings |= JOY_US_PRESENT;
  855. pgv->joyHWCurr.hws.dwFlags &= ~(JOY_HWS_HASR|JOY_HWS_HASZ|
  856. JOY_HWS_HASPOV|JOY_HWS_ISYOKE| JOY_HWS_ISGAMEPAD|
  857. JOY_HWS_ISCARCTRL| JOY_HWS_POVISPOLL|
  858. JOY_HWS_POVISBUTTONCOMBOS );
  859. /*
  860. * NOTE: for a custom joystick, we always assume that Z is
  861. * implemented on J2 Y.
  862. */
  863. if( pcv->bHasZ )
  864. pgv->joyHWCurr.hws.dwFlags |= JOY_HWS_HASZ;
  865. /*
  866. * NOTE: for a custom joystick, we always assume that R is
  867. * implemented on J2 X.
  868. */
  869. if( pcv->bHasR )
  870. pgv->joyHWCurr.hws.dwFlags |= JOY_HWS_HASR;
  871. if( pcv->bHasPOV )
  872. pgv->joyHWCurr.hws.dwFlags |= JOY_HWS_HASPOV;
  873. if( pcv->bIsYoke )
  874. pgv->joyHWCurr.hws.dwFlags |= JOY_HWS_ISYOKE;
  875. if( pcv->bIsGamePad )
  876. {
  877. pgv->joyHWCurr.hws.dwFlags |= JOY_HWS_ISGAMEPAD;
  878. }
  879. if( pcv->bIsCarCtrl )
  880. {
  881. pgv->joyHWCurr.hws.dwFlags |= JOY_HWS_ISCARCTRL;
  882. }
  883. if( pcv->bHas2Buttons )
  884. {
  885. pgv->joyHWCurr.hws.dwNumButtons = 2;
  886. } else
  887. {
  888. pgv->joyHWCurr.hws.dwNumButtons = 4;
  889. }
  890. DoFree( pcv );
  891. same = FALSE;
  892. }
  893. }
  894. /*
  895. * update the registry with the new current joystick
  896. */
  897. if( !same )
  898. {
  899. RegSaveCurrentJoyHW( pgv );
  900. RegistryUpdated( pgv );
  901. PropSheet_Changed( GetParent(hwnd), hwnd );
  902. pgv->joyActiveFlags = (unsigned) -1;
  903. enableActiveJoystick( pgv, hwnd );
  904. }
  905. } /* getNewJoyInfo */
  906. #endif //DEAD_CODE
  907. // initCurrentHW - set up the current hardware for the first time
  908. static void initCurrentHW( LPGLOBALVARS pgv )
  909. {
  910. assert(pgv);
  911. regGetCurrHW( pgv );
  912. pgv->joyActiveFlags = (unsigned) -1;
  913. saveHWSettings( pgv );
  914. } /* initCurrentHW */
  915. // newJoyId - set up for a new joystick id
  916. static LPGLOBALVARS newJoyId( LPGLOBALVARS pgv, HWND hwnd, int joyid )
  917. {
  918. assert(pgv);
  919. assert(hwnd);
  920. // if( joyid == pgv->iJoyId )
  921. // return pgv;
  922. #if !defined( WANT_SHEETS )
  923. pgv = &pgv->pjd->pgvlist[ joyid ];
  924. #endif
  925. pgv->iJoyId = joyid;
  926. /*
  927. * save the pointer to the variables
  928. */
  929. SetWindowLong( hwnd, DWL_USER, (LONG) pgv );
  930. #if defined( WANT_SHEETS )
  931. /*
  932. * set up current joystick hardware
  933. */
  934. initCurrentHW( pgv );
  935. #endif
  936. // set up windows
  937. pgv->joyActiveFlags = (unsigned) -1;
  938. enableActiveJoystick( pgv, hwnd );
  939. CheckDlgButton( hwnd, IDC_JOY1HASRUDDER, ( pgv->joyHWCurr.dwUsageSettings & JOY_US_HASRUDDER ) ? TRUE : FALSE);
  940. // select the current info
  941. // SendDlgItemMessage( hwnd, IDC_JOYSELECT, CB_SETCURSEL, pgv->joyHWCurr.dwType, 0L );
  942. #if !defined( WANT_SHEETS )
  943. // SendDlgItemMessage( hwnd, IDC_JOYCURRENTID, CB_SETCURSEL, pgv->iJoyId, 0L );
  944. #endif
  945. return(pgv);
  946. } /* newJoyId */
  947. /*
  948. * showResetInfo
  949. *
  950. static void showResetInfo( HWND hwnd, BOOL show )
  951. {
  952. ASSERT (::IsWindow(hwnd));
  953. // HWND hCtrl = GetDlgItem( hwnd, IDC_JOYTROUBLESHOOT_FRAME );
  954. // ASSERT (::IsWindow(hCtrl));
  955. // EnableWindow( hCtrl, show );
  956. // hCtrl = GetDlgItem( hwnd, IDC_JOYTROUBLESHOOT_TEXT );
  957. // ASSERT (::IsWindow(hCtrl));
  958. // EnableWindow( hCtrl, show );
  959. // hCtrl = GetDlgItem( hwnd, IDC_JOYRESET );
  960. // ASSERT (::IsWindow(hCtrl));
  961. // EnableWindow( hCtrl, show );
  962. } * showResetInfo */
  963. // doJoyDlgInitDialog - process initialization for joystick tabbed dialog
  964. static BOOL doJoyDlgInitDialog( HWND hwnd, LPARAM lParam )
  965. {
  966. assert(IsWindow(hwnd));
  967. HINSTANCE hinst = GetWindowInstance( hwnd );
  968. HINSTANCE hResInst = GetResourceInstance();
  969. LPPROPSHEETPAGE ppsp;
  970. // int i;
  971. // char str[MAX_STR];
  972. LPGLOBALVARS pgv;
  973. LPJOYDATA pjd;
  974. LPJOYDATAPTR pjdp;
  975. /*
  976. LRESULT lr;
  977. HKEY hKey;
  978. ULONG cb;
  979. PACKETINFO PacketInfo;
  980. //
  981. // set labels
  982. //
  983. // load icon
  984. if (fIsSideWinder)
  985. {
  986. HANDLE hDevice;
  987. DWORD dwVerSize;
  988. char sz[256];
  989. char sz2[256];
  990. JOYCAPS jc;
  991. // set icon
  992. HICON hIcon =(struct HICON__ *) LoadImage(hResInst,(PSTR)IDI_SIDEWINDER, IMAGE_ICON, 64, 64, 0);
  993. ASSERT(hIcon);
  994. HWND hCtrl = GetDlgItem(hwnd, IDC_SIDEWINDERICON);
  995. ASSERT (::IsWindow(hCtrl));
  996. ShowWindow(hCtrl, SW_SHOW);
  997. hCtrl = GetDlgItem(hwnd, IDC_SIDEWINDERICON);
  998. ASSERT (::IsWindow(hCtrl));
  999. Static_SetIcon(hCtrl, hIcon);
  1000. // set title
  1001. pszCommonString->LoadString(IDS_PROP_TBAR);
  1002. lstrcpy(sz, (LPCTSTR)*pszCommonString);
  1003. SetWindowText(GetParent(hwnd), sz);
  1004. // product name
  1005. SetDialogItemText(hwnd, IDC_TEXT_PRODUCTNAME, IDS_SETTING_PRODUCT_NAME+1);
  1006. // version
  1007. GetSystemDirectory(sz, sizeof(sz));
  1008. lstrcat(sz, "\\MSGAME.VXD");
  1009. dwVerSize = GetFileVersionInfoSize(sz, &cb);
  1010. if (dwVerSize)
  1011. {
  1012. VS_FIXEDFILEINFO* pVer;
  1013. UINT cbVer;
  1014. char* p = (char*)malloc(dwVerSize);
  1015. GetFileVersionInfo(sz, 0, dwVerSize, (void*)p);
  1016. VerQueryValue((void*)p, "\\", (void**)&pVer, &cbVer);
  1017. wsprintf(
  1018. sz, "%d.%02d.%02d",
  1019. HIWORD(pVer->dwFileVersionMS),
  1020. LOWORD(pVer->dwFileVersionMS),
  1021. LOWORD(pVer->dwFileVersionLS));
  1022. SetDlgItemText(hwnd, IDC_TEXT_VERSION, sz);
  1023. free(p);
  1024. }
  1025. // copyright
  1026. SetDialogItemText(hwnd, IDC_TEXT_COPYRIGHT, IDS_COPYRIGHT+1);
  1027. // PID
  1028. pszCommonString->LoadString(IDS_SETTING_PRODUCT_NAME+2);
  1029. lstrcpy(sz2, (LPCTSTR)*pszCommonString);
  1030. wsprintf(sz, "Software\\Microsoft\\%s\\1.0\\registration", sz2);
  1031. lr = RegOpenKey(HKEY_LOCAL_MACHINE, sz, &hKey);
  1032. *sz = 0;
  1033. cb = sizeof(sz);
  1034. lr = RegQueryValueEx(hKey, "ProductID", 0, 0, (BYTE*)sz, &cb);
  1035. RegCloseKey(hKey);
  1036. SetDlgItemText(hwnd, IDC_TEXT_PID, sz);
  1037. // diagnostics
  1038. joyGetDevCaps(0, &jc, sizeof(jc));
  1039. if (!strcmp(jc.szOEMVxD, "MSGAME.VXD"))
  1040. {
  1041. hDevice = CreateFile(
  1042. "\\\\.\\MSGAME.VXD",
  1043. 0, 0, 0, 0,
  1044. FILE_FLAG_DELETE_ON_CLOSE, 0);
  1045. if (hDevice!=INVALID_HANDLE_VALUE)
  1046. {
  1047. lr = DeviceIoControl(
  1048. hDevice, 6,
  1049. &PacketInfo, sizeof(PACKETINFO),
  1050. 0, 0, &cb, 0);
  1051. CloseHandle(hDevice);
  1052. }
  1053. wsprintf(
  1054. sz, "%08x-%08x-%02x",
  1055. PacketInfo.nFailures, PacketInfo.nAttempts, PacketInfo.iMode);
  1056. SetDlgItemText(hwnd, IDC_TEXT_DIAGNOSTIC, sz);
  1057. }
  1058. SetDlgItemText(hwnd, IDC_TEXT_DIAGNOSTIC, sz);
  1059. // hide calibration button and rudder options
  1060. hCtrl = GetDlgItem(hwnd, IDC_JOYCALIBRATE);
  1061. ASSERT (::IsWindow(hCtrl));
  1062. ShowWindow(hCtrl, 0);
  1063. hCtrl = GetDlgItem(hwnd, IDC_GROUP_RUDDER);
  1064. ASSERT (::IsWindow(hCtrl));
  1065. ShowWindow(hCtrl, 0);
  1066. hCtrl = GetDlgItem(hwnd, IDC_TEXT_RUDDERHELP);
  1067. ASSERT (::IsWindow(hCtrl));
  1068. ShowWindow(hCtrl, 0);
  1069. hCtrl = GetDlgItem(hwnd, IDC_JOY1HASRUDDER);
  1070. ASSERT (::IsWindow(hCtrl));
  1071. ShowWindow(hCtrl, 0);
  1072. }
  1073. */
  1074. // pointer to data
  1075. ppsp = (LPPROPSHEETPAGE) lParam;
  1076. pjdp = (LPJOYDATAPTR) ppsp->lParam;
  1077. pjd = pjdp->pjd;
  1078. // blj: Fix #8049, Assign the proper ID for the joysick assigned to this property sheet.
  1079. pjdp->iJoyId = gnID;
  1080. // create global variables. These will be used by all dialogs
  1081. #if defined( WANT_SHEETS )
  1082. pgv = DoAlloc( sizeof( GLOBALVARS ) );
  1083. assert(pgv);
  1084. if( pgv == NULL )
  1085. return(FALSE);
  1086. // get joystick id that this sheet is for
  1087. pgv->iJoyId = pjdp->iJoyId;
  1088. pgv->pjd = pjd;
  1089. DPF( "Tab for joystick %d started\r\n", pgv->iJoyId );
  1090. #else
  1091. pgv = &pjd->pgvlist[ pjdp->iJoyId ];
  1092. #endif
  1093. // get device caps
  1094. getDevCaps( pgv );
  1095. /* these are for the old combo boxes that used to display the controllers... this is no longer needed
  1096. // set up pre-defined joystick list
  1097. for( i=IDS_JOYHW0; i<IDS_JOYHWLAST; i++ )
  1098. {
  1099. if (LoadString( hResInst , i, str, sizeof( str )))
  1100. SendDlgItemMessage( hwnd, IDC_JOYSELECT, CB_ADDSTRING, 0, (LPARAM)(LPSTR) str );
  1101. }
  1102. // set up OEM joystick list
  1103. for( i=0;i<pjd->oemCount;i++ )
  1104. SendDlgItemMessage( hwnd, IDC_JOYSELECT, CB_ADDSTRING, 0, (LPARAM)(LPSTR) pjd->oemList[i].ident_string );
  1105. // this can all go away!!!
  1106. // set up joystick choices list
  1107. #if !defined(WANT_SHEETS)
  1108. {
  1109. int numdevs;
  1110. char strid[MAX_STR];
  1111. if( LoadString( hResInst, IDS_JOY, str, sizeof( str ) ) )
  1112. {
  1113. numdevs = joyGetNumDevs();
  1114. for( i=0;i<numdevs;i++ )
  1115. {
  1116. wsprintf( strid, "%s %d", str, i+1 );
  1117. SendDlgItemMessage( hwnd, IDC_JOYCURRENTID, CB_ADDSTRING, 0, (LPARAM)(LPSTR) strid );
  1118. }
  1119. }
  1120. }
  1121. #endif
  1122. */
  1123. // pgv->iJoyId = -1;
  1124. newJoyId( pgv, hwnd, pjdp->iJoyId);
  1125. // enable/disable our Reset button
  1126. // showResetInfo( hwnd, pjd->bHasNonStandardUserVals );
  1127. return(TRUE);
  1128. } /* doJoyDlgInitDialog */
  1129. /*
  1130. * doJoyDlgCommand - process WM_COMMAND message for main joystick tabbed dialog
  1131. */
  1132. static void doJoyDlgCommand( HWND hwnd, int id, HWND hctl, UINT code )
  1133. {
  1134. assert(hwnd);
  1135. LPGLOBALVARS pgv;
  1136. pgv = (LPGLOBALVARS) GetWindowLong( hwnd, DWL_USER );
  1137. assert(pgv);
  1138. switch( id )
  1139. {
  1140. #ifdef DEAD_CODE
  1141. // new joystick has been picked
  1142. case IDC_JOYSELECT:
  1143. if( code == CBN_SELCHANGE )
  1144. getNewJoyInfo( pgv, hwnd );
  1145. break;
  1146. #endif // DEAD_CODE
  1147. #if !defined( WANT_SHEET )
  1148. // new joystick id has been picked
  1149. case IDC_JOYCURRENTID:
  1150. if( code == CBN_SELCHANGE )
  1151. {
  1152. int joyid;
  1153. joyid = SendDlgItemMessage( hwnd, IDC_JOYCURRENTID, CB_GETCURSEL, 0, 0L );
  1154. pgv = newJoyId( pgv, hwnd, joyid );
  1155. regSetUserVals( pgv->pjd, TRUE );
  1156. RegSaveCurrentJoyHW( pgv );
  1157. RegistryUpdated( pgv );
  1158. }
  1159. break;
  1160. #endif
  1161. // calibrate current joystick
  1162. case IDC_JOYCALIBRATE:
  1163. pgv->pjd->bUseTimer = FALSE;
  1164. DoCalibrate( pgv, hwnd );
  1165. pgv->pjd->bUseTimer = TRUE;
  1166. break;
  1167. #ifdef DEAD_CODE
  1168. // test either joystick 1 or joystick 2
  1169. case IDC_JOYTEST:
  1170. pgv->pjd->bUseTimer = FALSE;
  1171. DoTest( pgv, hwnd, NULL, pgv );
  1172. pgv->pjd->bUseTimer = TRUE;
  1173. break;
  1174. #endif
  1175. // reset to user values
  1176. case IDC_JOYRESET:
  1177. pgv->pjd->bResetUserVals = TRUE;
  1178. PropSheet_Changed( GetParent(hwnd), hwnd );
  1179. break;
  1180. // rudder selected/unselected
  1181. case IDC_JOY1HASRUDDER:
  1182. {
  1183. LPJOYREGHWCONFIG pcfg;
  1184. // rudder status changed, force recalibration (leave POV alone if it was button based)
  1185. pcfg = &pgv->joyHWCurr;
  1186. assert(pcfg);
  1187. if( (pcfg->hws.dwFlags & JOY_HWS_HASPOV) && (pcfg->hws.dwFlags & JOY_HWS_POVISBUTTONCOMBOS) )
  1188. pcfg->hwv.dwCalFlags &= JOY_ISCAL_POV;
  1189. else
  1190. pcfg->hwv.dwCalFlags = 0;
  1191. if( IsDlgButtonChecked( hwnd, id ) )
  1192. pcfg->dwUsageSettings |= JOY_US_HASRUDDER;
  1193. else
  1194. pcfg->dwUsageSettings &= ~JOY_US_HASRUDDER;
  1195. pgv->joyActiveFlags = (unsigned) -1;
  1196. enableActiveJoystick( pgv, hwnd );
  1197. // tell vjoyd that the device has changed!
  1198. joyConfigChanged(0);
  1199. PropSheet_Changed( GetParent(hwnd), hwnd );
  1200. break;
  1201. }
  1202. case ID_APPLY:
  1203. {
  1204. DPF( "ID_APPLY\r\n" );
  1205. #if !defined( WANT_SHEETS )
  1206. {
  1207. // int i;
  1208. // int numjoys;
  1209. // numjoys = joyGetNumDevs();
  1210. // for( i=0;i<numjoys;i++ )
  1211. {
  1212. regPermSaveAllInfo( &pgv->pjd->pgvlist[gnID] );
  1213. saveHWSettings( &pgv->pjd->pgvlist[gnID] );
  1214. }
  1215. }
  1216. #else
  1217. regPermSaveAllInfo( pgv );
  1218. saveHWSettings( pgv );
  1219. #endif
  1220. if( pgv->pjd->bResetUserVals )
  1221. {
  1222. regUserValsFini( pgv->pjd );
  1223. regUserValsInit( pgv->pjd );
  1224. pgv->pjd->bResetUserVals = FALSE;
  1225. }
  1226. // showResetInfo( hwnd, pgv->pjd->bHasNonStandardUserVals );
  1227. // BUG 419 FIX: brute force method
  1228. InvalidateRect(GetParent(hwnd), 0, 0);
  1229. break;
  1230. }
  1231. case ID_INIT:
  1232. DPF( "ID_INIT\r\n" );
  1233. joyConfigChanged(0);
  1234. pgv->iJoyId = gnID;
  1235. // we've been re-activated, reset the current joystick settings
  1236. regSetUserVals( pgv->pjd, TRUE );
  1237. RegSaveCurrentJoyHW( pgv );
  1238. RegistryUpdated( pgv );
  1239. break;
  1240. case IDOK:
  1241. DPF( "IDOK\r\n" );
  1242. joyConfigChanged(0);
  1243. EndDialog(hwnd, TRUE );
  1244. break;
  1245. case IDCANCEL:
  1246. DPF( "IDCANCEL\r\n" );
  1247. pgv->pjd->bResetUserVals = FALSE;
  1248. #if !defined( WANT_SHEETS )
  1249. {
  1250. // int i;
  1251. // int numjoys;
  1252. // numjoys = joyGetNumDevs();
  1253. // for( i=0;i<numjoys;i++ ) {
  1254. restoreHWSettings( &pgv->pjd->pgvlist[gnID] );
  1255. // }
  1256. }
  1257. #else
  1258. restoreHWSettings( pgv );
  1259. #endif
  1260. RegistryUpdated( pgv );
  1261. EndDialog(hwnd, FALSE );
  1262. break;
  1263. default:
  1264. break;
  1265. }
  1266. } /* doJoyDlgCommand */
  1267. /*
  1268. * JoystickDlg - dialog procedure for joystick tabbed dialog
  1269. */
  1270. BOOL CALLBACK JoystickDlg( HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam)
  1271. {
  1272. BOOL rc;
  1273. switch( umsg )
  1274. {
  1275. case WM_HELP:
  1276. OnHelp(lParam);
  1277. return(1);
  1278. case WM_CONTEXTMENU:
  1279. OnContextMenu(wParam);
  1280. return(1);
  1281. case WM_INITDIALOG:
  1282. rc = doJoyDlgInitDialog( hwnd, lParam );
  1283. if( !rc )
  1284. EndDialog( hwnd, 0 );
  1285. return(FALSE);
  1286. case WM_COMMAND:
  1287. HANDLE_WM_COMMAND( hwnd, wParam, lParam, doJoyDlgCommand );
  1288. break;
  1289. case WM_ACTIVATE:
  1290. // we've been activated, pretend we were re-selected
  1291. if( LOWORD( wParam ) != WA_INACTIVE )
  1292. FORWARD_WM_COMMAND( hwnd, ID_INIT, 0, 0, SendMessage );
  1293. break;
  1294. case WM_DESTROY:
  1295. cleanUpJoyDlg( hwnd );
  1296. break;
  1297. case WM_NOTIFY:
  1298. {
  1299. NMHDR FAR * lpnm = (NMHDR FAR *)lParam;
  1300. switch( lpnm->code )
  1301. {
  1302. case PSN_KILLACTIVE:
  1303. FORWARD_WM_COMMAND( hwnd, IDOK, 0, 0, SendMessage );
  1304. FORWARD_WM_COMMAND( hwnd, ID_INIT, 0, 0, SendMessage );
  1305. // ADDED CML 7/03/96
  1306. KillTimer(hwnd, TIMER_ID);
  1307. return(TRUE);
  1308. case PSN_APPLY:
  1309. FORWARD_WM_COMMAND( hwnd, ID_APPLY, 0, 0, SendMessage );
  1310. return(TRUE);
  1311. case PSN_SETACTIVE:
  1312. FORWARD_WM_COMMAND( hwnd, ID_INIT, 0, 0, SendMessage );
  1313. // ADDED CML 7/03/96
  1314. // PSN_SETACTIVE gets sent for the first page on loading of the sheet,
  1315. // even if that page is not displayed
  1316. // check to see if we have been loaded
  1317. if( !fIsLoaded )
  1318. {
  1319. fIsLoaded=1; break;
  1320. }
  1321. return(TRUE);
  1322. case PSN_RESET:
  1323. FORWARD_WM_COMMAND( hwnd, IDCANCEL, 0, 0, SendMessage );
  1324. return(TRUE);
  1325. }
  1326. break;
  1327. }
  1328. default:
  1329. break;
  1330. }
  1331. return(FALSE);
  1332. } /* JoystickDlg */
  1333. /***************************************************************************
  1334. GLOBAL JOYSTICK DATA FUNCTIONS FOLLOW
  1335. ***************************************************************************/
  1336. // default joysticks
  1337. #define TYPE00 0
  1338. #define TYPE01 0
  1339. #define TYPE02 0
  1340. #define TYPE03 0
  1341. #define TYPE04 JOY_HWS_ISGAMEPAD
  1342. #define TYPE05 JOY_HWS_ISYOKE
  1343. #define TYPE06 JOY_HWS_HASZ | JOY_HWS_ISYOKE
  1344. #define TYPE07 JOY_HWS_HASZ
  1345. #define TYPE08 JOY_HWS_HASZ
  1346. #define TYPE09 JOY_HWS_ISGAMEPAD
  1347. #define TYPE10 JOY_HWS_ISYOKE
  1348. #define TYPE11 JOY_HWS_HASZ | JOY_HWS_ISYOKE
  1349. static JOYREGHWCONFIG _joyHWDefaults[] =
  1350. {
  1351. { {TYPE00,0},JOY_US_PRESENT,{{0,0,0,0,0,0,0,0,0},{0,0,0,0}},JOY_HW_NONE},
  1352. { {TYPE01,2},JOY_US_PRESENT,{{0,0,0,0,0,0,0,0,0},{0,0,0,0}},JOY_HW_CUSTOM},
  1353. { {TYPE02,2},JOY_US_PRESENT,{{0,0,0,0,0,0,0,0,0},{0,0,0,0}},JOY_HW_2A_2B_GENERIC},
  1354. { {TYPE03,4},JOY_US_PRESENT,{{0,0,0,0,0,0,0,0,0},{0,0,0,0}},JOY_HW_2A_4B_GENERIC},
  1355. { {TYPE04,2},JOY_US_PRESENT,{{0,0,0,0,0,0,0,0,0},{0,0,0,0}},JOY_HW_2B_GAMEPAD},
  1356. { {TYPE05,2},JOY_US_PRESENT,{{0,0,0,0,0,0,0,0,0},{0,0,0,0}},JOY_HW_2B_FLIGHTYOKE},
  1357. { {TYPE06,2},JOY_US_PRESENT,{{0,0,0,0,0,0,0,0,0},{0,0,0,0}},JOY_HW_2B_FLIGHTYOKETHROTTLE},
  1358. { {TYPE07,2},JOY_US_PRESENT,{{0,0,0,0,0,0,0,0,0},{0,0,0,0}},JOY_HW_3A_2B_GENERIC},
  1359. { {TYPE08,4},JOY_US_PRESENT,{{0,0,0,0,0,0,0,0,0},{0,0,0,0}},JOY_HW_3A_4B_GENERIC},
  1360. { {TYPE09,4},JOY_US_PRESENT,{{0,0,0,0,0,0,0,0,0},{0,0,0,0}},JOY_HW_4B_GAMEPAD},
  1361. { {TYPE10,4},JOY_US_PRESENT,{{0,0,0,0,0,0,0,0,0},{0,0,0,0}},JOY_HW_4B_FLIGHTYOKE},
  1362. { {TYPE11,4},JOY_US_PRESENT,{{0,0,0,0,0,0,0,0,0},{0,0,0,0}},JOY_HW_4B_FLIGHTYOKETHROTTLE},
  1363. };
  1364. // registry strings for calibration messages
  1365. static LPSTR _oemCalRegStrs[] =
  1366. {
  1367. REGSTR_VAL_JOYOEMCAL1,
  1368. REGSTR_VAL_JOYOEMCAL2,
  1369. REGSTR_VAL_JOYOEMCAL3,
  1370. REGSTR_VAL_JOYOEMCAL4,
  1371. REGSTR_VAL_JOYOEMCAL5,
  1372. REGSTR_VAL_JOYOEMCAL6,
  1373. REGSTR_VAL_JOYOEMCAL7,
  1374. REGSTR_VAL_JOYOEMCAL8,
  1375. REGSTR_VAL_JOYOEMCAL9,
  1376. REGSTR_VAL_JOYOEMCAL10,
  1377. REGSTR_VAL_JOYOEMCAL11,
  1378. REGSTR_VAL_JOYOEMCAL12,
  1379. };
  1380. /*
  1381. * base registry keys
  1382. */
  1383. static char szCfgKey[] = REGSTR_PATH_JOYCONFIG "\\";
  1384. static char szCurrCfgKey[] = "\\" REGSTR_KEY_JOYCURR;
  1385. static char szSettingsCfgKey[] = "\\" REGSTR_KEY_JOYSETTINGS;
  1386. // freeOEMListItem - free a list of oem data
  1387. static void freeOEMListItem( LPJOYDATA pjd, int i )
  1388. {
  1389. int j;
  1390. DoFree( pjd->oemList[i].keyname );
  1391. DoFree( pjd->oemList[i].ident_string );
  1392. DoFree( pjd->oemList[i].vxd_name );
  1393. DoFree( pjd->oemList[i].xy_label );
  1394. DoFree( pjd->oemList[i].z_label );
  1395. DoFree( pjd->oemList[i].r_label );
  1396. DoFree( pjd->oemList[i].u_label );
  1397. DoFree( pjd->oemList[i].v_label );
  1398. DoFree( pjd->oemList[i].pov_label );
  1399. DoFree( pjd->oemList[i].testmove_desc );
  1400. DoFree( pjd->oemList[i].testbutton_desc );
  1401. DoFree( pjd->oemList[i].testmove_cap );
  1402. DoFree( pjd->oemList[i].testbutton_cap );
  1403. DoFree( pjd->oemList[i].testwin_cap );
  1404. DoFree( pjd->oemList[i].cal_cap );
  1405. DoFree( pjd->oemList[i].calwin_cap );
  1406. for( j=0;j<NUM_CAL_STRS;j++ )
  1407. {
  1408. DoFree( pjd->oemList[i].cal_strs[j] );
  1409. }
  1410. } /* freeOEMListItem */
  1411. /*
  1412. * initHWDefaults - initialize the hardware list: use defaults + OEM types
  1413. * defined in the registry
  1414. */
  1415. static void initHWDefaults( LPJOYDATA pjd )
  1416. {
  1417. assert(pjd);
  1418. int list_size;
  1419. int def_size;
  1420. DWORD isubkey;
  1421. DWORD keyidx;
  1422. HKEY hkey;
  1423. HKEY hsubkey;
  1424. char str[MAX_STR];
  1425. DWORD clsize;
  1426. DWORD num_subkeys;
  1427. DWORD dont_care;
  1428. DWORD longest_key;
  1429. FILETIME ftime;
  1430. LPSTR keyname;
  1431. JOYREGHWSETTINGS hws;
  1432. DWORD longest_val;
  1433. DWORD type;
  1434. DWORD cb;
  1435. int i;
  1436. int j;
  1437. int ctype;
  1438. LPSTR tmpstr;
  1439. int fail;
  1440. def_size = sizeof( _joyHWDefaults )/sizeof( _joyHWDefaults[0] );
  1441. list_size = def_size;
  1442. pjd->oemCount = 0;
  1443. if( !RegOpenKey( HKEY_LOCAL_MACHINE, REGSTR_PATH_JOYOEM, &hkey ) )
  1444. {
  1445. clsize = sizeof( str );
  1446. if( !RegQueryInfoKey ( hkey, str, &clsize, NULL, &num_subkeys,
  1447. &longest_key, &dont_care, &dont_care, &dont_care,
  1448. &dont_care, // address of buffer for longest value data length
  1449. &dont_care, &ftime ) )
  1450. {
  1451. pjd->oemList = (OEMLIST *)DoAlloc( num_subkeys * sizeof( OEMLIST ));
  1452. if( pjd->oemList != NULL )
  1453. {
  1454. pjd->oemCount = num_subkeys;
  1455. list_size += num_subkeys;
  1456. }
  1457. longest_key++;
  1458. }
  1459. }
  1460. pjd->joyHWDefaults = (struct joyreghwconfig_tag *) DoAlloc( list_size * sizeof( JOYREGHWCONFIG ) );
  1461. if( pjd->joyHWDefaults == NULL )
  1462. {
  1463. pjd->joyHWDefaults = _joyHWDefaults;
  1464. } else
  1465. {
  1466. memcpy( pjd->joyHWDefaults, _joyHWDefaults, def_size * sizeof( JOYREGHWCONFIG ) );
  1467. /*
  1468. * if we have keys in the registry, go fetch them
  1469. */
  1470. if( list_size > def_size )
  1471. {
  1472. isubkey = 0;
  1473. keyidx = 0;
  1474. keyname = (char *) DoAlloc( longest_key );
  1475. if( keyname == NULL )
  1476. {
  1477. keyname = str;
  1478. longest_key = sizeof( str );
  1479. }
  1480. /*
  1481. * run through all keys, getting the info on them
  1482. */
  1483. while( !RegEnumKey( hkey, keyidx, keyname, longest_key ) )
  1484. {
  1485. if( !RegOpenKey( hkey, keyname, &hsubkey ) )
  1486. {
  1487. if( !RegQueryInfoKey ( hsubkey, str, &clsize, NULL,
  1488. &dont_care, &dont_care, &dont_care, &dont_care,
  1489. &dont_care, &longest_val, &dont_care, &ftime ) )
  1490. {
  1491. pjd->oemList[isubkey].keyname = (char *)DoAlloc( strlen( keyname ) +1 );
  1492. tmpstr = (char *) DoAlloc( longest_val+1 );
  1493. if( pjd->oemList[isubkey].keyname != NULL && tmpstr != NULL )
  1494. {
  1495. lstrcpy( pjd->oemList[isubkey].keyname, keyname );
  1496. cb = sizeof( hws );
  1497. if( !RegQueryValueEx( hsubkey, REGSTR_VAL_JOYOEMDATA, NULL,
  1498. &type, (CONST LPBYTE)&hws, &cb) )
  1499. {
  1500. if( type == REG_BINARY && cb == sizeof( hws ) )
  1501. {
  1502. pjd->oemList[isubkey].hws = hws;
  1503. }
  1504. }
  1505. fail = 0;
  1506. fail |= regGetOEMStr( hsubkey, REGSTR_VAL_JOYOEMCALLOUT,
  1507. tmpstr, longest_val,
  1508. &pjd->oemList[isubkey].vxd_name );
  1509. fail |= regGetOEMStr( hsubkey, REGSTR_VAL_JOYOEMNAME,
  1510. tmpstr, longest_val,
  1511. &pjd->oemList[isubkey].ident_string );
  1512. for( j=0;j<NUM_CAL_STRS;j++ )
  1513. {
  1514. fail |= regGetOEMStr( hsubkey, _oemCalRegStrs[j],
  1515. tmpstr, longest_val,
  1516. &pjd->oemList[isubkey].cal_strs[j] );
  1517. }
  1518. fail |= regGetOEMStr( hsubkey, REGSTR_VAL_JOYOEMXYLABEL,
  1519. tmpstr, longest_val,
  1520. &pjd->oemList[isubkey].xy_label );
  1521. fail |= regGetOEMStr( hsubkey, REGSTR_VAL_JOYOEMZLABEL,
  1522. tmpstr, longest_val,
  1523. &pjd->oemList[isubkey].z_label );
  1524. fail |= regGetOEMStr( hsubkey, REGSTR_VAL_JOYOEMRLABEL,
  1525. tmpstr, longest_val,
  1526. &pjd->oemList[isubkey].r_label );
  1527. fail |= regGetOEMStr( hsubkey, REGSTR_VAL_JOYOEMULABEL,
  1528. tmpstr, longest_val,
  1529. &pjd->oemList[isubkey].u_label );
  1530. fail |= regGetOEMStr( hsubkey, REGSTR_VAL_JOYOEMVLABEL,
  1531. tmpstr, longest_val,
  1532. &pjd->oemList[isubkey].v_label );
  1533. fail |= regGetOEMStr( hsubkey, REGSTR_VAL_JOYOEMPOVLABEL,
  1534. tmpstr, longest_val,
  1535. &pjd->oemList[isubkey].pov_label );
  1536. fail |= regGetOEMStr( hsubkey, REGSTR_VAL_JOYOEMTESTMOVEDESC,
  1537. tmpstr, longest_val,
  1538. &pjd->oemList[isubkey].testmove_desc );
  1539. fail |= regGetOEMStr( hsubkey, REGSTR_VAL_JOYOEMTESTBUTTONDESC,
  1540. tmpstr, longest_val,
  1541. &pjd->oemList[isubkey].testbutton_desc );
  1542. fail |= regGetOEMStr( hsubkey, REGSTR_VAL_JOYOEMTESTMOVECAP,
  1543. tmpstr, longest_val,
  1544. &pjd->oemList[isubkey].testmove_cap );
  1545. fail |= regGetOEMStr( hsubkey, REGSTR_VAL_JOYOEMTESTBUTTONCAP,
  1546. tmpstr, longest_val,
  1547. &pjd->oemList[isubkey].testbutton_cap );
  1548. fail |= regGetOEMStr( hsubkey, REGSTR_VAL_JOYOEMTESTWINCAP,
  1549. tmpstr, longest_val,
  1550. &pjd->oemList[isubkey].testwin_cap );
  1551. fail |= regGetOEMStr( hsubkey, REGSTR_VAL_JOYOEMCALCAP,
  1552. tmpstr, longest_val,
  1553. &pjd->oemList[isubkey].cal_cap );
  1554. fail |= regGetOEMStr( hsubkey, REGSTR_VAL_JOYOEMCALWINCAP,
  1555. tmpstr, longest_val,
  1556. &pjd->oemList[isubkey].calwin_cap );
  1557. if( fail )
  1558. {
  1559. freeOEMListItem( pjd, isubkey );
  1560. } else
  1561. {
  1562. isubkey++;
  1563. }
  1564. } else
  1565. {
  1566. DoFree( pjd->oemList[isubkey].keyname );
  1567. }
  1568. DoFree( tmpstr );
  1569. RegCloseKey( hsubkey );
  1570. }
  1571. }
  1572. keyidx++;
  1573. }
  1574. pjd->oemCount = isubkey;
  1575. /*
  1576. * sort the list, and then fill in the joyHWDefault array
  1577. */
  1578. if( pjd->oemCount > 0 )
  1579. {
  1580. for( i=0;i<pjd->oemCount;i++ )
  1581. {
  1582. for( j=i;j<pjd->oemCount;j++ )
  1583. {
  1584. OEMLIST ol;
  1585. if( lstrcmp( pjd->oemList[i].ident_string,
  1586. pjd->oemList[j].ident_string ) > 0 )
  1587. {
  1588. ol = pjd->oemList[i];
  1589. pjd->oemList[i] = pjd->oemList[j];
  1590. pjd->oemList[j] = ol;
  1591. }
  1592. }
  1593. }
  1594. for( i=0;i<pjd->oemCount;i++ )
  1595. {
  1596. ctype = i+JOY_HW_LASTENTRY;
  1597. memset( &pjd->joyHWDefaults[ctype], 0,
  1598. sizeof( pjd->joyHWDefaults[ctype] ) );
  1599. pjd->joyHWDefaults[ctype].hws = pjd->oemList[i].hws;
  1600. pjd->joyHWDefaults[ctype].dwUsageSettings = JOY_US_ISOEM|JOY_US_PRESENT;
  1601. pjd->joyHWDefaults[ctype].dwType = ctype;
  1602. }
  1603. }
  1604. if( keyname != str )
  1605. {
  1606. DoFree( keyname );
  1607. }
  1608. }
  1609. }
  1610. } /* initHWDefaults */
  1611. /*
  1612. * finiHWList - finished with the hardware list, free it
  1613. */
  1614. static void finiHWList( LPJOYDATA pjd )
  1615. {
  1616. int i;
  1617. assert(pjd);
  1618. if( pjd->joyHWDefaults != NULL )
  1619. {
  1620. if( pjd->joyHWDefaults != _joyHWDefaults )
  1621. {
  1622. DoFree( pjd->joyHWDefaults );
  1623. }
  1624. pjd->joyHWDefaults = NULL;
  1625. }
  1626. if( pjd->oemList != NULL )
  1627. {
  1628. for( i=0;i<pjd->oemCount;i++ )
  1629. {
  1630. freeOEMListItem( pjd, i );
  1631. }
  1632. DoFree( pjd->oemList );
  1633. pjd->oemList = NULL;
  1634. pjd->oemCount = 0;
  1635. }
  1636. } /* finiHWList */
  1637. /*
  1638. * getRegKeys - get the registry keys we need
  1639. */
  1640. static void getRegKeys( LPJOYDATA pjd )
  1641. {
  1642. JOYCAPS jc;
  1643. int len;
  1644. assert(pjd);
  1645. /*
  1646. * call with magic ID of -1, which retrieves base info without
  1647. * checking for anything joystick specific
  1648. */
  1649. joyGetDevCaps( (UINT) -1, &jc, sizeof( jc ) );
  1650. // set up registry keys
  1651. pjd->regCfgKey = NULL;
  1652. pjd->regCurrCfgKey = NULL;
  1653. pjd->regSettingsCfgKey = NULL;
  1654. len = sizeof( szCfgKey ) + strlen( jc.szRegKey );
  1655. pjd->regCfgKey = (char *) DoAlloc( len );
  1656. if( pjd->regCfgKey != NULL )
  1657. {
  1658. lstrcpy( pjd->regCfgKey, szCfgKey );
  1659. lstrcpy( &pjd->regCfgKey[ sizeof( szCfgKey ) - 1], jc.szRegKey );
  1660. pjd->regCurrCfgKey = (char *)DoAlloc( len + sizeof( szCurrCfgKey ) - 1 );
  1661. if( pjd->regCurrCfgKey != NULL )
  1662. {
  1663. lstrcpy( pjd->regCurrCfgKey, pjd->regCfgKey );
  1664. lstrcpy( &pjd->regCurrCfgKey[ len-1 ], szCurrCfgKey );
  1665. }
  1666. pjd->regSettingsCfgKey = (char *)DoAlloc( len + sizeof( szSettingsCfgKey ) - 1 );
  1667. if( pjd->regSettingsCfgKey != NULL )
  1668. {
  1669. lstrcpy( pjd->regSettingsCfgKey, pjd->regCfgKey );
  1670. lstrcpy( &pjd->regSettingsCfgKey[ len-1 ], szSettingsCfgKey );
  1671. }
  1672. }
  1673. } /* getRegKeys */
  1674. /*
  1675. * JoystickDataInit
  1676. */
  1677. LPJOYDATA JoystickDataInit( void )
  1678. {
  1679. LPJOYDATA pjd;
  1680. pjd = (JOYDATA *) DoAlloc( sizeof( JOYDATA ) );
  1681. assert(pjd);
  1682. if( pjd == NULL )
  1683. return(NULL);
  1684. // go set up all our defaults + oem lists
  1685. initHWDefaults( pjd );
  1686. // get registry keys used by everyone
  1687. getRegKeys( pjd );
  1688. // brushes for use by button display and bar display (z & r info)
  1689. pjd->hbUp = CreateSolidBrush( ACTIVE_COLOR );
  1690. pjd->hbDown = CreateSolidBrush( INACTIVE_COLOR );
  1691. // set up user values we like
  1692. regUserValsInit( pjd );
  1693. #if !defined( WANT_SHEETS )
  1694. {
  1695. // set up array of "global" vars (global to a joystick id)
  1696. int numjoys;
  1697. int i;
  1698. numjoys = joyGetNumDevs();
  1699. if( numjoys == 0 )
  1700. {
  1701. // blj: I'd love to have called JoyError Here, but we don't have a
  1702. // valid window handle to pass it!
  1703. char szTitle[STR_LEN_32];
  1704. char szMessage[STR_LEN_128];
  1705. if( LoadString(GetResourceInstance(), IDS_JOYREADERROR, szTitle, sizeof(szTitle)) == 0 )
  1706. {
  1707. OutputDebugString (TEXT("GCDEF.DLL: Unable to load string IDS_JOYREADERROR!\n"));
  1708. return(NULL);
  1709. }
  1710. if( LoadString(GetResourceInstance(), IDS_JOYUNPLUGGED, szMessage, sizeof(szMessage)) == 0 )
  1711. {
  1712. OutputDebugString (TEXT("GCDEF.DLL: Unable to load string IDS_JOYUNPLUGGED!\n"));
  1713. return(NULL);
  1714. }
  1715. MessageBox( NULL, szMessage, szTitle, MB_OK | MB_ICONERROR | MB_TASKMODAL );
  1716. return(NULL);
  1717. }
  1718. pjd->pgvlist = (_GLOBALVARS *)DoAlloc( sizeof( GLOBALVARS ) * numjoys );
  1719. if( pjd->pgvlist == NULL )
  1720. return(NULL);
  1721. for( i=0;i<numjoys;i++ )
  1722. {
  1723. pjd->pgvlist[i].iJoyId = i;
  1724. pjd->pgvlist[i].pjd = pjd;
  1725. initCurrentHW( &pjd->pgvlist[i] );
  1726. }
  1727. }
  1728. #endif
  1729. return(pjd);
  1730. } /* JoystickDataInit */
  1731. /*
  1732. * JoystickDataFini - finished with DLL wide joystick data data
  1733. */
  1734. void JoystickDataFini( LPJOYDATA pjd )
  1735. {
  1736. assert(pjd);
  1737. // ditch brushes
  1738. if( pjd->hbUp != NULL )
  1739. DeleteObject( pjd->hbUp );
  1740. if( pjd->hbDown != NULL )
  1741. DeleteObject( pjd->hbDown );
  1742. // done with hardware list
  1743. finiHWList( pjd );
  1744. // restore user values in registry
  1745. regUserValsFini( pjd );
  1746. // done with registry keys
  1747. DoFree( pjd->regCfgKey );
  1748. DoFree( pjd->regCurrCfgKey );
  1749. DoFree( pjd->regSettingsCfgKey );
  1750. #if !defined( WANT_SHEETS )
  1751. DoFree( pjd->pgvlist );
  1752. #endif
  1753. // free up the joystick data
  1754. DoFree( pjd );
  1755. #ifdef DEBUG
  1756. if( allocCount != 0 )
  1757. MBOX( "Memory left unfreed: %d allocations", allocCount );
  1758. #endif
  1759. } /* JoystickDataFini */
  1760. ////////////////////////////////////////////////////////////////////////////////////////
  1761. // OnContextMenu(WPARAM wParam)
  1762. ////////////////////////////////////////////////////////////////////////////////////////
  1763. void OnContextMenu(WPARAM wParam)
  1764. {
  1765. short nSize = STR_LEN_32;
  1766. // point to help file
  1767. char *pszHelpFileName = new char[nSize];
  1768. ASSERT (pszHelpFileName);
  1769. // returns help file name and size of string
  1770. GetHelpFileName(pszHelpFileName, &nSize);
  1771. WinHelp((HWND)wParam, pszHelpFileName, HELP_CONTEXTMENU, (DWORD)gaHelpIDs);
  1772. if( pszHelpFileName ) delete[] (pszHelpFileName);
  1773. }
  1774. ///////////////////////////////////////////////////////////////////////////////
  1775. // FUNCTION: GetHelpFileName(LPSTR lpszHelpFileName)
  1776. //
  1777. // PURPOSE: Populates lpszHelpFileName with the Help File Name from the registry
  1778. //
  1779. // RETURN: ERROR_SUCCESS if successfull, -1 otherwise
  1780. ///////////////////////////////////////////////////////////////////////////////
  1781. LRESULT GetHelpFileName(LPSTR lpszHelpFileName, short* nSize)
  1782. {
  1783. if( LoadString(GetResourceInstance(), IDS_HELPFILENAME, lpszHelpFileName, *nSize) )
  1784. return(S_OK);
  1785. else
  1786. return(E_FAIL);
  1787. }
  1788. void OnHelp(LPARAM lParam)
  1789. {
  1790. ASSERT ( lParam );
  1791. short nSize = STR_LEN_32;
  1792. // point to help file
  1793. char *pszHelpFileName = new char[nSize];
  1794. ASSERT (pszHelpFileName);
  1795. // returns help file name and size of string
  1796. GetHelpFileName(pszHelpFileName, &nSize);
  1797. LPHELPINFO lphi = (LPHELPINFO)lParam;
  1798. if( lphi->iContextType==HELPINFO_WINDOW )
  1799. WinHelp((HWND)lphi->hItemHandle, pszHelpFileName, HELP_WM_HELP, (DWORD)gaHelpIDs);
  1800. if( pszHelpFileName ) delete[] (pszHelpFileName);
  1801. }