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

3045 lines
92 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. LONG 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. /*
  757. * Read and merge any current value so that bits unused in
  758. * DX8 can be preserved. Although this is more work now it
  759. * should save adding Flags3 support next time.
  760. */
  761. AssertF( (pjti->dwFlags2 & ~JOYTYPE_FLAGS2_SETVALID) == 0x0 );
  762. /*
  763. * PREFIX warns (259898) that RegQueryValueEx reads the value
  764. * of dwTemp before it is set but then it checks lpData and
  765. * zeroes the value before it is used.
  766. */
  767. lRc = RegQueryValueEx( hkProp, REGSTR_VAL_FLAGS2, 0, 0, 0, &dwTemp );
  768. if( lRc == ERROR_FILE_NOT_FOUND )
  769. {
  770. lRc = ERROR_SUCCESS;
  771. dwTemp = cbX( pjti->dwFlags2 );
  772. }
  773. if( lRc == ERROR_SUCCESS )
  774. {
  775. if( dwTemp <= cbX( pjti->dwFlags2 ) )
  776. {
  777. CAssertF( cbX( dwTemp ) == cbX( pjti->dwFlags2 ) );
  778. JoyReg_GetValue( hkProp, REGSTR_VAL_FLAGS2,
  779. REG_BINARY, &dwTemp, cbX( dwTemp ) );
  780. dwTemp &= ~JOYTYPE_FLAGS2_SETVALID;
  781. dwTemp |= pjti->dwFlags2;
  782. if( dwTemp )
  783. {
  784. hres = JoyReg_SetValue( hkProp, REGSTR_VAL_FLAGS2,
  785. REG_BINARY, (PV)&dwTemp, cbX( dwTemp ) );
  786. } else
  787. {
  788. lRc = RegDeleteValue( hkProp, REGSTR_VAL_FLAGS2 );
  789. if (lRc == ERROR_FILE_NOT_FOUND)
  790. {
  791. lRc = ERROR_SUCCESS;
  792. }
  793. hres = hresLe( lRc );
  794. }
  795. }
  796. else
  797. {
  798. /*
  799. * Need to double buffer for the extra bytes
  800. */
  801. PBYTE pbFlags2;
  802. hres = AllocCbPpv( dwTemp, &pbFlags2 );
  803. if( SUCCEEDED( hres ) )
  804. {
  805. if ( ERROR_SUCCESS == RegQueryValueEx(
  806. hkProp, REGSTR_VAL_FLAGS2, 0, NULL, pbFlags2, &dwTemp ) )
  807. {
  808. CAssertF( JOYTYPE_FLAGS2_SETVALID == JOYTYPE_FLAGS2_GETVALID );
  809. *(PDWORD)pbFlags2 &= ~JOYTYPE_FLAGS2_SETVALID;
  810. *(PDWORD)pbFlags2 |= pjti->dwFlags2;
  811. if ( ERROR_SUCCESS == RegSetValueEx(
  812. hkProp, REGSTR_VAL_FLAGS2, 0, REG_BINARY, pbFlags2, dwTemp ) )
  813. {
  814. hres = S_OK;
  815. } else
  816. {
  817. SquirtSqflPtszV(sqfl | sqflError,
  818. TEXT( "IDIJC::SetTypeInfo: failed to write extended Flags2" ) );
  819. hres = E_FAIL;
  820. }
  821. } else
  822. {
  823. SquirtSqflPtszV(sqfl | sqflError,
  824. TEXT( "IDIJC::SetTypeInfo: failed to read extended Flags2" ) );
  825. hres = E_FAIL; /* Else, something bad happened */
  826. }
  827. FreePv( pbFlags2 );
  828. }
  829. }
  830. }
  831. else
  832. {
  833. SquirtSqflPtszV(sqfl | sqflError,
  834. TEXT( "IDIJC::SetTypeInfo: failed to read size of Flags2, error %d" ), lRc );
  835. hres = hresLe( lRc );
  836. }
  837. if( FAILED( hres ) )
  838. {
  839. hres = S_FALSE;
  840. goto closedoneprop;
  841. }
  842. }
  843. if( fl & DITC_MAPFILE )
  844. {
  845. hres = JoyReg_SetValue(hkProp,
  846. REGSTR_VAL_JOYOEMMAPFILE, REG_SZ,
  847. pjti->wszMapFile,
  848. cbX(pjti->wszMapFile));
  849. if( FAILED(hres) )
  850. {
  851. hres = S_FALSE;
  852. goto closedoneprop;
  853. }
  854. }
  855. hres = S_OK;
  856. closedoneprop:;
  857. RegCloseKey(hkProp);
  858. }
  859. else
  860. {
  861. RPF( "Failed to open DirectInput type property key" );
  862. }
  863. }
  864. if( hres == S_OK )
  865. {
  866. if( fl & DITC_INREGISTRY_DX6 )
  867. {
  868. HKEY hk;
  869. DWORD dwOptions = 0;
  870. if ( fl & DITC_VOLATILEREGKEY )
  871. {
  872. dwOptions = REG_OPTION_VOLATILE;
  873. } else
  874. {
  875. dwOptions = REG_OPTION_NON_VOLATILE;
  876. }
  877. #ifndef UNICODE
  878. {
  879. TCHAR tszType[MAX_PATH];
  880. UToA(tszType, cA(tszType), pwszType);
  881. hres = hresMumbleKeyEx(hkTypesW,
  882. tszType,
  883. DI_KEY_ALL_ACCESS,
  884. dwOptions,
  885. &hk);
  886. }
  887. #else
  888. hres = hresMumbleKeyEx(hkTypesW,
  889. pwszType,
  890. DI_KEY_ALL_ACCESS,
  891. dwOptions,
  892. &hk);
  893. #endif
  894. if ( SUCCEEDED(hres) )
  895. {
  896. if (fl & DITC_REGHWSETTINGS)
  897. {
  898. hres = JoyReg_SetValue(hk, REGSTR_VAL_JOYOEMDATA, REG_BINARY,
  899. (PV)&pjti->hws, cbX(pjti->hws));
  900. if (FAILED(hres))
  901. {
  902. goto closedone;
  903. }
  904. }
  905. if (fl & DITC_CLSIDCONFIG)
  906. {
  907. if (IsEqualGUID(&pjti->clsidConfig, &GUID_Null))
  908. {
  909. lRc = RegDeleteValue(hk, REGSTR_VAL_CPLCLSID);
  910. /*
  911. * It is not an error if the key does not already exist.
  912. */
  913. if (lRc == ERROR_FILE_NOT_FOUND)
  914. {
  915. lRc = ERROR_SUCCESS;
  916. }
  917. } else
  918. {
  919. TCHAR tszGuid[ctchNameGuid];
  920. NameFromGUID(tszGuid, &pjti->clsidConfig);
  921. lRc = RegSetValueEx(hk, REGSTR_VAL_CPLCLSID, 0, REG_SZ,
  922. (PV)&tszGuid[ctchNamePrefix], ctchGuid * cbX(tszGuid[0]) );
  923. }
  924. if (lRc == ERROR_SUCCESS)
  925. {
  926. } else
  927. {
  928. hres = E_FAIL;
  929. goto closedone;
  930. }
  931. }
  932. /* ISSUE-2001/03/29-timgill Needs more data checking
  933. Should make sure string is terminated properly */
  934. if (fl & DITC_DISPLAYNAME)
  935. {
  936. hres = JoyReg_SetValue(hk,
  937. REGSTR_VAL_JOYOEMNAME, REG_SZ,
  938. pjti->wszDisplayName,
  939. cbX(pjti->wszDisplayName));
  940. if (FAILED(hres))
  941. {
  942. goto closedone;
  943. }
  944. }
  945. #ifndef WINNT
  946. /* ISSUE-2001/03/29-timgill Needs more data checking
  947. Should make sure string is terminated properly */
  948. if (fl & DITC_CALLOUT)
  949. {
  950. hres = JoyReg_SetValue(hk,
  951. REGSTR_VAL_JOYOEMCALLOUT, REG_SZ,
  952. pjti->wszCallout,
  953. cbX(pjti->wszCallout));
  954. if (FAILED(hres))
  955. {
  956. hres = S_FALSE;
  957. //continue to go
  958. }
  959. }
  960. #endif
  961. if ( fl & DITC_HARDWAREID )
  962. {
  963. hres = JoyReg_SetValue(hk,
  964. REGSTR_VAL_JOYOEMHARDWAREID, REG_SZ,
  965. pjti->wszHardwareId,
  966. cbX(pjti->wszHardwareId) );
  967. if ( FAILED(hres) )
  968. {
  969. hres = S_FALSE;
  970. goto closedone;
  971. }
  972. }
  973. if ( fl & DITC_FLAGS1 )
  974. {
  975. AssertF( (pjti->dwFlags1 & ~JOYTYPE_FLAGS1_SETVALID) == 0x0 );
  976. hres = JoyReg_SetValue(hk,
  977. REGSTR_VAL_FLAGS1, REG_BINARY,
  978. (PV)&pjti->dwFlags1,
  979. cbX(pjti->dwFlags1) );
  980. if ( FAILED(hres) )
  981. {
  982. hres = S_FALSE;
  983. goto closedone;
  984. }
  985. }
  986. hres = S_OK;
  987. closedone:;
  988. RegCloseKey(hk);
  989. } else
  990. {
  991. hres = E_FAIL; /* Registry problem */
  992. }
  993. }
  994. }
  995. ExitOleProc();
  996. return hres;
  997. }
  998. /*****************************************************************************
  999. *
  1000. * @doc INTERNAL
  1001. *
  1002. * @func HRESULT | JoyReg_OpenConfigKey |
  1003. *
  1004. * Open the registry key that accesses joystick configuration data.
  1005. *
  1006. * Warning! Do not cache this regkey.
  1007. *
  1008. * If the user deletes the key and then re-creates it,
  1009. * the opened key will go stale and will become useless.
  1010. * You have to close the key and reopen it.
  1011. * To avoid worrying about that case, merely open it every time.
  1012. *
  1013. * @parm UINT | idJoy |
  1014. *
  1015. * Joystick number.
  1016. *
  1017. * @parm DWORD | sam |
  1018. *
  1019. * Access level desired.
  1020. *
  1021. * @parm IN DWORD | dwOptions |
  1022. * Option flags to RegCreateEx
  1023. *
  1024. * @parm PHKEY | phk |
  1025. *
  1026. * Receives created registry key.
  1027. *
  1028. * @returns
  1029. *
  1030. * Returns a COM error code. The following error codes are
  1031. * intended to be illustrative and not necessarily comprehensive.
  1032. *
  1033. * <c DI_OK> = <c S_OK>: The operation completed successfully.
  1034. *
  1035. * hresLe(ERROR_FILE_NOT_FOUND): The key does not exist.
  1036. *
  1037. *****************************************************************************/
  1038. STDMETHODIMP
  1039. JoyReg_OpenConfigKey(UINT idJoy, DWORD sam, DWORD dwOptions, PHKEY phk)
  1040. {
  1041. HRESULT hres;
  1042. EnterProc(JoyReg_OpenConfigKey, (_ "uxx", idJoy, sam, dwOptions));
  1043. #ifdef WINNT
  1044. hres = hresMumbleKeyEx(HKEY_LOCAL_MACHINE,
  1045. REGSTR_PATH_JOYCONFIG REGSTR_SZREGKEY REGSTR_KEY_JOYCURR,
  1046. sam, REG_OPTION_VOLATILE, phk);
  1047. #else
  1048. {
  1049. MMRESULT mmrc = MMSYSERR_ERROR;
  1050. JOYCAPS caps;
  1051. /*
  1052. * If we can't get the dev caps for the specified joystick,
  1053. * then use the magic joystick id "-1" to get non-specific
  1054. * caps.
  1055. */
  1056. mmrc = joyGetDevCaps(idJoy, &caps, cbX(caps));
  1057. if ( mmrc != JOYERR_NOERROR )
  1058. {
  1059. mmrc = joyGetDevCaps((DWORD)-1, &caps, cbX(caps));
  1060. }
  1061. if (mmrc == JOYERR_NOERROR)
  1062. {
  1063. TCHAR tsz[cA(REGSTR_PATH_JOYCONFIG) +
  1064. 1 + /* backslash */
  1065. cA(caps.szRegKey) +
  1066. 1 + /* backslash */
  1067. cA(REGSTR_KEY_JOYCURR) + 1];
  1068. /* tsz = MediaResources\Joystick\<drv>\CurrentJoystickSettings */
  1069. wsprintf(tsz, TEXT("%s\\%s\\") REGSTR_KEY_JOYCURR,
  1070. REGSTR_PATH_JOYCONFIG, caps.szRegKey);
  1071. hres = hresMumbleKeyEx(HKEY_LOCAL_MACHINE, tsz, sam, REG_OPTION_VOLATILE, phk);
  1072. } else
  1073. {
  1074. hres = E_FAIL;
  1075. }
  1076. }
  1077. #endif
  1078. ExitBenignOleProc();
  1079. return hres;
  1080. }
  1081. /*****************************************************************************
  1082. *
  1083. * @doc INTERNAL
  1084. *
  1085. * @func HRESULT | JoyReg_OpenSaveKey |
  1086. *
  1087. * Open the registry key that accesses joystick saved configurations
  1088. *
  1089. * Warning! Do not cache this regkey.
  1090. *
  1091. * If the user deletes the key and then re-creates it,
  1092. * the opened key will go stale and will become useless.
  1093. * You have to close the key and reopen it.
  1094. * To avoid worrying about that case, merely open it every time.
  1095. *
  1096. * @parm DWORD | dwType |
  1097. *
  1098. * Joystick type.
  1099. *
  1100. * This is either one of the standard ones in the range
  1101. *
  1102. * @parm IN LPCDIJOYCONFIG | pcfg |
  1103. *
  1104. * If the dwType represents an OEM type, this should point to a
  1105. * configuration data structure containing a valid wszType.
  1106. *
  1107. * @parm DWORD | sam |
  1108. *
  1109. * Access level desired.
  1110. *
  1111. * @parm PHKEY | phk |
  1112. *
  1113. * Receives created registry key.
  1114. *
  1115. * @returns
  1116. *
  1117. * Returns a COM error code. The following error codes are
  1118. * intended to be illustrative and not necessarily comprehensive.
  1119. *
  1120. * <c DI_OK> = <c S_OK>: The operation completed successfully.
  1121. *
  1122. * hresLe(ERROR_FILE_NOT_FOUND): The key does not exist.
  1123. *
  1124. *****************************************************************************/
  1125. STDMETHODIMP
  1126. JoyReg_OpenSaveKey(DWORD dwType, LPCDIJOYCONFIG pcfg, DWORD sam, PHKEY phk)
  1127. {
  1128. HRESULT hres;
  1129. JOYCAPS caps;
  1130. DWORD dwOptions = 0;
  1131. EnterProc(JoyReg_OpenSaveKey, (_ "upx", dwType, pcfg, sam));
  1132. #ifdef WINNT
  1133. lstrcpy(caps.szRegKey, REGSTR_SZREGKEY );
  1134. #else
  1135. /*
  1136. * use the magic joystick id "-1" to get non-specific caps.
  1137. */
  1138. if ( joyGetDevCaps((DWORD)-1, &caps, cbX(caps)) != JOYERR_NOERROR )
  1139. {
  1140. hres = E_FAIL;
  1141. } else
  1142. #endif
  1143. {
  1144. TCHAR tsz[cA(REGSTR_PATH_JOYCONFIG) +
  1145. 1 + /* backslash */
  1146. cA(caps.szRegKey) +
  1147. 1 + /* backslash */
  1148. cA(REGSTR_KEY_JOYSETTINGS) +
  1149. 1 + /* backslash */
  1150. max( cA(REGSTR_KEY_JOYPREDEFN), cA(pcfg->wszType) ) + 1 ];
  1151. /* tsz = MediaResources\Joystick\<drv>\JoystickSettings\<Type> */
  1152. if ( dwType >= JOY_HW_PREDEFMAX )
  1153. {
  1154. wsprintf(tsz, TEXT("%s\\%s\\%s\\%ls"),
  1155. REGSTR_PATH_JOYCONFIG, caps.szRegKey, REGSTR_KEY_JOYSETTINGS, pcfg->wszType);
  1156. } else
  1157. {
  1158. /*
  1159. * We will probably never have more than the current 11 predefined
  1160. * joysticks. Assume no more than 99 so %d is as many characters.
  1161. */
  1162. wsprintf(tsz, TEXT("%s\\%s\\%s\\" REGSTR_KEY_JOYPREDEFN),
  1163. REGSTR_PATH_JOYCONFIG, caps.szRegKey, REGSTR_KEY_JOYSETTINGS, dwType );
  1164. }
  1165. if ( pcfg->hwc.dwUsageSettings & JOY_US_VOLATILE )
  1166. dwOptions = REG_OPTION_VOLATILE;
  1167. else
  1168. dwOptions = REG_OPTION_NON_VOLATILE;
  1169. hres = hresMumbleKeyEx(HKEY_LOCAL_MACHINE, tsz, sam, dwOptions, phk);
  1170. }
  1171. ExitOleProc();
  1172. return hres;
  1173. }
  1174. /*****************************************************************************
  1175. *
  1176. * @doc INTERNAL
  1177. *
  1178. * @func HRESULT | JoyReg_GetSetConfigValue |
  1179. *
  1180. * Retrieve or update configuration information about a joystick,
  1181. * as stored in the registry instance key.
  1182. *
  1183. * @parm HKEY | hk |
  1184. *
  1185. * Registry key containing fun values.
  1186. *
  1187. * @parm LPCTSTR | ptszNValue |
  1188. *
  1189. * Registry value name, with "%d" where a joystick number
  1190. * should be.
  1191. *
  1192. * @parm UINT | idJoy |
  1193. *
  1194. * Zero-based joystick number.
  1195. *
  1196. * @parm DWORD | reg |
  1197. *
  1198. * Registry data type expected.
  1199. *
  1200. * @parm LPVOID | pvBuf |
  1201. *
  1202. * Buffer to receive information from registry (if getting)
  1203. * or containing value to set.
  1204. *
  1205. * @parm DWORD | cb |
  1206. *
  1207. * Size of buffer, in bytes.
  1208. *
  1209. * @parm BOOL | fSet |
  1210. *
  1211. * Nonzer if the value should be set; otherwise, it will be
  1212. * retrieved.
  1213. *
  1214. * @returns
  1215. *
  1216. * Returns a COM error code. The following error codes are
  1217. * intended to be illustrative and not necessarily comprehensive.
  1218. *
  1219. * <c DI_OK> = <c S_OK>: The operation completed successfully.
  1220. *
  1221. * <c E_FAIL>: Error reading/writing value to/from registry.
  1222. *
  1223. *****************************************************************************/
  1224. STDMETHODIMP
  1225. JoyReg_GetSetConfigValue(HKEY hk, LPCTSTR ptszNValue, UINT idJoy,
  1226. DWORD reg, PV pvBuf, DWORD cb, BOOL fSet)
  1227. {
  1228. HRESULT hres;
  1229. int ctch;
  1230. /* Extra +12 because a UINT can be as big as 4 billion */
  1231. TCHAR tsz[max(
  1232. max(
  1233. max(cA(REGSTR_VAL_JOYNCONFIG),
  1234. cA(REGSTR_VAL_JOYNOEMNAME)),
  1235. cA(REGSTR_VAL_JOYNOEMCALLOUT)),
  1236. cA(REGSTR_VAL_JOYNFFCONFIG)) + 12 + 1];
  1237. ctch = wsprintf(tsz, ptszNValue, idJoy + 1);
  1238. AssertF(ctch < cA(tsz));
  1239. if (fSet)
  1240. {
  1241. hres = JoyReg_SetValue(hk, tsz, reg, pvBuf, cb);
  1242. } else
  1243. {
  1244. hres = JoyReg_GetValue(hk, tsz, reg, pvBuf, cb);
  1245. }
  1246. return hres;
  1247. }
  1248. /*****************************************************************************
  1249. *
  1250. * @doc INTERNAL
  1251. *
  1252. * @func HRESULT | hresIdJoypInstanceGUID |
  1253. *
  1254. * Given a joystick ID obtain the corresponding GUID.
  1255. * This routine differs in implementation on WINNT and WIN9x
  1256. * On WINNT there are no predefined GUID for Joystick IDs.
  1257. *
  1258. * @parm IN UINT | idJoy |
  1259. *
  1260. * Joystick identification number.
  1261. *
  1262. * @parm OUT LPGUID | lpguid |
  1263. *
  1264. * Receives the joystick GUID. If no mapping exists,
  1265. * GUID_NULL is passed back
  1266. *
  1267. * On Windows NT all joysticks are HID devices. The corresponding function
  1268. * for WINNT is defined in diWinnt.c
  1269. *
  1270. *****************************************************************************/
  1271. HRESULT EXTERNAL hResIdJoypInstanceGUID_95
  1272. (
  1273. UINT idJoy,
  1274. LPGUID lpguid
  1275. )
  1276. {
  1277. HRESULT hRes;
  1278. hRes = S_OK;
  1279. if ( idJoy < cA(rgGUID_Joystick) )
  1280. {
  1281. *lpguid = rgGUID_Joystick[idJoy];
  1282. } else
  1283. {
  1284. hRes = DIERR_NOTFOUND;
  1285. ZeroX(*lpguid);
  1286. }
  1287. return hRes;
  1288. }
  1289. /*****************************************************************************
  1290. *
  1291. * @doc INTERNAL
  1292. *
  1293. * @func HRESULT | JoyReg_GetConfigInternal |
  1294. *
  1295. * Obtain information about a joystick's configuration.
  1296. *
  1297. * @parm UINT | uiJoy |
  1298. *
  1299. * Joystick identification number.
  1300. *
  1301. * @parm OUT LPDIJOYCONFIG | pcfg |
  1302. *
  1303. * Receives information about the joystick configuration.
  1304. * The caller is assumed to have validated the
  1305. * <e DIJOYCONFIG.dwSize> field.
  1306. *
  1307. * @parm DWORD | fl |
  1308. *
  1309. * Zero or more <c DIJC_*> flags
  1310. * which specify which parts of the structure pointed
  1311. * to by <p pjc> are to be filled in.
  1312. *
  1313. * @returns
  1314. *
  1315. * Returns a COM error code. The following error codes are
  1316. * intended to be illustrative and not necessarily comprehensive.
  1317. *
  1318. * <c DI_OK> = <c S_OK>: The operation completed successfully.
  1319. *
  1320. * <c DIERR_NOMOREITEMS>: No more joysticks.
  1321. *
  1322. *****************************************************************************/
  1323. STDMETHODIMP
  1324. JoyReg_GetConfigInternal(UINT idJoy, LPDIJOYCONFIG pcfg, DWORD fl)
  1325. {
  1326. HRESULT hres = E_FAIL;
  1327. EnterProc(JoyReg_GetConfigInternal, (_ "upx", idJoy, pcfg, fl));
  1328. AssertF((fl & ~DIJC_GETVALID) == 0);
  1329. /* We only support (0/16) joysticks */
  1330. if ( idJoy < cJoyMax )
  1331. {
  1332. /* Force a rescan of all HID device list
  1333. * Some device may have been attached
  1334. * since we last looked
  1335. */
  1336. DIHid_BuildHidList(FALSE);
  1337. if (fl & DIJC_GUIDINSTANCE)
  1338. {
  1339. hres = hResIdJoypInstanceGUID_WDM(idJoy, &pcfg->guidInstance);
  1340. #ifndef WINNT
  1341. if ( FAILED(hres) )
  1342. {
  1343. hres = hResIdJoypInstanceGUID_95(idJoy, &pcfg->guidInstance);
  1344. }
  1345. #endif
  1346. if ( FAILED(hres) )
  1347. {
  1348. goto done;
  1349. }
  1350. }
  1351. if ( fl & DIJC_INREGISTRY )
  1352. {
  1353. HKEY hk;
  1354. /* Does the registry entry exist ? */
  1355. hres = JoyReg_OpenConfigKey(idJoy, KEY_QUERY_VALUE, REG_OPTION_NON_VOLATILE , &hk);
  1356. if (SUCCEEDED(hres))
  1357. {
  1358. if (fl & DIJC_REGHWCONFIGTYPE)
  1359. {
  1360. hres = JoyReg_GetConfigValue(
  1361. hk, REGSTR_VAL_JOYNCONFIG,
  1362. idJoy, REG_BINARY,
  1363. &pcfg->hwc, cbX(pcfg->hwc));
  1364. if (FAILED(hres))
  1365. {
  1366. goto closedone;
  1367. }
  1368. pcfg->wszType[0] = TEXT('\0');
  1369. if ( (pcfg->hwc.dwUsageSettings & JOY_US_ISOEM)
  1370. #ifndef WINNT
  1371. ||( (pcfg->hwc.dwType >= JOY_HW_PREDEFMIN)
  1372. &&(pcfg->hwc.dwType < JOY_HW_PREDEFMAX) )
  1373. #endif
  1374. )
  1375. {
  1376. hres = JoyReg_GetConfigValue(
  1377. hk, REGSTR_VAL_JOYNOEMNAME, idJoy, REG_SZ,
  1378. pcfg->wszType, cbX(pcfg->wszType));
  1379. if (FAILED(hres))
  1380. {
  1381. goto closedone;
  1382. }
  1383. }
  1384. }
  1385. #ifndef WINNT
  1386. if (fl & DIJC_CALLOUT)
  1387. {
  1388. pcfg->wszCallout[0] = TEXT('\0');
  1389. hres = JoyReg_GetConfigValue(
  1390. hk, REGSTR_VAL_JOYNOEMCALLOUT, idJoy, REG_SZ,
  1391. pcfg->wszCallout, cbX(pcfg->wszCallout));
  1392. if (FAILED(hres))
  1393. {
  1394. ZeroX(pcfg->wszCallout);
  1395. hres = S_FALSE;
  1396. /* Note that we fall through and let hres = S_OK */
  1397. }
  1398. }
  1399. #endif
  1400. if (fl & DIJC_GAIN)
  1401. {
  1402. /*
  1403. * If there is no FF configuration, then
  1404. * default to DI_FFNOMINALMAX gain.
  1405. */
  1406. hres = JoyReg_GetConfigValue(hk,
  1407. REGSTR_VAL_JOYNFFCONFIG,
  1408. idJoy, REG_BINARY,
  1409. &pcfg->dwGain, cbX(pcfg->dwGain));
  1410. if (SUCCEEDED(hres) && ISVALIDGAIN(pcfg->dwGain))
  1411. {
  1412. /* Leave it alone; it's good */
  1413. } else
  1414. {
  1415. pcfg->dwGain = DI_FFNOMINALMAX;
  1416. hres = S_FALSE;
  1417. }
  1418. }
  1419. if ( fl & DIJC_WDMGAMEPORT )
  1420. {
  1421. PBUSDEVICEINFO pbdi;
  1422. /*
  1423. * If there is no Gameport Associated with this device
  1424. * then it must be a USB device
  1425. */
  1426. DllEnterCrit();
  1427. if ( pbdi = pbdiFromJoyId(idJoy) )
  1428. {
  1429. pcfg->guidGameport = pbdi->guid;
  1430. //lstrcpyW(pcfg->wszGameport, pbdi->wszDisplayName);
  1431. } else
  1432. {
  1433. ZeroX(pcfg->guidGameport);
  1434. hres = S_FALSE;
  1435. }
  1436. DllLeaveCrit();
  1437. }
  1438. }
  1439. closedone:
  1440. if( FAILED(hres) ) {
  1441. DIJOYTYPEINFO dijti;
  1442. AssertF( pcfg->dwSize == sizeof(DIJOYCONFIG_DX5)
  1443. || pcfg->dwSize == sizeof(DIJOYCONFIG_DX6) );
  1444. hres = DIWdm_JoyHidMapping(idJoy, NULL, pcfg, &dijti );
  1445. if( FAILED(hres) ) {
  1446. hres = E_FAIL;
  1447. }
  1448. }
  1449. RegCloseKey(hk);
  1450. }
  1451. } else
  1452. {
  1453. hres = DIERR_NOMOREITEMS;
  1454. }
  1455. done:
  1456. ExitBenignOleProc();
  1457. return hres;
  1458. }
  1459. /*****************************************************************************
  1460. *
  1461. * @doc INTERNAL
  1462. *
  1463. * @func HRESULT | JoyReg_GetConfig |
  1464. *
  1465. * Obtain information about a joystick's configuration,
  1466. * taking the *naive* MSGAME.VXD driver into account.
  1467. *
  1468. * @parm UINT | uiJoy |
  1469. *
  1470. * Joystick identification number.
  1471. *
  1472. * @parm OUT LPDIJOYCONFIG | pcfg |
  1473. *
  1474. * Receives information about the joystick configuration.
  1475. * The caller is assumed to have validated the
  1476. * <e DIJOYCONFIG.dwSize> field.
  1477. *
  1478. * @parm DWORD | fl |
  1479. *
  1480. * Zero or more <c DIJC_*> flags
  1481. * which specify which parts of the structure pointed
  1482. * to by <p pjc> are to be filled in.
  1483. *
  1484. * @returns
  1485. *
  1486. * Returns a COM error code. The following error codes are
  1487. * intended to be illustrative and not necessarily comprehensive.
  1488. *
  1489. * <c DI_OK> = <c S_OK>: The operation completed successfully.
  1490. *
  1491. * <c DIERR_NOMOREITEMS>: No more joysticks.
  1492. *
  1493. *****************************************************************************/
  1494. STDMETHODIMP
  1495. JoyReg_GetConfig(UINT idJoy, LPDIJOYCONFIG pcfg, DWORD fl)
  1496. {
  1497. HRESULT hres;
  1498. GUID guid;
  1499. EnterProc(JoyReg_GetConfig, (_ "upx", idJoy, pcfg, fl));
  1500. AssertF((fl & ~DIJC_GETVALID) == 0);
  1501. /*
  1502. * First determine if the joystick exits
  1503. * On NT, we use WDM driver.
  1504. * On Win9x, if WDM fails, use static guids.
  1505. */
  1506. hres = hResIdJoypInstanceGUID_WDM(idJoy, &guid);
  1507. #ifndef WINNT
  1508. if ( FAILED(hres) )
  1509. {
  1510. hres = hResIdJoypInstanceGUID_95(idJoy, &guid);
  1511. }
  1512. #endif
  1513. if ( SUCCEEDED( hres) )
  1514. {
  1515. hres = JoyReg_GetConfigInternal(idJoy, pcfg, fl);
  1516. #ifndef WINNT
  1517. /***************************************************
  1518. *
  1519. * Beginning of hack for *naive* Sidewinder Gamepad.
  1520. *
  1521. * The gamepad needs to be polled sixteen times
  1522. * before it realizes what is going on.
  1523. *
  1524. ***************************************************/
  1525. if (SUCCEEDED(hres) && (fl & DIJC_CALLOUT))
  1526. {
  1527. static WCHAR s_wszMSGAME[] = L"MSGAME.VXD";
  1528. if (memcmp(pcfg->wszCallout, s_wszMSGAME, cbX(s_wszMSGAME)) == 0)
  1529. {
  1530. SquirtSqflPtszV(sqfl,
  1531. TEXT("Making bonus polls for Sidewinder"));
  1532. /*
  1533. * Sigh. It's a Sidewinder. Make sixteen
  1534. * bonus polls to shake the stick into submission.
  1535. *
  1536. * There's no point in doing this over and over if we're
  1537. * in some kind of loop so make sure a "reasonable"
  1538. * length of time has passed since last time we tried.
  1539. * 3 seconds is a little less than the current CPL
  1540. * background refresh rate.
  1541. */
  1542. if ( !g_dwLastBonusPoll || ( GetTickCount() - g_dwLastBonusPoll > 3000 ) )
  1543. {
  1544. JOYINFOEX ji;
  1545. int i;
  1546. DWORD dwWait;
  1547. ji.dwSize = cbX(ji);
  1548. ji.dwFlags = JOY_RETURNALL;
  1549. for (i = 0; i < 16; i++)
  1550. {
  1551. MMRESULT mmrc = joyGetPosEx(idJoy, &ji);
  1552. SquirtSqflPtszV(sqfl,
  1553. TEXT("joyGetPosEx(%d) = %d"),
  1554. idJoy, mmrc);
  1555. /*
  1556. * Sleep 10ms between each poll because that
  1557. * seems to help a bit.
  1558. */
  1559. Sleep(10);
  1560. }
  1561. /*
  1562. * Bonus hack! Now sleep for some time.
  1563. * The amount of time we need to sleep is CPU-speed
  1564. * dependent, so we'll grab the sleep time from the
  1565. * registry to allow us to tweak it later.
  1566. *
  1567. * What a shame.
  1568. */
  1569. dwWait = RegQueryDIDword(NULL, REGSTR_VAL_GAMEPADDELAY, 100);
  1570. if (dwWait > 10 * 1000)
  1571. {
  1572. dwWait = 10 * 1000;
  1573. }
  1574. Sleep(dwWait);
  1575. /*
  1576. * And then check again.
  1577. */
  1578. hres = JoyReg_GetConfigInternal(idJoy, pcfg, fl);
  1579. g_dwLastBonusPoll = GetTickCount();
  1580. }
  1581. }
  1582. }
  1583. /***************************************************
  1584. *
  1585. * End of hack for *naive* Sidewinder Gamepad.
  1586. *
  1587. ***************************************************/
  1588. #endif
  1589. }
  1590. return hres;
  1591. }
  1592. #ifndef WINNT
  1593. /*****************************************************************************
  1594. *
  1595. * @doc INTERNAL
  1596. *
  1597. * @func HRESULT | JoyReg_JoyIdToDeviceInterface_95 |
  1598. *
  1599. * Given a joystick ID number, obtain the device interface
  1600. * corresponding to it.
  1601. *
  1602. * @parm UINT | idJoy |
  1603. *
  1604. * Joystick ID number, zero-based.
  1605. *
  1606. * @parm PVXDINITPARMS | pvip |
  1607. *
  1608. * Receives init parameters from the driver.
  1609. *
  1610. * @parm LPTSTR | ptszBuf |
  1611. *
  1612. * A buffer of size <c MAX_PATH> in which the device interface
  1613. * path is built. Note that we can get away with a buffer of
  1614. * this size, since the code path exists only on Windows 95,
  1615. * and Windows 95 does not support paths longer than <c MAX_PATH>.
  1616. * (I.e., there ain't no \\?\ support in Win95.)
  1617. *
  1618. * @returns
  1619. *
  1620. * A pointer to the part of the <p ptszBuf> buffer that
  1621. * contains the actual device interface path.
  1622. *
  1623. *****************************************************************************/
  1624. LPSTR EXTERNAL
  1625. JoyReg_JoyIdToDeviceInterface_95(UINT idJoy, PVXDINITPARMS pvip, LPSTR ptszBuf)
  1626. {
  1627. UINT cwch;
  1628. HRESULT hres;
  1629. LPSTR ptszRc;
  1630. hres = Hel_Joy_GetInitParms(idJoy, pvip);
  1631. if (SUCCEEDED(hres))
  1632. {
  1633. /*
  1634. * The length counter includes the terminating null.
  1635. */
  1636. cwch = LOWORD(pvip->dwFilenameLengths);
  1637. /*
  1638. * The name that comes from HID is "\DosDevices\blah"
  1639. * but we want to use "\\.\blah". So check if it indeed
  1640. * of the form "\DosDevices\blah" and if so, convert it.
  1641. * If not, then give up.
  1642. *
  1643. * For the string to possibly be a "\DosDevices\", it
  1644. * needs to be of length 12 or longer.
  1645. */
  1646. if (cwch >= 12 && cwch < MAX_PATH)
  1647. {
  1648. /*
  1649. * WideCharToMultiByte does parameter validation so we
  1650. * don't have to.
  1651. */
  1652. WideCharToMultiByte(CP_ACP, 0, pvip->pFilenameBuffer, cwch,
  1653. ptszBuf, MAX_PATH, 0, 0);
  1654. /*
  1655. * The 11th (zero-based) character must be a backslash.
  1656. * And the value of cwch had better be right.
  1657. */
  1658. if (ptszBuf[cwch-1] == ('\0') && ptszBuf[11] == ('\\'))
  1659. {
  1660. /*
  1661. * Wipe out the backslash and make sure the lead-in
  1662. * is "\DosDevices".
  1663. */
  1664. ptszBuf[11] = ('\0');
  1665. if (lstrcmpiA(ptszBuf, ("\\DosDevices")) == 0)
  1666. {
  1667. /*
  1668. * Create a "\\.\" at the start of the string.
  1669. * Note! This code never runs on Alphas so we
  1670. * can do evil unaligned data accesses.
  1671. *
  1672. * (Actually, 8 is a multiple of 4, so everything
  1673. * is aligned after all.)
  1674. */
  1675. *(LPDWORD)&ptszBuf[8] = 0x5C2E5C5C;
  1676. ptszRc = &ptszBuf[8];
  1677. } else
  1678. {
  1679. ptszRc = NULL;
  1680. }
  1681. } else
  1682. {
  1683. ptszRc = NULL;
  1684. }
  1685. } else
  1686. {
  1687. ptszRc = NULL;
  1688. }
  1689. } else
  1690. {
  1691. ptszRc = NULL;
  1692. }
  1693. return ptszRc;
  1694. }
  1695. /*****************************************************************************
  1696. *
  1697. * @doc INTERNAL
  1698. *
  1699. * @func void | JoyReg_SetCalibration |
  1700. *
  1701. * Store information about a joystick's configuration,
  1702. * shadowing the information back into the HID side of
  1703. * things as well.
  1704. *
  1705. * @parm UINT | uiJoy |
  1706. *
  1707. * Joystick identification number.
  1708. *
  1709. * @parm LPJOYREGHWCONFIG | phwc |
  1710. *
  1711. * Contains information about the joystick capabilities.
  1712. * This value supercedes the value in the <p pcfg>.
  1713. *
  1714. * @parm LPCDIJOYCONFIG | pcfg |
  1715. *
  1716. * Contains information about the joystick configuration.
  1717. * The caller is assumed to have validated all fields.
  1718. *
  1719. *****************************************************************************/
  1720. STDMETHODIMP
  1721. TFORM(CDIObj_FindDevice)(PV pdiT, REFGUID rguid,
  1722. LPCTSTR ptszName, LPGUID pguidOut);
  1723. void EXTERNAL
  1724. JoyReg_SetCalibration(UINT idJoy, LPJOYREGHWCONFIG phwc)
  1725. {
  1726. HRESULT hres;
  1727. VXDINITPARMS vip;
  1728. GUID guid;
  1729. CHAR tsz[MAX_PATH];
  1730. LPSTR pszPath;
  1731. TCHAR ptszPath[MAX_PATH];
  1732. EnterProc(JoyReg_SetCalibration, (_ "up", idJoy, phwc));
  1733. pszPath = JoyReg_JoyIdToDeviceInterface_95(idJoy, &vip, tsz);
  1734. if ( pszPath )
  1735. #ifdef UNICODE
  1736. AToU( ptszPath, MAX_PATH, pszPath );
  1737. #else
  1738. lstrcpy( (LPSTR)ptszPath, pszPath );
  1739. #endif
  1740. if (pszPath &&
  1741. SUCCEEDED(CDIObj_FindDeviceInternal(ptszPath, &guid)))
  1742. {
  1743. IDirectInputDeviceCallback *pdcb;
  1744. #ifdef DEBUG
  1745. CREATEDCB CreateDcb;
  1746. #endif
  1747. #ifdef DEBUG
  1748. /*
  1749. * If the associated HID device got unplugged, then
  1750. * the instance GUID is no more. So don't get upset
  1751. * if we can't find it. But if we do find it, then
  1752. * it had better be a HID device.
  1753. *
  1754. * CHid_New will properly fail if the associated
  1755. * device is not around.
  1756. */
  1757. hres = hresFindInstanceGUID(&guid, &CreateDcb, 1);
  1758. AssertF(fLimpFF(SUCCEEDED(hres), CreateDcb == CHid_New));
  1759. #endif
  1760. if (SUCCEEDED(hres = CHid_New(0, &guid,
  1761. &IID_IDirectInputDeviceCallback,
  1762. (PPV)&pdcb)))
  1763. {
  1764. LPDIDATAFORMAT pdf;
  1765. /*
  1766. * The VXDINITPARAMS structure tells us where JOYHID
  1767. * decided to place each of the axes. Follow that
  1768. * table to put them into their corresponding location
  1769. * in the HID side.
  1770. */
  1771. hres = pdcb->lpVtbl->GetDataFormat(pdcb, &pdf);
  1772. if (SUCCEEDED(hres))
  1773. {
  1774. UINT uiAxis;
  1775. DIPROPINFO propi;
  1776. propi.pguid = DIPROP_SPECIFICCALIBRATION;
  1777. /*
  1778. * For each axis...
  1779. */
  1780. for (uiAxis = 0; uiAxis < 6; uiAxis++)
  1781. {
  1782. DWORD dwUsage = vip.Usages[uiAxis];
  1783. /*
  1784. * If the axis is mapped to a usage...
  1785. */
  1786. if (dwUsage)
  1787. {
  1788. /*
  1789. * Convert the usage into an object index.
  1790. */
  1791. hres = pdcb->lpVtbl->MapUsage(pdcb, dwUsage,
  1792. &propi.iobj);
  1793. if (SUCCEEDED(hres))
  1794. {
  1795. DIPROPCAL cal;
  1796. /*
  1797. * Convert the old-style calibration into
  1798. * a new-style calibration.
  1799. */
  1800. #define CopyCalibration(f, ui) \
  1801. cal.l##f = (&phwc->hwv.jrvHardware.jp##f.dwX)[ui]
  1802. CopyCalibration(Min, uiAxis);
  1803. CopyCalibration(Max, uiAxis);
  1804. CopyCalibration(Center, uiAxis);
  1805. #undef CopyCalibration
  1806. /*
  1807. * Set the calibration property on the object.
  1808. */
  1809. propi.dwDevType =
  1810. pdf->rgodf[propi.iobj].dwType;
  1811. hres = pdcb->lpVtbl->SetProperty(pdcb, &propi,
  1812. &cal.diph);
  1813. }
  1814. }
  1815. }
  1816. }
  1817. Invoke_Release(&pdcb);
  1818. }
  1819. }
  1820. ExitProc();
  1821. }
  1822. #endif
  1823. /*****************************************************************************
  1824. *
  1825. * @doc INTERNAL
  1826. *
  1827. * @func HRESULT | JoyReg_SetHWConfig |
  1828. *
  1829. * Store information about a joystick's <t JOYREGHWCONFIG>.
  1830. *
  1831. * @parm UINT | uiJoy |
  1832. *
  1833. * Joystick identification number.
  1834. *
  1835. * @parm LPJOYREGHWCONFIG | phwc |
  1836. *
  1837. * Contains information about the joystick capabilities.
  1838. * This value supercedes the value in the <p pcfg>.
  1839. *
  1840. * @parm LPCDIJOYCONFIG | pcfg |
  1841. *
  1842. * Contains information about the joystick configuration.
  1843. * The caller is assumed to have validated all fields.
  1844. *
  1845. * @parm HKEY | hk |
  1846. *
  1847. * The type key we are munging.
  1848. *
  1849. *
  1850. * @returns
  1851. *
  1852. * Returns a COM error code. The following error codes are
  1853. * intended to be illustrative and not necessarily comprehensive.
  1854. *
  1855. * <c DI_OK> = <c S_OK>: The operation completed successfully.
  1856. *
  1857. *****************************************************************************/
  1858. HRESULT INTERNAL
  1859. JoyReg_SetHWConfig(UINT idJoy, LPJOYREGHWCONFIG phwc, LPCDIJOYCONFIG pcfg,
  1860. HKEY hk)
  1861. {
  1862. HRESULT hres;
  1863. HKEY hkSave;
  1864. DWORD dwSam;
  1865. /*
  1866. * The caller has set phwc->dwType, so use it to determine
  1867. * where the data comes from or goes to.
  1868. */
  1869. if ( phwc->dwType == JOY_HW_NONE )
  1870. {
  1871. /*
  1872. * Nothing to do
  1873. */
  1874. } else if ( phwc->dwType == JOY_HW_CUSTOM )
  1875. {
  1876. /*
  1877. /* ISSUE-2001/03/29-timgill Custom HWConfig not handled correctly
  1878. * We don't know the type name and the only time we can look
  1879. * it up is when were modifying an existing config so although we
  1880. * could store the config, we'd never be able to get it back.
  1881. * Should return no better than S_FALSE. This will have to wait.
  1882. */
  1883. } else
  1884. {
  1885. /*
  1886. * Try to access saved values
  1887. */
  1888. // ISSUE-2001/03/29-timgill Dangerous type cast
  1889. PDWORD pdw = (PDWORD)&phwc->hwv;
  1890. dwSam = KEY_QUERY_VALUE;
  1891. while ( pdw < &phwc->dwType )
  1892. {
  1893. if ( *pdw )
  1894. {
  1895. /*
  1896. * Real config data so write it
  1897. */
  1898. dwSam = KEY_SET_VALUE;
  1899. break;
  1900. }
  1901. pdw++;
  1902. }
  1903. /*
  1904. * If the device is autoloaded and yet the user is manually assigning it
  1905. * to an ID, set the volatile flag. The flag will be set to the driver
  1906. * defined value if a driver ever gets hotplug assigned to this ID but if
  1907. * not, this makes sure that the settings are removed on next reboot.
  1908. */
  1909. if (phwc->hws.dwFlags & JOY_HWS_AUTOLOAD)
  1910. {
  1911. phwc->dwUsageSettings |= JOY_US_VOLATILE;
  1912. }
  1913. hres = JoyReg_OpenSaveKey( phwc->dwType, pcfg, dwSam, &hkSave );
  1914. if ( SUCCEEDED(hres) )
  1915. {
  1916. if ( dwSam == KEY_SET_VALUE )
  1917. {
  1918. hres = JoyReg_SetConfigValue(hkSave, REGSTR_VAL_JOYNCONFIG,
  1919. idJoy, REG_BINARY,
  1920. phwc, cbX(*phwc));
  1921. if ( FAILED(hres) )
  1922. {
  1923. // Report the error but live with it
  1924. RPF("JoyReg_SetConfig: failed to set saved config %08x", hres );
  1925. }
  1926. } else
  1927. {
  1928. JOYREGHWCONFIG hwc;
  1929. /*
  1930. * Read it into an extra buffer because we only want it
  1931. * if it's complete.
  1932. */
  1933. hres = JoyReg_GetConfigValue(hkSave, REGSTR_VAL_JOYNCONFIG,
  1934. idJoy, REG_BINARY,
  1935. &hwc, cbX(hwc));
  1936. if ( hres == S_OK )
  1937. {
  1938. // Assert hws is first and no gap before dwUsageSettings
  1939. CAssertF( FIELD_OFFSET( JOYREGHWCONFIG, hws ) == 0 );
  1940. CAssertF( FIELD_OFFSET( JOYREGHWCONFIG, dwUsageSettings ) == sizeof( hwc.hws ) );
  1941. // Copy the whole structure except the hws
  1942. memcpy( &phwc->dwUsageSettings, &hwc.dwUsageSettings,
  1943. sizeof( hwc ) - sizeof( hwc.hws ) );
  1944. }
  1945. }
  1946. RegCloseKey( hkSave );
  1947. }
  1948. /*
  1949. * If we failed to read, there's probably nothing there and the
  1950. * structure is set up already for a blank config.
  1951. * If we failed to write there probably not much we can do
  1952. */
  1953. }
  1954. hres = JoyReg_SetConfigValue(hk, REGSTR_VAL_JOYNCONFIG,
  1955. idJoy, REG_BINARY,
  1956. phwc, cbX(*phwc));
  1957. if (FAILED(hres))
  1958. {
  1959. goto done;
  1960. }
  1961. if (phwc->dwUsageSettings & JOY_US_ISOEM)
  1962. {
  1963. hres = JoyReg_SetConfigValue(
  1964. hk, REGSTR_VAL_JOYNOEMNAME, idJoy, REG_SZ,
  1965. pcfg->wszType, cbX(pcfg->wszType));
  1966. } else
  1967. {
  1968. hres = JoyReg_SetConfigValue(
  1969. hk, REGSTR_VAL_JOYNOEMNAME, idJoy, REG_SZ,
  1970. 0, 0);
  1971. }
  1972. done:;
  1973. return hres;
  1974. }
  1975. /*****************************************************************************
  1976. *
  1977. * @doc INTERNAL
  1978. *
  1979. * @func HRESULT | JoyReg_SetConfig |
  1980. *
  1981. * Store information about a joystick's configuration.
  1982. *
  1983. * @parm UINT | uiJoy |
  1984. *
  1985. * Joystick identification number.
  1986. *
  1987. * @parm JOYREGHWCONFIG | phwc |
  1988. *
  1989. * Contains information about the joystick capabilities.
  1990. * This value supercedes the value in the <p pcfg>.
  1991. * It may be modified if we needed to load the config
  1992. * info from the saved settings.
  1993. *
  1994. * @parm LPCDIJOYCONFIG | pcfg |
  1995. *
  1996. * Contains information about the joystick configuration.
  1997. * The caller is assumed to have validated all fields.
  1998. *
  1999. * @parm DWORD | fl |
  2000. *
  2001. * Zero or more <c DIJC_*> flags
  2002. * which specify which parts of the structures pointed
  2003. * to by <p phwc> and <p pjc> are to be written out.
  2004. *
  2005. * @returns
  2006. *
  2007. * Returns a COM error code. The following error codes are
  2008. * intended to be illustrative and not necessarily comprehensive.
  2009. *
  2010. * <c DI_OK> = <c S_OK>: The operation completed successfully.
  2011. *
  2012. *****************************************************************************/
  2013. JOYREGHWVALUES null_hwv = { 0};
  2014. STDMETHODIMP
  2015. JoyReg_SetConfig(UINT idJoy, LPJOYREGHWCONFIG phwc,
  2016. LPCDIJOYCONFIG pcfg, DWORD fl)
  2017. {
  2018. HRESULT hres;
  2019. EnterProc(JoyReg_SetConfig, (_ "uppx", idJoy, phwc, pcfg, fl));
  2020. AssertF((fl & ~DIJC_INTERNALSETVALID) == 0);
  2021. if (idJoy < cJoyMax )
  2022. {
  2023. if (fl & DIJC_INREGISTRY)
  2024. {
  2025. HKEY hk;
  2026. DWORD dwOptions = 0;
  2027. hres = JoyReg_OpenConfigKey(idJoy, KEY_SET_VALUE, dwOptions, &hk);
  2028. if (SUCCEEDED(hres))
  2029. {
  2030. if (fl & DIJC_REGHWCONFIGTYPE)
  2031. {
  2032. hres = JoyReg_SetHWConfig(idJoy, phwc, pcfg, hk);
  2033. if (FAILED(hres))
  2034. {
  2035. goto closedone;
  2036. }
  2037. #ifndef WINNT
  2038. if (fl & DIJC_UPDATEALIAS)
  2039. {
  2040. JoyReg_SetCalibration(idJoy, phwc);
  2041. }
  2042. #endif
  2043. }
  2044. #ifndef WINNT
  2045. if (fl & DIJC_CALLOUT)
  2046. {
  2047. hres = JoyReg_SetConfigValue(
  2048. hk, REGSTR_VAL_JOYNOEMCALLOUT, idJoy, REG_SZ,
  2049. pcfg->wszCallout, cbX(pcfg->wszCallout));
  2050. if (FAILED(hres))
  2051. {
  2052. hres = S_FALSE;
  2053. //continue to go
  2054. }
  2055. }
  2056. #endif
  2057. if (fl & DIJC_GAIN)
  2058. {
  2059. if (ISVALIDGAIN(pcfg->dwGain))
  2060. {
  2061. /*
  2062. * If restoring to nominal, then the key
  2063. * can be deleted; the default value will
  2064. * be assumed subsequently.
  2065. */
  2066. if (pcfg->dwGain == DI_FFNOMINALMAX)
  2067. {
  2068. hres = JoyReg_SetConfigValue(hk,
  2069. TEXT("Joystick%dFFConfiguration"),
  2070. idJoy, REG_SZ, 0, 0);
  2071. } else
  2072. {
  2073. hres = JoyReg_SetConfigValue(hk,
  2074. TEXT("Joystick%dFFConfiguration"),
  2075. idJoy, REG_BINARY,
  2076. &pcfg->dwGain, cbX(pcfg->dwGain));
  2077. }
  2078. if (FAILED(hres))
  2079. {
  2080. hres = S_FALSE;
  2081. goto closedone;
  2082. }
  2083. } else
  2084. {
  2085. RPF("ERROR: SetConfig: Invalid dwGain");
  2086. hres = E_INVALIDARG;
  2087. goto closedone;
  2088. }
  2089. }
  2090. hres = S_OK;
  2091. closedone:;
  2092. RegCloseKey(hk);
  2093. }
  2094. } else
  2095. {
  2096. hres = S_OK;
  2097. }
  2098. } else
  2099. {
  2100. hres = E_FAIL;
  2101. }
  2102. ExitOleProc();
  2103. return hres;
  2104. }
  2105. /*****************************************************************************
  2106. *
  2107. * @doc INTERNAL
  2108. *
  2109. * @func int | ibJoyPosAxis |
  2110. *
  2111. * Returns the offset of the <p iAxis>'th joystick axis
  2112. * in the <t JOYPOS> structure.
  2113. *
  2114. * @parm int | iAxis |
  2115. *
  2116. * The index of the requested axis. X, Y, Z, R, U and V are
  2117. * respctively zero through five.
  2118. *
  2119. * @returns
  2120. *
  2121. * The offset relative to the structure.
  2122. *
  2123. *****************************************************************************/
  2124. #define ibJoyPosAxis(iAxis) \
  2125. (FIELD_OFFSET(JOYPOS, dwX) + cbX(DWORD) * (iAxis)) \
  2126. #define pJoyValue(jp, i) \
  2127. (LPDWORD)pvAddPvCb(&(jp), ibJoyPosAxis(i)) \
  2128. /*
  2129. * The following doesn't do anything at runtime. It is a compile-time
  2130. * check that everything is okay.
  2131. */
  2132. void INLINE
  2133. JoyReg_CheckJoyPosAxis(void)
  2134. {
  2135. #define CheckAxis(x) \
  2136. CAssertF(ibJoyPosAxis(iJoyPosAxis##x) == FIELD_OFFSET(JOYPOS, dw##x))
  2137. CheckAxis(X);
  2138. CheckAxis(Y);
  2139. CheckAxis(Z);
  2140. CheckAxis(R);
  2141. CheckAxis(U);
  2142. CheckAxis(V);
  2143. #undef CheckAxis
  2144. }
  2145. /*****************************************************************************
  2146. *
  2147. * @doc INTERNAL
  2148. *
  2149. * @func HRESULT | JoyReg_IsValidUserValues |
  2150. *
  2151. * Retermine whether the values are ostensibly valid.
  2152. *
  2153. * @parm IN LPCDIJOYUSERVALUES | pjuv |
  2154. *
  2155. * Contains information about the user joystick configuration.
  2156. *
  2157. * @returns
  2158. *
  2159. * Returns a COM error code. The following error codes are
  2160. * intended to be illustrative and not necessarily comprehensive.
  2161. *
  2162. * <c DI_OK> = <c S_OK>: The operation completed successfully.
  2163. *
  2164. * <c DIERR_INVALIDPARAM> = <c E_INVALIDARG>:
  2165. * Something looks bad.
  2166. *
  2167. *****************************************************************************/
  2168. STDMETHODIMP
  2169. JoyReg_IsValidUserValues(LPCDIJOYUSERVALUES pjuv)
  2170. {
  2171. HRESULT hres;
  2172. int iAxis;
  2173. /*
  2174. * First set up the values to values that are out of range so
  2175. * that we will fall back to defaults.
  2176. */
  2177. for (iAxis = 0; iAxis < cJoyPosAxisMax; iAxis++)
  2178. {
  2179. if ((int)*pJoyValue(pjuv->ruv.jrvRanges.jpMax, iAxis) < 0)
  2180. {
  2181. RPF("JOYUSERVALUES: Negative jpMax not a good idea");
  2182. goto bad;
  2183. }
  2184. if (*pJoyValue(pjuv->ruv.jrvRanges.jpMin, iAxis) >
  2185. *pJoyValue(pjuv->ruv.jrvRanges.jpMax, iAxis))
  2186. {
  2187. RPF("JOYUSERVALUES: Min > Max not a good idea");
  2188. goto bad;
  2189. }
  2190. if (!fInOrder(0, *pJoyValue(pjuv->ruv.jpDeadZone, iAxis), 100))
  2191. {
  2192. RPF("JOYUSERVALUES: DeadZone > 100 not a good idea");
  2193. goto bad;
  2194. }
  2195. }
  2196. hres = S_OK;
  2197. return hres;
  2198. bad:;
  2199. hres = E_INVALIDARG;
  2200. return hres;
  2201. }
  2202. /*****************************************************************************
  2203. *
  2204. * @doc INTERNAL
  2205. *
  2206. * @func HRESULT | JoyReg_GetUserValues |
  2207. *
  2208. * Obtain information about user settings for the joystick.
  2209. *
  2210. *
  2211. * @parm IN OUT LPDIJOYUSERVALUES | pjuv |
  2212. *
  2213. * Receives information about the user joystick configuration.
  2214. * The caller is assumed to have validated the
  2215. * <e DIJOYUSERVALUES.dwSize> field.
  2216. *
  2217. * @parm DWORD | fl |
  2218. *
  2219. * Zero or more <c DIJU_*> flags specifying which parts
  2220. * of the <t DIJOYUSERVALUES> structure contain values
  2221. * which are to be retrieved.
  2222. *
  2223. * @returns
  2224. *
  2225. * Returns a COM error code. The following error codes are
  2226. * intended to be illustrative and not necessarily comprehensive.
  2227. *
  2228. * <c DI_OK> = <c S_OK>: The operation completed successfully.
  2229. *
  2230. * <c DIERR_INVALIDPARAM> = <c E_INVALIDARG>: One or more
  2231. * parameters was invalid.
  2232. *
  2233. *****************************************************************************/
  2234. STDMETHODIMP
  2235. JoyReg_GetUserValues(LPDIJOYUSERVALUES pjuv, DWORD fl)
  2236. {
  2237. HRESULT hres;
  2238. HKEY hk;
  2239. LONG lRc;
  2240. EnterProc(JoyReg_GetUserValues, (_ "px", pjuv, fl));
  2241. hres = S_OK; /* If nothing happens, then success */
  2242. if (fl & DIJU_USERVALUES)
  2243. {
  2244. /*
  2245. * Okay, now get the user settings.
  2246. *
  2247. * If anything goes wrong, then just limp with the default values.
  2248. */
  2249. lRc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_JOYCONFIG,
  2250. 0, KEY_QUERY_VALUE, &hk);
  2251. if (lRc == ERROR_SUCCESS)
  2252. {
  2253. hres = JoyReg_GetValue(hk, REGSTR_VAL_JOYUSERVALUES,
  2254. REG_BINARY, &pjuv->ruv, cbX(pjuv->ruv));
  2255. if (SUCCEEDED(hres))
  2256. {
  2257. /*
  2258. * Sanity-check the values. If anything is screwy,
  2259. * then fall back to the defaults.
  2260. */
  2261. hres = JoyReg_IsValidUserValues(pjuv);
  2262. }
  2263. if (FAILED(hres))
  2264. {
  2265. /*
  2266. * Oh well. Just use the default values, then.
  2267. *
  2268. * Stolen from ibmjoy\msjstick.c.
  2269. */
  2270. ZeroMemory(&pjuv->ruv, cbX(pjuv->ruv));
  2271. #define DEFAULT_RANGE_MAX 65535
  2272. #define DEFAULT_TIMEOUT 5000
  2273. #define DEFAULT_DEADZONE 5
  2274. pjuv->ruv.jrvRanges.jpMax.dwX = DEFAULT_RANGE_MAX;
  2275. pjuv->ruv.jrvRanges.jpMax.dwY = DEFAULT_RANGE_MAX;
  2276. pjuv->ruv.jrvRanges.jpMax.dwZ = DEFAULT_RANGE_MAX;
  2277. pjuv->ruv.jrvRanges.jpMax.dwR = DEFAULT_RANGE_MAX;
  2278. pjuv->ruv.jrvRanges.jpMax.dwU = DEFAULT_RANGE_MAX;
  2279. pjuv->ruv.jrvRanges.jpMax.dwV = DEFAULT_RANGE_MAX;
  2280. pjuv->ruv.jpDeadZone.dwX = DEFAULT_DEADZONE;
  2281. pjuv->ruv.jpDeadZone.dwY = DEFAULT_DEADZONE;
  2282. pjuv->ruv.dwTimeOut = DEFAULT_TIMEOUT;
  2283. }
  2284. RegCloseKey(hk);
  2285. }
  2286. }
  2287. if (fl & DIJU_INDRIVERREGISTRY)
  2288. {
  2289. hres = JoyReg_OpenConfigKey((UINT)-1, KEY_QUERY_VALUE, FALSE, &hk);
  2290. if (SUCCEEDED(hres))
  2291. {
  2292. if (fl & DIJU_GLOBALDRIVER)
  2293. {
  2294. /*
  2295. * If it doesn't work, then return the default value
  2296. * of "MSANALOG.VXD". We can't blindly use
  2297. * JoyReg_GetValue, because that treats a nonexistent
  2298. * value as having a default of the null string.
  2299. */
  2300. lRc = RegQueryValueEx(hk, REGSTR_VAL_JOYOEMCALLOUT,
  2301. 0, 0, 0, 0);
  2302. if ((lRc == ERROR_SUCCESS || lRc == ERROR_MORE_DATA) &&
  2303. SUCCEEDED(
  2304. hres = JoyReg_GetValue(hk, REGSTR_VAL_JOYOEMCALLOUT,
  2305. REG_SZ, pjuv->wszGlobalDriver,
  2306. cbX(pjuv->wszGlobalDriver))))
  2307. {
  2308. /* Yay, it worked */
  2309. } else
  2310. {
  2311. CopyMemory(pjuv->wszGlobalDriver,
  2312. c_wszDefPortDriver,
  2313. cbX(c_wszDefPortDriver));
  2314. }
  2315. }
  2316. if (fl & DIJU_GAMEPORTEMULATOR)
  2317. {
  2318. /*
  2319. * If it doesn't work, then just return a null string.
  2320. */
  2321. hres = JoyReg_GetValue(hk, REGSTR_VAL_JOYGAMEPORTEMULATOR,
  2322. REG_SZ, pjuv->wszGameportEmulator,
  2323. cbX(pjuv->wszGameportEmulator));
  2324. if (FAILED(hres))
  2325. {
  2326. pjuv->wszGameportEmulator[0] = TEXT('\0');
  2327. }
  2328. }
  2329. RegCloseKey(hk);
  2330. }
  2331. }
  2332. /*
  2333. * Warning! CJoy_InitRanges() assumes this never fails.
  2334. */
  2335. hres = S_OK;
  2336. ExitOleProcR();
  2337. return hres;
  2338. }
  2339. /*****************************************************************************
  2340. *
  2341. * @doc INTERNAL
  2342. *
  2343. * @func HRESULT | JoyReg_SetUserValues |
  2344. *
  2345. * Store information about user settings for the joystick.
  2346. *
  2347. *
  2348. * @parm IN LPCDIJOYUSERVALUES | pjuv |
  2349. *
  2350. * Contains information about the user joystick configuration.
  2351. * The caller is assumed to have validated the
  2352. * <e DIJOYUSERVALUES.dwSize> field.
  2353. *
  2354. * @parm DWORD | fl |
  2355. *
  2356. * Zero or more <c DIJU_*> flags specifying which parts
  2357. * of the <t DIJOYUSERVALUES> structure contain values
  2358. * which are to be set.
  2359. *
  2360. * @returns
  2361. *
  2362. * Returns a COM error code. The following error codes are
  2363. * intended to be illustrative and not necessarily comprehensive.
  2364. *
  2365. * <c DI_OK> = <c S_OK>: The operation completed successfully.
  2366. *
  2367. * <c DIERR_INVALIDPARAM> = <c E_INVALIDARG>: One or more
  2368. * parameters was invalid.
  2369. *
  2370. *****************************************************************************/
  2371. STDMETHODIMP
  2372. JoyReg_SetUserValues(LPCDIJOYUSERVALUES pjuv, DWORD fl)
  2373. {
  2374. HRESULT hres = E_FAIL;
  2375. HKEY hk;
  2376. EnterProc(JoyReg_SetUserValues, (_ "px", pjuv, fl));
  2377. if (fl & DIJU_USERVALUES)
  2378. {
  2379. /*
  2380. * See if the values are sane.
  2381. */
  2382. if (fl & DIJU_USERVALUES)
  2383. {
  2384. hres = JoyReg_IsValidUserValues(pjuv);
  2385. if (FAILED(hres))
  2386. {
  2387. goto done;
  2388. }
  2389. }
  2390. /*
  2391. * Off to the registry we go.
  2392. */
  2393. hres = hresMumbleKeyEx(HKEY_LOCAL_MACHINE,
  2394. REGSTR_PATH_JOYCONFIG,
  2395. DI_KEY_ALL_ACCESS,
  2396. REG_OPTION_NON_VOLATILE,
  2397. &hk);
  2398. if (SUCCEEDED(hres))
  2399. {
  2400. hres = JoyReg_SetValue(hk, REGSTR_VAL_JOYUSERVALUES,
  2401. REG_BINARY, &pjuv->ruv,
  2402. cbX(pjuv->ruv));
  2403. RegCloseKey(hk);
  2404. if (FAILED(hres))
  2405. {
  2406. goto done;
  2407. }
  2408. } else
  2409. {
  2410. goto done;
  2411. }
  2412. }
  2413. if (fl & DIJU_INDRIVERREGISTRY)
  2414. {
  2415. hres = JoyReg_OpenConfigKey((UINT)-1, KEY_SET_VALUE, FALSE, &hk);
  2416. if (SUCCEEDED(hres))
  2417. {
  2418. if (fl & DIJU_GLOBALDRIVER)
  2419. {
  2420. /*
  2421. * This is a weird key. The default value is
  2422. * "MSANALOG.VXD", so if we get a null string, we
  2423. * can't use JoyReg_SetValue, because that will
  2424. * delete the key.
  2425. */
  2426. if (pjuv->wszGlobalDriver[0])
  2427. {
  2428. hres = JoyReg_SetValue(hk, REGSTR_VAL_JOYOEMCALLOUT,
  2429. REG_SZ, pjuv->wszGlobalDriver,
  2430. cbX(pjuv->wszGlobalDriver));
  2431. } else
  2432. {
  2433. LONG lRc;
  2434. lRc = RegSetValueEx(hk, REGSTR_VAL_JOYOEMCALLOUT, 0,
  2435. REG_SZ, (PV)TEXT(""), cbCtch(1));
  2436. if (lRc == ERROR_SUCCESS)
  2437. {
  2438. hres = S_OK;
  2439. } else
  2440. {
  2441. RPF("Unable to write %s to registry",
  2442. REGSTR_VAL_JOYOEMCALLOUT);
  2443. hres = E_FAIL; /* Else, something bad happened */
  2444. }
  2445. }
  2446. if (FAILED(hres))
  2447. {
  2448. goto regdone;
  2449. }
  2450. }
  2451. if (fl & DIJU_GAMEPORTEMULATOR)
  2452. {
  2453. hres = JoyReg_SetValue(hk, REGSTR_VAL_JOYGAMEPORTEMULATOR,
  2454. REG_SZ, pjuv->wszGameportEmulator,
  2455. cbX(pjuv->wszGameportEmulator));
  2456. if (FAILED(hres))
  2457. {
  2458. goto regdone;
  2459. }
  2460. }
  2461. regdone:;
  2462. RegCloseKey(hk);
  2463. } else
  2464. {
  2465. goto done;
  2466. }
  2467. }
  2468. done:;
  2469. ExitOleProcR();
  2470. return hres;
  2471. }
  2472. /*****************************************************************************
  2473. *
  2474. * @doc INTERNAL
  2475. *
  2476. * @func HRESULT | JoyReg_OpenFFKey |
  2477. *
  2478. * Given a type key, move to its force feedback subkey.
  2479. *
  2480. * @parm HKEY | hkType |
  2481. *
  2482. * The parent type key.
  2483. *
  2484. * @parm REGSAM | sam |
  2485. *
  2486. * Access level desired.
  2487. *
  2488. * @parm PHKEY | phk |
  2489. *
  2490. * Receives created registry key.
  2491. *
  2492. * @returns
  2493. *
  2494. * Returns a COM error code. The following error codes are
  2495. * intended to be illustrative and not necessarily comprehensive.
  2496. *
  2497. * <c DI_OK> = <c S_OK>: The operation completed successfully.
  2498. *
  2499. * <c DIERR_NOTFOUND>: Couldn't open the key.
  2500. *
  2501. *****************************************************************************/
  2502. STDMETHODIMP
  2503. JoyReg_OpenFFKey(HKEY hkType, REGSAM sam, PHKEY phk)
  2504. {
  2505. HRESULT hres;
  2506. EnterProc(JoyReg_OpenFFKey, (_ "xx", hkType, sam));
  2507. *phk = 0;
  2508. if (hkType)
  2509. {
  2510. if (RegOpenKeyEx(hkType, TEXT("OEMForceFeedback"), 0, sam, phk) == 0)
  2511. {
  2512. hres = S_OK;
  2513. } else
  2514. {
  2515. hres = E_FAIL;
  2516. }
  2517. } else
  2518. {
  2519. hres = DIERR_NOTFOUND;
  2520. }
  2521. ExitBenignOleProc();
  2522. return hres;
  2523. }
  2524. /*****************************************************************************
  2525. *
  2526. * @doc INTERNAL
  2527. *
  2528. * @func TCHAR | CJoyCfg_CharFromType |
  2529. *
  2530. * Convert a predefined type number to a character.
  2531. *
  2532. * @func UINT | CJoyCfg_TypeFromChar |
  2533. *
  2534. * Convert a character back to a predefined type number.
  2535. *
  2536. *****************************************************************************/
  2537. #define JoyCfg_CharFromType(t) ((TCHAR)(L'0' + t))
  2538. #define JoyCfg_TypeFromChar(tch) ((tch) - L'0')
  2539. /*****************************************************************************
  2540. *
  2541. * @doc EXTERNAL
  2542. *
  2543. * @func HRESULT | JoyReg_GetPredefTypeInfo |
  2544. *
  2545. * Obtain information about a predefined joystick type.
  2546. *
  2547. * @parm LPCWSTR | pwszType |
  2548. *
  2549. * Points to the name of the type. It is known to begin
  2550. * with a "#". The remainder has not yet been parsed.
  2551. *
  2552. * @parm IN OUT LPDIJOYTYPEINFO | pjti |
  2553. *
  2554. * Receives information about the joystick type,
  2555. * already validated.
  2556. *
  2557. * @parm DWORD | dwFlags |
  2558. *
  2559. * Zero or more <c DITC_*> flags
  2560. * which specify which parts of the structure pointed
  2561. * to by <p pjti> are to be filled in.
  2562. *
  2563. * @returns
  2564. *
  2565. * Returns a COM error code. The following error codes are
  2566. * intended to be illustrative and not necessarily comprehensive.
  2567. *
  2568. * <c DI_OK> = <c S_OK>: The operation completed successfully.
  2569. *
  2570. * <c DIERR_NOTFOUND>: The joystick type was not found.
  2571. *
  2572. *****************************************************************************/
  2573. HRESULT EXTERNAL
  2574. JoyReg_GetPredefTypeInfo(LPCWSTR pwszType, LPDIJOYTYPEINFO pjti, DWORD fl)
  2575. {
  2576. HRESULT hres;
  2577. UINT itype;
  2578. EnterProcI(JoyReg_GetPredefTypeInfo, (_ "Wpx", pwszType, pjti, fl));
  2579. AssertF(pwszType[0] == L'#');
  2580. itype = JoyCfg_TypeFromChar(pwszType[1]);
  2581. if (fInOrder(JOY_HW_PREDEFMIN, itype, JOY_HW_PREDEFMAX) &&
  2582. pwszType[2] == L'\0')
  2583. {
  2584. /*
  2585. * No real point in checking the bits in fl, since
  2586. * setting it up is so easy.
  2587. */
  2588. pjti->hws = c_rghwsPredef[itype - JOY_HW_PREDEFMIN];
  2589. LoadStringW(g_hinst, IDS_PREDEFJOYTYPE + itype,
  2590. pjti->wszDisplayName, cA(pjti->wszDisplayName));
  2591. pjti->wszCallout[0] = L'\0';
  2592. ZeroX(pjti->clsidConfig);
  2593. pjti->dwFlags1 = 0x0;
  2594. if ( fl & DITC_HARDWAREID )
  2595. {
  2596. lstrcpyW(pjti->wszHardwareId, c_rghwIdPredef[itype-JOY_HW_PREDEFMIN] );
  2597. }
  2598. pjti->dwFlags2 = 0x0;
  2599. pjti->wszMapFile[0] = L'\0';
  2600. hres = S_OK;
  2601. } else
  2602. {
  2603. hres = DIERR_NOTFOUND;
  2604. }
  2605. ExitOleProc();
  2606. return hres;
  2607. }
  2608. #if 0 //don't delete it now.
  2609. /*****************************************************************************
  2610. *
  2611. * @doc INTERNAL
  2612. *
  2613. * @func HRESULT | JoyCfg_GetIDByOemName |
  2614. *
  2615. * Get the Id by OEMNAME
  2616. *
  2617. * @parm IN LPTSTR | szOEMNAME |
  2618. *
  2619. * String used to find the ID.
  2620. *
  2621. * @parm IN LPUNIT | lpID |
  2622. *
  2623. * The ID to get.
  2624. *
  2625. * @returns
  2626. *
  2627. * A COM success code unless the current configuration key could not
  2628. * be opened, or could not find the OEMNAME.
  2629. *
  2630. *****************************************************************************/
  2631. HRESULT EXTERNAL JoyReg_GetIDByOemName( LPTSTR szOemName, PUINT pId )
  2632. {
  2633. HRESULT hres = E_FAIL;
  2634. LONG lRc;
  2635. HKEY hkCurrCfg;
  2636. UINT JoyId;
  2637. TCHAR szTestName[MAX_JOYSTRING];
  2638. TCHAR szOemNameKey[MAX_JOYSTRING];
  2639. DWORD cb;
  2640. EnterProcI(JoyReg_GetIDByOemName, (_ "sp", szOemName, pId ));
  2641. hres = JoyReg_OpenConfigKey( (UINT)(-1), KEY_WRITE, REG_OPTION_NON_VOLATILE, &hkCurrCfg );
  2642. if ( SUCCEEDED( hres ) )
  2643. {
  2644. for ( JoyId = 0; (JoyId < 16) || ( lRc == ERROR_SUCCESS ); JoyId++ )
  2645. {
  2646. wsprintf( szOemNameKey, REGSTR_VAL_JOYNOEMNAME, JoyId+1 );
  2647. cb = sizeof( szTestName );
  2648. lRc = RegQueryValueEx( hkCurrCfg, szOemNameKey, 0, NULL, (PBYTE)szTestName, &cb );
  2649. if ( lRc == ERROR_SUCCESS )
  2650. {
  2651. if ( !lstrcmpi( szOemName, szTestName ) )
  2652. {
  2653. *pId = JoyId;
  2654. pId ++;
  2655. hres = S_OK;
  2656. break;
  2657. }
  2658. }
  2659. }
  2660. } else
  2661. {
  2662. SquirtSqflPtszV(sqfl | sqflError,
  2663. TEXT("JoyReg_OpenConfigKey failed code 0x%08x"), hres );
  2664. }
  2665. ExitOleProc();
  2666. return hres;
  2667. } /* JoyReg_GetIDByOemName */
  2668. #endif