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.

746 lines
20 KiB

  1. /*****************************************************************************
  2. *
  3. * DIDEnum.c
  4. *
  5. * Copyright (c) 1996 Microsoft Corporation. All Rights Reserved.
  6. *
  7. * Abstract:
  8. *
  9. * The IDirectInput device enumerator.
  10. *
  11. * We don't bother making this an honest OLE enumerator because
  12. * there's no point. There's no way to access it from the outside.
  13. *
  14. * Contents:
  15. *
  16. * CDIDEnum_New
  17. * CDIDEnum_Next
  18. * CDIDEnum_Release
  19. *
  20. *****************************************************************************/
  21. #include "dinputpr.h"
  22. /*****************************************************************************
  23. *
  24. * The sqiffle for this file.
  25. *
  26. *****************************************************************************/
  27. #define sqfl sqflDEnum
  28. /*****************************************************************************
  29. *
  30. * @doc INTERNAL
  31. *
  32. * @struct _CDIDEnum |
  33. *
  34. * Records the state of a device enumeration. Note that this
  35. * is not free-threaded.
  36. *
  37. * @field PDIW | pdiW |
  38. *
  39. * The <i IDirectInputW> object that owns the enumeration.
  40. *
  41. * @field DWORD | dwDevType |
  42. *
  43. * Device type filter.
  44. *
  45. * @field DWORD | edfl |
  46. *
  47. * Enumeration flags.
  48. *
  49. * @field int | idosdStatic |
  50. *
  51. * The next static device to enumerate. Static devices live
  52. * in <c c_rgdosdStatic>.
  53. *
  54. * @field DWORD | dwVer |
  55. *
  56. * Version of DirectX we are emulating.
  57. *
  58. * If we are emulating DirectX 3.0 or less, then don't
  59. * reveal joysticks.
  60. *
  61. * @field int | idosdDynamic |
  62. *
  63. * The next dynamic device to enumerate. Dyanmic devices
  64. * are kept in the <e CDIDEnum.rgdosdDynamic> array. They
  65. * are snapshotted into the enumeration structure to avoid
  66. * race conditions if a device comes or goes while we are
  67. * in the middle of an enumeration.
  68. *
  69. * @field PHIDDEVICELIST | phdl |
  70. *
  71. * List of HID devices to be returned by the enumeration.
  72. *
  73. *****************************************************************************/
  74. typedef struct _CDIDEnum
  75. {
  76. D(DWORD dwSig;)
  77. PDIW pdiW;
  78. DWORD dwDevType;
  79. DWORD edfl;
  80. int idosdStatic;
  81. DWORD dwVer;
  82. int idosdDynamic;
  83. PHIDDEVICELIST phdl;
  84. PDIDW pdidW;
  85. } DENUM, *PDENUM, **PPDENUM;
  86. #define CDIDENUM_SIGNATURE 0x4D554E45 /* "ENUM" */
  87. #define AssertPde(pde) AssertF((pde)->dwSig == CDIDENUM_SIGNATURE)
  88. /*****************************************************************************
  89. *
  90. * @doc INTERNAL
  91. *
  92. * @global DIOBJECTSTATICDATA | c_rgdosdStatic[] |
  93. *
  94. * Right now, the list of device is static and hard-coded.
  95. * Eventually, we'll
  96. * use plug and play to enumerate devices of class "input" and
  97. * get information from their config/software keys.
  98. *
  99. *****************************************************************************/
  100. #pragma BEGIN_CONST_DATA
  101. /*
  102. * Our array of static joystick instance guids.
  103. *
  104. */
  105. GUID rgGUID_Joystick[cJoyMax] = {
  106. { 0x6F1D2B70,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00},
  107. { 0x6F1D2B71,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00},
  108. { 0x6F1D2B72,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00},
  109. { 0x6F1D2B73,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00},
  110. { 0x6F1D2B74,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00},
  111. { 0x6F1D2B75,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00},
  112. { 0x6F1D2B76,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00},
  113. { 0x6F1D2B77,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00},
  114. { 0x6F1D2B78,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00},
  115. { 0x6F1D2B79,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00},
  116. { 0x6F1D2B7A,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00},
  117. { 0x6F1D2B7B,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00},
  118. { 0x6F1D2B7C,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00},
  119. { 0x6F1D2B7D,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00},
  120. { 0x6F1D2B7E,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00},
  121. { 0x6F1D2B7F,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00},
  122. };
  123. #if cJoyMax != 16
  124. #error rgGUID_Joystick supports only 16 joysticks.
  125. #endif
  126. /*
  127. * Note that we recycle the SysMouse GUID as the instance GUID too,
  128. * since there will never be more than one system mouse installed in
  129. * the system. Similarly for SysKeyboard.
  130. */
  131. DIOBJECTSTATICDATA c_rgdosdStatic[] = {
  132. { &GUID_SysMouse, DI8DEVTYPE_MOUSE, CMouse_New,},
  133. { &GUID_SysMouseEm, DI8DEVTYPE_MOUSE, CMouse_New,},
  134. { &GUID_SysMouseEm2, DI8DEVTYPE_MOUSE, CMouse_New,},
  135. { &GUID_SysKeyboard, DI8DEVTYPE_KEYBOARD, CKbd_New,},
  136. { &GUID_SysKeyboardEm, DI8DEVTYPE_KEYBOARD, CKbd_New,},
  137. { &GUID_SysKeyboardEm2, DI8DEVTYPE_KEYBOARD, CKbd_New,},
  138. #ifndef WINNT
  139. /*
  140. * On WINNT all joysticks are HID devices.
  141. * So it is pointless to include predefined
  142. * Joystick GUIDs
  143. */
  144. #define MAKEJOY(n) \
  145. { &rgGUID_Joystick[n],DI8DEVCLASS_GAMECTRL, CJoy_New, }
  146. MAKEJOY( 0),
  147. MAKEJOY( 1),
  148. MAKEJOY( 2),
  149. MAKEJOY( 3),
  150. MAKEJOY( 4),
  151. MAKEJOY( 5),
  152. MAKEJOY( 6),
  153. MAKEJOY( 7),
  154. MAKEJOY( 8),
  155. MAKEJOY( 9),
  156. MAKEJOY(10),
  157. MAKEJOY(11),
  158. MAKEJOY(12),
  159. MAKEJOY(13),
  160. MAKEJOY(14),
  161. MAKEJOY(15),
  162. #undef MAKEJOY
  163. #endif
  164. };
  165. #pragma END_CONST_DATA
  166. /*****************************************************************************
  167. *
  168. * @doc INTERNAL
  169. *
  170. * @func HRESULT | hresFindInstanceGUID |
  171. *
  172. * Locates information given an instance GUID.
  173. *
  174. * @parm IN PCGUID | pguid |
  175. *
  176. * The instance GUID to be located.
  177. *
  178. * @parm OUT CREATEDCB * | pcdcb |
  179. *
  180. * Receives pointer to the <f CreateDcb> function for the object.
  181. *
  182. *****************************************************************************/
  183. HRESULT EXTERNAL
  184. hresFindInstanceGUID_(PCGUID pguid, CREATEDCB *pcdcb,
  185. LPCSTR s_szProc, int iarg)
  186. {
  187. HRESULT hres;
  188. EnterProcS(hresFindInstance, (_ "G", pguid));
  189. if(SUCCEEDED(hres = hresFullValidGuid(pguid, iarg)))
  190. {
  191. int idosd;
  192. /*
  193. * First try the list of static devices. Since this
  194. * list never changes, we don't need to protect it
  195. * with a critical section.
  196. */
  197. for(idosd = 0; idosd < cA(c_rgdosdStatic); idosd++)
  198. {
  199. if(IsEqualGUID(pguid, c_rgdosdStatic[idosd].rguidInstance))
  200. {
  201. *pcdcb = c_rgdosdStatic[idosd].CreateDcb;
  202. goto done;
  203. }
  204. }
  205. /*
  206. * So it wasn't one of the static devices. See if it's
  207. * one of the dynamic HID devices we've already found.
  208. */
  209. hres = hresFindHIDInstanceGUID(pguid, pcdcb);
  210. if(FAILED(hres))
  211. {
  212. /*
  213. * Not on our list of dynamic HID devices.
  214. * Re-enumerate them and try again. Maybe it was
  215. * for a device that we recently added.
  216. */
  217. DIHid_BuildHidList(TRUE);
  218. hres = hresFindHIDInstanceGUID(pguid, pcdcb);
  219. }
  220. if(FAILED(hres))
  221. {
  222. #ifdef WINNT
  223. /*
  224. * NT Bug#351951.
  225. * If they are directly asking for one of the predefined joystick
  226. * IDs then see if we have a device mapped to that ID. If so,
  227. * pretend they asked for that GUID instead.
  228. */
  229. /*
  230. * Weakly Assert the range of predefined static joystick instance GUIDs
  231. */
  232. AssertF( ( rgGUID_Joystick[0].Data1 & 0x0f ) == 0 );
  233. AssertF( ( rgGUID_Joystick[0x0f].Data1 & 0x0f ) == 0x0f );
  234. /*
  235. * Check the GUID is the same as the first static one ignoring LS 4 bits
  236. */
  237. if( ( (pguid->Data1 & 0xf0) == (rgGUID_Joystick[0].Data1 & 0xf0) )
  238. && !memcmp( ((PBYTE)&rgGUID_Joystick)+1, ((PBYTE)pguid)+1, sizeof(*pguid) - 1 ) )
  239. {
  240. RPF("%s: Using predefined instance GUIDs is bad and should not work!", s_szProc);
  241. if( phdiFindJoyId( pguid->Data1 & 0x0f ) )
  242. {
  243. *pcdcb = CHid_New;
  244. hres = S_OK;
  245. }
  246. else
  247. {
  248. *pcdcb = 0;
  249. hres = DIERR_DEVICENOTREG;
  250. }
  251. }
  252. else
  253. {
  254. RPF("%s: Warning: GUID is not installed in this system", s_szProc);
  255. *pcdcb = 0;
  256. hres = DIERR_DEVICENOTREG;
  257. }
  258. #else
  259. RPF("%s: Warning: GUID is not installed in this system", s_szProc);
  260. *pcdcb = 0;
  261. hres = DIERR_DEVICENOTREG;
  262. #endif
  263. }
  264. }
  265. done:;
  266. ExitOleProcPpv(pcdcb);
  267. return hres;
  268. }
  269. /*****************************************************************************
  270. *
  271. * @doc INTERNAL
  272. *
  273. * @func void | CDIDEnum_Release |
  274. *
  275. * Free the enumeration object and its associated resources.
  276. *
  277. * @parm CDIDEnum * | pde |
  278. *
  279. * The enumeration state to be released.
  280. *
  281. *****************************************************************************/
  282. void EXTERNAL
  283. CDIDEnum_Release(PDENUM pde)
  284. {
  285. EnterProcI(CDIDEnum_Release, (_ "p", pde));
  286. AssertPde(pde);
  287. /*
  288. * First, release any last enumerated device
  289. */
  290. if( pde->pdidW )
  291. {
  292. OLE_Release(pde->pdidW);
  293. }
  294. OLE_Release(pde->pdiW);
  295. FreePpv(&pde->phdl);
  296. FreePv(pde);
  297. }
  298. #define S_SKIP hresUs(2)
  299. /*****************************************************************************
  300. *
  301. * @doc INTERNAL
  302. *
  303. * @func HRESULT | hresIsDeviceTypeMatch |
  304. *
  305. * Test if a device type matches the filter.
  306. *
  307. * @parm BYTE | bFilter |
  308. *
  309. * The device type or class to filter by.
  310. *
  311. * @parm BYTE | bDevType |
  312. *
  313. * The device type to be tested.
  314. *
  315. * @returns
  316. *
  317. * Returns <c S_OK> if the device matches the filter
  318. * or <c S_SKIP> if it does not.
  319. *
  320. *****************************************************************************/
  321. HRESULT hresIsDeviceTypeMatch
  322. (
  323. BYTE bFilter,
  324. BYTE bDevType
  325. )
  326. {
  327. HRESULT hres;
  328. AssertF( bDevType >= DI8DEVTYPE_MIN );
  329. AssertF( bDevType < DI8DEVTYPE_MAX );
  330. if( ( bFilter == 0 )
  331. || ( bFilter == bDevType ) )
  332. {
  333. hres = S_OK;
  334. }
  335. else
  336. {
  337. hres = S_SKIP;
  338. switch( bFilter )
  339. {
  340. case DI8DEVCLASS_DEVICE:
  341. if( bDevType == DI8DEVTYPE_DEVICE )
  342. {
  343. hres = S_OK;
  344. }
  345. break;
  346. case DI8DEVCLASS_POINTER:
  347. if( ( bDevType == DI8DEVTYPE_MOUSE )
  348. || ( bDevType == DI8DEVTYPE_SCREENPOINTER ) )
  349. {
  350. hres = S_OK;
  351. }
  352. break;
  353. case DI8DEVCLASS_KEYBOARD:
  354. if( bDevType == DI8DEVTYPE_KEYBOARD )
  355. {
  356. hres = S_OK;
  357. }
  358. break;
  359. case DI8DEVCLASS_GAMECTRL:
  360. if( (( bDevType >= DI8DEVTYPE_GAMEMIN )
  361. && ( bDevType < DI8DEVTYPE_GAMEMAX )) ||
  362. ( bDevType == DI8DEVTYPE_SCREENPOINTER ) || /* Windows bug 385284 (jacklin) - DI8DEVCLASS_GAMECTRL should */
  363. ( bDevType == DI8DEVTYPE_SUPPLEMENTAL ) ) /* include DI8DEVTYPE_SCREENPOINTER and DI8DEVTYPE_SUPPLEMENTAL */
  364. {
  365. hres = S_OK;
  366. }
  367. break;
  368. }
  369. }
  370. return hres;
  371. }
  372. /*****************************************************************************
  373. *
  374. * @doc INTERNAL
  375. *
  376. * @func HRESULT | CDIDEnum_Next |
  377. *
  378. * Return the next device.
  379. *
  380. * Note that this is not the same as the OLE <mf IEnumXxx::Next>
  381. * function. Not that it'd be hard to convert over; it's just
  382. * not needed yet.
  383. *
  384. * @parm CDIDEnum * | pde |
  385. *
  386. * Maintains enumeration state.
  387. *
  388. * @parm LPGUID | pguid |
  389. *
  390. * Receives the enumerated GUID.
  391. *
  392. * @parm LPDIDEVICEINSTANCEW | pddiW |
  393. *
  394. * Receives device attributes.
  395. *
  396. * @returns
  397. *
  398. * Returns <c S_OK> if the object was successfully obtained,
  399. * or <c S_FALSE> if there aren't any more objects.
  400. *
  401. * Warning! <f CDIObj_EnumDevicesW> assumes that this function
  402. * cannot fail.
  403. *
  404. *****************************************************************************/
  405. STDMETHODIMP
  406. CDIDEnum_Next(PDENUM pde, LPDIDEVICEINSTANCEW pddiW)
  407. {
  408. HRESULT hres;
  409. EnterProcI(CDIDEnum_Next, (_ "p", pde));
  410. AssertPde(pde);
  411. AssertF(pddiW->dwSize == cbX(*pddiW));
  412. /*
  413. * Keep going until something works.
  414. */
  415. do
  416. {
  417. PDIOBJECTSTATICDATA pdosd;
  418. /*
  419. * Release any previously enumerated or looked at device
  420. */
  421. if( pde->pdidW )
  422. {
  423. OLE_Release(pde->pdidW);
  424. pde->pdidW = NULL;
  425. }
  426. /*
  427. * Pull one from the static list first.
  428. * If that is empty, then pull from the dynamic list.
  429. * If that is empty, then we're done.
  430. */
  431. if(pde->idosdStatic < cA(c_rgdosdStatic))
  432. {
  433. pdosd = &c_rgdosdStatic[pde->idosdStatic++];
  434. } else if(pde->phdl && pde->idosdDynamic < pde->phdl->chdi)
  435. {
  436. pdosd = &pde->phdl->rghdi[pde->idosdDynamic].osd;
  437. pdosd->rguidInstance = &pde->phdl->rghdi[pde->idosdDynamic].guid;
  438. pde->idosdDynamic++;
  439. } else
  440. {
  441. hres = S_FALSE;
  442. goto done;
  443. }
  444. /*
  445. * ISSUE-2001/03/03-MarcAnd Filtered device enumerations are slow
  446. * Since DI8DEVTYPEs can be generated on the fly and can be
  447. * overridden we can no longer filter before creating the device.
  448. * This is badness. Ideally, we need to add the WinMM and system
  449. * devices to our dynamic device list, tidy that info up and add
  450. * all the info we need to that list.
  451. */
  452. if( 1 )
  453. {
  454. hres = IDirectInput_CreateDevice(pde->pdiW, pdosd->rguidInstance,
  455. (PV)&pde->pdidW, 0);
  456. if(SUCCEEDED(hres))
  457. {
  458. if(CDIObj_TestDeviceFlags(pde->pdidW, pde->edfl) == S_OK)
  459. {
  460. pddiW->dwSize = cbX(*pddiW);
  461. hres = IDirectInputDevice_GetDeviceInfo(pde->pdidW, pddiW);
  462. if( SUCCEEDED( hres ) )
  463. {
  464. AssertF( IsEqualGUID(pdosd->rguidInstance, &pddiW->guidInstance) );
  465. hres = hresIsDeviceTypeMatch( GET_DIDEVICE_TYPE(pde->dwDevType), GET_DIDEVICE_TYPE(pddiW->dwDevType) );
  466. }
  467. } else
  468. {
  469. hres = S_SKIP;
  470. }
  471. } else
  472. {
  473. hres = S_SKIP;
  474. }
  475. } else
  476. {
  477. hres = S_SKIP;
  478. }
  479. } while(hres == S_SKIP);
  480. done:;
  481. AssertF(hres == S_OK || hres == S_FALSE);
  482. ScrambleBit(&pddiW->dwDevType, DIDEVTYPE_RANDOM);
  483. return hres;
  484. }
  485. STDMETHODIMP
  486. CDIDEnum_InternalNext(PDENUM pde, LPDIDEVICEINSTANCEW pddiW, LPDIRECTINPUTDEVICE8W *ppdid8W)
  487. {
  488. HRESULT hres;
  489. EnterProcI(CDIDEnum_Next, (_ "p", pde));
  490. AssertPde(pde);
  491. AssertF(pddiW->dwSize == cbX(*pddiW));
  492. /*
  493. * Keep going until something works.
  494. */
  495. do
  496. {
  497. PDIOBJECTSTATICDATA pdosd;
  498. /*
  499. * Release any previously enumerated or looked at device
  500. */
  501. if( pde->pdidW )
  502. {
  503. OLE_Release(pde->pdidW);
  504. pde->pdidW = NULL;
  505. }
  506. /*
  507. * Pull one from the static list first.
  508. * If that is empty, then pull from the dynamic list.
  509. * If that is empty, then we're done.
  510. */
  511. if(pde->idosdStatic < cA(c_rgdosdStatic))
  512. {
  513. pdosd = &c_rgdosdStatic[pde->idosdStatic++];
  514. } else if(pde->phdl && pde->idosdDynamic < pde->phdl->chdi)
  515. {
  516. pdosd = &pde->phdl->rghdi[pde->idosdDynamic].osd;
  517. pdosd->rguidInstance = &pde->phdl->rghdi[pde->idosdDynamic].guid;
  518. pde->idosdDynamic++;
  519. } else
  520. {
  521. hres = S_FALSE;
  522. goto done;
  523. }
  524. hres = IDirectInput_CreateDevice(pde->pdiW, pdosd->rguidInstance,
  525. (PV)&pde->pdidW, 0);
  526. if(SUCCEEDED(hres))
  527. {
  528. if(CDIObj_TestDeviceFlags(pde->pdidW, pde->edfl) == S_OK)
  529. {
  530. pddiW->dwSize = cbX(*pddiW);
  531. hres = IDirectInputDevice_GetDeviceInfo(pde->pdidW, pddiW);
  532. *ppdid8W = (LPDIRECTINPUTDEVICE8W)pde->pdidW;
  533. AssertF(fLimpFF(SUCCEEDED(hres),
  534. IsEqualGUID(pdosd->rguidInstance,
  535. &pddiW->guidInstance)));
  536. /*
  537. * Do filtering here (see ISSUE in CDIDEnum_Next for why)
  538. */
  539. hres = hresIsDeviceTypeMatch( GET_DIDEVICE_TYPE(pde->dwDevType), GET_DIDEVICE_TYPE(pddiW->dwDevType) );
  540. } else
  541. {
  542. hres = S_SKIP;
  543. }
  544. } else
  545. {
  546. hres = S_SKIP;
  547. }
  548. } while(hres == S_SKIP);
  549. done:;
  550. AssertF(hres == S_OK || hres == S_FALSE);
  551. ScrambleBit(&pddiW->dwDevType, DIDEVTYPE_RANDOM);
  552. return hres;
  553. }
  554. /*****************************************************************************
  555. *
  556. * @doc INTERNAL
  557. *
  558. * @func HRESULT | CDIDEnum_New |
  559. *
  560. * Create an enumeration object.
  561. *
  562. * The enumeration object snapshots the system device state
  563. * and farms them out one at a time.
  564. *
  565. * @parm PDIW | pdiW |
  566. *
  567. * Parent <i IDirectInputW> we piggyback off of for device
  568. * creation.
  569. *
  570. * @field DWORD | dwDevType |
  571. *
  572. * Device type filter.
  573. *
  574. * @field DWORD | edfl |
  575. *
  576. * Enumeration flags.
  577. *
  578. * @field DWORD | dwVer |
  579. *
  580. * Version of DirectX we are emulating.
  581. *
  582. * This should always be DirectX 8.0.
  583. *
  584. * @parm CDIDEnum ** | ppde |
  585. *
  586. * Receives the enumeration object.
  587. *
  588. * @returns
  589. *
  590. * Returns <c S_OK> on success or an error code on failure.
  591. *
  592. *****************************************************************************/
  593. STDMETHODIMP
  594. CDIDEnum_New(PDIW pdiW, DWORD dwDevType, DWORD edfl, DWORD dwVer, PPDENUM ppde)
  595. {
  596. HRESULT hres;
  597. EnterProcI(CDIDEnum_New, (_ "pxx", pdiW, dwDevType, edfl));
  598. /*
  599. * Refresh the HID device list so the enumeration is fresh.
  600. */
  601. DIHid_BuildHidList(TRUE);
  602. hres = AllocCbPpv(cbX(CDIDEnum), ppde);
  603. if(SUCCEEDED(hres))
  604. {
  605. PDENUM pde = *ppde;
  606. D(pde->dwSig = CDIDENUM_SIGNATURE);
  607. pde->pdiW = pdiW;
  608. pde->dwDevType = dwDevType;
  609. pde->edfl = edfl;
  610. pde->dwVer = dwVer;
  611. /*
  612. * Make sure last enumerated device pointer is cleared
  613. */
  614. pde->pdidW = NULL;
  615. AssertF(pde->idosdStatic == 0);
  616. /*
  617. * If enumerating only HID devices, then skip over all
  618. * the static (non-HID) devices. This is important so
  619. * we don't go into infinite recursion death with WINMM.DLL,
  620. * which does an enumeration to find HID joysticks
  621. * in the first place.
  622. */
  623. if(pde->dwDevType & DIDEVTYPE_HID)
  624. {
  625. pde->idosdStatic = cA(c_rgdosdStatic);
  626. }
  627. AssertF(pde->idosdDynamic == 0);
  628. /*
  629. * Clone the device list. This must be done under the
  630. * critical section to avoid races.
  631. */
  632. DllEnterCrit();
  633. if(g_phdl)
  634. {
  635. hres = AllocCbPpv(cbHdlChdi(g_phdl->chdi), &pde->phdl);
  636. if(SUCCEEDED(hres))
  637. {
  638. CopyMemory(pde->phdl, g_phdl, cbHdlChdi(g_phdl->chdi));
  639. SquirtSqflPtszV(sqfl, TEXT("%S: Have %d HID devices"),
  640. s_szProc, pde->phdl->chdi);
  641. hres = S_OK;
  642. }
  643. } else
  644. {
  645. hres = S_OK;
  646. }
  647. DllLeaveCrit();
  648. if(SUCCEEDED(hres))
  649. {
  650. OLE_AddRef(pde->pdiW);
  651. hres = S_OK;
  652. }
  653. }
  654. ExitOleProcPpv(ppde);
  655. return hres;
  656. }