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

1724 lines
52 KiB

  1. //===========================================================================
  2. // dmtinput.cpp
  3. //
  4. // DirectInput functionality
  5. //
  6. // Functions:
  7. //
  8. // History:
  9. // 08/30/1999 - davidkl - created
  10. //===========================================================================
  11. #include "dimaptst.h"
  12. #include "dmtinput.h"
  13. #include "dmttest.h"
  14. //---------------------------------------------------------------------------
  15. //===========================================================================
  16. // dmtinputCreateDeviceList
  17. //
  18. // Creates a linked list of DirectInputDevice8A objects. Either enumerates
  19. // suitable or all joystick/gamepad devices.
  20. //
  21. // NOTE: The actual work of adding a node to the list is performed by the
  22. // dmtinputEnumDevicesCallback() function. This function exists merely to
  23. // present a consistant look & feel with the rest of the list creation
  24. // functions used in this app.
  25. //
  26. // Parameters:
  27. //
  28. // Returns: HRESULT
  29. //
  30. // History:
  31. // 08/27/1999 - davidkl - created
  32. // 08/30/1999 - davidkl - moved & renamed
  33. // 10/26/1999 - davidkl - added axis range setting
  34. // 10/27/1999 - davidkl - house cleaning
  35. // 02/21/2000 - davidkl - added hwnd and call to dmtinputGetRegisteredMapFile
  36. //===========================================================================
  37. HRESULT dmtinputCreateDeviceList(HWND hwnd,
  38. BOOL fEnumSuitable,
  39. DMTSUBGENRE_NODE *pdmtsg,
  40. DMTDEVICE_NODE **ppdmtdList)
  41. {
  42. HRESULT hRes = S_OK;
  43. DWORD dwActions = 0;
  44. DWORD dwType = 0;
  45. DMTDEVICE_NODE *pDevice = NULL;
  46. DMTDEVICEOBJECT_NODE *pObject = NULL;
  47. DMTACTION_NODE *pAction = NULL;
  48. IDirectInput8A *pdi = NULL;
  49. DIACTIONA *pdia = NULL;
  50. DIACTIONFORMATA diaf;
  51. DIPROPRANGE dipr;
  52. // validate pdmtsg
  53. //
  54. // this only needs to be valid if fEnumSuitable == TRUE
  55. // if(fEnumSuitable)
  56. // {
  57. DPF(4, "dmtinputCreateDeviceList - Enumerating for "
  58. "suitable devices... validating pdmtsg");
  59. if(IsBadReadPtr((void*)pdmtsg, sizeof(DMTSUBGENRE_NODE)))
  60. {
  61. DPF(0, "dmtinputCreateDeviceList - invalid pdmtsg (%016Xh)",
  62. pdmtsg);
  63. return E_POINTER;
  64. }
  65. // }
  66. // validate ppdmtdList
  67. //
  68. // This validation will be performed by dmtinputEnumDevicesCallback
  69. __try
  70. {
  71. // create the dinput object
  72. hRes = dmtinputCreateDirectInput(ghinst,
  73. &pdi);
  74. if(FAILED(hRes))
  75. {
  76. DPF(0, "dmtinputCreateDeviceList - unable to create "
  77. "DirectInput object (%s == %08Xh)",
  78. dmtxlatHRESULT(hRes), hRes);
  79. hRes = DMT_E_INPUT_CREATE_FAILED;
  80. __leave;
  81. }
  82. // enumerate devices
  83. //
  84. // NOTE: this will create the linked list we want
  85. // however, it will not create the object list.
  86. // if(fEnumSuitable)
  87. // {
  88. // count the actions
  89. dwActions = 0;
  90. pAction = pdmtsg->pActionList;
  91. while(pAction)
  92. {
  93. dwActions++;
  94. pAction = pAction->pNext;
  95. }
  96. // allocate the diaction array
  97. pdia = (DIACTIONA*)LocalAlloc(LMEM_FIXED,
  98. dwActions * sizeof(DIACTIONA));
  99. if(!pdia)
  100. {
  101. DPF(0, "dmtinputCreateDeviceList - unable to allocate "
  102. "DIACTION array");
  103. hRes = E_OUTOFMEMORY;
  104. __leave;
  105. }
  106. // fill the array with ALL of the actions
  107. // for the selected subgenre
  108. hRes = dmtinputPopulateActionArray(pdia,
  109. (UINT)dwActions,
  110. pdmtsg->pActionList);
  111. if(FAILED(hRes))
  112. {
  113. DPF(0, "dmtinputCreateDeviceList - unable to populate "
  114. "DIACTION array (%s == %08Xh)",
  115. dmtxlatHRESULT(hRes), hRes);
  116. __leave;
  117. }
  118. // build the diactionformat structure
  119. ZeroMemory((void*)&diaf, sizeof(DIACTIONFORMATA));
  120. diaf.dwSize = sizeof(DIACTIONFORMATA);
  121. diaf.dwActionSize = sizeof(DIACTIONA);
  122. diaf.dwNumActions = dwActions;
  123. diaf.rgoAction = pdia;
  124. diaf.dwDataSize = 4 * diaf.dwNumActions;
  125. diaf.guidActionMap = GUID_DIMapTst;
  126. diaf.dwGenre = pdmtsg->dwGenreId;
  127. diaf.dwBufferSize = DMTINPUT_BUFFERSIZE;
  128. lstrcpyA(diaf.tszActionMap, DMT_APP_CAPTION);
  129. // now, enumerate for joystick devices
  130. /*
  131. hRes = pdi->EnumDevicesBySemantics((LPCSTR)NULL,
  132. &diaf,
  133. dmtinputEnumDevicesCallback,
  134. (void*)ppdmtdList,
  135. DIEDFL_ATTACHEDONLY);
  136. */
  137. // }
  138. // else
  139. // {
  140. DPF(0, "Calling EnumDevicesBySemantics");
  141. // hRes = pdi->EnumDevicesBySemantics("TestMe",
  142. hRes = pdi->EnumDevicesBySemantics((LPCSTR)NULL,
  143. &diaf,
  144. dmtinputEnumDevicesCallback,
  145. (void*)ppdmtdList,
  146. 0);//JJFix 34616//DIEDBSFL_ATTACHEDONLY);
  147. // }
  148. DPF(0, "Returned from EnumDevicesBySemantics");
  149. if(FAILED(hRes))
  150. {
  151. DPF(0, "dmtinputCreateDeviceList - Enum%sDevices "
  152. "failed (%s == %08Xh)",
  153. fEnumSuitable ? "Suitable" : "",
  154. dmtxlatHRESULT(hRes), hRes);
  155. __leave;
  156. }
  157. // the device enumeration function does not create
  158. // the object linked list, we will create it now
  159. //
  160. // steps to do this:
  161. // * walk the list. for each node:
  162. // ** call dmtinputCreateObjectList()
  163. pDevice = *ppdmtdList;
  164. while(pDevice)
  165. {
  166. // get a list of the device's objects
  167. hRes = dmtinputCreateObjectList(pDevice->pdid,
  168. pDevice->guidInstance,
  169. &(pDevice->pObjectList));
  170. if(FAILED(hRes))
  171. {
  172. DPF(0, "dmtinputCreateDeviceList - failed to create "
  173. "device %s object list (%s == %08Xh)",
  174. pDevice->szName,
  175. dmtxlatHRESULT(hRes), hRes);
  176. hRes = S_FALSE;
  177. }
  178. // get the registered map file name (if exists)
  179. // ISSUE-2001/03/29-timgill possible S_FALSE hResult from previous call is ignored
  180. // (previous call to dmtinputCreateObjectList)
  181. hRes = dmtinputGetRegisteredMapFile(hwnd,
  182. pDevice,
  183. pDevice->szFilename,
  184. sizeof(char) * MAX_PATH);
  185. if(FAILED(hRes))
  186. {
  187. DPF(0, "dmtinputCreateDeviceList - failed to retrieve "
  188. "device %s mapfile name (%s == %08Xh)",
  189. pDevice->szName,
  190. dmtxlatHRESULT(hRes), hRes);
  191. hRes = S_FALSE;
  192. }
  193. // next device
  194. pDevice = pDevice->pNext;
  195. }
  196. }
  197. __finally
  198. {
  199. // free the action array
  200. if(pdia)
  201. {
  202. if(LocalFree((HLOCAL)pdia))
  203. {
  204. // memory leak
  205. DPF(0, "dmtinputCreateDeviceList - MEMORY LEAK - pdia");
  206. pdia = NULL;
  207. }
  208. }
  209. // if something failed, cleanup the linked list
  210. if(FAILED(hRes))
  211. {
  212. dmtinputFreeDeviceList(ppdmtdList);
  213. }
  214. // we don't need the dinput object any more
  215. SAFE_RELEASE(pdi);
  216. }
  217. // done
  218. return hRes;
  219. } //*** end dmtinputCreateDeviceList()
  220. //===========================================================================
  221. // dmtinputFreeDeviceList
  222. //
  223. // Frees the linked list created by dmtinputCreateDeviceList
  224. //
  225. // Parameters:
  226. //
  227. // Returns: HRESULT
  228. //
  229. // History:
  230. // 08/27/1999 - davidkl - created
  231. // 08/30/1999 - davidkl - moved & renamed. added call to pdid->Release()
  232. //===========================================================================
  233. HRESULT dmtinputFreeDeviceList(DMTDEVICE_NODE **ppdmtdList)
  234. {
  235. HRESULT hRes = S_OK;
  236. DMTDEVICE_NODE *pNode = NULL;
  237. // validate ppdmtaList
  238. if(IsBadWritePtr((void*)ppdmtdList, sizeof(DMTDEVICE_NODE*)))
  239. {
  240. DPF(0, "dmtFreeDeviceList - Invalid ppdmtaList (%016Xh)",
  241. ppdmtdList);
  242. return E_POINTER;
  243. }
  244. // validate *ppdmtdList
  245. if(IsBadReadPtr((void*)*ppdmtdList, sizeof(DMTDEVICE_NODE)))
  246. {
  247. if(NULL != *ppdmtdList)
  248. {
  249. DPF(0, "dmtFreeDeviceList - Invalid *ppdmtdList (%016Xh)",
  250. *ppdmtdList);
  251. return E_POINTER;
  252. }
  253. else
  254. {
  255. // if NULL, then return "did nothing"
  256. DPF(3, "dmtFreeDeviceList - Nothing to do....");
  257. return S_FALSE;
  258. }
  259. }
  260. // walk the list and free each object
  261. while(*ppdmtdList)
  262. {
  263. pNode = *ppdmtdList;
  264. *ppdmtdList = (*ppdmtdList)->pNext;
  265. // free the object list first
  266. //
  267. // no need to check error results here..
  268. //
  269. // error reporting is handled in dmtinputFreeObjectList
  270. dmtinputFreeObjectList(&(pNode->pObjectList));
  271. // release the device object
  272. SAFE_RELEASE((pNode->pdid));
  273. // delete the node
  274. DPF(5, "dmtFreeDeviceList - deleting Node (%016Xh)", pNode);
  275. if(LocalFree((HLOCAL)pNode))
  276. {
  277. DPF(0, "dmtFreeDeviceList - MEMORY LEAK - "
  278. "LocalFree() failed (%d)...",
  279. GetLastError());
  280. hRes = DMT_S_MEMORYLEAK;
  281. }
  282. DPF(5, "dmtFreeDeviceList - Node deleted");
  283. }
  284. // make sure that we set *ppObjList to NULL
  285. *ppdmtdList = NULL;
  286. // done
  287. return hRes;
  288. } //*** end dmtinputFreeDeviceList()
  289. //===========================================================================
  290. // dmtinputCreateObjectList
  291. //
  292. // Creates a linked list of device's objects (axes, buttons, povs).
  293. //
  294. // Parameters:
  295. //
  296. // Returns: HRESULT
  297. //
  298. // History:
  299. // 08/30/1999 - davidkl - created
  300. // 09/01/1999 - dvaidkl - added pdid
  301. // 02/18/2000 - davidkl - fixed object enumeration to filter anything not
  302. // an axis, button or pov
  303. //===========================================================================
  304. HRESULT dmtinputCreateObjectList(IDirectInputDevice8A *pdid,
  305. GUID guidInstance,
  306. DMTDEVICEOBJECT_NODE **ppdmtoList)
  307. {
  308. HRESULT hRes = S_OK;
  309. DMTDEVICEOBJECT_NODE *pObject = NULL;
  310. // validate pdid
  311. if(IsBadReadPtr((void*)pdid, sizeof(IDirectInputDevice8A)))
  312. {
  313. DPF(0, "dmtinputCreateObjectList - invalid pdid (%016Xh)",
  314. pdid);
  315. return E_POINTER;
  316. }
  317. // validate ppdmtoList
  318. if(IsBadReadPtr((void*)ppdmtoList, sizeof(DMTDEVICEOBJECT_NODE*)))
  319. {
  320. DPF(0, "dmtinputCreateObjectList - invalid ppdmtoList (%016Xh)",
  321. ppdmtoList);
  322. return E_POINTER;
  323. }
  324. // validate guidInstance
  325. if(IsEqualGUID(GUID_NULL, guidInstance))
  326. {
  327. DPF(0, "dmtinputCreateObjectList - invalid guidInstance (GUID_NULL)");
  328. return E_INVALIDARG;
  329. }
  330. __try
  331. {
  332. // enumerate device objects
  333. //
  334. // NOTE: this call will create the linked list we want
  335. hRes = pdid->EnumObjects(dmtinputEnumDeviceObjectsCallback,
  336. (void*)ppdmtoList,
  337. DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV);
  338. if(FAILED(hRes))
  339. {
  340. __leave;
  341. }
  342. // walk the list and add the guidInstance of the device
  343. pObject = *ppdmtoList;
  344. while(pObject)
  345. {
  346. // copy the device's guidInstance
  347. pObject->guidDeviceInstance = guidInstance;
  348. // next object
  349. pObject = pObject->pNext;
  350. }
  351. }
  352. __finally
  353. {
  354. // if something failed, cleanup the linked list
  355. if(FAILED(hRes))
  356. {
  357. // ISSUE-2001/03/29-timgill Needs error case handling
  358. }
  359. }
  360. // done
  361. return hRes;
  362. } //*** end dmtinputCreateObjectList()
  363. //===========================================================================
  364. // dmtinputFreeObjectList
  365. //
  366. // Frees the linked list created by dmtinputCreateObjectList
  367. //
  368. // Parameters:
  369. //
  370. // Returns: HRESULT
  371. //
  372. // History:
  373. // 08/30/1999 - davidkl - created
  374. // 09/01/1999 - davidkl - implemented
  375. //===========================================================================
  376. HRESULT dmtinputFreeObjectList(DMTDEVICEOBJECT_NODE **ppdmtoList)
  377. {
  378. HRESULT hRes = S_OK;
  379. DMTDEVICEOBJECT_NODE *pNode = NULL;
  380. // validate ppdmtaList
  381. if(IsBadWritePtr((void*)ppdmtoList, sizeof(DMTDEVICEOBJECT_NODE*)))
  382. {
  383. DPF(0, "dmtinputFreeObjectList - Invalid ppdmtoList (%016Xh)",
  384. ppdmtoList);
  385. return E_POINTER;
  386. }
  387. // validate *ppdmtdList
  388. if(IsBadReadPtr((void*)*ppdmtoList, sizeof(DMTDEVICEOBJECT_NODE)))
  389. {
  390. if(NULL != *ppdmtoList)
  391. {
  392. DPF(0, "dmtinputFreeObjectList - Invalid *ppdmtdList (%016Xh)",
  393. *ppdmtoList);
  394. return E_POINTER;
  395. }
  396. else
  397. {
  398. // if NULL, then return "did nothing"
  399. DPF(3, "dmtinputFreeObjectList - Nothing to do....");
  400. return S_FALSE;
  401. }
  402. }
  403. // walk the list and free each object
  404. while(*ppdmtoList)
  405. {
  406. pNode = *ppdmtoList;
  407. *ppdmtoList = (*ppdmtoList)->pNext;
  408. // delete the node
  409. DPF(5, "dmtinputFreeObjectList - deleting Node (%016Xh)", pNode);
  410. if(LocalFree((HLOCAL)pNode))
  411. {
  412. DPF(0, "dmtinputFreeObjectList - MEMORY LEAK - "
  413. "LocalFree() failed (%d)...",
  414. GetLastError());
  415. hRes = DMT_S_MEMORYLEAK;
  416. }
  417. DPF(5, "dmtinputFreeObjectList - Node deleted");
  418. }
  419. // make sure that we set *ppObjList to NULL
  420. *ppdmtoList = NULL;
  421. // done
  422. return hRes;
  423. } //*** end dmtinputFreeObjectList()
  424. //===========================================================================
  425. // dmtinputEnumDevicesCallback
  426. //
  427. // Enumeration callback funtion called by DirectInput in response to an app
  428. // calling IDirectInput#A::EnumDevices().
  429. //
  430. // Parameters:
  431. // LPCDIDEVICEINSTANCEA pddi - device instance data (ANSI version)
  432. // void *pvData - app specific data
  433. //
  434. // Returns:
  435. // BOOL : DIENUM_CONTINUE or DIENUM_STOP
  436. //
  437. // History:
  438. // 08/30/1999 - davidkl - created
  439. // 11/08/1999 - davidkl - added object counts
  440. // 12/01/1999 - davidkl - now keeping product name
  441. // 02/23/2000 - davidkl - updated to EnumDevicesBySemantic
  442. //===========================================================================
  443. BOOL CALLBACK dmtinputEnumDevicesCallback(LPCDIDEVICEINSTANCEA pddi,
  444. IDirectInputDevice8A *pdid,
  445. DWORD,
  446. DWORD,
  447. void *pvData)
  448. {
  449. HRESULT hRes = S_OK;
  450. BOOL fDirective = DIENUM_CONTINUE;
  451. DMTDEVICE_NODE **ppList = (DMTDEVICE_NODE**)pvData;
  452. DMTDEVICE_NODE *pCurrent = NULL;
  453. DMTDEVICE_NODE *pNew = NULL;
  454. DIDEVCAPS didc;
  455. DIPROPDWORD dipdw;
  456. DPF(0, "dmtinputEnumDevicesCallback - IN");
  457. // validate pddi
  458. //
  459. // NOTE: we are going to trust (for now) that DirectInput will
  460. // pass us valid data
  461. // validate pdid
  462. //
  463. // NOTE: we are going to trust (for now) that DirectInput will
  464. // pass us valid data
  465. // validate ppList
  466. if(IsBadWritePtr((void*)ppList, sizeof(DMTDEVICE_NODE*)))
  467. {
  468. return DIENUM_STOP;
  469. }
  470. // validate *ppList
  471. if(IsBadWritePtr((void*)*ppList, sizeof(DMTDEVICE_NODE)))
  472. {
  473. if(NULL != *ppList)
  474. {
  475. return DIENUM_STOP;
  476. }
  477. }
  478. __try
  479. {
  480. // we are handed a mouse or keyboard
  481. //
  482. // skip to the next device
  483. if((DI8DEVTYPE_MOUSE == DIDFT_GETTYPE(pddi->dwDevType)) ||
  484. (DI8DEVTYPE_KEYBOARD == DIDFT_GETTYPE(pddi->dwDevType)))
  485. {
  486. DPF(2, "dmtinputEnumDevicesCallback - "
  487. "Keyboard/Mouse found. Skipping.");
  488. fDirective = DIENUM_CONTINUE;
  489. __leave;
  490. }
  491. pCurrent = *ppList;
  492. // default to "keep enumerating, unless there is nothing else to find"
  493. fDirective = DIENUM_CONTINUE;
  494. // get info regarding the device
  495. ZeroMemory((void*)&didc, sizeof(DIDEVCAPS));
  496. didc.dwSize = sizeof(DIDEVCAPS);
  497. hRes = pdid->GetCapabilities(&didc);
  498. if(FAILED(hRes))
  499. {
  500. // unable to retrieve device info... this is bad
  501. DPF(0, "dmtinputEnumDevicesCallback - failed to "
  502. "retrieve dev caps (%s == %08Xh)",
  503. dmtxlatHRESULT(hRes), hRes);
  504. DebugBreak();
  505. hRes = E_UNEXPECTED;
  506. __leave;
  507. }
  508. DPF(3, "dmtinputEnumDevicesCallback - Device: %s",
  509. pddi->tszProductName);
  510. // allocate a new node
  511. pNew = (DMTDEVICE_NODE*)LocalAlloc(LMEM_FIXED,
  512. sizeof(DMTDEVICE_NODE));
  513. if(!pNew)
  514. {
  515. DPF(1, "dmtinputEnumDevicesCallback - insufficient "
  516. "memory to allocate device node");
  517. fDirective = DIENUM_STOP;
  518. __leave;
  519. }
  520. // populate the new node
  521. ZeroMemory((void*)pNew, sizeof(DMTDEVICE_NODE));
  522. // name(s)
  523. lstrcpyA(pNew->szName, pddi->tszInstanceName);
  524. lstrcpyA(pNew->szProductName, pddi->tszProductName);
  525. // instance guid
  526. pNew->guidInstance = pddi->guidInstance;
  527. // device type/subtype
  528. pNew->dwDeviceType = pddi->dwDevType;
  529. // # axes
  530. pNew->dwAxes = didc.dwAxes;
  531. // # buttons
  532. pNew->dwButtons = didc.dwButtons;
  533. // # povs
  534. pNew->dwPovs = didc.dwPOVs;
  535. // is this a polled device?
  536. if(DIDC_POLLEDDEVICE & didc.dwFlags)
  537. {
  538. // yep,
  539. //
  540. // better make sure we call IDirectInputDevice8A::Poll
  541. DPF(4, "dmttestGetInput - Polled device");
  542. pNew->fPolled = TRUE;
  543. }
  544. // device object ptr
  545. pNew->pdid = pdid;
  546. pdid->AddRef();
  547. // vendor id / product id
  548. ZeroMemory((void*)&dipdw, sizeof(DIPROPDWORD));
  549. dipdw.diph.dwSize = sizeof(DIPROPDWORD);
  550. dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
  551. dipdw.diph.dwHow = DIPH_DEVICE;
  552. hRes = (pNew->pdid)->GetProperty(DIPROP_VIDPID,
  553. &(dipdw.diph));
  554. if(SUCCEEDED(hRes))
  555. {
  556. // extract the VID and PID
  557. pNew->wVendorId = LOWORD(dipdw.dwData);
  558. pNew->wProductId = HIWORD(dipdw.dwData);
  559. }
  560. else
  561. {
  562. // property call failed, assume no VID|PID
  563. pNew->wVendorId = 0;
  564. pNew->wProductId = 0;
  565. // this property call is not critical
  566. // it's ok to mask the failure
  567. hRes = S_FALSE;
  568. }
  569. // filename
  570. lstrcpyA(pNew->szFilename, "\0");
  571. // append to the end of the list
  572. if(!pCurrent)
  573. {
  574. // make sure we return the head
  575. *ppList = pNew;
  576. }
  577. else
  578. {
  579. // walk to the end of the list
  580. while(pCurrent->pNext)
  581. {
  582. pCurrent = pCurrent->pNext;
  583. }
  584. // add the node
  585. pCurrent->pNext = pNew;
  586. }
  587. }
  588. __finally
  589. {
  590. // general cleanup
  591. // in failure case, free pNew
  592. if(FAILED(hRes))
  593. {
  594. DPF(1, "dmtinputEnumDevicesCallback - something failed... ");
  595. if(pNew)
  596. {
  597. DPF(1, "dmtinputEnumDevicesCallback - freeing new device node");
  598. if(LocalFree((HLOCAL)pNew))
  599. {
  600. // ISSUE-2001/03/29-timgill Needs error case handling
  601. }
  602. }
  603. }
  604. }
  605. // continue enumerating
  606. return fDirective;
  607. } //*** end dmtinputEnumDevicesCallback()
  608. //===========================================================================
  609. // dmtinputEnumDeviceObjectsCallback
  610. //
  611. // Enumeration callback funtion called by DirectInput in response to an app
  612. // calling IDirectInpuDevice#A::EnumDevices()
  613. //
  614. // Parameters:
  615. // LPCDIDEVICEOBJECTINSTANCEA pddi - device object instance data
  616. // (ANSI version)
  617. // void *pvData - app specific data
  618. //
  619. // Returns:
  620. // BOOL : DIENUM_CONTINUE or DIENUM_STOP
  621. //
  622. // History:
  623. // 08/30/1999 - davidkl - created
  624. // 10/21/1999 - davidkl - added object type filtering
  625. //===========================================================================
  626. BOOL CALLBACK dmtinputEnumDeviceObjectsCallback(LPCDIDEVICEOBJECTINSTANCEA pddoi,
  627. void *pvData)
  628. {
  629. BOOL fDirective = DIENUM_CONTINUE;
  630. WORD wOffset = 0;
  631. DMTDEVICEOBJECT_NODE **ppList = (DMTDEVICEOBJECT_NODE**)pvData;
  632. DMTDEVICEOBJECT_NODE *pCurrent = NULL;
  633. DMTDEVICEOBJECT_NODE *pNew = NULL;
  634. // validate ppList
  635. if(IsBadWritePtr((void*)ppList, sizeof(DMTDEVICEOBJECT_NODE*)))
  636. {
  637. return DIENUM_STOP;
  638. }
  639. // validate *ppList
  640. if(IsBadWritePtr((void*)*ppList, sizeof(DMTDEVICEOBJECT_NODE)))
  641. {
  642. if(NULL != *ppList)
  643. {
  644. return DIENUM_STOP;
  645. }
  646. }
  647. __try
  648. {
  649. pCurrent = *ppList;
  650. // default to "keep enumerating, unless there is nothing else to find"
  651. fDirective = DIENUM_CONTINUE;
  652. /*
  653. // filter HID collections
  654. if(DIDFT_COLLECTION & (pddoi->dwType))
  655. {
  656. // skip this object
  657. DPF(3, "dmtinputEnumDeviceObjectsCallback - "
  658. "object is a collection... skipping");
  659. __leave;
  660. }
  661. */
  662. // allocate a new node
  663. pNew = (DMTDEVICEOBJECT_NODE*)LocalAlloc(LMEM_FIXED,
  664. sizeof(DMTDEVICEOBJECT_NODE));
  665. if(!pNew)
  666. {
  667. fDirective = DIENUM_STOP;
  668. __leave;
  669. }
  670. // populate the new node
  671. ZeroMemory((void*)pNew, sizeof(DMTDEVICEOBJECT_NODE));
  672. // name
  673. lstrcpyA(pNew->szName, (LPSTR)pddoi->tszName);
  674. // object type
  675. pNew->dwObjectType = pddoi->dwType;
  676. // object offset
  677. pNew->dwObjectOffset = pddoi->dwOfs;
  678. // HID usage page
  679. pNew->wUsagePage = pddoi->wUsagePage;
  680. // HID usage
  681. pNew->wUsage = pddoi->wUsage;
  682. // control "identifier"
  683. switch(DIDFT_GETTYPE(pddoi->dwType))
  684. {
  685. case DIDFT_AXIS:
  686. case DIDFT_ABSAXIS:
  687. case DIDFT_RELAXIS:
  688. pNew->wCtrlId = IDC_AXIS_X + DIDFT_GETINSTANCE(pddoi->dwType);
  689. break;
  690. case DIDFT_BUTTON:
  691. case DIDFT_PSHBUTTON:
  692. case DIDFT_TGLBUTTON:
  693. // this is a button, encode as follows:
  694. // (BTN1 + (instance % NUM_DISPBTNS)) +
  695. // (BTNS_1_32 + (instance / NUM_DISPBTNS))
  696. wOffset = DIDFT_GETINSTANCE(pddoi->dwType) / NUM_DISPBTNS;
  697. pNew->wCtrlId = (wOffset << 8) |
  698. (DIDFT_GETINSTANCE(pddoi->dwType) % NUM_DISPBTNS);
  699. break;
  700. case DIDFT_POV:
  701. pNew->wCtrlId = IDC_POV1 + DIDFT_GETINSTANCE(pddoi->dwType);
  702. break;
  703. default:
  704. // we should never hit this
  705. // as we filter out objects that are
  706. // not one of the types we care about
  707. break;
  708. }
  709. // append to the end of the list
  710. if(!pCurrent)
  711. {
  712. // list head
  713. pCurrent = pNew;
  714. // make sure we return the head
  715. *ppList = pCurrent;
  716. }
  717. else
  718. {
  719. // walk to the end of the list
  720. while(pCurrent->pNext)
  721. {
  722. pCurrent = pCurrent->pNext;
  723. }
  724. // add the node
  725. pCurrent->pNext = pNew;
  726. }
  727. }
  728. __finally
  729. {
  730. // ISSUE-2001/03/29-timgill Needs error case handling
  731. // Needs some sort of error handling
  732. }
  733. // continue enumerating
  734. return fDirective;
  735. } //*** end dmtinputEnumDeviceObjectsCallback()
  736. //===========================================================================
  737. // dmtinputPopulateActionArray
  738. //
  739. // Fills DIACTIONA array with data from the DMTACTION_NODE list
  740. //
  741. // Parameters:
  742. //
  743. // Returns: HRESULT
  744. //
  745. // History:
  746. // 09/08/1999 - davidkl - created
  747. //===========================================================================
  748. HRESULT dmtinputPopulateActionArray(DIACTIONA *pdia,
  749. UINT uElements,
  750. DMTACTION_NODE *pdmtaList)
  751. {
  752. HRESULT hRes = S_OK;
  753. UINT u = 0;
  754. // validate pdia
  755. if(IsBadWritePtr((void*)pdia, uElements * sizeof(DIACTIONA)))
  756. {
  757. DPF(0, "dmtinputPopulateActionArray - invalid pdia (%016Xh)",
  758. pdia);
  759. return E_POINTER;
  760. }
  761. // validate pdmtaList
  762. if(IsBadReadPtr((void*)pdmtaList, sizeof(DMTACTION_NODE)))
  763. {
  764. DPF(0, "dmtinputPopulateActionArray - invalid pdmtaList (%016Xh)",
  765. pdmtaList);
  766. return E_POINTER;
  767. }
  768. // first, flush whatever is currently in the array
  769. ZeroMemory((void*)pdia, uElements * sizeof(DIACTIONA));
  770. // next, copy the following DIACTION elements
  771. // from the action list to the action array
  772. //
  773. // NOTE: All strings referenced in these structurs
  774. // are ANSI strings (we are using DIACTIONA)
  775. //
  776. // DIACTION DMTACTION_NODE
  777. // ======== ==============
  778. // dwSemantic dwActionId
  779. // lptszActionName szName
  780. //
  781. for(u = 0; u < uElements; u++)
  782. {
  783. // make sure there is some data to copy
  784. if(!pdmtaList)
  785. {
  786. DPF(1, "dmtinputPopulateActionArray - Ran out of "
  787. "list nodes before fully populating DIACTION array");
  788. hRes = S_FALSE;
  789. break;
  790. }
  791. // copy the data
  792. (pdia+u)->dwSemantic = pdmtaList->dwActionId;
  793. (pdia+u)->lptszActionName = pdmtaList->szName;
  794. // go to next list element
  795. pdmtaList = pdmtaList->pNext;
  796. }
  797. // done
  798. return hRes;
  799. } //*** end dmtinputPopulateActionArray()
  800. //===========================================================================
  801. // dmtinputXlatDIDFTtoInternalType
  802. //
  803. // Converts from the DIDFT_* value (DIDEVICEOBJECTINSTANCE.dwType) to our
  804. // internal control type value (DMTA_TYPE_*)
  805. //
  806. // Parameters:
  807. // DWORD dwType - value of DIDEVICEOBJECTINSTANCE.dwType
  808. // DWORD *pdwInternalType - ptr to recieve DMTA_TYPE_* value
  809. //
  810. // Returns: HRESULT
  811. //
  812. // History:
  813. // 09/09/1999 - davidkl - created
  814. //===========================================================================
  815. HRESULT dmtinputXlatDIDFTtoInternalType(DWORD dwType,
  816. DWORD *pdwInternalType)
  817. {
  818. HRESULT hRes = S_OK;
  819. // validate pdwInternalType
  820. if(IsBadWritePtr((void*)pdwInternalType, sizeof(DWORD)))
  821. {
  822. DPF(0, "dmtinputXlatDIDFTtoInternalType - invalid pdwInternalType "
  823. "(%016Xh)", pdwInternalType);
  824. return E_POINTER;
  825. }
  826. // translate
  827. //
  828. // OR together axis, button and pov masks,
  829. // AND that with the type passed in
  830. //
  831. switch((DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV) & dwType)
  832. {
  833. case DIDFT_AXIS:
  834. case DIDFT_RELAXIS:
  835. case DIDFT_ABSAXIS:
  836. DPF(5, "dmtinputXlatDIDFTtoInternalType - AXIS");
  837. *pdwInternalType = DMTA_TYPE_AXIS;
  838. break;
  839. case DIDFT_PSHBUTTON:
  840. case DIDFT_TGLBUTTON:
  841. case DIDFT_BUTTON:
  842. DPF(5, "dmtinputXlatDIDFTtoInternalType - BUTTON");
  843. *pdwInternalType = DMTA_TYPE_BUTTON;
  844. break;
  845. case DIDFT_POV:
  846. DPF(5, "dmtinputXlatDIDFTtoInternalType - POV");
  847. *pdwInternalType = DMTA_TYPE_POV;
  848. break;
  849. default:
  850. DPF(5, "dmtinputXlatDIDFTtoInternalType - WHAT IS THIS?");
  851. *pdwInternalType = DMTA_TYPE_UNKNOWN;
  852. hRes = S_FALSE;
  853. break;
  854. }
  855. // done
  856. return hRes;
  857. } //*** end dmtinputXlatDIDFTtoInternalType()
  858. //===========================================================================
  859. // dmtinputPrepDevice
  860. //
  861. // Prepares the device for data retrieval. Performs the following steps:
  862. // * Set the cooperative level
  863. // * Set the data format
  864. // * Set the buffer size
  865. //
  866. // Parameters:
  867. // HWND hwnd - handle of app window
  868. // DWORD dwGenreId - identifier of genre to be tested
  869. // IDirectInputDevice8A *pdid - ptr to device object
  870. //
  871. // Returns: HRESULT
  872. //
  873. // History:
  874. // 09/21/1999 - davidkl - created
  875. // 10/07/1999 - davidkl - added Get/ApplyActionMap calls
  876. // 10/27/1999 - davidkl - added uAppData to pdia, changed param list
  877. //===========================================================================
  878. HRESULT dmtinputPrepDevice(HWND hwnd,
  879. DWORD dwGenreId,
  880. DMTDEVICE_NODE *pDevice,
  881. DWORD dwActions,
  882. DIACTIONA *pdia)
  883. {
  884. HRESULT hRes = S_OK;
  885. DWORD dw = 0;
  886. IDirectInputDevice8A *pdid = NULL;
  887. DMTDEVICEOBJECT_NODE *pObject = NULL;
  888. DIACTIONFORMATA diaf;
  889. DIPROPDWORD dipdw;
  890. // validate pDevice
  891. if(IsBadReadPtr((void*)pDevice, sizeof(DMTDEVICE_NODE)))
  892. {
  893. DPF(0, "dmtinputPrepDevice - invalid pDevice (%016Xh)",
  894. pDevice);
  895. return E_POINTER;
  896. }
  897. // validate pdia
  898. if(IsBadReadPtr((void*)pdia, dwActions * sizeof(DIACTIONA)))
  899. {
  900. DPF(0, "dmtinputPrepDevice - invalid pdia (%016Xh)",
  901. pdia);
  902. return E_POINTER;
  903. }
  904. // validate pDevice->pdid
  905. if(IsBadReadPtr((void*)(pDevice->pdid), sizeof(IDirectInputDevice8A)))
  906. {
  907. DPF(0, "dmtinputPrepDevice - invalid pDevice->pdid (%016Xh)",
  908. pDevice->pdid);
  909. return E_INVALIDARG;
  910. }
  911. // save some typing
  912. pdid = pDevice->pdid;
  913. __try
  914. {
  915. // set the cooperative level
  916. hRes = pdid->SetCooperativeLevel(hwnd,
  917. DISCL_NONEXCLUSIVE | DISCL_BACKGROUND);
  918. if(FAILED(hRes))
  919. {
  920. DPF(0, "dmtinputPrepDevice - SetCooperativeLevel(non-exclusive | "
  921. "background) failed (%s == %08Xh)",
  922. dmtxlatHRESULT(hRes), hRes);
  923. __leave;
  924. }
  925. // set data buffer size
  926. ZeroMemory((void*)&dipdw, sizeof(DIPROPDWORD));
  927. dipdw.diph.dwSize = sizeof(DIPROPDWORD);
  928. dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
  929. dipdw.diph.dwHow = DIPH_DEVICE;
  930. dipdw.diph.dwObj = 0;
  931. dipdw.dwData = DMTINPUT_BUFFERSIZE;
  932. hRes = pdid->SetProperty(DIPROP_BUFFERSIZE,
  933. &(dipdw.diph));
  934. if(FAILED(hRes))
  935. {
  936. DPF(0, "dmtinputPrepDevice - SetProperty(buffer size) "
  937. "failed (%s == %08Xh)",
  938. dmtxlatHRESULT(hRes), hRes);
  939. __leave;
  940. }
  941. // populate the diactionformat structure
  942. ZeroMemory((void*)&diaf, sizeof(DIACTIONFORMATA));
  943. diaf.dwSize = sizeof(DIACTIONFORMATA);
  944. diaf.dwActionSize = sizeof(DIACTIONA);
  945. diaf.dwNumActions = dwActions;
  946. diaf.rgoAction = pdia;
  947. diaf.dwDataSize = 4 * diaf.dwNumActions;
  948. diaf.guidActionMap = GUID_DIMapTst;
  949. diaf.dwGenre = dwGenreId;
  950. diaf.dwBufferSize = DMTINPUT_BUFFERSIZE;
  951. lstrcpyA(diaf.tszActionMap, DMT_APP_CAPTION);
  952. // get the action map for this genre (from the device)
  953. hRes = pdid->BuildActionMap(&diaf,
  954. (LPCSTR)NULL,
  955. DIDBAM_HWDEFAULTS);
  956. DPF(1, "dmtinputPrepDevice - GetActionMap returned %s (%08Xh)",
  957. dmtxlatHRESULT, hRes);
  958. if(FAILED(hRes))
  959. {
  960. DPF(0, "dmtinputPrepDevice - GetActionMap failed (%s == %08Xh)",
  961. dmtxlatHRESULT(hRes), hRes);
  962. __leave;
  963. }
  964. // add the control id/type info to the
  965. // action array
  966. pObject = pDevice->pObjectList;
  967. while(pObject)
  968. {
  969. // spin through the array
  970. //
  971. // look for matching elements
  972. // (match == same guidInstance & same offset
  973. for(dw = 0; dw < dwActions; dw++)
  974. {
  975. // first check the guid
  976. if(IsEqualGUID(pObject->guidDeviceInstance, (pdia+dw)->guidInstance))
  977. {
  978. // then compare the offset
  979. if((pdia+dw)->dwObjID == pObject->dwObjectType)
  980. {
  981. // store the CtrlId and Type
  982. (pdia+dw)->uAppData = (DIDFT_GETTYPE(pObject->dwObjectType) << 16) |
  983. (pObject->wCtrlId);
  984. // skip out of the for loop
  985. break;
  986. }
  987. }
  988. }
  989. // next object
  990. pObject = pObject->pNext;
  991. }
  992. // apply the action map for this genre
  993. //
  994. // this accomplishes the same task as calling SetDataFormat
  995. hRes = pdid->SetActionMap(&diaf,
  996. NULL,
  997. DIDSAM_DEFAULT);
  998. DPF(1, "dmtinputPrepDevice - ApplyActionMap returned %s (%08Xh)",
  999. dmtxlatHRESULT, hRes);
  1000. if(FAILED(hRes))
  1001. {
  1002. DPF(0, "dmtinputPrepDevice - ApplyActionMap failed (%s == %08Xh)",
  1003. dmtxlatHRESULT(hRes), hRes);
  1004. __leave;
  1005. }
  1006. }
  1007. __finally
  1008. {
  1009. // ISSUE-2001/03/29-timgill Needs error case handling
  1010. }
  1011. // done
  1012. return hRes;
  1013. } //*** end dmtinputPrepDevice()
  1014. //===========================================================================
  1015. // dmtinputGetActionPri
  1016. //
  1017. // Extracts the action priority from the DirectInput semantic
  1018. //
  1019. // Parameters:
  1020. // DWORD dwSemantic - DirectInput action semantic
  1021. //
  1022. // Returns: int (Action priority)
  1023. //
  1024. // History:
  1025. // 09/28/1999 - davidkl - created
  1026. // 10/27/1999 - davidkl - code review cleanup
  1027. //===========================================================================
  1028. DWORD dmtinputGetActionPri(DWORD dwSemantic)
  1029. {
  1030. // action priority is 0 based, we want to return
  1031. // priority 1 based for display purposes
  1032. return (DWORD)(DISEM_PRI_GET(dwSemantic) + 1);
  1033. } //*** end dmtinputGetActionPri()
  1034. //===========================================================================
  1035. // dmtinputGetActionObjectType
  1036. //
  1037. // Extracts the object type from the DirectInput semantic and returns it
  1038. // as one of DIMapTst's internal object types.
  1039. //
  1040. // Parameters:
  1041. // DWORD dwSemantic - DirectInput action semantic
  1042. //
  1043. // Returns: DWORD (internal object type)
  1044. //
  1045. // History:
  1046. // 09/28/1999 - davidkl - created
  1047. //===========================================================================
  1048. DWORD dmtinputGetActionObjectType(DWORD dwSemantic)
  1049. {
  1050. DWORD dwObjType = DMTA_TYPE_UNKNOWN;
  1051. // we achieve our goal by:
  1052. // * extracting and shifting object typw with DISEM_TYPE_GET
  1053. // ** value becomes 1, 2, or 3 (DirectInput's system)
  1054. // * subtracting 1 to be 0 based
  1055. // ** value becomes 0, 1, or 2 (DIMapTst's system)
  1056. dwObjType = DISEM_TYPE_GET(dwSemantic) - 1;
  1057. // done
  1058. return dwObjType;
  1059. } //*** end dmtinputGetActionObjectType()
  1060. //===========================================================================
  1061. // dmtinputCreateDirectInput
  1062. //
  1063. // Creates a DirectInpu8A object
  1064. //
  1065. // Parameters:
  1066. // IDirectInput8A **ppdi - ptr to directinput object ptr
  1067. //
  1068. // Returns: HRESULT
  1069. //
  1070. // History:
  1071. // 10/06/1999 - davidkl - created
  1072. // 10/27/1999 - davidkl - house cleaning
  1073. //===========================================================================
  1074. HRESULT dmtinputCreateDirectInput(HINSTANCE hinst,
  1075. IDirectInput8A **ppdi)
  1076. {
  1077. HRESULT hRes = S_OK;
  1078. // validate ppdi
  1079. if(IsBadWritePtr((void*)ppdi, sizeof(IDirectInput8A*)))
  1080. {
  1081. DPF(0, "dmtinputCreateDirectInput - invalid ppdi (%016Xh)",
  1082. ppdi);
  1083. return E_POINTER;
  1084. }
  1085. __try
  1086. {
  1087. // cocreate IDirectInput8A
  1088. hRes = CoCreateInstance(CLSID_DirectInput8,
  1089. NULL,
  1090. CLSCTX_ALL,
  1091. IID_IDirectInput8A,
  1092. (void**)ppdi);
  1093. if(FAILED(hRes))
  1094. {
  1095. DPF(0, "dmtinputCreateDirectInput - "
  1096. "CoCreateInstance failed (%s == %08Xh)",
  1097. dmtxlatHRESULT(hRes), hRes);
  1098. __leave;
  1099. }
  1100. // initialize the new dinput object
  1101. hRes = (*ppdi)->Initialize(hinst,
  1102. DIRECTINPUT_VERSION);
  1103. if(FAILED(hRes))
  1104. {
  1105. DPF(0, "dmtinputCreateDirectInput - IDirectInput8A::"
  1106. "Initialize failed (%s == %08Xh)",
  1107. dmtxlatHRESULT(hRes), hRes);
  1108. __leave;
  1109. }
  1110. }
  1111. __finally
  1112. {
  1113. // if something fails...
  1114. // release the device object
  1115. if(FAILED(hRes))
  1116. {
  1117. SAFE_RELEASE((*ppdi));
  1118. }
  1119. }
  1120. // done
  1121. return hRes;
  1122. } //*** end dmtinputCreateDirectInput()
  1123. //===========================================================================
  1124. // dmtinputDeviceHasObject
  1125. //
  1126. // Determines (from a the supplied object list) whether or not a device
  1127. // reports as having at least one object of the specified type.
  1128. //
  1129. // Parameters:
  1130. //
  1131. // Returns: BOOL (FALSE if any invalid parameters)
  1132. //
  1133. // History:
  1134. // 10/28/1999 - davidkl - created
  1135. //===========================================================================
  1136. BOOL dmtinputDeviceHasObject(DMTDEVICEOBJECT_NODE *pObjectList,
  1137. DWORD dwType)
  1138. {
  1139. BOOL fRet = FALSE;
  1140. DWORD dwObjType = DMTA_TYPE_UNKNOWN;
  1141. DMTDEVICEOBJECT_NODE *pObject = NULL;
  1142. pObject = pObjectList;
  1143. while(pObject)
  1144. {
  1145. if(FAILED(dmtinputXlatDIDFTtoInternalType(pObject->dwObjectType,
  1146. &dwObjType)))
  1147. {
  1148. // ISSUE-2001/03/29-timgill Needs error case handling
  1149. }
  1150. DPF(3, "dmtinputDeviceHasObject - %s : DIDFT type %08Xh, internal type %d",
  1151. pObject->szName,
  1152. pObject->dwObjectType,
  1153. dwObjType);
  1154. if(dwType == dwObjType)
  1155. {
  1156. fRet = TRUE;
  1157. break;
  1158. }
  1159. // next object
  1160. pObject = pObject->pNext;
  1161. }
  1162. // done
  1163. return fRet;
  1164. } //*** end dmtinputDeviceHasObject()
  1165. //===========================================================================
  1166. // dmtinputRegisterMapFile
  1167. //
  1168. // Queries DirectInput for the proper location and registers the map file
  1169. // for the specified device.
  1170. //
  1171. // Parameters:
  1172. //
  1173. // Returns: HRESULT
  1174. //
  1175. // History:
  1176. // 11/04/1999 - davidkl - created
  1177. //===========================================================================
  1178. HRESULT dmtinputRegisterMapFile(HWND hwnd,
  1179. DMTDEVICE_NODE *pDevice)
  1180. {
  1181. HRESULT hRes = S_OK;
  1182. LONG lRet = 0L;
  1183. HKEY hkType = NULL;
  1184. IDirectInput8A *pdi = NULL;
  1185. IDirectInputJoyConfig *pjoycfg = NULL;
  1186. DIPROPDWORD dipdw;
  1187. DIJOYCONFIG dijc;
  1188. // validate pDevice
  1189. if(IsBadReadPtr((void*)pDevice, sizeof(DMTDEVICE_NODE)))
  1190. {
  1191. DPF(0, "dmtinputRegisterMapFile - invalid pDevice (%016Xh)",
  1192. pDevice);
  1193. return E_POINTER;
  1194. }
  1195. // validate pDevice->pdid
  1196. if(IsBadReadPtr((void*)(pDevice->pdid), sizeof(IDirectInputDevice8A)))
  1197. {
  1198. DPF(0, "dmtinputRegisterMapFile - invalid pDevice->pdid (%016Xh)",
  1199. pDevice->pdid);
  1200. return E_INVALIDARG;
  1201. }
  1202. __try
  1203. {
  1204. // create a directinput object
  1205. hRes = dmtinputCreateDirectInput(ghinst,
  1206. &pdi);
  1207. if(FAILED(hRes))
  1208. {
  1209. DPF(0, "dmtinputRegisterMapFile - unable to create pdi (%s == %08Xh)",
  1210. dmtxlatHRESULT(hRes), hRes);
  1211. __leave;
  1212. }
  1213. // query for the joyconfig interface
  1214. hRes = pdi->QueryInterface(IID_IDirectInputJoyConfig8,
  1215. (void**)&pjoycfg);
  1216. if(FAILED(hRes))
  1217. {
  1218. DPF(0, "dmtinputRegisterMapFile - QI(JoyConfig) failed (%s == %08Xh)",
  1219. dmtxlatHRESULT(hRes), hRes);
  1220. __leave;
  1221. }
  1222. // get the device id
  1223. //
  1224. // use DIPROP_JOYSTICKID
  1225. ZeroMemory((void*)&dipdw, sizeof(DIPROPDWORD));
  1226. dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
  1227. dipdw.diph.dwSize = sizeof(DIPROPDWORD);
  1228. dipdw.diph.dwHow = DIPH_DEVICE;
  1229. dipdw.diph.dwObj = 0;
  1230. hRes = (pDevice->pdid)->GetProperty(DIPROP_JOYSTICKID,
  1231. &(dipdw.diph));
  1232. if(FAILED(hRes))
  1233. {
  1234. DPF(0, "dmtinputRegisterMapFile - GetProperty(joystick id) failed (%s == %08Xh)",
  1235. dmtxlatHRESULT(hRes), hRes);
  1236. __leave;
  1237. }
  1238. // prepare the config structure
  1239. ZeroMemory((void*)&dijc, sizeof(DIJOYCONFIG));
  1240. dijc.dwSize = sizeof(DIJOYCONFIG);
  1241. // set the joycfg cooperative level
  1242. hRes = pjoycfg->SetCooperativeLevel(hwnd,
  1243. DISCL_EXCLUSIVE | DISCL_BACKGROUND);
  1244. if(FAILED(hRes))
  1245. {
  1246. DPF(0, "dmtinputRegisterMapFile - SetCooperativeLevel failed (%s == %08Xh)",
  1247. dmtxlatHRESULT(hRes), hRes);
  1248. __leave;
  1249. }
  1250. // acquire joyconfig
  1251. hRes = pjoycfg->Acquire();
  1252. if(FAILED(hRes))
  1253. {
  1254. DPF(0, "dmtinputRegisterMapFile - Acquire() failed (%s == %08Xh)",
  1255. dmtxlatHRESULT(hRes), hRes);
  1256. __leave;
  1257. }
  1258. // retrieve the config data
  1259. hRes = pjoycfg->GetConfig((UINT)(dipdw.dwData),
  1260. &dijc,
  1261. DIJC_GUIDINSTANCE |
  1262. DIJC_REGHWCONFIGTYPE);
  1263. if(FAILED(hRes))
  1264. {
  1265. DPF(0, "dmtinputRegisterMapFile - GetConfig failed (%s == %08Xh)",
  1266. dmtxlatHRESULT(hRes), hRes);
  1267. __leave;
  1268. }
  1269. // open the type key
  1270. //
  1271. // we are opening for read as well as write so we can
  1272. // save the previous value
  1273. hRes = dmtOpenTypeKey(dijc.wszType,
  1274. KEY_READ|KEY_WRITE,
  1275. &hkType);
  1276. if(FAILED(hRes))
  1277. {
  1278. DPF(0, "dmtinputRegisterMapFile - OpenTypeKey failed (%s == %08Xh)",
  1279. dmtxlatHRESULT(hRes), hRes);
  1280. __leave;
  1281. }
  1282. // write the map file name
  1283. lRet = RegSetValueExA(hkType,
  1284. "OEMMapFile",
  1285. 0,
  1286. REG_SZ,
  1287. (CONST BYTE*)(pDevice->szFilename),
  1288. sizeof(char) *
  1289. (lstrlenA(pDevice->szFilename) + 1));
  1290. if(ERROR_SUCCESS)
  1291. {
  1292. DPF(0, "dmtinputRegisterMapFile - RegSetValueExA failed (%d)",
  1293. GetLastError());
  1294. __leave;
  1295. }
  1296. // notify dinput that we changed something
  1297. hRes = pjoycfg->SendNotify();
  1298. if(FAILED(hRes))
  1299. {
  1300. DPF(0, "dmtinputRegisterMapFile - SendNotify failed (%s == %08Xh)",
  1301. dmtxlatHRESULT(hRes), hRes);
  1302. hRes = S_FALSE;
  1303. __leave;
  1304. }
  1305. }
  1306. __finally
  1307. {
  1308. // cleanup
  1309. if(pjoycfg)
  1310. {
  1311. pjoycfg->Unacquire();
  1312. }
  1313. SAFE_RELEASE(pjoycfg);
  1314. SAFE_RELEASE(pdi);
  1315. }
  1316. // done
  1317. return hRes;
  1318. } //*** end dmtinputRegisterMapFile()
  1319. //===========================================================================
  1320. // dmtinputGetRegisteredMapFile
  1321. //
  1322. // Retrieves the map file name for the specified device
  1323. //
  1324. // Parameters:
  1325. // HWND hwnd
  1326. // DMTDEVICE_NODE *pDevice
  1327. // PSTR pszFilename
  1328. //
  1329. // Returns: HRESULT
  1330. //
  1331. // History:
  1332. // 12/01/1999 - davidkl - created
  1333. // 02/21/2000 - davidkl - initial implementation
  1334. //===========================================================================
  1335. HRESULT dmtinputGetRegisteredMapFile(HWND hwnd,
  1336. DMTDEVICE_NODE *pDevice,
  1337. PSTR pszFilename,
  1338. DWORD cbFilename)
  1339. {
  1340. HRESULT hRes = S_OK;
  1341. LONG lRet = 0L;
  1342. HKEY hkType = NULL;
  1343. HKEY hKey = NULL;
  1344. IDirectInput8A *pdi = NULL;
  1345. IDirectInputJoyConfig *pjoycfg = NULL;
  1346. DIPROPDWORD dipdw;
  1347. DIJOYCONFIG dijc;
  1348. // validate pDevice
  1349. if(IsBadReadPtr((void*)pDevice, sizeof(DMTDEVICE_NODE)))
  1350. {
  1351. DPF(0, "dmtinputGetRegisteredMapFile - invalid pDevice (%016Xh)",
  1352. pDevice);
  1353. return E_POINTER;
  1354. }
  1355. // validate pDevice->pdid
  1356. if(IsBadReadPtr((void*)(pDevice->pdid), sizeof(IDirectInputDevice8A)))
  1357. {
  1358. DPF(0, "dmtinputGetRegisteredMapFile - invalid pDevice->pdid (%016Xh)",
  1359. pDevice->pdid);
  1360. return E_INVALIDARG;
  1361. }
  1362. __try
  1363. {
  1364. // create a directinput object
  1365. hRes = dmtinputCreateDirectInput(ghinst,
  1366. &pdi);
  1367. if(FAILED(hRes))
  1368. {
  1369. DPF(0, "dmtinputGetRegisteredMapFile - unable to create pdi (%s == %08Xh)",
  1370. dmtxlatHRESULT(hRes), hRes);
  1371. __leave;
  1372. }
  1373. // query for the joyconfig interface
  1374. hRes = pdi->QueryInterface(IID_IDirectInputJoyConfig8,
  1375. (void**)&pjoycfg);
  1376. if(FAILED(hRes))
  1377. {
  1378. DPF(0, "dmtinputGetRegisteredMapFile - QI(JoyConfig) failed (%s == %08Xh)",
  1379. dmtxlatHRESULT(hRes), hRes);
  1380. __leave;
  1381. }
  1382. // get the device id
  1383. //
  1384. // use DIPROP_JOYSTICKID
  1385. ZeroMemory((void*)&dipdw, sizeof(DIPROPDWORD));
  1386. dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
  1387. dipdw.diph.dwSize = sizeof(DIPROPDWORD);
  1388. dipdw.diph.dwHow = DIPH_DEVICE;
  1389. dipdw.diph.dwObj = 0;
  1390. hRes = (pDevice->pdid)->GetProperty(DIPROP_JOYSTICKID,
  1391. &(dipdw.diph));
  1392. if(FAILED(hRes))
  1393. {
  1394. DPF(0, "dmtinputGetRegisteredMapFile - GetProperty(joystick id) failed (%s == %08Xh)",
  1395. dmtxlatHRESULT(hRes), hRes);
  1396. __leave;
  1397. }
  1398. // prepare the config structure
  1399. ZeroMemory((void*)&dijc, sizeof(DIJOYCONFIG));
  1400. dijc.dwSize = sizeof(DIJOYCONFIG);
  1401. // set the joycfg cooperative level
  1402. hRes = pjoycfg->SetCooperativeLevel(hwnd,
  1403. DISCL_EXCLUSIVE | DISCL_BACKGROUND);
  1404. if(FAILED(hRes))
  1405. {
  1406. DPF(0, "dmtinputGetRegisteredMapFile - SetCooperativeLevel failed (%s == %08Xh)",
  1407. dmtxlatHRESULT(hRes), hRes);
  1408. __leave;
  1409. }
  1410. // acquire joyconfig
  1411. hRes = pjoycfg->Acquire();
  1412. if(FAILED(hRes))
  1413. {
  1414. DPF(0, "dmtinputGetRegisteredMapFile - Acquire() failed (%s == %08Xh)",
  1415. dmtxlatHRESULT(hRes), hRes);
  1416. __leave;
  1417. }
  1418. // retrieve the config data
  1419. hRes = pjoycfg->GetConfig((UINT)(dipdw.dwData),
  1420. &dijc,
  1421. DIJC_GUIDINSTANCE |
  1422. DIJC_REGHWCONFIGTYPE);
  1423. if(FAILED(hRes))
  1424. {
  1425. DPF(0, "dmtinputGetRegisteredMapFile - GetConfig failed (%s == %08Xh)",
  1426. dmtxlatHRESULT(hRes), hRes);
  1427. __leave;
  1428. }
  1429. // open the type key
  1430. //
  1431. // we are opening for read as well as write so we can
  1432. // save the previous value
  1433. hRes = dmtOpenTypeKey(dijc.wszType,
  1434. KEY_ALL_ACCESS,
  1435. &hkType);
  1436. if(FAILED(hRes))
  1437. {
  1438. DPF(0, "dmtinputGetRegisteredMapFile - OpenTypeKey failed (%s == %08Xh)",
  1439. dmtxlatHRESULT(hRes), hRes);
  1440. __leave;
  1441. }
  1442. // read the value of OEMMapfile
  1443. lRet = RegQueryValueExA(hkType,
  1444. "OEMMapFile",
  1445. NULL,
  1446. NULL,
  1447. (BYTE*)pszFilename,
  1448. &cbFilename);
  1449. if(ERROR_SUCCESS != lRet)
  1450. {
  1451. // ISSUE-2001/03/29-timgill Need to determine what the error code means and translate -> HRESULT
  1452. hRes = S_FALSE;
  1453. DPF(0, "dmtinputGetRegisteredMapFile - RegQueryValueEx failed (%08Xh)",
  1454. lRet);
  1455. lstrcpyA(pszFilename, "");
  1456. __leave;
  1457. }
  1458. }
  1459. __finally
  1460. {
  1461. // cleanup
  1462. if(pjoycfg)
  1463. {
  1464. pjoycfg->Unacquire();
  1465. }
  1466. SAFE_RELEASE(pjoycfg);
  1467. SAFE_RELEASE(pdi);
  1468. }
  1469. // done
  1470. return hRes;
  1471. } //*** end dmtinputGetRegisteredMapFile()
  1472. //===========================================================================
  1473. // dmtOpenTypeKey
  1474. //
  1475. // Opens the hard coded DInput registry key...replaces IDirectInputJoyConfig::OpenTypeKey
  1476. //
  1477. // Parameters:
  1478. // LPCWSTR wszType
  1479. // DWORD hKey
  1480. // PHKEY phKey
  1481. //
  1482. // Returns: HRESULT
  1483. //
  1484. // History:
  1485. // 08/09/2000 - rossy - initial implementation
  1486. //===========================================================================
  1487. HRESULT dmtOpenTypeKey( LPCWSTR wszType, DWORD hKey, PHKEY phKey )
  1488. {
  1489. char szRegStr[200];
  1490. char* szReg = "System\\CurrentControlSet\\Control\\MediaProperties\\PrivateProperties\\DirectInput\\";
  1491. wsprintf(szRegStr, TEXT("%s%S"), szReg, wszType);
  1492. if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szRegStr , 0, hKey, phKey))
  1493. {
  1494. return S_OK;
  1495. }
  1496. else
  1497. {
  1498. return E_FAIL;
  1499. }
  1500. }//*** end dmtOpenTypeKey()
  1501. //===========================================================================
  1502. //===========================================================================
  1503. //===========================================================================
  1504. //===========================================================================
  1505. //===========================================================================
  1506. //===========================================================================