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.

3039 lines
88 KiB

  1. /*****************************************************************************
  2. *
  3. * DIJoyReg.c
  4. *
  5. * Copyright (c) 1996 Microsoft Corporation. All Rights Reserved.
  6. *
  7. * Abstract:
  8. *
  9. * Registry access services for joystick configuration.
  10. *
  11. * Contents:
  12. *
  13. * JoyReg_GetConfig
  14. *
  15. *****************************************************************************/
  16. #include "dinputpr.h"
  17. /*****************************************************************************
  18. *
  19. * The sqiffle for this file.
  20. *
  21. *****************************************************************************/
  22. #define sqfl sqflJoyReg
  23. #pragma BEGIN_CONST_DATA
  24. /*****************************************************************************
  25. *
  26. * @doc INTERNAL
  27. *
  28. * @global JOYREGHWSETTINGS | c_rghwsPredef[] |
  29. *
  30. * Array of predefined hardware settings.
  31. *
  32. *****************************************************************************/
  33. JOYREGHWSETTINGS c_rghwsPredef[] = {
  34. /* dwFlags dwNumButtons */
  35. { 0, 2}, /* JOY_HW_2A_2B_GENERIC */
  36. { 0, 4}, /* JOY_HW_2A_4B_GENERIC */
  37. { JOY_HWS_ISGAMEPAD, 2}, /* JOY_HW_2B_GAMEPAD */
  38. { JOY_HWS_ISYOKE, 2}, /* JOY_HW_2B_FLIGHTYOKE */
  39. { JOY_HWS_HASZ | JOY_HWS_ISYOKE, 2}, /* JOY_HW_2B_FLIGHTYOKETHROTTLE */
  40. { JOY_HWS_HASZ, 2}, /* JOY_HW_3A_2B_GENERIC */
  41. { JOY_HWS_HASZ, 4}, /* JOY_HW_3A_4B_GENERIC */
  42. { JOY_HWS_ISGAMEPAD, 4}, /* JOY_HW_4B_GAMEPAD */
  43. { JOY_HWS_ISYOKE, 4}, /* JOY_HW_4B_FLIGHTYOKE */
  44. { JOY_HWS_HASZ | JOY_HWS_ISYOKE, 4}, /* JOY_HW_4B_FLIGHTYOKETHROTTLE */
  45. { JOY_HWS_HASR , 2}, /* JOY_HW_TWO_2A_2B_WITH_Y */
  46. /* To prevent the CPL from allowing
  47. a user to add a rudder to to JOY_HWS_TWO_2A_2B_WITH_Y case, we
  48. will pretend that it already has a rudder. This should not be a problem
  49. as this struct is internal to DInput
  50. */
  51. };
  52. /* Hardware IDs for Predefined Joystick types */
  53. LPCWSTR c_rghwIdPredef[] =
  54. {
  55. L"GAMEPORT\\VID_045E&PID_0102", // L"GAMEPORT\\Generic2A2B",
  56. L"GAMEPORT\\VID_045E&PID_0103", // L"GAMEPORT\\Generic2A4B",
  57. L"GAMEPORT\\VID_045E&PID_0104", // L"GAMEPORT\\Gamepad2B",
  58. L"GAMEPORT\\VID_045E&PID_0105", // L"GAMEPORT\\FlightYoke2B",
  59. L"GAMEPORT\\VID_045E&PID_0106", // L"GAMEPORT\\FlightYokeThrottle2B",
  60. L"GAMEPORT\\VID_045E&PID_0107", // L"GAMEPORT\\Generic3A2B",
  61. L"GAMEPORT\\VID_045E&PID_0108", // L"GAMEPORT\\Generic3A4B",
  62. L"GAMEPORT\\VID_045E&PID_0109", // L"GAMEPORT\\Gamepad4B",
  63. L"GAMEPORT\\VID_045E&PID_010A", // L"GAMEPORT\\FlightYoke4B",
  64. L"GAMEPORT\\VID_045E&PID_010B", // L"GAMEPORT\\FlightYokeThrottle4B",
  65. L"GAMEPORT\\VID_045E&PID_010C", // L"GAMEPORT\\YConnectTwo2A2B",
  66. };
  67. WCHAR c_hwIdPrefix[] = L"GAMEPORT\\"; // Prefix for custom devices
  68. /*****************************************************************************
  69. *
  70. * The default global port driver.
  71. *
  72. *****************************************************************************/
  73. WCHAR c_wszDefPortDriver[] = L"MSANALOG.VXD";
  74. #ifdef WINNT
  75. #define REGSTR_SZREGKEY TEXT("\\DINPUT.DLL\\")
  76. #endif
  77. /*****************************************************************************
  78. *
  79. * @doc INTERNAL
  80. *
  81. * @func HRESULT | JoyReg_GetValue |
  82. *
  83. * Retrieve registry information. If the data is short, and
  84. * the type is <c REG_BINARY>, then the extra is zero-filled.
  85. *
  86. * @parm HKEY | hk |
  87. *
  88. * Registry key containing fun values.
  89. *
  90. * @parm LPCTSTR | ptszValue |
  91. *
  92. * Registry value name.
  93. *
  94. * @parm DWORD | reg |
  95. *
  96. * Registry data type expected.
  97. *
  98. * @parm LPVOID | pvBuf |
  99. *
  100. * Buffer to receive information from registry.
  101. *
  102. * @parm DWORD | cb |
  103. *
  104. * Size of recipient buffer, in bytes.
  105. *
  106. * @returns
  107. *
  108. * Returns a COM error code. The following error codes are
  109. * intended to be illustrative and not necessarily comprehensive.
  110. *
  111. * <c DI_OK> = <c S_OK>: The operation completed successfully.
  112. *
  113. * <c S_FALSE>: The binary read was short. The remainder of the
  114. * buffer is zero-filled.
  115. *
  116. * <c E_FAIL>: Error reading value from registry.
  117. *
  118. *****************************************************************************/
  119. STDMETHODIMP
  120. JoyReg_GetValue(HKEY hk, LPCTSTR ptszValue, DWORD reg, PV pvBuf, DWORD cb)
  121. {
  122. HRESULT hres;
  123. DWORD cbOut;
  124. LONG lRc;
  125. /*
  126. * Strings must be handled differently from binaries.
  127. *
  128. * Strings are retrieved in UNICODE and may be short.
  129. *
  130. * Binaries are retrieved as binary (duh) and may be long.
  131. *
  132. */
  133. cbOut = cb;
  134. if (reg == REG_SZ)
  135. {
  136. lRc = RegQueryStringValueW(hk, ptszValue, pvBuf, &cbOut);
  137. if (lRc == ERROR_SUCCESS)
  138. {
  139. hres = S_OK;
  140. } else
  141. {
  142. hres = hresLe(lRc); /* Else, something bad happened */
  143. }
  144. } else
  145. {
  146. AssertF(reg == REG_BINARY);
  147. lRc = RegQueryValueEx(hk, ptszValue, 0, NULL, pvBuf, &cbOut);
  148. if (lRc == ERROR_SUCCESS)
  149. {
  150. if (cb == cbOut)
  151. {
  152. hres = S_OK;
  153. } else
  154. {
  155. /*
  156. * Zero out the extra.
  157. */
  158. ZeroBuf(pvAddPvCb(pvBuf, cbOut), cb - cbOut);
  159. hres = S_FALSE;
  160. }
  161. } else if (lRc == ERROR_MORE_DATA)
  162. {
  163. /*
  164. * Need to double-buffer the call and throw away
  165. * the extra...
  166. */
  167. LPVOID pv;
  168. hres = AllocCbPpv(cbOut, &pv);
  169. // prefix 29344, odd chance that cbOut is 0x0
  170. if (SUCCEEDED(hres) && ( pv != NULL) )
  171. {
  172. lRc = RegQueryValueEx(hk, ptszValue, 0, NULL, pv, &cbOut);
  173. if (lRc == ERROR_SUCCESS)
  174. {
  175. CopyMemory(pvBuf, pv, cb);
  176. hres = S_OK;
  177. } else
  178. {
  179. ZeroBuf(pvBuf, cb);
  180. hres = hresLe(lRc); /* Else, something bad happened */
  181. }
  182. FreePv(pv);
  183. }
  184. } else
  185. {
  186. if (lRc == ERROR_KEY_DELETED || lRc == ERROR_BADKEY)
  187. {
  188. lRc = ERROR_FILE_NOT_FOUND;
  189. }
  190. hres = hresLe(lRc);
  191. ZeroBuf(pvBuf, cb);
  192. }
  193. }
  194. #ifdef DEBUG
  195. /*
  196. * Don't whine if the key we couldn't find was
  197. * REGSTR_VAL_JOYUSERVALUES, because almost no one has it.
  198. */
  199. if (FAILED(hres) && lstrcmpi(ptszValue, REGSTR_VAL_JOYUSERVALUES) )
  200. {
  201. SquirtSqflPtszV(sqfl | sqflVerbose,
  202. TEXT("Unable to read %s from registry"),
  203. ptszValue);
  204. }
  205. #endif
  206. return hres;
  207. }
  208. #ifndef WINNT
  209. /*****************************************************************************
  210. *
  211. * @doc INTERNAL
  212. *
  213. * @func HRESULT | JoyReg_IsWdmGameport |
  214. *
  215. * To test whether the joy type is WDM device or not.
  216. *
  217. * @parm HKEY | hk |
  218. *
  219. * Registry key containing fun values.
  220. *
  221. * @returns
  222. *
  223. * S_OK: if it uses WDM driver
  224. *
  225. * E_FAIL>: Not uses WDM driver
  226. *
  227. *****************************************************************************/
  228. STDMETHODIMP
  229. JoyReg_IsWdmGameport( HKEY hk )
  230. {
  231. HRESULT hres = E_FAIL;
  232. if ( hk )
  233. {
  234. WCHAR wsz[MAX_JOYSTRING];
  235. // Whistler PREFIX Bug # 45075, 45076
  236. // Wsz is not initialized
  237. ZeroX(wsz);
  238. if ( ( SUCCEEDED( JoyReg_GetValue( hk, REGSTR_VAL_JOYOEMHARDWAREID, REG_SZ,
  239. &wsz, cbX(wsz) ) ) )
  240. &&( wsz[0] ) )
  241. {
  242. hres = S_OK;
  243. } else if ( SUCCEEDED( JoyReg_GetValue( hk, REGSTR_VAL_JOYOEMCALLOUT, REG_SZ,
  244. &wsz, cbX(wsz) ) ) )
  245. {
  246. static WCHAR wszJoyhid[] = L"joyhid.vxd";
  247. int Idx;
  248. #define WLOWER 0x0020
  249. CAssertF( cbX(wszJoyhid) <= cbX(wsz) );
  250. /*
  251. * Since neither CharUpperW nor lstrcmpiW are really
  252. * implemented on 9x, do it by hand.
  253. */
  254. for ( Idx=cA(wszJoyhid)-2; Idx>=0; Idx-- )
  255. {
  256. if ( ( wsz[Idx] | WLOWER ) != wszJoyhid[Idx] )
  257. {
  258. break;
  259. }
  260. }
  261. if ( ( Idx < 0 ) && ( wsz[cA(wszJoyhid)-1] == 0 ) )
  262. {
  263. hres = S_OK;
  264. }
  265. #undef WLOWER
  266. }
  267. }
  268. return hres;
  269. }
  270. #endif /* ndef WINNT */
  271. #if 0
  272. /*
  273. * This function should be in diutil.c Putting here is just to keep it together with
  274. * JoyReg_IsWdmGameport();
  275. */
  276. STDMETHODIMP
  277. JoyReg_IsWdmGameportFromDeviceInstance( LPTSTR ptszDeviceInst )
  278. {
  279. /*
  280. * ptszDeviceInst's format is like this:
  281. * HID\VID_045E&PID_0102\0000GAMEPORT&PVID_....
  282. */
  283. WCHAR wszDeviceInst[MAX_PATH];
  284. HRESULT hres = E_FAIL;
  285. if ( ptszDeviceInst )
  286. {
  287. memset( wszDeviceInst, 0, cbX(wszDeviceInst) );
  288. TToU( wszDeviceInst, MAX_PATH, ptszDeviceInst );
  289. wszDeviceInst[34] = 0;
  290. if ( memcmp( &wszDeviceInst[26], c_hwIdPrefix, 16 ) == 0 )
  291. {
  292. hres = S_OK;
  293. }
  294. }
  295. return hres;
  296. }
  297. #endif
  298. /*****************************************************************************
  299. *
  300. * @doc INTERNAL
  301. *
  302. * @func HRESULT | JoyReg_SetValue |
  303. *
  304. * Write registry information.
  305. *
  306. * @parm HKEY | hk |
  307. *
  308. * Registry key containing fun values.
  309. *
  310. * @parm LPCTSTR | ptszValue |
  311. *
  312. * Registry value name.
  313. *
  314. * @parm DWORD | reg |
  315. *
  316. * Registry data type to set.
  317. *
  318. * @parm LPCVOID | pvBuf |
  319. *
  320. * Buffer containing information to write to registry.
  321. *
  322. * @parm DWORD | cb |
  323. *
  324. * Size of buffer, in bytes. Ignored if writing a string.
  325. *
  326. * @returns
  327. *
  328. * Returns a COM error code. The following error codes are
  329. * intended to be illustrative and not necessarily comprehensive.
  330. *
  331. * <c DI_OK> = <c S_OK>: The operation completed successfully.
  332. *
  333. * <c E_FAIL>: Error writing value to registry.
  334. *
  335. *****************************************************************************/
  336. STDMETHODIMP
  337. JoyReg_SetValue(HKEY hk, LPCTSTR ptszValue, DWORD reg, PCV pvBuf, DWORD cb)
  338. {
  339. HRESULT hres;
  340. LONG lRc;
  341. /*
  342. * Strings must be handled differently from binaries.
  343. *
  344. * A null string translates into deleting the key.
  345. */
  346. if (reg == REG_SZ)
  347. {
  348. lRc = RegSetStringValueW(hk, ptszValue, pvBuf);
  349. } else
  350. {
  351. lRc = RegSetValueEx(hk, ptszValue, 0, reg, pvBuf, cb);
  352. }
  353. if (lRc == ERROR_SUCCESS)
  354. {
  355. hres = S_OK;
  356. } else
  357. {
  358. RPF("Unable to write %s to registry", ptszValue);
  359. hres = E_FAIL; /* Else, something bad happened */
  360. }
  361. return hres;
  362. }
  363. /*****************************************************************************
  364. *
  365. * @doc INTERNAL
  366. *
  367. * @func HRESULT | JoyReg_OpenTypeKey |
  368. *
  369. * Open the joystick registry key that corresponds to a
  370. * joystick type.
  371. *
  372. * @parm LPCWSTR | pwszTypeName |
  373. *
  374. * The name of the type.
  375. *
  376. * @parm DWORD | sam |
  377. *
  378. * Desired security access mask.
  379. *
  380. * @parm OUT PHKEY | phk |
  381. *
  382. * Receives the opened registry key on success.
  383. *
  384. * @returns
  385. *
  386. * Returns a COM error code. The following error codes are
  387. * intended to be illustrative and not necessarily comprehensive.
  388. *
  389. * <c DI_OK> = <c S_OK>: The operation completed successfully.
  390. *
  391. * <c DIERR_NOTFOUND>: The joystick type was not found.
  392. *
  393. *****************************************************************************/
  394. STDMETHODIMP
  395. JoyReg_OpenTypeKey(LPCWSTR pwszType, DWORD sam, DWORD dwOptions, PHKEY phk)
  396. {
  397. HRESULT hres;
  398. HKEY hkTypes;
  399. EnterProc(JoyReg_OpenTypeKey, (_ "W", pwszType));
  400. /*
  401. * Note that it is not safe to cache the registry key.
  402. * If somebody deletes the registry key, our handle
  403. * goes stale and becomes useless.
  404. */
  405. hres = hresMumbleKeyEx(HKEY_LOCAL_MACHINE,
  406. REGSTR_PATH_JOYOEM,
  407. sam,
  408. REG_OPTION_NON_VOLATILE,
  409. &hkTypes);
  410. if ( SUCCEEDED(hres) )
  411. {
  412. #ifndef UNICODE
  413. TCHAR tszType[MAX_PATH];
  414. UToA( tszType, cA(tszType), pwszType );
  415. hres = hresMumbleKeyEx(hkTypes,
  416. tszType,
  417. sam,
  418. dwOptions,
  419. phk);
  420. #else
  421. hres = hresMumbleKeyEx(hkTypes,
  422. pwszType,
  423. sam,
  424. dwOptions,
  425. phk);
  426. #endif
  427. RegCloseKey(hkTypes);
  428. }
  429. if (FAILED(hres))
  430. {
  431. *phk = 0;
  432. }
  433. ExitBenignOleProcPpv(phk);
  434. return hres;
  435. }
  436. /*****************************************************************************
  437. *
  438. * @doc INTERNAL
  439. *
  440. * @func HRESULT | JoyReg_OpenPropKey |
  441. *
  442. * Open the Dinput properties registry key that corresponds to a
  443. * device type. This key contains the OEMMapFile and dwFlags2 information
  444. * Nominally the location HKLM/REGSTR_PATH_PRIVATEPROPERTIES/DirectInput.
  445. *
  446. * @parm LPCWSTR | pwszTypeName |
  447. *
  448. * The name of the type.
  449. *
  450. * @parm DWORD | sam |
  451. *
  452. * Desired security access mask.
  453. *
  454. * @parm OUT PHKEY | phk |
  455. *
  456. * Receives the opened registry key on success.
  457. *
  458. * @returns
  459. *
  460. * Returns a COM error code. The following error codes are
  461. * intended to be illustrative and not necessarily comprehensive.
  462. *
  463. * <c DI_OK> = <c S_OK>: The operation completed successfully.
  464. *
  465. * <c DIERR_NOTFOUND>: The type was not found.
  466. *
  467. *****************************************************************************/
  468. STDMETHODIMP
  469. JoyReg_OpenPropKey(LPCWSTR pwszType, DWORD sam, DWORD dwOptions, PHKEY phk)
  470. {
  471. HRESULT hres;
  472. HKEY hkTypes;
  473. EnterProc(JoyReg_OpenTypeKey, (_ "W", pwszType));
  474. /*
  475. * Note that it is not safe to cache the registry key.
  476. * If somebody deletes the registry key, our handle
  477. * goes stale and becomes useless.
  478. */
  479. hres = hresMumbleKeyEx(HKEY_LOCAL_MACHINE,
  480. REGSTR_PATH_DITYPEPROP,
  481. sam,
  482. REG_OPTION_NON_VOLATILE,
  483. &hkTypes);
  484. if ( SUCCEEDED(hres) )
  485. {
  486. #ifndef UNICODE
  487. TCHAR tszType[MAX_PATH];
  488. UToA( tszType, cA(tszType), pwszType );
  489. hres = hresMumbleKeyEx(hkTypes,
  490. tszType,
  491. sam,
  492. dwOptions,
  493. phk);
  494. #else
  495. hres = hresMumbleKeyEx(hkTypes,
  496. pwszType,
  497. sam,
  498. dwOptions,
  499. phk);
  500. #endif
  501. RegCloseKey(hkTypes);
  502. }
  503. if (FAILED(hres))
  504. {
  505. *phk = 0;
  506. }
  507. ExitBenignOleProcPpv(phk);
  508. return hres;
  509. }
  510. /*****************************************************************************
  511. *
  512. * @doc INTERNAL
  513. *
  514. * @func HRESULT | JoyReg_GetTypeInfo |
  515. *
  516. * Obtain information about a non-predefined joystick type.
  517. *
  518. * @parm LPCWSTR | pwszTypeName |
  519. *
  520. * The name of the type.
  521. *
  522. * @parm OUT LPDIJOYTYPEINFO | pjti |
  523. *
  524. * Receives information about the joystick type.
  525. * The caller is assumed to have validated the
  526. * <e DIJOYCONFIG.dwSize> field.
  527. *
  528. * @parm DWORD | fl |
  529. *
  530. * Zero or more <c DITC_*> flags
  531. * which specify which parts of the structure pointed
  532. * to by <p pjti> are to be filled in.
  533. *
  534. * @returns
  535. *
  536. * Returns a COM error code. The following error codes are
  537. * intended to be illustrative and not necessarily comprehensive.
  538. *
  539. * <c DI_OK> = <c S_OK>: The operation completed successfully.
  540. * <c S_FALSE> if some of the data was not available.
  541. *
  542. * <c DIERR_NOTFOUND>: The joystick type was not found.
  543. *
  544. *****************************************************************************/
  545. STDMETHODIMP
  546. JoyReg_GetTypeInfo(LPCWSTR pwszType, LPDIJOYTYPEINFO pjti, DWORD fl)
  547. {
  548. HRESULT hres = S_FALSE;
  549. HKEY hk;
  550. BOOL fPartialData = FALSE;
  551. EnterProc(JoyReg_GetTypeInfo, (_ "Wx", pwszType, fl));
  552. ZeroX(pjti->clsidConfig);
  553. if( fl & ( DITC_FLAGS2 | DITC_MAPFILE ) )
  554. {
  555. /*
  556. * The new registry branch is likely to be empty for many devices
  557. * so don't fail for anything here.
  558. */
  559. hres = JoyReg_OpenPropKey(pwszType, KEY_QUERY_VALUE, REG_OPTION_NON_VOLATILE, &hk);
  560. if( SUCCEEDED( hres ) )
  561. {
  562. if( fl & DITC_FLAGS2 )
  563. {
  564. hres = JoyReg_GetValue(hk,
  565. REGSTR_VAL_FLAGS2, REG_BINARY,
  566. &pjti->dwFlags2,
  567. cbX(pjti->dwFlags2) );
  568. pjti->dwFlags2 &= JOYTYPE_FLAGS2_GETVALID;
  569. if( FAILED( hres ) )
  570. {
  571. pjti->dwFlags2 = 0x0;
  572. fPartialData = TRUE;
  573. }
  574. }
  575. if( fl & DITC_MAPFILE )
  576. {
  577. hres = JoyReg_GetValue(hk,
  578. REGSTR_VAL_JOYOEMMAPFILE, REG_SZ,
  579. pjti->wszMapFile,
  580. cbX(pjti->wszMapFile));
  581. if( FAILED( hres ) )
  582. {
  583. ZeroX(pjti->wszMapFile);
  584. fPartialData = TRUE;
  585. }
  586. }
  587. RegCloseKey(hk);
  588. }
  589. else
  590. {
  591. pjti->dwFlags2 = 0x0;
  592. ZeroX(pjti->wszMapFile);
  593. fPartialData = TRUE;
  594. }
  595. hres = S_OK;
  596. }
  597. if( fl & DITC_INREGISTRY_DX6 )
  598. {
  599. hres = JoyReg_OpenTypeKey(pwszType, KEY_QUERY_VALUE, REG_OPTION_NON_VOLATILE, &hk);
  600. if (SUCCEEDED(hres))
  601. {
  602. if (fl & DITC_REGHWSETTINGS)
  603. {
  604. hres = JoyReg_GetValue(hk,
  605. REGSTR_VAL_JOYOEMDATA, REG_BINARY,
  606. &pjti->hws, cbX(pjti->hws));
  607. if (FAILED(hres))
  608. {
  609. goto closedone;
  610. }
  611. }
  612. /*
  613. * Note that this never fails.
  614. */
  615. if (fl & DITC_CLSIDCONFIG)
  616. {
  617. TCHAR tszGuid[ctchGuid];
  618. LONG lRc;
  619. lRc = RegQueryString(hk, REGSTR_VAL_CPLCLSID, tszGuid, cA(tszGuid));
  620. if (lRc == ERROR_SUCCESS &&
  621. ParseGUID(&pjti->clsidConfig, tszGuid))
  622. {
  623. /* Guid is good */
  624. } else
  625. {
  626. ZeroX(pjti->clsidConfig);
  627. }
  628. }
  629. if (fl & DITC_DISPLAYNAME)
  630. {
  631. hres = JoyReg_GetValue(hk,
  632. REGSTR_VAL_JOYOEMNAME, REG_SZ,
  633. pjti->wszDisplayName,
  634. cbX(pjti->wszDisplayName));
  635. if (FAILED(hres))
  636. {
  637. goto closedone;
  638. }
  639. }
  640. #ifndef WINNT
  641. if (fl & DITC_CALLOUT)
  642. {
  643. hres = JoyReg_GetValue(hk,
  644. REGSTR_VAL_JOYOEMCALLOUT, REG_SZ,
  645. pjti->wszCallout,
  646. cbX(pjti->wszCallout));
  647. if (FAILED(hres))
  648. {
  649. ZeroX(pjti->wszCallout);
  650. hres = S_FALSE;
  651. fPartialData = TRUE;
  652. }
  653. }
  654. #endif
  655. if ( fl & DITC_HARDWAREID )
  656. {
  657. hres = JoyReg_GetValue(hk,
  658. REGSTR_VAL_JOYOEMHARDWAREID, REG_SZ,
  659. pjti->wszHardwareId,
  660. cbX(pjti->wszHardwareId));
  661. if ( FAILED(hres))
  662. {
  663. ZeroX(pjti->wszHardwareId);
  664. hres = S_FALSE;
  665. fPartialData = TRUE;
  666. }
  667. }
  668. if ( fl & DITC_FLAGS1 )
  669. {
  670. hres = JoyReg_GetValue(hk,
  671. REGSTR_VAL_FLAGS1, REG_BINARY,
  672. &pjti->dwFlags1,
  673. cbX(pjti->dwFlags1) );
  674. if ( FAILED(hres) )
  675. {
  676. pjti->dwFlags1 = 0x0;
  677. hres = S_FALSE;
  678. fPartialData = TRUE;
  679. }
  680. pjti->dwFlags1 &= JOYTYPE_FLAGS1_GETVALID;
  681. }
  682. hres = S_OK;
  683. closedone:;
  684. RegCloseKey(hk);
  685. } else
  686. {
  687. // ISSUE-2001/03/29-timgill debug string code should be higher
  688. // (MarcAnd) this really should be at least sqflError but
  689. // this happens a lot, probably due to not filtering out predefs
  690. SquirtSqflPtszV(sqfl | sqflBenign,
  691. TEXT( "IDirectInputJoyConfig::GetTypeInfo: Nonexistent type %lS" ),
  692. pwszType);
  693. hres = DIERR_NOTFOUND;
  694. }
  695. }
  696. if( SUCCEEDED( hres ) && fPartialData )
  697. {
  698. hres = S_FALSE;
  699. }
  700. ExitOleProc();
  701. return hres;
  702. }
  703. /*****************************************************************************
  704. *
  705. * @doc INTERNAL
  706. *
  707. * @func HRESULT | JoyReg_SetTypeInfo |
  708. *
  709. * Store information about a non-predefined joystick type
  710. * into the registry.
  711. *
  712. * @parm HKEY | hkTypeW |
  713. *
  714. * Registry key to the types branch with write access.
  715. *
  716. * @parm LPCWSTR | pwszTypeName |
  717. *
  718. * The name of the type.
  719. *
  720. * @parm IN LPCDIJOYTYPEINFO | pjti |
  721. *
  722. * Contains information about the joystick type.
  723. *
  724. * @parm DWORD | fl |
  725. *
  726. * Zero or more <c DITC_*> flags
  727. * which specify which parts of the structure pointed
  728. * to by <p pjti> contain values which are to be set.
  729. *
  730. * @returns
  731. *
  732. * Returns a COM error code. The following error codes are
  733. * intended to be illustrative and not necessarily comprehensive.
  734. *
  735. * <c DI_OK> = <c S_OK>: The operation completed successfully.
  736. *
  737. * <c DIERR_NOTFOUND>: The joystick type was not found.
  738. *
  739. *****************************************************************************/
  740. STDMETHODIMP
  741. JoyReg_SetTypeInfo(HKEY hkTypesW,
  742. LPCWSTR pwszType, LPCDIJOYTYPEINFO pjti, DWORD fl)
  743. {
  744. HRESULT hres = S_OK; /* Vacuous success in case of no flags set */
  745. ULONG lRc;
  746. EnterProc(JoyRegSetTypeInfo, (_ "Wx", pwszType, fl));
  747. if( fl & ( DITC_FLAGS2 | DITC_MAPFILE ) )
  748. {
  749. HKEY hkProp;
  750. hres = JoyReg_OpenPropKey(pwszType, DI_KEY_ALL_ACCESS, REG_OPTION_NON_VOLATILE, &hkProp);
  751. if( SUCCEEDED( hres ) )
  752. {
  753. if( fl & DITC_FLAGS2 )
  754. {
  755. DWORD dwTemp;
  756. LONG lRc;
  757. /*
  758. * Read and merge any current value so that bits unused in
  759. * DX8 can be preserved. Although this is more work now it
  760. * should save adding Flags3 support next time.
  761. */
  762. AssertF( (pjti->dwFlags2 & ~JOYTYPE_FLAGS2_SETVALID) == 0x0 );
  763. /*
  764. * PREFIX warns (259898) that RegQueryValueEx reads the value
  765. * of dwTemp before it is set but then it checks lpData and
  766. * zeroes the value before it is used.
  767. */
  768. lRc = RegQueryValueEx( hkProp, REGSTR_VAL_FLAGS2, 0, 0, 0, &dwTemp );
  769. if( lRc == ERROR_FILE_NOT_FOUND )
  770. {
  771. lRc = ERROR_SUCCESS;
  772. dwTemp = cbX( pjti->dwFlags2 );
  773. }
  774. if( lRc == ERROR_SUCCESS )
  775. {
  776. if( dwTemp <= cbX( pjti->dwFlags2 ) )
  777. {
  778. CAssertF( cbX( dwTemp ) == cbX( pjti->dwFlags2 ) );
  779. JoyReg_GetValue( hkProp, REGSTR_VAL_FLAGS2,
  780. REG_BINARY, &dwTemp, cbX( dwTemp ) );
  781. dwTemp &= ~JOYTYPE_FLAGS2_SETVALID;
  782. dwTemp |= pjti->dwFlags2;
  783. if( dwTemp )
  784. {
  785. hres = JoyReg_SetValue( hkProp, REGSTR_VAL_FLAGS2,
  786. REG_BINARY, (PV)&dwTemp, cbX( dwTemp ) );
  787. } else
  788. {
  789. lRc = RegDeleteValue( hkProp, REGSTR_VAL_FLAGS2 );
  790. if (lRc == ERROR_FILE_NOT_FOUND)
  791. {
  792. lRc = ERROR_SUCCESS;
  793. }
  794. hres = hresLe( lRc );
  795. }
  796. }
  797. else
  798. {
  799. /*
  800. * Need to double buffer for the extra bytes
  801. */
  802. PBYTE pbFlags2;
  803. hres = AllocCbPpv( dwTemp, &pbFlags2 );
  804. if( SUCCEEDED( hres ) )
  805. {
  806. if ( ERROR_SUCCESS == RegQueryValueEx(
  807. hkProp, REGSTR_VAL_FLAGS2, 0, NULL, pbFlags2, &dwTemp ) )
  808. {
  809. CAssertF( JOYTYPE_FLAGS2_SETVALID == JOYTYPE_FLAGS2_GETVALID );
  810. *(PDWORD)pbFlags2 &= ~JOYTYPE_FLAGS2_SETVALID;
  811. *(PDWORD)pbFlags2 |= pjti->dwFlags2;
  812. if ( ERROR_SUCCESS == RegSetValueEx(
  813. hkProp, REGSTR_VAL_FLAGS2, 0, REG_BINARY, pbFlags2, dwTemp ) )
  814. {
  815. hres = S_OK;
  816. } else
  817. {
  818. SquirtSqflPtszV(sqfl | sqflError,
  819. TEXT( "IDIJC::SetTypeInfo: failed to write extended Flags2" ) );
  820. hres = E_FAIL;
  821. }
  822. } else
  823. {
  824. SquirtSqflPtszV(sqfl | sqflError,
  825. TEXT( "IDIJC::SetTypeInfo: failed to read extended Flags2" ) );
  826. hres = E_FAIL; /* Else, something bad happened */
  827. }
  828. FreePv( pbFlags2 );
  829. }
  830. }
  831. }
  832. else
  833. {
  834. SquirtSqflPtszV(sqfl | sqflError,
  835. TEXT( "IDIJC::SetTypeInfo: failed to read size of Flags2, error %d" ), lRc );
  836. hres = hresLe( lRc );
  837. }
  838. if( FAILED( hres ) )
  839. {
  840. hres = S_FALSE;
  841. goto closedoneprop;
  842. }
  843. }
  844. if( fl & DITC_MAPFILE )
  845. {
  846. hres = JoyReg_SetValue(hkProp,
  847. REGSTR_VAL_JOYOEMMAPFILE, REG_SZ,
  848. pjti->wszMapFile,
  849. cbX(pjti->wszMapFile));
  850. if( FAILED(hres) )
  851. {
  852. hres = S_FALSE;
  853. goto closedoneprop;
  854. }
  855. }
  856. hres = S_OK;
  857. closedoneprop:;
  858. RegCloseKey(hkProp);
  859. }
  860. else
  861. {
  862. RPF( "Failed to open DirectInput type property key" );
  863. }
  864. }
  865. if( hres == S_OK )
  866. {
  867. if( fl & DITC_INREGISTRY_DX6 )
  868. {
  869. HKEY hk;
  870. DWORD dwOptions = 0;
  871. if ( fl & DITC_VOLATILEREGKEY )
  872. {
  873. dwOptions = REG_OPTION_VOLATILE;
  874. } else
  875. {
  876. dwOptions = REG_OPTION_NON_VOLATILE;
  877. }
  878. #ifndef UNICODE
  879. {
  880. TCHAR tszType[MAX_PATH];
  881. UToA(tszType, cA(tszType), pwszType);
  882. hres = hresMumbleKeyEx(hkTypesW,
  883. tszType,
  884. DI_KEY_ALL_ACCESS,
  885. dwOptions,
  886. &hk);
  887. }
  888. #else
  889. hres = hresMumbleKeyEx(hkTypesW,
  890. pwszType,
  891. DI_KEY_ALL_ACCESS,
  892. dwOptions,
  893. &hk);
  894. #endif
  895. if ( SUCCEEDED(hres) )
  896. {
  897. if (fl & DITC_REGHWSETTINGS)
  898. {
  899. hres = JoyReg_SetValue(hk, REGSTR_VAL_JOYOEMDATA, REG_BINARY,
  900. (PV)&pjti->hws, cbX(pjti->hws));
  901. if (FAILED(hres))
  902. {
  903. goto closedone;
  904. }
  905. }
  906. if (fl & DITC_CLSIDCONFIG)
  907. {
  908. if (IsEqualGUID(&pjti->clsidConfig, &GUID_Null))
  909. {
  910. lRc = RegDeleteValue(hk, REGSTR_VAL_CPLCLSID);
  911. /*
  912. * It is not an error if the key does not already exist.
  913. */
  914. if (lRc == ERROR_FILE_NOT_FOUND)
  915. {
  916. lRc = ERROR_SUCCESS;
  917. }
  918. } else
  919. {
  920. TCHAR tszGuid[ctchNameGuid];
  921. NameFromGUID(tszGuid, &pjti->clsidConfig);
  922. lRc = RegSetValueEx(hk, REGSTR_VAL_CPLCLSID, 0, REG_SZ,
  923. (PV)&tszGuid[ctchNamePrefix], ctchGuid * cbX(tszGuid[0]) );
  924. }
  925. if (lRc == ERROR_SUCCESS)
  926. {
  927. } else
  928. {
  929. hres = E_FAIL;
  930. goto closedone;
  931. }
  932. }
  933. /* ISSUE-2001/03/29-timgill Needs more data checking
  934. Should make sure string is terminated properly */
  935. if (fl & DITC_DISPLAYNAME)
  936. {
  937. hres = JoyReg_SetValue(hk,
  938. REGSTR_VAL_JOYOEMNAME, REG_SZ,
  939. pjti->wszDisplayName,
  940. cbX(pjti->wszDisplayName));
  941. if (FAILED(hres))
  942. {
  943. goto closedone;
  944. }
  945. }
  946. #ifndef WINNT
  947. /* ISSUE-2001/03/29-timgill Needs more data checking
  948. Should make sure string is terminated properly */
  949. if (fl & DITC_CALLOUT)
  950. {
  951. hres = JoyReg_SetValue(hk,
  952. REGSTR_VAL_JOYOEMCALLOUT, REG_SZ,
  953. pjti->wszCallout,
  954. cbX(pjti->wszCallout));
  955. if (FAILED(hres))
  956. {
  957. hres = S_FALSE;
  958. //continue to go
  959. }
  960. }
  961. #endif
  962. if ( fl & DITC_HARDWAREID )
  963. {
  964. hres = JoyReg_SetValue(hk,
  965. REGSTR_VAL_JOYOEMHARDWAREID, REG_SZ,
  966. pjti->wszHardwareId,
  967. cbX(pjti->wszHardwareId) );
  968. if ( FAILED(hres) )
  969. {
  970. hres = S_FALSE;
  971. goto closedone;
  972. }
  973. }
  974. if ( fl & DITC_FLAGS1 )
  975. {
  976. AssertF( (pjti->dwFlags1 & ~JOYTYPE_FLAGS1_SETVALID) == 0x0 );
  977. hres = JoyReg_SetValue(hk,
  978. REGSTR_VAL_FLAGS1, REG_BINARY,
  979. (PV)&pjti->dwFlags1,
  980. cbX(pjti->dwFlags1) );
  981. if ( FAILED(hres) )
  982. {
  983. hres = S_FALSE;
  984. goto closedone;
  985. }
  986. }
  987. hres = S_OK;
  988. closedone:;
  989. RegCloseKey(hk);
  990. } else
  991. {
  992. hres = E_FAIL; /* Registry problem */
  993. }
  994. }
  995. }
  996. ExitOleProc();
  997. return hres;
  998. }
  999. /*****************************************************************************
  1000. *
  1001. * @doc INTERNAL
  1002. *
  1003. * @func HRESULT | JoyReg_OpenConfigKey |
  1004. *
  1005. * Open the registry key that accesses joystick configuration data.
  1006. *
  1007. * Warning! Do not cache this regkey.
  1008. *
  1009. * If the user deletes the key and then re-creates it,
  1010. * the opened key will go stale and will become useless.
  1011. * You have to close the key and reopen it.
  1012. * To avoid worrying about that case, merely open it every time.
  1013. *
  1014. * @parm UINT | idJoy |
  1015. *
  1016. * Joystick number.
  1017. *
  1018. * @parm DWORD | sam |
  1019. *
  1020. * Access level desired.
  1021. *
  1022. * @parm IN DWORD | dwOptions |
  1023. * Option flags to RegCreateEx
  1024. *
  1025. * @parm PHKEY | phk |
  1026. *
  1027. * Receives created registry key.
  1028. *
  1029. * @returns
  1030. *
  1031. * Returns a COM error code. The following error codes are
  1032. * intended to be illustrative and not necessarily comprehensive.
  1033. *
  1034. * <c DI_OK> = <c S_OK>: The operation completed successfully.
  1035. *
  1036. * hresLe(ERROR_FILE_NOT_FOUND): The key does not exist.
  1037. *
  1038. *****************************************************************************/
  1039. STDMETHODIMP
  1040. JoyReg_OpenConfigKey(UINT idJoy, DWORD sam, DWORD dwOptions, PHKEY phk)
  1041. {
  1042. HRESULT hres;
  1043. EnterProc(JoyReg_OpenConfigKey, (_ "uxx", idJoy, sam, dwOptions));
  1044. #ifdef WINNT
  1045. hres = hresMumbleKeyEx(HKEY_LOCAL_MACHINE,
  1046. REGSTR_PATH_JOYCONFIG REGSTR_SZREGKEY REGSTR_KEY_JOYCURR,
  1047. sam, REG_OPTION_VOLATILE, phk);
  1048. #else
  1049. {
  1050. MMRESULT mmrc = MMSYSERR_ERROR;
  1051. JOYCAPS caps;
  1052. /*
  1053. * If we can't get the dev caps for the specified joystick,
  1054. * then use the magic joystick id "-1" to get non-specific
  1055. * caps.
  1056. */
  1057. mmrc = joyGetDevCaps(idJoy, &caps, cbX(caps));
  1058. if ( mmrc != JOYERR_NOERROR )
  1059. {
  1060. mmrc = joyGetDevCaps((DWORD)-1, &caps, cbX(caps));
  1061. }
  1062. if (mmrc == JOYERR_NOERROR)
  1063. {
  1064. TCHAR tsz[cA(REGSTR_PATH_JOYCONFIG) +
  1065. 1 + /* backslash */
  1066. cA(caps.szRegKey) +
  1067. 1 + /* backslash */
  1068. cA(REGSTR_KEY_JOYCURR) + 1];
  1069. /* tsz = MediaResources\Joystick\<drv>\CurrentJoystickSettings */
  1070. wsprintf(tsz, TEXT("%s\\%s\\") REGSTR_KEY_JOYCURR,
  1071. REGSTR_PATH_JOYCONFIG, caps.szRegKey);
  1072. hres = hresMumbleKeyEx(HKEY_LOCAL_MACHINE, tsz, sam, REG_OPTION_VOLATILE, phk);
  1073. } else
  1074. {
  1075. hres = E_FAIL;
  1076. }
  1077. }
  1078. #endif
  1079. ExitBenignOleProc();
  1080. return hres;
  1081. }
  1082. /*****************************************************************************
  1083. *
  1084. * @doc INTERNAL
  1085. *
  1086. * @func HRESULT | JoyReg_OpenSaveKey |
  1087. *
  1088. * Open the registry key that accesses joystick saved configurations
  1089. *
  1090. * Warning! Do not cache this regkey.
  1091. *
  1092. * If the user deletes the key and then re-creates it,
  1093. * the opened key will go stale and will become useless.
  1094. * You have to close the key and reopen it.
  1095. * To avoid worrying about that case, merely open it every time.
  1096. *
  1097. * @parm DWORD | dwType |
  1098. *
  1099. * Joystick type.
  1100. *
  1101. * This is either one of the standard ones in the range
  1102. *
  1103. * @parm IN LPCDIJOYCONFIG | pcfg |
  1104. *
  1105. * If the dwType represents an OEM type, this should point to a
  1106. * configuration data structure containing a valid wszType.
  1107. *
  1108. * @parm DWORD | sam |
  1109. *
  1110. * Access level desired.
  1111. *
  1112. * @parm PHKEY | phk |
  1113. *
  1114. * Receives created registry key.
  1115. *
  1116. * @returns
  1117. *
  1118. * Returns a COM error code. The following error codes are
  1119. * intended to be illustrative and not necessarily comprehensive.
  1120. *
  1121. * <c DI_OK> = <c S_OK>: The operation completed successfully.
  1122. *
  1123. * hresLe(ERROR_FILE_NOT_FOUND): The key does not exist.
  1124. *
  1125. *****************************************************************************/
  1126. STDMETHODIMP
  1127. JoyReg_OpenSaveKey(DWORD dwType, LPCDIJOYCONFIG pcfg, DWORD sam, PHKEY phk)
  1128. {
  1129. HRESULT hres;
  1130. JOYCAPS caps;
  1131. DWORD dwOptions = 0;
  1132. EnterProc(JoyReg_OpenSaveKey, (_ "upx", dwType, pcfg, sam));
  1133. #ifdef WINNT
  1134. lstrcpy(caps.szRegKey, REGSTR_SZREGKEY );
  1135. #else
  1136. /*
  1137. * use the magic joystick id "-1" to get non-specific caps.
  1138. */
  1139. if ( joyGetDevCaps((DWORD)-1, &caps, cbX(caps)) != JOYERR_NOERROR )
  1140. {
  1141. hres = E_FAIL;
  1142. } else
  1143. #endif
  1144. {
  1145. TCHAR tsz[cA(REGSTR_PATH_JOYCONFIG) +
  1146. 1 + /* backslash */
  1147. cA(caps.szRegKey) +
  1148. 1 + /* backslash */
  1149. cA(REGSTR_KEY_JOYSETTINGS) +
  1150. 1 + /* backslash */
  1151. max( cA(REGSTR_KEY_JOYPREDEFN), cA(pcfg->wszType) ) + 1 ];
  1152. /* tsz = MediaResources\Joystick\<drv>\JoystickSettings\<Type> */
  1153. if ( dwType >= JOY_HW_PREDEFMAX )
  1154. {
  1155. wsprintf(tsz, TEXT("%s\\%s\\%s\\%ls"),
  1156. REGSTR_PATH_JOYCONFIG, caps.szRegKey, REGSTR_KEY_JOYSETTINGS, pcfg->wszType);
  1157. } else
  1158. {
  1159. /*
  1160. * We will probably never have more than the current 11 predefined
  1161. * joysticks. Assume no more than 99 so %d is as many characters.
  1162. */
  1163. wsprintf(tsz, TEXT("%s\\%s\\%s\\" REGSTR_KEY_JOYPREDEFN),
  1164. REGSTR_PATH_JOYCONFIG, caps.szRegKey, REGSTR_KEY_JOYSETTINGS, dwType );
  1165. }
  1166. if ( pcfg->hwc.dwUsageSettings & JOY_US_VOLATILE )
  1167. dwOptions = REG_OPTION_VOLATILE;
  1168. else
  1169. dwOptions = REG_OPTION_NON_VOLATILE;
  1170. hres = hresMumbleKeyEx(HKEY_LOCAL_MACHINE, tsz, sam, dwOptions, phk);
  1171. }
  1172. ExitOleProc();
  1173. return hres;
  1174. }
  1175. /*****************************************************************************
  1176. *
  1177. * @doc INTERNAL
  1178. *
  1179. * @func HRESULT | JoyReg_GetSetConfigValue |
  1180. *
  1181. * Retrieve or update configuration information about a joystick,
  1182. * as stored in the registry instance key.
  1183. *
  1184. * @parm HKEY | hk |
  1185. *
  1186. * Registry key containing fun values.
  1187. *
  1188. * @parm LPCTSTR | ptszNValue |
  1189. *
  1190. * Registry value name, with "%d" where a joystick number
  1191. * should be.
  1192. *
  1193. * @parm UINT | idJoy |
  1194. *
  1195. * Zero-based joystick number.
  1196. *
  1197. * @parm DWORD | reg |
  1198. *
  1199. * Registry data type expected.
  1200. *
  1201. * @parm LPVOID | pvBuf |
  1202. *
  1203. * Buffer to receive information from registry (if getting)
  1204. * or containing value to set.
  1205. *
  1206. * @parm DWORD | cb |
  1207. *
  1208. * Size of buffer, in bytes.
  1209. *
  1210. * @parm BOOL | fSet |
  1211. *
  1212. * Nonzer if the value should be set; otherwise, it will be
  1213. * retrieved.
  1214. *
  1215. * @returns
  1216. *
  1217. * Returns a COM error code. The following error codes are
  1218. * intended to be illustrative and not necessarily comprehensive.
  1219. *
  1220. * <c DI_OK> = <c S_OK>: The operation completed successfully.
  1221. *
  1222. * <c E_FAIL>: Error reading/writing value to/from registry.
  1223. *
  1224. *****************************************************************************/
  1225. STDMETHODIMP
  1226. JoyReg_GetSetConfigValue(HKEY hk, LPCTSTR ptszNValue, UINT idJoy,
  1227. DWORD reg, PV pvBuf, DWORD cb, BOOL fSet)
  1228. {
  1229. HRESULT hres;
  1230. int ctch;
  1231. /* Extra +12 because a UINT can be as big as 4 billion */
  1232. TCHAR tsz[max(
  1233. max(
  1234. max(cA(REGSTR_VAL_JOYNCONFIG),
  1235. cA(REGSTR_VAL_JOYNOEMNAME)),
  1236. cA(REGSTR_VAL_JOYNOEMCALLOUT)),
  1237. cA(REGSTR_VAL_JOYNFFCONFIG)) + 12 + 1];
  1238. ctch = wsprintf(tsz, ptszNValue, idJoy + 1);
  1239. AssertF(ctch < cA(tsz));
  1240. if (fSet)
  1241. {
  1242. hres = JoyReg_SetValue(hk, tsz, reg, pvBuf, cb);
  1243. } else
  1244. {
  1245. hres = JoyReg_GetValue(hk, tsz, reg, pvBuf, cb);
  1246. }
  1247. return hres;
  1248. }
  1249. /*****************************************************************************
  1250. *
  1251. * @doc INTERNAL
  1252. *
  1253. * @func HRESULT | hresIdJoypInstanceGUID |
  1254. *
  1255. * Given a joystick ID obtain the corresponding GUID.
  1256. * This routine differs in implementation on WINNT and WIN9x
  1257. * On WINNT there are no predefined GUID for Joystick IDs.
  1258. *
  1259. * @parm IN UINT | idJoy |
  1260. *
  1261. * Joystick identification number.
  1262. *
  1263. * @parm OUT LPGUID | lpguid |
  1264. *
  1265. * Receives the joystick GUID. If no mapping exists,
  1266. * GUID_NULL is passed back
  1267. *
  1268. * On Windows NT all joysticks are HID devices. The corresponding function
  1269. * for WINNT is defined in diWinnt.c
  1270. *
  1271. *****************************************************************************/
  1272. HRESULT EXTERNAL hResIdJoypInstanceGUID_95
  1273. (
  1274. UINT idJoy,
  1275. LPGUID lpguid
  1276. )
  1277. {
  1278. HRESULT hRes;
  1279. hRes = S_OK;
  1280. if ( idJoy < cA(rgGUID_Joystick) )
  1281. {
  1282. *lpguid = rgGUID_Joystick[idJoy];
  1283. } else
  1284. {
  1285. hRes = DIERR_NOTFOUND;
  1286. ZeroX(*lpguid);
  1287. }
  1288. return hRes;
  1289. }
  1290. /*****************************************************************************
  1291. *
  1292. * @doc INTERNAL
  1293. *
  1294. * @func HRESULT | JoyReg_GetConfigInternal |
  1295. *
  1296. * Obtain information about a joystick's configuration.
  1297. *
  1298. * @parm UINT | uiJoy |
  1299. *
  1300. * Joystick identification number.
  1301. *
  1302. * @parm OUT LPDIJOYCONFIG | pcfg |
  1303. *
  1304. * Receives information about the joystick configuration.
  1305. * The caller is assumed to have validated the
  1306. * <e DIJOYCONFIG.dwSize> field.
  1307. *
  1308. * @parm DWORD | fl |
  1309. *
  1310. * Zero or more <c DIJC_*> flags
  1311. * which specify which parts of the structure pointed
  1312. * to by <p pjc> are to be filled in.
  1313. *
  1314. * @returns
  1315. *
  1316. * Returns a COM error code. The following error codes are
  1317. * intended to be illustrative and not necessarily comprehensive.
  1318. *
  1319. * <c DI_OK> = <c S_OK>: The operation completed successfully.
  1320. *
  1321. * <c DIERR_NOMOREITEMS>: No more joysticks.
  1322. *
  1323. *****************************************************************************/
  1324. STDMETHODIMP
  1325. JoyReg_GetConfigInternal(UINT idJoy, LPDIJOYCONFIG pcfg, DWORD fl)
  1326. {
  1327. HRESULT hres = E_FAIL;
  1328. EnterProc(JoyReg_GetConfigInternal, (_ "upx", idJoy, pcfg, fl));
  1329. AssertF((fl & ~DIJC_GETVALID) == 0);
  1330. /* We only support (0/16) joysticks */
  1331. if ( idJoy < cJoyMax )
  1332. {
  1333. /* Force a rescan of all HID device list
  1334. * Some device may have been attached
  1335. * since we last looked
  1336. */
  1337. DIHid_BuildHidList(FALSE);
  1338. if (fl & DIJC_GUIDINSTANCE)
  1339. {
  1340. hres = hResIdJoypInstanceGUID_WDM(idJoy, &pcfg->guidInstance);
  1341. #ifndef WINNT
  1342. if ( FAILED(hres) )
  1343. {
  1344. hres = hResIdJoypInstanceGUID_95(idJoy, &pcfg->guidInstance);
  1345. }
  1346. #endif
  1347. if ( FAILED(hres) )
  1348. {
  1349. goto done;
  1350. }
  1351. }
  1352. if ( fl & DIJC_INREGISTRY )
  1353. {
  1354. HKEY hk;
  1355. /* Does the registry entry exist ? */
  1356. hres = JoyReg_OpenConfigKey(idJoy, KEY_QUERY_VALUE, REG_OPTION_NON_VOLATILE , &hk);
  1357. if (SUCCEEDED(hres))
  1358. {
  1359. if (fl & DIJC_REGHWCONFIGTYPE)
  1360. {
  1361. hres = JoyReg_GetConfigValue(
  1362. hk, REGSTR_VAL_JOYNCONFIG,
  1363. idJoy, REG_BINARY,
  1364. &pcfg->hwc, cbX(pcfg->hwc));
  1365. if (FAILED(hres))
  1366. {
  1367. goto closedone;
  1368. }
  1369. pcfg->wszType[0] = TEXT('\0');
  1370. if ( (pcfg->hwc.dwUsageSettings & JOY_US_ISOEM)
  1371. #ifndef WINNT
  1372. ||( (pcfg->hwc.dwType >= JOY_HW_PREDEFMIN)
  1373. &&(pcfg->hwc.dwType < JOY_HW_PREDEFMAX) )
  1374. #endif
  1375. )
  1376. {
  1377. hres = JoyReg_GetConfigValue(
  1378. hk, REGSTR_VAL_JOYNOEMNAME, idJoy, REG_SZ,
  1379. pcfg->wszType, cbX(pcfg->wszType));
  1380. if (FAILED(hres))
  1381. {
  1382. goto closedone;
  1383. }
  1384. }
  1385. }
  1386. #ifndef WINNT
  1387. if (fl & DIJC_CALLOUT)
  1388. {
  1389. pcfg->wszCallout[0] = TEXT('\0');
  1390. hres = JoyReg_GetConfigValue(
  1391. hk, REGSTR_VAL_JOYNOEMCALLOUT, idJoy, REG_SZ,
  1392. pcfg->wszCallout, cbX(pcfg->wszCallout));
  1393. if (FAILED(hres))
  1394. {
  1395. ZeroX(pcfg->wszCallout);
  1396. hres = S_FALSE;
  1397. /* Note that we fall through and let hres = S_OK */
  1398. }
  1399. }
  1400. #endif
  1401. if (fl & DIJC_GAIN)
  1402. {
  1403. /*
  1404. * If there is no FF configuration, then
  1405. * default to DI_FFNOMINALMAX gain.
  1406. */
  1407. hres = JoyReg_GetConfigValue(hk,
  1408. REGSTR_VAL_JOYNFFCONFIG,
  1409. idJoy, REG_BINARY,
  1410. &pcfg->dwGain, cbX(pcfg->dwGain));
  1411. if (SUCCEEDED(hres) && ISVALIDGAIN(pcfg->dwGain))
  1412. {
  1413. /* Leave it alone; it's good */
  1414. } else
  1415. {
  1416. hres = S_FALSE;
  1417. pcfg->dwGain = DI_FFNOMINALMAX;
  1418. /* Note that we fall through and let hres = S_OK */
  1419. }
  1420. }
  1421. if ( fl & DIJC_WDMGAMEPORT )
  1422. {
  1423. PBUSDEVICEINFO pbdi;
  1424. /*
  1425. * If there is no Gameport Associated with this device
  1426. * then it must be a USB device
  1427. */
  1428. DllEnterCrit();
  1429. if ( pbdi = pbdiFromJoyId(idJoy) )
  1430. {
  1431. pcfg->guidGameport = pbdi->guid;
  1432. //lstrcpyW(pcfg->wszGameport, pbdi->wszDisplayName);
  1433. } else
  1434. {
  1435. ZeroX(pcfg->guidGameport);
  1436. //pcfg->wszGameport[0] = TEXT('\0');
  1437. }
  1438. DllLeaveCrit();
  1439. }
  1440. }
  1441. closedone:
  1442. RegCloseKey(hk);
  1443. }
  1444. } else
  1445. {
  1446. hres = DIERR_NOMOREITEMS;
  1447. }
  1448. done:
  1449. ExitBenignOleProc();
  1450. return hres;
  1451. }
  1452. /*****************************************************************************
  1453. *
  1454. * @doc INTERNAL
  1455. *
  1456. * @func HRESULT | JoyReg_GetConfig |
  1457. *
  1458. * Obtain information about a joystick's configuration,
  1459. * taking the *naive* MSGAME.VXD driver into account.
  1460. *
  1461. * @parm UINT | uiJoy |
  1462. *
  1463. * Joystick identification number.
  1464. *
  1465. * @parm OUT LPDIJOYCONFIG | pcfg |
  1466. *
  1467. * Receives information about the joystick configuration.
  1468. * The caller is assumed to have validated the
  1469. * <e DIJOYCONFIG.dwSize> field.
  1470. *
  1471. * @parm DWORD | fl |
  1472. *
  1473. * Zero or more <c DIJC_*> flags
  1474. * which specify which parts of the structure pointed
  1475. * to by <p pjc> are to be filled in.
  1476. *
  1477. * @returns
  1478. *
  1479. * Returns a COM error code. The following error codes are
  1480. * intended to be illustrative and not necessarily comprehensive.
  1481. *
  1482. * <c DI_OK> = <c S_OK>: The operation completed successfully.
  1483. *
  1484. * <c DIERR_NOMOREITEMS>: No more joysticks.
  1485. *
  1486. *****************************************************************************/
  1487. STDMETHODIMP
  1488. JoyReg_GetConfig(UINT idJoy, LPDIJOYCONFIG pcfg, DWORD fl)
  1489. {
  1490. HRESULT hres;
  1491. GUID guid;
  1492. EnterProc(JoyReg_GetConfig, (_ "upx", idJoy, pcfg, fl));
  1493. AssertF((fl & ~DIJC_GETVALID) == 0);
  1494. /*
  1495. * First determine if the joystick exits
  1496. * On NT, we use WDM driver.
  1497. * On Win9x, if WDM fails, use static guids.
  1498. */
  1499. hres = hResIdJoypInstanceGUID_WDM(idJoy, &guid);
  1500. #ifndef WINNT
  1501. if ( FAILED(hres) )
  1502. {
  1503. hres = hResIdJoypInstanceGUID_95(idJoy, &guid);
  1504. }
  1505. #endif
  1506. if ( SUCCEEDED( hres) )
  1507. {
  1508. hres = JoyReg_GetConfigInternal(idJoy, pcfg, fl);
  1509. #ifndef WINNT
  1510. /***************************************************
  1511. *
  1512. * Beginning of hack for *naive* Sidewinder Gamepad.
  1513. *
  1514. * The gamepad needs to be polled sixteen times
  1515. * before it realizes what is going on.
  1516. *
  1517. ***************************************************/
  1518. if (SUCCEEDED(hres) && (fl & DIJC_CALLOUT))
  1519. {
  1520. static WCHAR s_wszMSGAME[] = L"MSGAME.VXD";
  1521. if (memcmp(pcfg->wszCallout, s_wszMSGAME, cbX(s_wszMSGAME)) == 0)
  1522. {
  1523. SquirtSqflPtszV(sqfl,
  1524. TEXT("Making bonus polls for Sidewinder"));
  1525. /*
  1526. * Sigh. It's a Sidewinder. Make sixteen
  1527. * bonus polls to shake the stick into submission.
  1528. *
  1529. * There's no point in doing this over and over if we're
  1530. * in some kind of loop so make sure a "reasonable"
  1531. * length of time has passed since last time we tried.
  1532. * 3 seconds is a little less than the current CPL
  1533. * background refresh rate.
  1534. */
  1535. if ( !g_dwLastBonusPoll || ( GetTickCount() - g_dwLastBonusPoll > 3000 ) )
  1536. {
  1537. JOYINFOEX ji;
  1538. int i;
  1539. DWORD dwWait;
  1540. ji.dwSize = cbX(ji);
  1541. ji.dwFlags = JOY_RETURNALL;
  1542. for (i = 0; i < 16; i++)
  1543. {
  1544. MMRESULT mmrc = joyGetPosEx(idJoy, &ji);
  1545. SquirtSqflPtszV(sqfl,
  1546. TEXT("joyGetPosEx(%d) = %d"),
  1547. idJoy, mmrc);
  1548. /*
  1549. * Sleep 10ms between each poll because that
  1550. * seems to help a bit.
  1551. */
  1552. Sleep(10);
  1553. }
  1554. /*
  1555. * Bonus hack! Now sleep for some time.
  1556. * The amount of time we need to sleep is CPU-speed
  1557. * dependent, so we'll grab the sleep time from the
  1558. * registry to allow us to tweak it later.
  1559. *
  1560. * What a shame.
  1561. */
  1562. dwWait = RegQueryDIDword(NULL, REGSTR_VAL_GAMEPADDELAY, 100);
  1563. if (dwWait > 10 * 1000)
  1564. {
  1565. dwWait = 10 * 1000;
  1566. }
  1567. Sleep(dwWait);
  1568. /*
  1569. * And then check again.
  1570. */
  1571. hres = JoyReg_GetConfigInternal(idJoy, pcfg, fl);
  1572. g_dwLastBonusPoll = GetTickCount();
  1573. }
  1574. }
  1575. }
  1576. /***************************************************
  1577. *
  1578. * End of hack for *naive* Sidewinder Gamepad.
  1579. *
  1580. ***************************************************/
  1581. #endif
  1582. }
  1583. return hres;
  1584. }
  1585. #ifndef WINNT
  1586. /*****************************************************************************
  1587. *
  1588. * @doc INTERNAL
  1589. *
  1590. * @func HRESULT | JoyReg_JoyIdToDeviceInterface_95 |
  1591. *
  1592. * Given a joystick ID number, obtain the device interface
  1593. * corresponding to it.
  1594. *
  1595. * @parm UINT | idJoy |
  1596. *
  1597. * Joystick ID number, zero-based.
  1598. *
  1599. * @parm PVXDINITPARMS | pvip |
  1600. *
  1601. * Receives init parameters from the driver.
  1602. *
  1603. * @parm LPTSTR | ptszBuf |
  1604. *
  1605. * A buffer of size <c MAX_PATH> in which the device interface
  1606. * path is built. Note that we can get away with a buffer of
  1607. * this size, since the code path exists only on Windows 95,
  1608. * and Windows 95 does not support paths longer than <c MAX_PATH>.
  1609. * (I.e., there ain't no \\?\ support in Win95.)
  1610. *
  1611. * @returns
  1612. *
  1613. * A pointer to the part of the <p ptszBuf> buffer that
  1614. * contains the actual device interface path.
  1615. *
  1616. *****************************************************************************/
  1617. LPSTR EXTERNAL
  1618. JoyReg_JoyIdToDeviceInterface_95(UINT idJoy, PVXDINITPARMS pvip, LPSTR ptszBuf)
  1619. {
  1620. UINT cwch;
  1621. HRESULT hres;
  1622. LPSTR ptszRc;
  1623. hres = Hel_Joy_GetInitParms(idJoy, pvip);
  1624. if (SUCCEEDED(hres))
  1625. {
  1626. /*
  1627. * The length counter includes the terminating null.
  1628. */
  1629. cwch = LOWORD(pvip->dwFilenameLengths);
  1630. /*
  1631. * The name that comes from HID is "\DosDevices\blah"
  1632. * but we want to use "\\.\blah". So check if it indeed
  1633. * of the form "\DosDevices\blah" and if so, convert it.
  1634. * If not, then give up.
  1635. *
  1636. * For the string to possibly be a "\DosDevices\", it
  1637. * needs to be of length 12 or longer.
  1638. */
  1639. if (cwch >= 12 && cwch < MAX_PATH)
  1640. {
  1641. /*
  1642. * WideCharToMultiByte does parameter validation so we
  1643. * don't have to.
  1644. */
  1645. WideCharToMultiByte(CP_ACP, 0, pvip->pFilenameBuffer, cwch,
  1646. ptszBuf, MAX_PATH, 0, 0);
  1647. /*
  1648. * The 11th (zero-based) character must be a backslash.
  1649. * And the value of cwch had better be right.
  1650. */
  1651. if (ptszBuf[cwch-1] == ('\0') && ptszBuf[11] == ('\\'))
  1652. {
  1653. /*
  1654. * Wipe out the backslash and make sure the lead-in
  1655. * is "\DosDevices".
  1656. */
  1657. ptszBuf[11] = ('\0');
  1658. if (lstrcmpiA(ptszBuf, ("\\DosDevices")) == 0)
  1659. {
  1660. /*
  1661. * Create a "\\.\" at the start of the string.
  1662. * Note! This code never runs on Alphas so we
  1663. * can do evil unaligned data accesses.
  1664. *
  1665. * (Actually, 8 is a multiple of 4, so everything
  1666. * is aligned after all.)
  1667. */
  1668. *(LPDWORD)&ptszBuf[8] = 0x5C2E5C5C;
  1669. ptszRc = &ptszBuf[8];
  1670. } else
  1671. {
  1672. ptszRc = NULL;
  1673. }
  1674. } else
  1675. {
  1676. ptszRc = NULL;
  1677. }
  1678. } else
  1679. {
  1680. ptszRc = NULL;
  1681. }
  1682. } else
  1683. {
  1684. ptszRc = NULL;
  1685. }
  1686. return ptszRc;
  1687. }
  1688. /*****************************************************************************
  1689. *
  1690. * @doc INTERNAL
  1691. *
  1692. * @func void | JoyReg_SetCalibration |
  1693. *
  1694. * Store information about a joystick's configuration,
  1695. * shadowing the information back into the HID side of
  1696. * things as well.
  1697. *
  1698. * @parm UINT | uiJoy |
  1699. *
  1700. * Joystick identification number.
  1701. *
  1702. * @parm LPJOYREGHWCONFIG | phwc |
  1703. *
  1704. * Contains information about the joystick capabilities.
  1705. * This value supercedes the value in the <p pcfg>.
  1706. *
  1707. * @parm LPCDIJOYCONFIG | pcfg |
  1708. *
  1709. * Contains information about the joystick configuration.
  1710. * The caller is assumed to have validated all fields.
  1711. *
  1712. *****************************************************************************/
  1713. STDMETHODIMP
  1714. TFORM(CDIObj_FindDevice)(PV pdiT, REFGUID rguid,
  1715. LPCTSTR ptszName, LPGUID pguidOut);
  1716. void EXTERNAL
  1717. JoyReg_SetCalibration(UINT idJoy, LPJOYREGHWCONFIG phwc)
  1718. {
  1719. HRESULT hres;
  1720. VXDINITPARMS vip;
  1721. GUID guid;
  1722. CHAR tsz[MAX_PATH];
  1723. LPSTR pszPath;
  1724. TCHAR ptszPath[MAX_PATH];
  1725. EnterProc(JoyReg_SetCalibration, (_ "up", idJoy, phwc));
  1726. pszPath = JoyReg_JoyIdToDeviceInterface_95(idJoy, &vip, tsz);
  1727. if ( pszPath )
  1728. #ifdef UNICODE
  1729. AToU( ptszPath, MAX_PATH, pszPath );
  1730. #else
  1731. lstrcpy( (LPSTR)ptszPath, pszPath );
  1732. #endif
  1733. if (pszPath &&
  1734. SUCCEEDED(CDIObj_FindDeviceInternal(ptszPath, &guid)))
  1735. {
  1736. IDirectInputDeviceCallback *pdcb;
  1737. #ifdef DEBUG
  1738. CREATEDCB CreateDcb;
  1739. #endif
  1740. #ifdef DEBUG
  1741. /*
  1742. * If the associated HID device got unplugged, then
  1743. * the instance GUID is no more. So don't get upset
  1744. * if we can't find it. But if we do find it, then
  1745. * it had better be a HID device.
  1746. *
  1747. * CHid_New will properly fail if the associated
  1748. * device is not around.
  1749. */
  1750. hres = hresFindInstanceGUID(&guid, &CreateDcb, 1);
  1751. AssertF(fLimpFF(SUCCEEDED(hres), CreateDcb == CHid_New));
  1752. #endif
  1753. if (SUCCEEDED(hres = CHid_New(0, &guid,
  1754. &IID_IDirectInputDeviceCallback,
  1755. (PPV)&pdcb)))
  1756. {
  1757. LPDIDATAFORMAT pdf;
  1758. /*
  1759. * The VXDINITPARAMS structure tells us where JOYHID
  1760. * decided to place each of the axes. Follow that
  1761. * table to put them into their corresponding location
  1762. * in the HID side.
  1763. */
  1764. hres = pdcb->lpVtbl->GetDataFormat(pdcb, &pdf);
  1765. if (SUCCEEDED(hres))
  1766. {
  1767. UINT uiAxis;
  1768. DIPROPINFO propi;
  1769. propi.pguid = DIPROP_SPECIFICCALIBRATION;
  1770. /*
  1771. * For each axis...
  1772. */
  1773. for (uiAxis = 0; uiAxis < 6; uiAxis++)
  1774. {
  1775. DWORD dwUsage = vip.Usages[uiAxis];
  1776. /*
  1777. * If the axis is mapped to a usage...
  1778. */
  1779. if (dwUsage)
  1780. {
  1781. /*
  1782. * Convert the usage into an object index.
  1783. */
  1784. hres = pdcb->lpVtbl->MapUsage(pdcb, dwUsage,
  1785. &propi.iobj);
  1786. if (SUCCEEDED(hres))
  1787. {
  1788. DIPROPCAL cal;
  1789. /*
  1790. * Convert the old-style calibration into
  1791. * a new-style calibration.
  1792. */
  1793. #define CopyCalibration(f, ui) \
  1794. cal.l##f = (&phwc->hwv.jrvHardware.jp##f.dwX)[ui]
  1795. CopyCalibration(Min, uiAxis);
  1796. CopyCalibration(Max, uiAxis);
  1797. CopyCalibration(Center, uiAxis);
  1798. #undef CopyCalibration
  1799. /*
  1800. * Set the calibration property on the object.
  1801. */
  1802. propi.dwDevType =
  1803. pdf->rgodf[propi.iobj].dwType;
  1804. hres = pdcb->lpVtbl->SetProperty(pdcb, &propi,
  1805. &cal.diph);
  1806. }
  1807. }
  1808. }
  1809. }
  1810. Invoke_Release(&pdcb);
  1811. }
  1812. }
  1813. ExitProc();
  1814. }
  1815. #endif
  1816. /*****************************************************************************
  1817. *
  1818. * @doc INTERNAL
  1819. *
  1820. * @func HRESULT | JoyReg_SetHWConfig |
  1821. *
  1822. * Store information about a joystick's <t JOYREGHWCONFIG>.
  1823. *
  1824. * @parm UINT | uiJoy |
  1825. *
  1826. * Joystick identification number.
  1827. *
  1828. * @parm LPJOYREGHWCONFIG | phwc |
  1829. *
  1830. * Contains information about the joystick capabilities.
  1831. * This value supercedes the value in the <p pcfg>.
  1832. *
  1833. * @parm LPCDIJOYCONFIG | pcfg |
  1834. *
  1835. * Contains information about the joystick configuration.
  1836. * The caller is assumed to have validated all fields.
  1837. *
  1838. * @parm HKEY | hk |
  1839. *
  1840. * The type key we are munging.
  1841. *
  1842. *
  1843. * @returns
  1844. *
  1845. * Returns a COM error code. The following error codes are
  1846. * intended to be illustrative and not necessarily comprehensive.
  1847. *
  1848. * <c DI_OK> = <c S_OK>: The operation completed successfully.
  1849. *
  1850. *****************************************************************************/
  1851. HRESULT INTERNAL
  1852. JoyReg_SetHWConfig(UINT idJoy, LPJOYREGHWCONFIG phwc, LPCDIJOYCONFIG pcfg,
  1853. HKEY hk)
  1854. {
  1855. HRESULT hres;
  1856. HKEY hkSave;
  1857. DWORD dwSam;
  1858. /*
  1859. * The caller has set phwc->dwType, so use it to determine
  1860. * where the data comes from or goes to.
  1861. */
  1862. if ( phwc->dwType == JOY_HW_NONE )
  1863. {
  1864. /*
  1865. * Nothing to do
  1866. */
  1867. } else if ( phwc->dwType == JOY_HW_CUSTOM )
  1868. {
  1869. /*
  1870. /* ISSUE-2001/03/29-timgill Custom HWConfig not handled correctly
  1871. * We don't know the type name and the only time we can look
  1872. * it up is when were modifying an existing config so although we
  1873. * could store the config, we'd never be able to get it back.
  1874. * Should return no better than S_FALSE. This will have to wait.
  1875. */
  1876. } else
  1877. {
  1878. /*
  1879. * Try to access saved values
  1880. */
  1881. // ISSUE-2001/03/29-timgill Dangerous type cast
  1882. PDWORD pdw = (PDWORD)&phwc->hwv;
  1883. dwSam = KEY_QUERY_VALUE;
  1884. while ( pdw < &phwc->dwType )
  1885. {
  1886. if ( *pdw )
  1887. {
  1888. /*
  1889. * Real config data so write it
  1890. */
  1891. dwSam = KEY_SET_VALUE;
  1892. break;
  1893. }
  1894. pdw++;
  1895. }
  1896. /*
  1897. * If the device is autoloaded and yet the user is manually assigning it
  1898. * to an ID, set the volatile flag. The flag will be set to the driver
  1899. * defined value if a driver ever gets hotplug assigned to this ID but if
  1900. * not, this makes sure that the settings are removed on next reboot.
  1901. */
  1902. if (phwc->hws.dwFlags & JOY_HWS_AUTOLOAD)
  1903. {
  1904. phwc->dwUsageSettings |= JOY_US_VOLATILE;
  1905. }
  1906. hres = JoyReg_OpenSaveKey( phwc->dwType, pcfg, dwSam, &hkSave );
  1907. if ( SUCCEEDED(hres) )
  1908. {
  1909. if ( dwSam == KEY_SET_VALUE )
  1910. {
  1911. hres = JoyReg_SetConfigValue(hkSave, REGSTR_VAL_JOYNCONFIG,
  1912. idJoy, REG_BINARY,
  1913. phwc, cbX(*phwc));
  1914. if ( FAILED(hres) )
  1915. {
  1916. // Report the error but live with it
  1917. RPF("JoyReg_SetConfig: failed to set saved config %08x", hres );
  1918. }
  1919. } else
  1920. {
  1921. JOYREGHWCONFIG hwc;
  1922. /*
  1923. * Read it into an extra buffer because we only want it
  1924. * if it's complete.
  1925. */
  1926. hres = JoyReg_GetConfigValue(hkSave, REGSTR_VAL_JOYNCONFIG,
  1927. idJoy, REG_BINARY,
  1928. &hwc, cbX(hwc));
  1929. if ( hres == S_OK )
  1930. {
  1931. // Assert hws is first and no gap before dwUsageSettings
  1932. CAssertF( FIELD_OFFSET( JOYREGHWCONFIG, hws ) == 0 );
  1933. CAssertF( FIELD_OFFSET( JOYREGHWCONFIG, dwUsageSettings ) == sizeof( hwc.hws ) );
  1934. // Copy the whole structure except the hws
  1935. memcpy( &phwc->dwUsageSettings, &hwc.dwUsageSettings,
  1936. sizeof( hwc ) - sizeof( hwc.hws ) );
  1937. }
  1938. }
  1939. RegCloseKey( hkSave );
  1940. }
  1941. /*
  1942. * If we failed to read, there's probably nothing there and the
  1943. * structure is set up already for a blank config.
  1944. * If we failed to write there probably not much we can do
  1945. */
  1946. }
  1947. hres = JoyReg_SetConfigValue(hk, REGSTR_VAL_JOYNCONFIG,
  1948. idJoy, REG_BINARY,
  1949. phwc, cbX(*phwc));
  1950. if (FAILED(hres))
  1951. {
  1952. goto done;
  1953. }
  1954. if (phwc->dwUsageSettings & JOY_US_ISOEM)
  1955. {
  1956. hres = JoyReg_SetConfigValue(
  1957. hk, REGSTR_VAL_JOYNOEMNAME, idJoy, REG_SZ,
  1958. pcfg->wszType, cbX(pcfg->wszType));
  1959. } else
  1960. {
  1961. hres = JoyReg_SetConfigValue(
  1962. hk, REGSTR_VAL_JOYNOEMNAME, idJoy, REG_SZ,
  1963. 0, 0);
  1964. }
  1965. done:;
  1966. return hres;
  1967. }
  1968. /*****************************************************************************
  1969. *
  1970. * @doc INTERNAL
  1971. *
  1972. * @func HRESULT | JoyReg_SetConfig |
  1973. *
  1974. * Store information about a joystick's configuration.
  1975. *
  1976. * @parm UINT | uiJoy |
  1977. *
  1978. * Joystick identification number.
  1979. *
  1980. * @parm JOYREGHWCONFIG | phwc |
  1981. *
  1982. * Contains information about the joystick capabilities.
  1983. * This value supercedes the value in the <p pcfg>.
  1984. * It may be modified if we needed to load the config
  1985. * info from the saved settings.
  1986. *
  1987. * @parm LPCDIJOYCONFIG | pcfg |
  1988. *
  1989. * Contains information about the joystick configuration.
  1990. * The caller is assumed to have validated all fields.
  1991. *
  1992. * @parm DWORD | fl |
  1993. *
  1994. * Zero or more <c DIJC_*> flags
  1995. * which specify which parts of the structures pointed
  1996. * to by <p phwc> and <p pjc> are to be written out.
  1997. *
  1998. * @returns
  1999. *
  2000. * Returns a COM error code. The following error codes are
  2001. * intended to be illustrative and not necessarily comprehensive.
  2002. *
  2003. * <c DI_OK> = <c S_OK>: The operation completed successfully.
  2004. *
  2005. *****************************************************************************/
  2006. JOYREGHWVALUES null_hwv = { 0};
  2007. STDMETHODIMP
  2008. JoyReg_SetConfig(UINT idJoy, LPJOYREGHWCONFIG phwc,
  2009. LPCDIJOYCONFIG pcfg, DWORD fl)
  2010. {
  2011. HRESULT hres;
  2012. EnterProc(JoyReg_SetConfig, (_ "uppx", idJoy, phwc, pcfg, fl));
  2013. AssertF((fl & ~DIJC_INTERNALSETVALID) == 0);
  2014. if (idJoy < cJoyMax )
  2015. {
  2016. if (fl & DIJC_INREGISTRY)
  2017. {
  2018. HKEY hk;
  2019. DWORD dwOptions = 0;
  2020. hres = JoyReg_OpenConfigKey(idJoy, KEY_SET_VALUE, dwOptions, &hk);
  2021. if (SUCCEEDED(hres))
  2022. {
  2023. if (fl & DIJC_REGHWCONFIGTYPE)
  2024. {
  2025. hres = JoyReg_SetHWConfig(idJoy, phwc, pcfg, hk);
  2026. if (FAILED(hres))
  2027. {
  2028. goto closedone;
  2029. }
  2030. #ifndef WINNT
  2031. if (fl & DIJC_UPDATEALIAS)
  2032. {
  2033. JoyReg_SetCalibration(idJoy, phwc);
  2034. }
  2035. #endif
  2036. }
  2037. #ifndef WINNT
  2038. if (fl & DIJC_CALLOUT)
  2039. {
  2040. hres = JoyReg_SetConfigValue(
  2041. hk, REGSTR_VAL_JOYNOEMCALLOUT, idJoy, REG_SZ,
  2042. pcfg->wszCallout, cbX(pcfg->wszCallout));
  2043. if (FAILED(hres))
  2044. {
  2045. hres = S_FALSE;
  2046. //continue to go
  2047. }
  2048. }
  2049. #endif
  2050. if (fl & DIJC_GAIN)
  2051. {
  2052. if (ISVALIDGAIN(pcfg->dwGain))
  2053. {
  2054. /*
  2055. * If restoring to nominal, then the key
  2056. * can be deleted; the default value will
  2057. * be assumed subsequently.
  2058. */
  2059. if (pcfg->dwGain == DI_FFNOMINALMAX)
  2060. {
  2061. hres = JoyReg_SetConfigValue(hk,
  2062. TEXT("Joystick%dFFConfiguration"),
  2063. idJoy, REG_SZ, 0, 0);
  2064. } else
  2065. {
  2066. hres = JoyReg_SetConfigValue(hk,
  2067. TEXT("Joystick%dFFConfiguration"),
  2068. idJoy, REG_BINARY,
  2069. &pcfg->dwGain, cbX(pcfg->dwGain));
  2070. }
  2071. if (FAILED(hres))
  2072. {
  2073. hres = S_FALSE;
  2074. goto closedone;
  2075. }
  2076. } else
  2077. {
  2078. RPF("ERROR: SetConfig: Invalid dwGain");
  2079. hres = E_INVALIDARG;
  2080. goto closedone;
  2081. }
  2082. }
  2083. hres = S_OK;
  2084. closedone:;
  2085. RegCloseKey(hk);
  2086. }
  2087. } else
  2088. {
  2089. hres = S_OK;
  2090. }
  2091. } else
  2092. {
  2093. hres = E_FAIL;
  2094. }
  2095. ExitOleProc();
  2096. return hres;
  2097. }
  2098. /*****************************************************************************
  2099. *
  2100. * @doc INTERNAL
  2101. *
  2102. * @func int | ibJoyPosAxis |
  2103. *
  2104. * Returns the offset of the <p iAxis>'th joystick axis
  2105. * in the <t JOYPOS> structure.
  2106. *
  2107. * @parm int | iAxis |
  2108. *
  2109. * The index of the requested axis. X, Y, Z, R, U and V are
  2110. * respctively zero through five.
  2111. *
  2112. * @returns
  2113. *
  2114. * The offset relative to the structure.
  2115. *
  2116. *****************************************************************************/
  2117. #define ibJoyPosAxis(iAxis) \
  2118. (FIELD_OFFSET(JOYPOS, dwX) + cbX(DWORD) * (iAxis)) \
  2119. #define pJoyValue(jp, i) \
  2120. (LPDWORD)pvAddPvCb(&(jp), ibJoyPosAxis(i)) \
  2121. /*
  2122. * The following doesn't do anything at runtime. It is a compile-time
  2123. * check that everything is okay.
  2124. */
  2125. void INLINE
  2126. JoyReg_CheckJoyPosAxis(void)
  2127. {
  2128. #define CheckAxis(x) \
  2129. CAssertF(ibJoyPosAxis(iJoyPosAxis##x) == FIELD_OFFSET(JOYPOS, dw##x))
  2130. CheckAxis(X);
  2131. CheckAxis(Y);
  2132. CheckAxis(Z);
  2133. CheckAxis(R);
  2134. CheckAxis(U);
  2135. CheckAxis(V);
  2136. #undef CheckAxis
  2137. }
  2138. /*****************************************************************************
  2139. *
  2140. * @doc INTERNAL
  2141. *
  2142. * @func HRESULT | JoyReg_IsValidUserValues |
  2143. *
  2144. * Retermine whether the values are ostensibly valid.
  2145. *
  2146. * @parm IN LPCDIJOYUSERVALUES | pjuv |
  2147. *
  2148. * Contains information about the user joystick configuration.
  2149. *
  2150. * @returns
  2151. *
  2152. * Returns a COM error code. The following error codes are
  2153. * intended to be illustrative and not necessarily comprehensive.
  2154. *
  2155. * <c DI_OK> = <c S_OK>: The operation completed successfully.
  2156. *
  2157. * <c DIERR_INVALIDPARAM> = <c E_INVALIDARG>:
  2158. * Something looks bad.
  2159. *
  2160. *****************************************************************************/
  2161. STDMETHODIMP
  2162. JoyReg_IsValidUserValues(LPCDIJOYUSERVALUES pjuv)
  2163. {
  2164. HRESULT hres;
  2165. int iAxis;
  2166. /*
  2167. * First set up the values to values that are out of range so
  2168. * that we will fall back to defaults.
  2169. */
  2170. for (iAxis = 0; iAxis < cJoyPosAxisMax; iAxis++)
  2171. {
  2172. if ((int)*pJoyValue(pjuv->ruv.jrvRanges.jpMax, iAxis) < 0)
  2173. {
  2174. RPF("JOYUSERVALUES: Negative jpMax not a good idea");
  2175. goto bad;
  2176. }
  2177. if (*pJoyValue(pjuv->ruv.jrvRanges.jpMin, iAxis) >
  2178. *pJoyValue(pjuv->ruv.jrvRanges.jpMax, iAxis))
  2179. {
  2180. RPF("JOYUSERVALUES: Min > Max not a good idea");
  2181. goto bad;
  2182. }
  2183. if (!fInOrder(0, *pJoyValue(pjuv->ruv.jpDeadZone, iAxis), 100))
  2184. {
  2185. RPF("JOYUSERVALUES: DeadZone > 100 not a good idea");
  2186. goto bad;
  2187. }
  2188. }
  2189. hres = S_OK;
  2190. return hres;
  2191. bad:;
  2192. hres = E_INVALIDARG;
  2193. return hres;
  2194. }
  2195. /*****************************************************************************
  2196. *
  2197. * @doc INTERNAL
  2198. *
  2199. * @func HRESULT | JoyReg_GetUserValues |
  2200. *
  2201. * Obtain information about user settings for the joystick.
  2202. *
  2203. *
  2204. * @parm IN OUT LPDIJOYUSERVALUES | pjuv |
  2205. *
  2206. * Receives information about the user joystick configuration.
  2207. * The caller is assumed to have validated the
  2208. * <e DIJOYUSERVALUES.dwSize> field.
  2209. *
  2210. * @parm DWORD | fl |
  2211. *
  2212. * Zero or more <c DIJU_*> flags specifying which parts
  2213. * of the <t DIJOYUSERVALUES> structure contain values
  2214. * which are to be retrieved.
  2215. *
  2216. * @returns
  2217. *
  2218. * Returns a COM error code. The following error codes are
  2219. * intended to be illustrative and not necessarily comprehensive.
  2220. *
  2221. * <c DI_OK> = <c S_OK>: The operation completed successfully.
  2222. *
  2223. * <c DIERR_INVALIDPARAM> = <c E_INVALIDARG>: One or more
  2224. * parameters was invalid.
  2225. *
  2226. *****************************************************************************/
  2227. STDMETHODIMP
  2228. JoyReg_GetUserValues(LPDIJOYUSERVALUES pjuv, DWORD fl)
  2229. {
  2230. HRESULT hres;
  2231. HKEY hk;
  2232. LONG lRc;
  2233. EnterProc(JoyReg_GetUserValues, (_ "px", pjuv, fl));
  2234. hres = S_OK; /* If nothing happens, then success */
  2235. if (fl & DIJU_USERVALUES)
  2236. {
  2237. /*
  2238. * Okay, now get the user settings.
  2239. *
  2240. * If anything goes wrong, then just limp with the default values.
  2241. */
  2242. lRc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_JOYCONFIG,
  2243. 0, KEY_QUERY_VALUE, &hk);
  2244. if (lRc == ERROR_SUCCESS)
  2245. {
  2246. hres = JoyReg_GetValue(hk, REGSTR_VAL_JOYUSERVALUES,
  2247. REG_BINARY, &pjuv->ruv, cbX(pjuv->ruv));
  2248. if (SUCCEEDED(hres))
  2249. {
  2250. /*
  2251. * Sanity-check the values. If anything is screwy,
  2252. * then fall back to the defaults.
  2253. */
  2254. hres = JoyReg_IsValidUserValues(pjuv);
  2255. }
  2256. if (FAILED(hres))
  2257. {
  2258. /*
  2259. * Oh well. Just use the default values, then.
  2260. *
  2261. * Stolen from ibmjoy\msjstick.c.
  2262. */
  2263. ZeroMemory(&pjuv->ruv, cbX(pjuv->ruv));
  2264. #define DEFAULT_RANGE_MAX 65535
  2265. #define DEFAULT_TIMEOUT 5000
  2266. #define DEFAULT_DEADZONE 5
  2267. pjuv->ruv.jrvRanges.jpMax.dwX = DEFAULT_RANGE_MAX;
  2268. pjuv->ruv.jrvRanges.jpMax.dwY = DEFAULT_RANGE_MAX;
  2269. pjuv->ruv.jrvRanges.jpMax.dwZ = DEFAULT_RANGE_MAX;
  2270. pjuv->ruv.jrvRanges.jpMax.dwR = DEFAULT_RANGE_MAX;
  2271. pjuv->ruv.jrvRanges.jpMax.dwU = DEFAULT_RANGE_MAX;
  2272. pjuv->ruv.jrvRanges.jpMax.dwV = DEFAULT_RANGE_MAX;
  2273. pjuv->ruv.jpDeadZone.dwX = DEFAULT_DEADZONE;
  2274. pjuv->ruv.jpDeadZone.dwY = DEFAULT_DEADZONE;
  2275. pjuv->ruv.dwTimeOut = DEFAULT_TIMEOUT;
  2276. }
  2277. RegCloseKey(hk);
  2278. }
  2279. }
  2280. if (fl & DIJU_INDRIVERREGISTRY)
  2281. {
  2282. hres = JoyReg_OpenConfigKey((UINT)-1, KEY_QUERY_VALUE, FALSE, &hk);
  2283. if (SUCCEEDED(hres))
  2284. {
  2285. if (fl & DIJU_GLOBALDRIVER)
  2286. {
  2287. LONG lRc;
  2288. /*
  2289. * If it doesn't work, then return the default value
  2290. * of "MSANALOG.VXD". We can't blindly use
  2291. * JoyReg_GetValue, because that treats a nonexistent
  2292. * value as having a default of the null string.
  2293. */
  2294. lRc = RegQueryValueEx(hk, REGSTR_VAL_JOYOEMCALLOUT,
  2295. 0, 0, 0, 0);
  2296. if ((lRc == ERROR_SUCCESS || lRc == ERROR_MORE_DATA) &&
  2297. SUCCEEDED(
  2298. hres = JoyReg_GetValue(hk, REGSTR_VAL_JOYOEMCALLOUT,
  2299. REG_SZ, pjuv->wszGlobalDriver,
  2300. cbX(pjuv->wszGlobalDriver))))
  2301. {
  2302. /* Yay, it worked */
  2303. } else
  2304. {
  2305. CopyMemory(pjuv->wszGlobalDriver,
  2306. c_wszDefPortDriver,
  2307. cbX(c_wszDefPortDriver));
  2308. }
  2309. }
  2310. if (fl & DIJU_GAMEPORTEMULATOR)
  2311. {
  2312. /*
  2313. * If it doesn't work, then just return a null string.
  2314. */
  2315. hres = JoyReg_GetValue(hk, REGSTR_VAL_JOYGAMEPORTEMULATOR,
  2316. REG_SZ, pjuv->wszGameportEmulator,
  2317. cbX(pjuv->wszGameportEmulator));
  2318. if (FAILED(hres))
  2319. {
  2320. pjuv->wszGameportEmulator[0] = TEXT('\0');
  2321. }
  2322. }
  2323. RegCloseKey(hk);
  2324. }
  2325. }
  2326. /*
  2327. * Warning! CJoy_InitRanges() assumes this never fails.
  2328. */
  2329. hres = S_OK;
  2330. ExitOleProcR();
  2331. return hres;
  2332. }
  2333. /*****************************************************************************
  2334. *
  2335. * @doc INTERNAL
  2336. *
  2337. * @func HRESULT | JoyReg_SetUserValues |
  2338. *
  2339. * Store information about user settings for the joystick.
  2340. *
  2341. *
  2342. * @parm IN LPCDIJOYUSERVALUES | pjuv |
  2343. *
  2344. * Contains information about the user joystick configuration.
  2345. * The caller is assumed to have validated the
  2346. * <e DIJOYUSERVALUES.dwSize> field.
  2347. *
  2348. * @parm DWORD | fl |
  2349. *
  2350. * Zero or more <c DIJU_*> flags specifying which parts
  2351. * of the <t DIJOYUSERVALUES> structure contain values
  2352. * which are to be set.
  2353. *
  2354. * @returns
  2355. *
  2356. * Returns a COM error code. The following error codes are
  2357. * intended to be illustrative and not necessarily comprehensive.
  2358. *
  2359. * <c DI_OK> = <c S_OK>: The operation completed successfully.
  2360. *
  2361. * <c DIERR_INVALIDPARAM> = <c E_INVALIDARG>: One or more
  2362. * parameters was invalid.
  2363. *
  2364. *****************************************************************************/
  2365. STDMETHODIMP
  2366. JoyReg_SetUserValues(LPCDIJOYUSERVALUES pjuv, DWORD fl)
  2367. {
  2368. HRESULT hres = E_FAIL;
  2369. HKEY hk;
  2370. EnterProc(JoyReg_SetUserValues, (_ "px", pjuv, fl));
  2371. if (fl & DIJU_USERVALUES)
  2372. {
  2373. /*
  2374. * See if the values are sane.
  2375. */
  2376. if (fl & DIJU_USERVALUES)
  2377. {
  2378. hres = JoyReg_IsValidUserValues(pjuv);
  2379. if (FAILED(hres))
  2380. {
  2381. goto done;
  2382. }
  2383. }
  2384. /*
  2385. * Off to the registry we go.
  2386. */
  2387. hres = hresMumbleKeyEx(HKEY_LOCAL_MACHINE,
  2388. REGSTR_PATH_JOYCONFIG,
  2389. DI_KEY_ALL_ACCESS,
  2390. REG_OPTION_NON_VOLATILE,
  2391. &hk);
  2392. if (SUCCEEDED(hres))
  2393. {
  2394. hres = JoyReg_SetValue(hk, REGSTR_VAL_JOYUSERVALUES,
  2395. REG_BINARY, &pjuv->ruv,
  2396. cbX(pjuv->ruv));
  2397. RegCloseKey(hk);
  2398. if (FAILED(hres))
  2399. {
  2400. goto done;
  2401. }
  2402. } else
  2403. {
  2404. goto done;
  2405. }
  2406. }
  2407. if (fl & DIJU_INDRIVERREGISTRY)
  2408. {
  2409. hres = JoyReg_OpenConfigKey((UINT)-1, KEY_SET_VALUE, FALSE, &hk);
  2410. if (SUCCEEDED(hres))
  2411. {
  2412. if (fl & DIJU_GLOBALDRIVER)
  2413. {
  2414. /*
  2415. * This is a weird key. The default value is
  2416. * "MSANALOG.VXD", so if we get a null string, we
  2417. * can't use JoyReg_SetValue, because that will
  2418. * delete the key.
  2419. */
  2420. if (pjuv->wszGlobalDriver[0])
  2421. {
  2422. hres = JoyReg_SetValue(hk, REGSTR_VAL_JOYOEMCALLOUT,
  2423. REG_SZ, pjuv->wszGlobalDriver,
  2424. cbX(pjuv->wszGlobalDriver));
  2425. } else
  2426. {
  2427. LONG lRc;
  2428. lRc = RegSetValueEx(hk, REGSTR_VAL_JOYOEMCALLOUT, 0,
  2429. REG_SZ, (PV)TEXT(""), cbCtch(1));
  2430. if (lRc == ERROR_SUCCESS)
  2431. {
  2432. hres = S_OK;
  2433. } else
  2434. {
  2435. RPF("Unable to write %s to registry",
  2436. REGSTR_VAL_JOYOEMCALLOUT);
  2437. hres = E_FAIL; /* Else, something bad happened */
  2438. }
  2439. }
  2440. if (FAILED(hres))
  2441. {
  2442. goto regdone;
  2443. }
  2444. }
  2445. if (fl & DIJU_GAMEPORTEMULATOR)
  2446. {
  2447. hres = JoyReg_SetValue(hk, REGSTR_VAL_JOYGAMEPORTEMULATOR,
  2448. REG_SZ, pjuv->wszGameportEmulator,
  2449. cbX(pjuv->wszGameportEmulator));
  2450. if (FAILED(hres))
  2451. {
  2452. goto regdone;
  2453. }
  2454. }
  2455. regdone:;
  2456. RegCloseKey(hk);
  2457. } else
  2458. {
  2459. goto done;
  2460. }
  2461. }
  2462. done:;
  2463. ExitOleProcR();
  2464. return hres;
  2465. }
  2466. /*****************************************************************************
  2467. *
  2468. * @doc INTERNAL
  2469. *
  2470. * @func HRESULT | JoyReg_OpenFFKey |
  2471. *
  2472. * Given a type key, move to its force feedback subkey.
  2473. *
  2474. * @parm HKEY | hkType |
  2475. *
  2476. * The parent type key.
  2477. *
  2478. * @parm REGSAM | sam |
  2479. *
  2480. * Access level desired.
  2481. *
  2482. * @parm PHKEY | phk |
  2483. *
  2484. * Receives created registry key.
  2485. *
  2486. * @returns
  2487. *
  2488. * Returns a COM error code. The following error codes are
  2489. * intended to be illustrative and not necessarily comprehensive.
  2490. *
  2491. * <c DI_OK> = <c S_OK>: The operation completed successfully.
  2492. *
  2493. * <c DIERR_NOTFOUND>: Couldn't open the key.
  2494. *
  2495. *****************************************************************************/
  2496. STDMETHODIMP
  2497. JoyReg_OpenFFKey(HKEY hkType, REGSAM sam, PHKEY phk)
  2498. {
  2499. HRESULT hres;
  2500. EnterProc(JoyReg_OpenFFKey, (_ "xx", hkType, sam));
  2501. *phk = 0;
  2502. if (hkType)
  2503. {
  2504. if (RegOpenKeyEx(hkType, TEXT("OEMForceFeedback"), 0, sam, phk) == 0)
  2505. {
  2506. hres = S_OK;
  2507. } else
  2508. {
  2509. hres = E_FAIL;
  2510. }
  2511. } else
  2512. {
  2513. hres = DIERR_NOTFOUND;
  2514. }
  2515. ExitBenignOleProc();
  2516. return hres;
  2517. }
  2518. /*****************************************************************************
  2519. *
  2520. * @doc INTERNAL
  2521. *
  2522. * @func TCHAR | CJoyCfg_CharFromType |
  2523. *
  2524. * Convert a predefined type number to a character.
  2525. *
  2526. * @func UINT | CJoyCfg_TypeFromChar |
  2527. *
  2528. * Convert a character back to a predefined type number.
  2529. *
  2530. *****************************************************************************/
  2531. #define JoyCfg_CharFromType(t) ((TCHAR)(L'0' + t))
  2532. #define JoyCfg_TypeFromChar(tch) ((tch) - L'0')
  2533. /*****************************************************************************
  2534. *
  2535. * @doc EXTERNAL
  2536. *
  2537. * @func HRESULT | JoyReg_GetPredefTypeInfo |
  2538. *
  2539. * Obtain information about a predefined joystick type.
  2540. *
  2541. * @parm LPCWSTR | pwszType |
  2542. *
  2543. * Points to the name of the type. It is known to begin
  2544. * with a "#". The remainder has not yet been parsed.
  2545. *
  2546. * @parm IN OUT LPDIJOYTYPEINFO | pjti |
  2547. *
  2548. * Receives information about the joystick type,
  2549. * already validated.
  2550. *
  2551. * @parm DWORD | dwFlags |
  2552. *
  2553. * Zero or more <c DITC_*> flags
  2554. * which specify which parts of the structure pointed
  2555. * to by <p pjti> are to be filled in.
  2556. *
  2557. * @returns
  2558. *
  2559. * Returns a COM error code. The following error codes are
  2560. * intended to be illustrative and not necessarily comprehensive.
  2561. *
  2562. * <c DI_OK> = <c S_OK>: The operation completed successfully.
  2563. *
  2564. * <c DIERR_NOTFOUND>: The joystick type was not found.
  2565. *
  2566. *****************************************************************************/
  2567. HRESULT EXTERNAL
  2568. JoyReg_GetPredefTypeInfo(LPCWSTR pwszType, LPDIJOYTYPEINFO pjti, DWORD fl)
  2569. {
  2570. HRESULT hres;
  2571. UINT itype;
  2572. EnterProcI(JoyReg_GetPredefTypeInfo, (_ "Wpx", pwszType, pjti, fl));
  2573. AssertF(pwszType[0] == L'#');
  2574. itype = JoyCfg_TypeFromChar(pwszType[1]);
  2575. if (fInOrder(JOY_HW_PREDEFMIN, itype, JOY_HW_PREDEFMAX) &&
  2576. pwszType[2] == L'\0')
  2577. {
  2578. /*
  2579. * No real point in checking the bits in fl, since
  2580. * setting it up is so easy.
  2581. */
  2582. pjti->hws = c_rghwsPredef[itype - JOY_HW_PREDEFMIN];
  2583. LoadStringW(g_hinst, IDS_PREDEFJOYTYPE + itype,
  2584. pjti->wszDisplayName, cA(pjti->wszDisplayName));
  2585. pjti->wszCallout[0] = L'\0';
  2586. ZeroX(pjti->clsidConfig);
  2587. pjti->dwFlags1 = 0x0;
  2588. if ( fl & DITC_HARDWAREID )
  2589. {
  2590. lstrcpyW(pjti->wszHardwareId, c_rghwIdPredef[itype-JOY_HW_PREDEFMIN] );
  2591. }
  2592. pjti->dwFlags2 = 0x0;
  2593. pjti->wszMapFile[0] = L'\0';
  2594. hres = S_OK;
  2595. } else
  2596. {
  2597. hres = DIERR_NOTFOUND;
  2598. }
  2599. ExitOleProc();
  2600. return hres;
  2601. }
  2602. #if 0 //don't delete it now.
  2603. /*****************************************************************************
  2604. *
  2605. * @doc INTERNAL
  2606. *
  2607. * @func HRESULT | JoyCfg_GetIDByOemName |
  2608. *
  2609. * Get the Id by OEMNAME
  2610. *
  2611. * @parm IN LPTSTR | szOEMNAME |
  2612. *
  2613. * String used to find the ID.
  2614. *
  2615. * @parm IN LPUNIT | lpID |
  2616. *
  2617. * The ID to get.
  2618. *
  2619. * @returns
  2620. *
  2621. * A COM success code unless the current configuration key could not
  2622. * be opened, or could not find the OEMNAME.
  2623. *
  2624. *****************************************************************************/
  2625. HRESULT EXTERNAL JoyReg_GetIDByOemName( LPTSTR szOemName, PUINT pId )
  2626. {
  2627. HRESULT hres = E_FAIL;
  2628. LONG lRc;
  2629. HKEY hkCurrCfg;
  2630. UINT JoyId;
  2631. TCHAR szTestName[MAX_JOYSTRING];
  2632. TCHAR szOemNameKey[MAX_JOYSTRING];
  2633. DWORD cb;
  2634. EnterProcI(JoyReg_GetIDByOemName, (_ "sp", szOemName, pId ));
  2635. hres = JoyReg_OpenConfigKey( (UINT)(-1), KEY_WRITE, REG_OPTION_NON_VOLATILE, &hkCurrCfg );
  2636. if ( SUCCEEDED( hres ) )
  2637. {
  2638. for ( JoyId = 0; (JoyId < 16) || ( lRc == ERROR_SUCCESS ); JoyId++ )
  2639. {
  2640. wsprintf( szOemNameKey, REGSTR_VAL_JOYNOEMNAME, JoyId+1 );
  2641. cb = sizeof( szTestName );
  2642. lRc = RegQueryValueEx( hkCurrCfg, szOemNameKey, 0, NULL, (PBYTE)szTestName, &cb );
  2643. if ( lRc == ERROR_SUCCESS )
  2644. {
  2645. if ( !lstrcmpi( szOemName, szTestName ) )
  2646. {
  2647. *pId = JoyId;
  2648. pId ++;
  2649. hres = S_OK;
  2650. break;
  2651. }
  2652. }
  2653. }
  2654. } else
  2655. {
  2656. SquirtSqflPtszV(sqfl | sqflError,
  2657. TEXT("JoyReg_OpenConfigKey failed code 0x%08x"), hres );
  2658. }
  2659. ExitOleProc();
  2660. return hres;
  2661. } /* JoyReg_GetIDByOemName */
  2662. #endif