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.

491 lines
15 KiB

  1. /*****************************************************************************
  2. *
  3. * DIJoyTyp.c
  4. *
  5. * Copyright (c) 1996 Microsoft Corporation. All Rights Reserved.
  6. *
  7. * Abstract:
  8. *
  9. * Functions that pull data out of the joystick type key
  10. * (wherever it is).
  11. *
  12. * Contents:
  13. *
  14. * ?
  15. *
  16. *****************************************************************************/
  17. #include "dinputpr.h"
  18. /*****************************************************************************
  19. *
  20. * The sqiffle for this file.
  21. *
  22. *****************************************************************************/
  23. #define sqfl sqflJoyType
  24. /*****************************************************************************
  25. *
  26. * @doc INTERNAL
  27. *
  28. * @func HRESULT | CType_OpenIdSubkey |
  29. *
  30. * Given an object ID, attempt to open the subkey that
  31. * corresponds to it for reading.
  32. *
  33. * @parm HKEY | hkType |
  34. *
  35. * The joystick type key, possibly <c NULL> if we don't
  36. * have a type key. (For example, if it was never created.)
  37. *
  38. * @parm DWORD | dwId |
  39. *
  40. * Object id.
  41. *
  42. * @parm REGSAM | regsam |
  43. *
  44. * Registry security access mask.
  45. *
  46. * @parm PHKEY | phk |
  47. *
  48. * Receives the object key on success.
  49. *
  50. * @returns
  51. *
  52. * Returns a COM error code.
  53. *
  54. *****************************************************************************/
  55. STDMETHODIMP
  56. CType_OpenIdSubkey(HKEY hkType, DWORD dwId, REGSAM sam, PHKEY phk)
  57. {
  58. HRESULT hres;
  59. EnterProc(CType_OpenIdSubkey, (_ "xx", hkType, dwId));
  60. *phk = 0;
  61. if(hkType)
  62. {
  63. /*
  64. * Worst case is "Actuators\65535" which has length 15.
  65. */
  66. TCHAR tsz[32];
  67. LPCTSTR ptszType;
  68. if(dwId & DIDFT_AXIS)
  69. {
  70. ptszType = TEXT("Axes");
  71. } else if(dwId & DIDFT_BUTTON)
  72. {
  73. ptszType = TEXT("Buttons");
  74. } else if(dwId & DIDFT_POV)
  75. {
  76. ptszType = TEXT("POVs");
  77. } else if(dwId & DIDFT_NODATA)
  78. {
  79. ptszType = TEXT("Actuators");
  80. } else
  81. {
  82. hres = E_NOTIMPL;
  83. goto done;
  84. }
  85. // ISSUE-2001/03/29-timgill Need to scale back for pos vs state
  86. // MarcAnd -- I believe this means: if you're trying to
  87. // look for the X axis, we should use the position
  88. // instance, not the velocity one.
  89. wsprintf(tsz, TEXT("%s\\%u"), ptszType, DIDFT_GETINSTANCE(dwId));
  90. hres = hresMumbleKeyEx(hkType, tsz, sam, REG_OPTION_NON_VOLATILE, phk);
  91. } else
  92. {
  93. hres = DIERR_NOTFOUND;
  94. }
  95. done:;
  96. if(hres == DIERR_NOTFOUND)
  97. {
  98. ExitBenignOleProcPpv(phk);
  99. } else
  100. {
  101. ExitOleProcPpv(phk);
  102. }
  103. return hres;
  104. }
  105. /*****************************************************************************
  106. *
  107. * @doc INTERNAL
  108. *
  109. * @func void | CType_RegGetObjectInfo |
  110. *
  111. * Given an object ID, look into the registry subkey for the
  112. * object and extract anything we can find.
  113. *
  114. * If we find nothing, then do nothing.
  115. *
  116. * @parm HKEY | hkType |
  117. *
  118. * The joystick type key, possibly <c NULL> if we don't
  119. * have a type key. (For example, if it was never created.)
  120. *
  121. * @parm DWORD | dwId |
  122. *
  123. * Object id.
  124. *
  125. * @parm LPDIDEVICEOBJECTINSTANCEW | pdidoiW |
  126. *
  127. * Structure to receive information. The
  128. * <e DIDEVICEOBJECTINSTANCE.guidType>,
  129. * <e DIDEVICEOBJECTINSTANCE.dwOfs>,
  130. * and
  131. * <e DIDEVICEOBJECTINSTANCE.dwType>
  132. * <e DIDEVICEOBJECTINSTANCE.dwFlags>
  133. * fields have already been filled in so we should only not override
  134. * these with default data.
  135. *
  136. *****************************************************************************/
  137. void EXTERNAL
  138. CType_RegGetObjectInfo(HKEY hkType, DWORD dwId,
  139. LPDIDEVICEOBJECTINSTANCEW pdidoiW)
  140. {
  141. HRESULT hres;
  142. HKEY hk;
  143. EnterProc(CType_RegKeyObjectInfo, (_ "xx", hkType, dwId));
  144. /*
  145. * Extract information about this item from the registry.
  146. */
  147. hres = CType_OpenIdSubkey(hkType, dwId, KEY_QUERY_VALUE, &hk);
  148. if(SUCCEEDED(hres))
  149. {
  150. DIOBJECTATTRIBUTES attr;
  151. /*
  152. * Read the regular and HID attributes.
  153. */
  154. hres = JoyReg_GetValue(hk, TEXT("Attributes"),
  155. REG_BINARY, &attr,
  156. cbX(attr));
  157. if(SUCCEEDED(hres))
  158. {
  159. /*
  160. * Copy the bit fields.
  161. * PREFIX warns (333540) that attr.dwFlags is not initialized
  162. * however JoyReg_GetValue zeroes any part of the buffer after
  163. * the bytes read from the registry if the buffer size is larger
  164. * than what was read.
  165. */
  166. pdidoiW->dwFlags |= (attr.dwFlags & ~DIDOI_ASPECTMASK);
  167. /*
  168. * Don't add FF if the dwId did not have it.
  169. * (See comment on FF attrs below for why.)
  170. */
  171. if( ( dwId & ( DIDFT_FFEFFECTTRIGGER | DIDFT_FFACTUATOR ) ) == 0 )
  172. {
  173. pdidoiW->dwFlags &= ~( DIDOI_FFACTUATOR | DIDOI_FFEFFECTTRIGGER );
  174. }
  175. /*
  176. * Copy the aspect, but don't change
  177. * the aspect from "known" to "unknown". If the
  178. * registry doesn't have an aspect, then use the
  179. * aspect we got from the caller.
  180. */
  181. if((attr.dwFlags & DIDOI_ASPECTMASK) != DIDOI_ASPECTUNKNOWN)
  182. {
  183. pdidoiW->dwFlags = (pdidoiW->dwFlags & ~DIDOI_ASPECTMASK) |
  184. (attr.dwFlags & DIDOI_ASPECTMASK);
  185. }
  186. }
  187. /*
  188. * If the caller wants force feedback info,
  189. * then get it.
  190. */
  191. if(pdidoiW->dwSize >= cbX(DIDEVICEOBJECTINSTANCE_DX5W))
  192. {
  193. /*
  194. * Only copy the usages if they are valid.
  195. * JoyReg_GetValue zeros any buffer beyond what is read.
  196. */
  197. if(SUCCEEDED(hres) && attr.wUsagePage && attr.wUsage )
  198. {
  199. pdidoiW->wUsagePage = attr.wUsagePage;
  200. pdidoiW->wUsage = attr.wUsage;
  201. }
  202. /*
  203. * Only try to read the FF attributes if the object supports FF
  204. * This may save time but is primarily to allow us to ignore FF
  205. * attributes in the registry for objects (such as FF driving
  206. * controller pedals) which IHVs mark incorrectly.
  207. */
  208. if( dwId & ( DIDFT_FFEFFECTTRIGGER | DIDFT_FFACTUATOR ) )
  209. {
  210. /*
  211. * Assert that we can read the DIFFOBJECTATTRIBUTES
  212. * directly into the DIDEVICEOBJECTINSTANCE_DX5.
  213. */
  214. CAssertF(FIELD_OFFSET(DIFFOBJECTATTRIBUTES,
  215. dwFFMaxForce) == 0);
  216. CAssertF(FIELD_OFFSET(DIFFOBJECTATTRIBUTES,
  217. dwFFForceResolution) == 4);
  218. CAssertF(FIELD_OFFSET(DIDEVICEOBJECTINSTANCE_DX5,
  219. dwFFMaxForce) + 4 ==
  220. FIELD_OFFSET(DIDEVICEOBJECTINSTANCE_DX5,
  221. dwFFForceResolution));
  222. CAssertF(cbX(DIFFOBJECTATTRIBUTES) == 8);
  223. /*
  224. * If this doesn't work, gee that's too bad.
  225. * JoyReg_GetValue will zero-fill the error parts.
  226. */
  227. JoyReg_GetValue(hk, TEXT("FFAttributes"),
  228. REG_BINARY, &pdidoiW->dwFFMaxForce,
  229. cbX(DIFFOBJECTATTRIBUTES));
  230. }
  231. else
  232. {
  233. AssertF( ( pdidoiW->dwFFMaxForce | pdidoiW->dwFFForceResolution ) == 0 );
  234. }
  235. }
  236. /*
  237. * Read the optional custom name.
  238. *
  239. * Note that JoyReg_GetValue(REG_SZ) uses
  240. * RegQueryStringValueW, which sets the
  241. * string to null on error so we don't have to.
  242. */
  243. hres = JoyReg_GetValue(hk, 0, REG_SZ,
  244. pdidoiW->tszName, cbX(pdidoiW->tszName));
  245. if(SUCCEEDED(hres))
  246. {
  247. } else
  248. {
  249. AssertF(pdidoiW->tszName[0] == L'\0');
  250. }
  251. RegCloseKey(hk);
  252. } else
  253. {
  254. AssertF(pdidoiW->tszName[0] == L'\0');
  255. }
  256. }
  257. /*****************************************************************************
  258. *
  259. * @doc INTERNAL
  260. *
  261. * @func void | CType_RegGetTypeInfo |
  262. *
  263. * Given an object ID, look into the registry subkey for the
  264. * object and extract attribute bits that should be OR'd
  265. * into the object ID.
  266. *
  267. * This needs to be done during device initialization to
  268. * establish the attributes in the data format so that
  269. *
  270. * 1. <mf IDirectInputDevice::EnumObjects> filters properly, and
  271. *
  272. * 2. >mf IDirectInputEffect::SetParameters> can validate properly.
  273. *
  274. * @parm HKEY | hkType |
  275. *
  276. * The joystick type key, possibly <c NULL> if we don't
  277. * have a type key. (For example, if it was never created.)
  278. *
  279. * @parm LPDIOBJECTDATAFORMAT | podf |
  280. *
  281. * Structure to receive more information. The
  282. * <e DIOBJECTDATAFORMAT.dwType> field identifies the object.
  283. *
  284. * On return the
  285. * <e DIOBJECTDATAFORMAT.dwType>
  286. * and
  287. * <e DIOBJECTDATAFORMAT.dwFlags>
  288. * fields are updated.
  289. *
  290. *****************************************************************************/
  291. void EXTERNAL
  292. CType_RegGetTypeInfo(HKEY hkType, LPDIOBJECTDATAFORMAT podf, BOOL fPidDevice)
  293. {
  294. HRESULT hres;
  295. HKEY hk;
  296. EnterProc(CType_RegKeyObjectInfo, (_ "xx", hkType, podf->dwType));
  297. hres = CType_OpenIdSubkey(hkType, podf->dwType, KEY_QUERY_VALUE, &hk);
  298. if(SUCCEEDED(hres))
  299. {
  300. DWORD dwFlags;
  301. CAssertF(FIELD_OFFSET(DIOBJECTATTRIBUTES, dwFlags) == 0);
  302. hres = JoyReg_GetValue(hk, TEXT("Attributes"),
  303. REG_BINARY, &dwFlags, cbX(dwFlags));
  304. if(SUCCEEDED(hres))
  305. {
  306. /*
  307. * Propagate the attributes into the type code.
  308. */
  309. CAssertF(DIDOI_FFACTUATOR == DIDFT_GETATTR(DIDFT_FFACTUATOR));
  310. CAssertF(DIDOI_FFEFFECTTRIGGER
  311. == DIDFT_GETATTR(DIDFT_FFEFFECTTRIGGER));
  312. /*
  313. * PREFIX warns (333539) that dwFlags is not initialized however
  314. * JoyReg_GetValue zeroes any part of the buffer after the bytes
  315. * read from the registry if the buffer size is larger than what
  316. * was read.
  317. */
  318. podf->dwType |= DIDFT_MAKEATTR(dwFlags);
  319. podf->dwFlags |= (dwFlags & ~DIDOI_ASPECTMASK);
  320. /*
  321. * Copy the aspect, but don't change
  322. * the aspect from "known" to "unknown". If the
  323. * registry doesn't have an aspect, then use the
  324. * aspect we got from the caller.
  325. */
  326. if((dwFlags & DIDOI_ASPECTMASK) != DIDOI_ASPECTUNKNOWN)
  327. {
  328. podf->dwFlags = (podf->dwFlags & ~DIDOI_ASPECTMASK) |
  329. (dwFlags & DIDOI_ASPECTMASK);
  330. }
  331. }
  332. RegCloseKey(hk);
  333. }else
  334. {
  335. #ifndef WINNT
  336. // Post Dx7Gold Patch
  337. // This is for Win9x only.
  338. // On Win9x, a device that is being accessed through the vjoyd path
  339. // will not get forces, as the attributes necessary for FF have not
  340. // been appropriately marked.
  341. // THe following code will mark the
  342. DWORD dwFlags = DIDFT_GETATTR( podf->dwType & ~DIDFT_ATTRMASK )
  343. | ( podf->dwFlags & ~DIDOI_ASPECTMASK);
  344. if( dwFlags != 0x0
  345. && fPidDevice )
  346. {
  347. hres = CType_OpenIdSubkey(hkType, podf->dwType, DI_KEY_ALL_ACCESS, &hk);
  348. if(SUCCEEDED(hres) )
  349. {
  350. hres = JoyReg_SetValue(hk, TEXT("Attributes"),
  351. REG_BINARY, &dwFlags, cbX(dwFlags));
  352. RegCloseKey(hk);
  353. }
  354. }
  355. #endif // ! WINNT
  356. }
  357. }
  358. /*****************************************************************************
  359. *
  360. * @doc INTERNAL
  361. *
  362. * @func void | CType_MakeGameCtrlName |
  363. *
  364. * Make a game controller name from the attributes of the controller.
  365. * Used as a last resort when a name is needed but none is available.
  366. *
  367. * @parm PWCHAR | wszName |
  368. *
  369. * Output buffer where name will be generated.
  370. *
  371. * @parm DWORD | dwType |
  372. *
  373. * DI8DEVTYPE value for the controller.
  374. *
  375. * @parm DWORD | dwAxes |
  376. *
  377. * The number of axes the device has.
  378. *
  379. * @parm DWORD | dwButtons |
  380. *
  381. * The numer of buttons the device has.
  382. *
  383. * @parm DWORD | dwPOVs |
  384. *
  385. * The number of POVs the device has.
  386. *
  387. *****************************************************************************/
  388. void EXTERNAL
  389. CType_MakeGameCtrlName
  390. (
  391. PWCHAR wszOutput,
  392. DWORD dwDevType,
  393. DWORD dwAxes,
  394. DWORD dwButtons,
  395. DWORD dwPOVs
  396. )
  397. {
  398. TCHAR tsz[64];
  399. TCHAR tszPOV[64];
  400. TCHAR tszFormat[64];
  401. #ifndef UNICODE
  402. TCHAR tszOut[cA(tsz)+cA(tszFormat)+cA(tszPOV)];
  403. #endif
  404. /* tszFormat = %d axis, %d button %s */
  405. LoadString(g_hinst, IDS_TEXT_TEMPLATE, tszFormat, cA(tszFormat));
  406. /* tsz = joystick, gamepad, etc. */
  407. if( ( GET_DIDEVICE_TYPE( dwDevType ) >= DI8DEVTYPE_JOYSTICK )
  408. && ( GET_DIDEVICE_TYPE( dwDevType ) <= DI8DEVTYPE_FLIGHT ) )
  409. {
  410. LoadString(g_hinst, GET_DIDEVICE_TYPE( dwDevType ) + IDS_PLAIN_STICK - DI8DEVTYPE_JOYSTICK,
  411. tsz, cA(tsz));
  412. }
  413. else if( GET_DIDEVICE_TYPEANDSUBTYPE( dwDevType )
  414. == MAKE_DIDEVICE_TYPE( DI8DEVTYPE_SUPPLEMENTAL, DI8DEVTYPESUPPLEMENTAL_HEADTRACKER ) )
  415. {
  416. LoadString(g_hinst, IDS_HEAD_TRACKER, tsz, cA(tsz));
  417. }
  418. else
  419. {
  420. LoadString(g_hinst, IDS_DEVICE_NAME, tsz, cA(tsz));
  421. }
  422. if( dwPOVs )
  423. {
  424. LoadString(g_hinst, IDS_WITH_POV, tszPOV, cA(tszPOV));
  425. }
  426. else
  427. {
  428. tszPOV[0] = TEXT( '\0' );
  429. }
  430. #ifdef UNICODE
  431. wsprintfW(wszOutput, tszFormat, dwAxes, dwButtons, tsz, tszPOV);
  432. #else
  433. wsprintfA(tszOut, tszFormat, dwAxes, dwButtons, tsz, tszPOV);
  434. TToU(wszOutput, cA(tszOut), tszOut);
  435. #endif
  436. }