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.

3158 lines
92 KiB

  1. //===========================================================================
  2. // dmtcfg.cpp
  3. //
  4. // File / code creation functionality
  5. //
  6. // Functions:
  7. // dmtcfgCreatePropertySheet
  8. // dmtcfgDlgProc
  9. // dmtcfgOnInitDialog
  10. // dmtcfgOnClose
  11. // dmtcfgOnCommand
  12. // dmtcfgOnNotify
  13. // dmtcfgCreateGenreList
  14. // dmtcfgFreeGenreList
  15. // dmtcfgCreateSubGenreList
  16. // dmtcfgFreeSubGenreList
  17. // dmtcfgCreateActionList
  18. // dmtcfgFreeActionList
  19. //
  20. // History:
  21. // 08/20/1999 - davidkl - created
  22. //===========================================================================
  23. #include "dimaptst.h"
  24. #include "dmtinput.h"
  25. //#include "dmtwrite.h"
  26. #include "dmtcfg.h"
  27. //---------------------------------------------------------------------------
  28. //===========================================================================
  29. // dmtcfgCreatePropertySheet
  30. //
  31. // Create property sheet dialog for device action map configuration
  32. //
  33. // Parameters:
  34. // HINSTANCE hinst - app instance handle
  35. // HWND hwndParent - parent window handle
  36. // LPSTR szSelectedGenre
  37. // DMTGENRE_NODE* pGenreList
  38. // DMTGENRE_NODE* pDeviceNode
  39. // BOOL fStartWithDefaults
  40. //
  41. // Returns: HRESULT
  42. //
  43. // History:
  44. // 08/23/1999 - davidkl - created
  45. // 09/08/1999 - davidkl - changed param list
  46. //===========================================================================
  47. HRESULT dmtcfgCreatePropertySheet(HINSTANCE hinst,
  48. HWND hwndParent,
  49. LPSTR szSelectedGenre,
  50. DMTGENRE_NODE *pGenreList,
  51. DMTDEVICE_NODE *pDeviceNode,
  52. BOOL fStartWithDefaults)
  53. {
  54. HRESULT hRes = S_OK;
  55. UINT u = 0;
  56. UINT uSel = 0;
  57. DMTGENRE_NODE *pNode = NULL;
  58. PROPSHEETPAGEA *pPages = NULL;
  59. PROPSHEETHEADERA psh;
  60. char szCaption[MAX_PATH];
  61. DMT_APPINFO *pdmtai = NULL;
  62. DMTDEVICE_NODE dmtd;
  63. // validate pGenreList
  64. if(IsBadReadPtr((void*)pGenreList, sizeof(DMTGENRE_NODE)))
  65. {
  66. DPF(0, "dmtcfgCreatePropertySheet - invalid pGenreList (%016Xh)",
  67. pGenreList);
  68. return E_POINTER;
  69. }
  70. // validate pDeviceNode
  71. if(IsBadReadPtr((void*)pDeviceNode, sizeof(DMTDEVICE_NODE)))
  72. {
  73. DPF(0, "dmtcfgCreatePropertySheet - invalid pDeviceNode (%016Xh)",
  74. pDeviceNode);
  75. return E_POINTER;
  76. }
  77. __try
  78. {
  79. // count the genres
  80. //
  81. // find the node we care about
  82. u = 0;
  83. pNode = pGenreList;
  84. while(pNode)
  85. {
  86. // if we find our genre, start on that page
  87. if(!lstrcmpiA(szSelectedGenre, pNode->szName))
  88. {
  89. uSel = u;
  90. }
  91. // increment the number of genres
  92. u++;
  93. pNode = pNode->pNext;
  94. }
  95. // allocate the page array (dw pages)
  96. pPages = (PROPSHEETPAGEA*)LocalAlloc(LMEM_FIXED,
  97. sizeof(PROPSHEETPAGEA) * u);
  98. if(!pPages)
  99. {
  100. DPF(0, "dmtcfgCreatePropertySheet - insufficient mempory to "
  101. "allocate pPages array");
  102. hRes = E_OUTOFMEMORY;
  103. __leave;
  104. }
  105. // add device name to caption
  106. wsprintfA(szCaption,
  107. "Configure Device Action Map - %s",
  108. pDeviceNode->szName);
  109. // strip the next ptr from the selected device node
  110. CopyMemory((void*)&dmtd, (void*)pDeviceNode, sizeof(DMTDEVICE_NODE));
  111. dmtd.pNext = NULL;
  112. // allocate app info data struct for pages
  113. pdmtai = (DMT_APPINFO*)LocalAlloc(LMEM_FIXED,
  114. u * sizeof(DMT_APPINFO));
  115. if(!pdmtai)
  116. {
  117. hRes = E_OUTOFMEMORY;
  118. __leave;
  119. }
  120. ZeroMemory((void*)pdmtai, u * sizeof(DMT_APPINFO));
  121. // prepare property sheet header
  122. psh.dwSize = sizeof(PROPSHEETHEADERA);
  123. psh.dwFlags = PSH_PROPSHEETPAGE |
  124. PSP_USETITLE | PSH_NOAPPLYNOW;
  125. psh.hwndParent = hwndParent;
  126. psh.hInstance = hinst;
  127. psh.pszCaption = szCaption;
  128. psh.nPages = u;
  129. psh.nStartPage = uSel;
  130. psh.ppsp = pPages;
  131. // describe sheets
  132. pNode = pGenreList;
  133. for(u = 0; u < (DWORD)(psh.nPages); u++)
  134. {
  135. if(!pNode)
  136. {
  137. DPF(0, "dmtcfgCreatePropertySheet - we messed up! "
  138. "we allocated less than %d pages",
  139. psh.nPages);
  140. DPF(0, "PLEASE find someone to look at this NOW");
  141. hRes = E_UNEXPECTED;
  142. DebugBreak();
  143. __leave;
  144. }
  145. // populate the app info for the page
  146. (pdmtai + u)->pGenreList = pNode;
  147. (pdmtai + u)->pDeviceList = &dmtd;
  148. (pdmtai + u)->fStartWithDefaults = fStartWithDefaults;
  149. (pdmtai + u)->fLaunchCplEditMode = FALSE;
  150. // populate the page array entry
  151. ZeroMemory((void*)(pPages + u), sizeof(PROPSHEETPAGEA));
  152. (pPages + u)->dwSize = sizeof(PROPSHEETPAGEA);
  153. (pPages + u)->dwFlags = PSP_USETITLE;
  154. (pPages + u)->hInstance = hinst;
  155. (pPages + u)->pszTemplate = MAKEINTRESOURCEA(IDD_CONFIGURE_MAPPING_PAGE);
  156. (pPages + u)->pfnDlgProc = (DLGPROC)dmtcfgDlgProc;
  157. (pPages + u)->pszTitle = pNode->szName;
  158. (pPages + u)->lParam = (LPARAM)(pdmtai + u);
  159. // next node
  160. pNode = pNode->pNext;
  161. }
  162. // create this thing
  163. if(0 > PropertySheetA(&psh))
  164. {
  165. DPF(0, "dmtcfgCreatePropertySheet - dialog creation failed (%08Xh)",
  166. GetLastError());
  167. hRes = E_UNEXPECTED;
  168. __leave;
  169. }
  170. }
  171. __finally
  172. {
  173. // free the app info array
  174. if(pdmtai)
  175. {
  176. if(LocalFree((HLOCAL)pdmtai))
  177. {
  178. DPF(0, "dmtcfgCreaatePropertySheet - !!!MEMORY LEAK!!! "
  179. "LocalFree(pdmtai) failed (%08X)",
  180. GetLastError());
  181. hRes = S_FALSE;
  182. }
  183. pdmtai = NULL;
  184. }
  185. // free the page array
  186. if(pPages)
  187. {
  188. if(LocalFree((HLOCAL)pPages))
  189. {
  190. DPF(0, "dmtcfgCreaatePropertySheet - !!!MEMORY LEAK!!! "
  191. "LocalFree(pPages) failed (%08X)",
  192. GetLastError());
  193. hRes = S_FALSE;
  194. }
  195. pPages = NULL;
  196. }
  197. }
  198. // done
  199. return hRes;
  200. } //*** end dmtcfgCreatePropertySheet()
  201. //===========================================================================
  202. // dmtcfgDlgProc
  203. //
  204. // Configure Device Action Map dialog processing function
  205. //
  206. // Parameters: (see SDK help for parameter details)
  207. // HWND hwnd
  208. // UINT uMsg
  209. // WPARAM wparam
  210. // LPARAM lparam
  211. //
  212. // Returns: (see SDK help for return value details)
  213. // BOOL
  214. //
  215. // History:
  216. // 08/20/1999 - davidkl - created
  217. //===========================================================================
  218. BOOL CALLBACK dmtcfgDlgProc(HWND hwnd,
  219. UINT uMsg,
  220. WPARAM wparam,
  221. LPARAM lparam)
  222. {
  223. switch(uMsg)
  224. {
  225. case WM_INITDIALOG:
  226. return dmtcfgOnInitDialog(hwnd,
  227. (HWND)wparam,
  228. lparam);
  229. case WM_COMMAND:
  230. return dmtcfgOnCommand(hwnd,
  231. LOWORD(wparam),
  232. (HWND)lparam,
  233. HIWORD(wparam));
  234. case WM_NOTIFY:
  235. return dmtcfgOnNotify(hwnd,
  236. (PSHNOTIFY *)lparam);
  237. case WM_DMT_UPDATE_LISTS:
  238. return dmtcfgOnUpdateLists(hwnd);
  239. }
  240. return FALSE;
  241. } //*** end dmtcfgDlgProc()
  242. //===========================================================================
  243. // dmtcfgOnInitDialog
  244. //
  245. // Handle WM_INITDIALOG processing for the config device box
  246. //
  247. // Parameters:
  248. // HWND hwnd - handle to property page
  249. // HWND hwndFocus - handle of ctrl with focus
  250. // LPARAM lparam - user data (in this case, PROPSHEETPAGE*)
  251. //
  252. // Returns: BOOL
  253. //
  254. // History:
  255. // 08/20/1999 - davidkl - created
  256. //===========================================================================
  257. BOOL dmtcfgOnInitDialog(HWND hwnd,
  258. HWND hwndFocus,
  259. LPARAM lparam)
  260. {
  261. HRESULT hRes = S_OK;
  262. PROPSHEETPAGEA *ppsp = (PROPSHEETPAGEA*)lparam;
  263. DMTGENRE_NODE *pGenre = NULL;
  264. DMTSUBGENRE_NODE *pSubNode = NULL;
  265. DMTMAPPING_NODE *pMapNode = NULL;
  266. //LONG lPrev = 0L;
  267. //JJ 64Bit Compat
  268. LONG_PTR lPrev = 0;
  269. // int nIdx = 0;
  270. LONG_PTR nIdx = 0;
  271. DMTDEVICE_NODE *pDevice = NULL;
  272. DMT_APPINFO *pdmtai = NULL;
  273. UINT u = 0;
  274. WORD wTypeCtrl = 0;
  275. DIACTIONFORMATA diaf;
  276. DPF(5, "dmtcfgOnInitDialog");
  277. // validate ppsp (lparam)
  278. if(IsBadWritePtr((void*)ppsp, sizeof(PROPSHEETPAGEA)))
  279. {
  280. DPF(0, "dmtcfgOnInitDialog - invalid lParam (%016Xh)",
  281. ppsp);
  282. return FALSE;
  283. }
  284. // pdmtai == ppsp->lParam
  285. pdmtai = (DMT_APPINFO*)(ppsp->lParam);
  286. // validate pdmtai
  287. if(IsBadWritePtr((void*)pdmtai, sizeof(DMT_APPINFO)))
  288. {
  289. DPF(0, "dmtcfgOnInitDialog - invalid ppsp.ptp (%016Xh)",
  290. pdmtai);
  291. return FALSE;
  292. }
  293. // pGenre == pdmtai->pGenreList
  294. pGenre = pdmtai->pGenreList;
  295. // valdiate pGenre
  296. if(IsBadWritePtr((void*)pGenre, sizeof(DMTGENRE_NODE)))
  297. {
  298. DPF(0, "dmtcfgOnInitDialog - invalid pGenre (%016Xh)",
  299. pGenre);
  300. return FALSE;
  301. }
  302. // pDevice == pdmtai->pDeviceList
  303. pDevice = pdmtai->pDeviceList;
  304. // valdiate pGenre
  305. if(IsBadWritePtr((void*)pDevice, sizeof(DMTDEVICE_NODE)))
  306. {
  307. DPF(0, "dmtcfgOnInitDialog - invalid pDevice (%016Xh)",
  308. pDevice);
  309. return FALSE;
  310. }
  311. // change the property sheet dialog button text
  312. // Ok -> Save
  313. SetWindowTextA(GetDlgItem(GetParent(hwnd), IDOK),
  314. "&Save");
  315. // Apply -> Load
  316. //SetWindowTextA(GetDlgItem(GetParent(hwnd), IDC_PS_APPLY),
  317. // "Load");
  318. // Cancel -> Close
  319. SetWindowTextA(GetDlgItem(GetParent(hwnd), IDCANCEL),
  320. "&Close");
  321. __try
  322. {
  323. // store the app info in the property page's user data
  324. SetLastError(0);
  325. //lPrev = SetWindowLong(hwnd,
  326. // GWL_USERDATA,
  327. // (LONG)pdmtai);
  328. //JJ 64Bit Compat
  329. lPrev = SetWindowLongPtr(hwnd,
  330. GWLP_USERDATA,
  331. (LONG_PTR)pdmtai);
  332. if(!lPrev && GetLastError())
  333. {
  334. // serious app problem.
  335. // we need to stop things right here and now
  336. DPF(0, "dmtcfgOnInitDialog - This is bad... "
  337. "We failed to store pdmtai");
  338. DPF(0, "dmtcfgOnInitDialog - Please find someone "
  339. "to look at this right away");
  340. DebugBreak();
  341. hRes = E_FAIL;
  342. __leave;
  343. }
  344. // walk the list and populate the subgenre list box
  345. //
  346. // store the ptr to the subgenre node in the listbox
  347. // entry user data
  348. pSubNode = pGenre->pSubGenreList;
  349. while(pSubNode)
  350. {
  351. // add the subgenre name to the list
  352. nIdx = SendMessageA(GetDlgItem(hwnd, IDC_SUBGENRE),
  353. CB_ADDSTRING,
  354. 0,
  355. (LPARAM)(pSubNode->szName));
  356. // store the subgenre node in the list entry
  357. SendMessageA(GetDlgItem(hwnd, IDC_SUBGENRE),
  358. CB_SETITEMDATA,
  359. nIdx,
  360. (LPARAM)pSubNode);
  361. // if the user has requested default mappings
  362. // get them for the specified device
  363. if(pdmtai->fStartWithDefaults)
  364. {
  365. // walk the mappings list until the selected
  366. // device is found
  367. pMapNode = pSubNode->pMappingList;
  368. while(pMapNode)
  369. {
  370. // try to match on guidInstance
  371. if(IsEqualGUID(pDevice->guidInstance,
  372. pMapNode->guidInstance))
  373. {
  374. // match found
  375. break;
  376. }
  377. // next mapping
  378. pMapNode = pMapNode->pNext;
  379. }
  380. if(pMapNode)
  381. {
  382. ZeroMemory((void*)&diaf, sizeof(DIACTIONFORMATA));
  383. diaf.dwSize = sizeof(DIACTIONFORMATA);
  384. diaf.dwActionSize = sizeof(DIACTIONA);
  385. diaf.dwNumActions = (DWORD)(pMapNode->uActions);
  386. diaf.rgoAction = pMapNode->pdia;
  387. diaf.dwDataSize = 4 * diaf.dwNumActions;
  388. diaf.guidActionMap = GUID_DIMapTst;
  389. diaf.dwGenre = pSubNode->dwGenreId;
  390. diaf.dwBufferSize = DMTINPUT_BUFFERSIZE;
  391. lstrcpyA(diaf.tszActionMap, DMT_APP_CAPTION);
  392. // get the default mappings
  393. hRes = (pDevice->pdid)->BuildActionMap(&diaf,
  394. (LPCSTR)NULL,
  395. DIDBAM_HWDEFAULTS);
  396. if(FAILED(hRes))
  397. {
  398. // ISSUE-2001/03/29-timgill Needs error case handling
  399. }
  400. }
  401. else
  402. {
  403. // ISSUE-2001/03/29-timgill needs error handling
  404. }
  405. }
  406. // next subgenre
  407. pSubNode = pSubNode->pNext;
  408. }
  409. // set the subgenre list selection
  410. SendMessageA(GetDlgItem(hwnd, IDC_SUBGENRE),
  411. CB_SETCURSEL,
  412. 0,
  413. 0);
  414. // selectively disable axis/button/pov radio buttons
  415. //
  416. // this is done if the selected device does not
  417. // actually have one of these objects
  418. //
  419. // since axes are our "prefered" initial display
  420. // option, check them last
  421. if(dmtinputDeviceHasObject(pDevice->pObjectList,
  422. DMTA_TYPE_POV))
  423. {
  424. EnableWindow(GetDlgItem(hwnd, IDC_TYPE_POV), TRUE);
  425. wTypeCtrl = IDC_TYPE_POV;
  426. }
  427. if(dmtinputDeviceHasObject(pDevice->pObjectList,
  428. DMTA_TYPE_BUTTON))
  429. {
  430. EnableWindow(GetDlgItem(hwnd, IDC_TYPE_BUTTON), TRUE);
  431. wTypeCtrl = IDC_TYPE_BUTTON;
  432. }
  433. if(dmtinputDeviceHasObject(pDevice->pObjectList,
  434. DMTA_TYPE_AXIS))
  435. {
  436. EnableWindow(GetDlgItem(hwnd, IDC_TYPE_AXIS), TRUE);
  437. wTypeCtrl = IDC_TYPE_AXIS;
  438. }
  439. // select the axes radio button
  440. if(0 == wTypeCtrl)
  441. {
  442. // we have a "device" that has no objects...
  443. //
  444. // this is very bad
  445. DebugBreak();
  446. return TRUE;
  447. }
  448. CheckRadioButton(hwnd,
  449. IDC_TYPE_POV,
  450. IDC_TYPE_AXIS,
  451. wTypeCtrl);
  452. // for the default subgenre, walk the list and populate
  453. // the actions list box
  454. //
  455. // store the ptr to the actions node in the listbox
  456. // entry user data
  457. pSubNode = (DMTSUBGENRE_NODE*)SendMessageA(GetDlgItem(hwnd, IDC_SUBGENRE),
  458. CB_GETITEMDATA,
  459. 0,
  460. 0L);
  461. // update the lists
  462. SendMessageA(hwnd,
  463. WM_DMT_UPDATE_LISTS,
  464. 0,
  465. 0L);
  466. // select the first entry in each list
  467. SendMessageA(GetDlgItem(hwnd, IDC_CONTROLS),
  468. LB_SETCURSEL,
  469. 0,
  470. 0L);
  471. SendMessageA(GetDlgItem(hwnd, IDC_ACTIONS),
  472. LB_SETCURSEL,
  473. 0,
  474. 0L);
  475. // display the subgenre description
  476. SetDlgItemTextA(hwnd,
  477. IDC_DESCRIPTION,
  478. pSubNode->szDescription);
  479. // make sure the map/unmap buttons are enabled correctly
  480. SendMessageA(hwnd,
  481. WM_COMMAND,
  482. IDC_CONTROLS,
  483. 0L);
  484. }
  485. __finally
  486. {
  487. // if failure case, clean house
  488. if(FAILED(hRes))
  489. {
  490. // ISSUE-2001/03/29-timgill Needs error case handling
  491. }
  492. }
  493. // done
  494. return TRUE;
  495. } //*** end dmtcfgOnInitDialog()
  496. //===========================================================================
  497. // dmtcfgOnCommand
  498. //
  499. // Handle WM_COMMAND processing for the config device box
  500. //
  501. // Parameters:
  502. // HWND hwnd - handle to property page
  503. // WORD wId - control identifier (LOWORD(wparam))
  504. // HWND hwndCtrl - handle to control ((HWND)lparam)
  505. // WORD wNotifyCode - notification code (HIWORD(wparam))
  506. //
  507. // Returns: BOOL
  508. //
  509. // History:
  510. // 08/20/1999 - davidkl - created
  511. //===========================================================================
  512. BOOL dmtcfgOnCommand(HWND hwnd,
  513. WORD wId,
  514. HWND hwndCtrl,
  515. WORD wNotifyCode)
  516. {
  517. HRESULT hRes = S_OK;
  518. // UINT uSel = 0;
  519. //JJ 64Bit Compat
  520. UINT_PTR uSel = 0;
  521. UINT uActions = 0;
  522. BOOL fEnable = FALSE;
  523. DMT_APPINFO *pdmtai = NULL;
  524. DMTSUBGENRE_NODE *pSubGenre = NULL;
  525. DMTMAPPING_NODE *pMapping = NULL;
  526. DIACTIONA *pdia = NULL;
  527. DPF(5, "dmtcfgOnCommand");
  528. // get the window data
  529. //pdmtai = (DMT_APPINFO*)GetWindowLong(hwnd, GWL_USERDATA);
  530. //JJ 64Bit Compat
  531. pdmtai = (DMT_APPINFO*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  532. if(!pdmtai)
  533. {
  534. // big problem
  535. //
  536. // this should NEVER happen
  537. // ISSUE-2001/03/29-timgill Needs error case handling
  538. }
  539. // what is the currently selected subgenre?
  540. uSel = SendMessageA(GetDlgItem(hwnd, IDC_SUBGENRE),
  541. CB_GETCURSEL,
  542. 0,
  543. 0L);
  544. pSubGenre = (DMTSUBGENRE_NODE*)SendMessageA(GetDlgItem(hwnd,
  545. IDC_SUBGENRE),
  546. CB_GETITEMDATA,
  547. uSel,
  548. 0L);
  549. if(!pSubGenre)
  550. {
  551. // big problem
  552. //
  553. // this should NEVER happen
  554. // ISSUE-2001/03/29-timgill Needs error case handling
  555. }
  556. // get the active DIACTION array
  557. pMapping = pSubGenre->pMappingList;
  558. while(pMapping)
  559. {
  560. // match pdmtai->pDeviceList->guidInstance with
  561. // pMapping->guidInstance
  562. if(IsEqualGUID(pdmtai->pDeviceList->guidInstance,
  563. pMapping->guidInstance))
  564. {
  565. break;
  566. }
  567. // next mapping
  568. pMapping = pMapping->pNext;
  569. }
  570. if(pMapping)
  571. {
  572. pdia = pMapping->pdia;
  573. uActions = pMapping->uActions;
  574. }
  575. // update genre description
  576. SetDlgItemTextA(hwnd,
  577. IDC_DESCRIPTION,
  578. pSubGenre->szDescription);
  579. switch(wId)
  580. {
  581. case IDC_SUBGENRE:
  582. // based on the selected subgenre
  583. //
  584. // display the objects/actions for the selected type
  585. // (see type IDs below)
  586. if(CBN_SELCHANGE == wNotifyCode)
  587. {
  588. // update the lists
  589. SendMessageA(hwnd,
  590. WM_DMT_UPDATE_LISTS,
  591. 0,
  592. 0L);
  593. }
  594. break;
  595. case IDC_TYPE_AXIS:
  596. case IDC_TYPE_BUTTON:
  597. case IDC_TYPE_POV:
  598. // update the lists
  599. SendMessageA(hwnd,
  600. WM_DMT_UPDATE_LISTS,
  601. 0,
  602. 0L);
  603. // make sure the unmap button is selected as appropriate
  604. SendMessageA(hwnd,
  605. WM_COMMAND,
  606. IDC_CONTROLS,
  607. 0L);
  608. break;
  609. case IDC_CONTROLS:
  610. // if a mapped action is selected
  611. // enable the "Unmap action" button
  612. fEnable = dmtcfgIsControlMapped(hwnd,
  613. pdia,
  614. uActions);
  615. EnableWindow(GetDlgItem(hwnd, IDC_UNMAP),
  616. fEnable);
  617. // do NOT enable the map button if there are no
  618. // more actions
  619. if(!SendMessage(GetDlgItem(hwnd, IDC_ACTIONS),
  620. LB_GETCOUNT,
  621. 0, 0L))
  622. {
  623. EnableWindow(GetDlgItem(hwnd, IDC_STORE_MAPPING),
  624. FALSE);
  625. }
  626. else
  627. {
  628. EnableWindow(GetDlgItem(hwnd, IDC_STORE_MAPPING),
  629. !fEnable);
  630. }
  631. // if >any< controls are mapped
  632. // enable the "Unmap all" button
  633. fEnable = dmtcfgAreAnyControlsMapped(hwnd,
  634. pdia,
  635. uActions);
  636. EnableWindow(GetDlgItem(hwnd, IDC_UNMAP_ALL),
  637. fEnable);
  638. break;
  639. case IDC_STORE_MAPPING: // "Map action"
  640. // map it
  641. hRes = dmtcfgMapAction(hwnd,
  642. pdmtai->pDeviceList->guidInstance,
  643. pdia,
  644. uActions);
  645. if(FAILED(hRes))
  646. {
  647. // ISSUE-2001/03/29-timgill Needs error case handling
  648. }
  649. // set the changed flag
  650. pMapping->fChanged = TRUE;
  651. break;
  652. case IDC_UNMAP: // "Unmap action"
  653. // unmap it
  654. hRes = dmtcfgUnmapAction(hwnd,
  655. pdia,
  656. uActions);
  657. if(FAILED(hRes))
  658. {
  659. // ISSUE-2001/03/29-timgill Needs error case handling
  660. }
  661. // set the changed flag
  662. pMapping->fChanged = TRUE;
  663. break;
  664. case IDC_UNMAP_ALL: // "Unmap all"
  665. hRes = dmtcfgUnmapAllActions(hwnd,
  666. pdia,
  667. uActions);
  668. if(FAILED(hRes))
  669. {
  670. // ISSUE-2001/03/29-timgill Needs error case handling
  671. }
  672. // set the changed flag
  673. pMapping->fChanged = TRUE;
  674. break;
  675. }
  676. // done
  677. return FALSE;
  678. } //*** end dmtcfgOnCommand()
  679. //===========================================================================
  680. // dmtcfgOnNotify
  681. //
  682. // Handle WM_NOTIFY processing for the config device box
  683. //
  684. // Parameters:
  685. // HWND hwnd - handle to property page
  686. // PSHNOTIFY *ppsh - PSHNOTIFY ptr
  687. //
  688. // Returns: BOOL
  689. //
  690. // History:
  691. // 08/20/1999 - davidkl - created
  692. // 10/14/1999 - davidkl - implemented save calls
  693. //===========================================================================
  694. BOOL dmtcfgOnNotify(HWND hwnd,
  695. PSHNOTIFY *pNotify)
  696. {
  697. //int n = 0;
  698. //JJ 64Bit Compat
  699. INT_PTR n = 0;
  700. BOOL fSave = FALSE;
  701. DMT_APPINFO *pdmtai = NULL;
  702. // 7/19/2000(a-JiTay): IA64: Use %p format specifier for 32/64-bit pointers.
  703. DPF(5, "dmtcfgOnNotify: hwnd == %Ph", hwnd);
  704. // get the window data
  705. //pdmtai = (DMT_APPINFO*)GetWindowLong(hwnd, GWL_USERDATA);
  706. //JJ 64Bit Compat
  707. pdmtai = (DMT_APPINFO*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  708. if(!pdmtai)
  709. {
  710. // bad news
  711. // ISSUE-2001/03/29-timgill Needs error case handling
  712. }
  713. switch(pNotify->hdr.code)
  714. {
  715. case PSN_SETACTIVE:
  716. DPF(5, "PSN_SETACTIVE");
  717. // force the apply button to be enabled
  718. SendMessageA(GetParent(hwnd),
  719. PSM_CHANGED,
  720. (WPARAM)hwnd,
  721. 0L);
  722. break;
  723. case PSN_KILLACTIVE:
  724. DPF(5, "PSN_KILLACTIVE");
  725. // make sure we get a PSN_APPLY message
  726. //SetWindowLong(hwnd, DWL_MSGRESULT, (LONG)FALSE);
  727. SetWindowLong(hwnd, DWLP_MSGRESULT, (LONG)FALSE);
  728. break;
  729. case PSN_APPLY:
  730. DPF(5, "PSN_APPLY - %s",
  731. (pNotify->lParam) ? "Ok" : "Apply");
  732. // save/load mapping data
  733. //
  734. // OK == Save
  735. // Apply == Load
  736. // which button was clicked?
  737. if(pNotify->lParam)
  738. {
  739. // save mapping data
  740. SendMessage(hwnd,
  741. WM_DMT_FILE_SAVE,
  742. 0,0L);
  743. }
  744. else
  745. {
  746. // load mapping data
  747. // ISSUE-2001/03/29-timgill Load Mapping Data not yet implemented
  748. MessageBoxA(hwnd, "Load - Not Yet Implemented",
  749. pdmtai->pDeviceList->szName,
  750. MB_OK);
  751. }
  752. // DO NOT allow the dialog to close
  753. //SetWindowLong(hwnd,
  754. // DWL_MSGRESULT,
  755. // (LONG)PSNRET_INVALID_NOCHANGEPAGE);
  756. //JJ 64Bit Compat
  757. SetWindowLongPtr(hwnd,
  758. DWLP_MSGRESULT,
  759. (LONG_PTR)PSNRET_INVALID_NOCHANGEPAGE);
  760. break;
  761. }
  762. // done
  763. return TRUE;
  764. } //*** end dmtcfgOnNotify()
  765. //===========================================================================
  766. // dmtcfgOnUpdateLists
  767. //
  768. // Handle WM_DMT_UPDATE_LISTS message
  769. //
  770. // Parameters:
  771. //
  772. // Returns: BOOL
  773. //
  774. // History:
  775. // 08/25/1999 - davidkl - created
  776. // 11/12/1999 - dvaidkl - fixed problem with control selection setting
  777. //===========================================================================
  778. BOOL dmtcfgOnUpdateLists(HWND hwnd)
  779. {
  780. //int nIdx = -1;
  781. //int nSelCtrl = -1;
  782. //JJ 64Bit Compat
  783. INT_PTR nSelCtrl = -1;
  784. INT_PTR nIdx = -1;
  785. int n = 0;
  786. INT_PTR nControls = 0;
  787. INT_PTR nActions = 0;
  788. //int nControls = 0;
  789. //int nActions = 0;
  790. DWORD dwType = DMTA_TYPE_UNKNOWN;
  791. DWORD dwObjType = DMTA_TYPE_UNKNOWN;
  792. DMTSUBGENRE_NODE *pSubGenre = NULL;
  793. DMTACTION_NODE *pAction = NULL;
  794. DMTMAPPING_NODE *pMapping = NULL;
  795. DMTDEVICEOBJECT_NODE *pObjectList = NULL;
  796. DMTDEVICEOBJECT_NODE *pObjectNode = NULL;
  797. DMT_APPINFO *pdmtai = NULL;
  798. DIACTION *pdia = NULL;
  799. BOOL fFound = FALSE;
  800. char szBuf[MAX_PATH];
  801. DPF(5, "dmtcfgOnUpdateLists");
  802. // get the window data
  803. //pdmtai = (DMT_APPINFO*)GetWindowLong(hwnd, GWL_USERDATA);
  804. //JJ 64Bit Compat
  805. pdmtai = (DMT_APPINFO*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  806. if(!pdmtai)
  807. {
  808. // bad news
  809. // ISSUE-2001/03/29-timgill Needs error case handling
  810. }
  811. // device object list
  812. pObjectList = pdmtai->pDeviceList->pObjectList;
  813. // get the currently selected control
  814. nSelCtrl = SendMessageA(GetDlgItem(hwnd, IDC_CONTROLS),
  815. LB_GETCURSEL,
  816. 0,
  817. 0L);
  818. // clear the list box contents
  819. // actions
  820. SendMessageA(GetDlgItem(hwnd, IDC_ACTIONS),
  821. LB_RESETCONTENT,
  822. 0,
  823. 0L);
  824. // controls
  825. SendMessageA(GetDlgItem(hwnd, IDC_CONTROLS),
  826. LB_RESETCONTENT,
  827. 0,
  828. 0L);
  829. // get the current selection
  830. nIdx = SendMessageA(GetDlgItem(hwnd, IDC_SUBGENRE),
  831. CB_GETCURSEL,
  832. 0,
  833. 0L);
  834. // get the item data
  835. pSubGenre = (DMTSUBGENRE_NODE*)SendMessageA(GetDlgItem(hwnd,
  836. IDC_SUBGENRE),
  837. CB_GETITEMDATA,
  838. nIdx,
  839. 0L);
  840. // get the DIACTION array specific to the current device
  841. pMapping = pSubGenre->pMappingList;
  842. while(pMapping)
  843. {
  844. // match pdmtai->pDeviceList->guidInstance
  845. // with pMapping->guidInstance
  846. if(IsEqualGUID(pdmtai->pDeviceList->guidInstance,
  847. pMapping->guidInstance))
  848. {
  849. break;
  850. }
  851. // next mapping
  852. pMapping = pMapping->pNext;
  853. }
  854. if(!pMapping)
  855. {
  856. // this is very bad and should NEVER happen
  857. // ISSUE-2001/03/29-timgill Needs error case handling
  858. DebugBreak();
  859. }
  860. pdia = pMapping->pdia;
  861. nActions = (int)pMapping->uActions;
  862. // what control type is selected?
  863. dwType = IDC_TYPE_AXIS - (dmtGetCheckedRadioButton(hwnd,
  864. IDC_TYPE_POV,
  865. IDC_TYPE_AXIS));
  866. // populate the action list
  867. nIdx = 0;
  868. pAction = pSubGenre->pActionList;
  869. while(pAction)
  870. {
  871. // filter to the selected control type
  872. if(dwType == pAction->dwType)
  873. {
  874. // filter actions that are already assigned
  875. // first, find a matching action in the array
  876. fFound = FALSE;
  877. for(n = 0; n < nActions; n++)
  878. {
  879. // match based on the semantic / action id
  880. if((pdia+n)->dwSemantic == pAction->dwActionId)
  881. {
  882. DPF(2, "dmtcfgOnUpdateLists- found matching action "
  883. "pAction->dwActionId (%08Xh) == "
  884. "(pdia+u)->dwSemantic (%08Xh)",
  885. pAction->dwActionId,
  886. (pdia+n)->dwSemantic);
  887. fFound = TRUE;
  888. break;
  889. }
  890. }
  891. // next, read the action array entry,
  892. // if GUID_NULL == guidInstance, add the entry
  893. if(!fFound ||
  894. IsEqualGUID(GUID_NULL, (pdia+n)->guidInstance))
  895. {
  896. // prepend the action priority
  897. wsprintfA(szBuf, "(Pri%d) %s",
  898. pAction->dwPriority,
  899. pAction->szName);
  900. // add the action name
  901. nIdx = SendMessageA(GetDlgItem(hwnd, IDC_ACTIONS),
  902. LB_ADDSTRING,
  903. 0,
  904. (LPARAM)szBuf);
  905. // add the item data (action node)
  906. SendMessageA(GetDlgItem(hwnd, IDC_ACTIONS),
  907. LB_SETITEMDATA,
  908. nIdx,
  909. (LPARAM)pAction);
  910. } //* assigned action filter
  911. } //* control type filter
  912. // next action
  913. pAction = pAction->pNext;
  914. }
  915. // populate the control list
  916. nIdx = 0;
  917. pObjectNode = pObjectList;
  918. while(pObjectNode)
  919. {
  920. // convert dinput's DIDFT to our
  921. // internal control type
  922. if(FAILED(dmtinputXlatDIDFTtoInternalType(pObjectNode->dwObjectType,
  923. &dwObjType)))
  924. {
  925. // ISSUE-2001/03/29-timgill Needs error case handling
  926. }
  927. DPF(3, "dmtcfgOnUpdateLists - %s : DIDFT type %08Xh, internal type %d",
  928. pObjectNode->szName,
  929. pObjectNode->dwObjectType,
  930. dwObjType);
  931. // filter on control type
  932. //
  933. // dwType populated above
  934. if(dwType == dwObjType)
  935. {
  936. // check to if mapped
  937. //
  938. // we do this by scanning the DIACTION array, looking
  939. // for actions that contain our device's guidInstance
  940. // and our object's offset
  941. // if so, put the mapping info in ()
  942. wsprintfA(szBuf, "%s",
  943. pObjectNode->szName);
  944. for(n = 0; n < nActions; n++)
  945. {
  946. if(IsEqualGUID((pdia+n)->guidInstance,
  947. pdmtai->pDeviceList->guidInstance) &&
  948. ((pdia+n)->dwObjID ==
  949. pObjectNode->dwObjectType))
  950. {
  951. wsprintfA(szBuf, "%s (%s)",
  952. pObjectNode->szName,
  953. (pdia+n)->lptszActionName);
  954. break;
  955. }
  956. }
  957. // add the control name
  958. nIdx = SendMessageA(GetDlgItem(hwnd, IDC_CONTROLS),
  959. LB_ADDSTRING,
  960. 0,
  961. (LPARAM)szBuf);
  962. // add the item data (object node)
  963. SendMessageA(GetDlgItem(hwnd, IDC_CONTROLS),
  964. LB_SETITEMDATA,
  965. nIdx,
  966. (LPARAM)pObjectNode);
  967. } //* control type filter
  968. // next control
  969. pObjectNode = pObjectNode->pNext;
  970. }
  971. // count the number of entries in each list
  972. nControls = SendMessage(GetDlgItem(hwnd, IDC_CONTROLS),
  973. LB_GETCOUNT,
  974. 0,
  975. 0L);
  976. nActions = SendMessage(GetDlgItem(hwnd, IDC_ACTIONS),
  977. LB_GETCOUNT,
  978. 0,
  979. 0L);
  980. // set the selected entry in each list
  981. //
  982. // only do this if there are entries in the lists
  983. if(nControls)
  984. {
  985. if(nSelCtrl > nControls)
  986. {
  987. nSelCtrl = 0;
  988. }
  989. SendMessageA(GetDlgItem(hwnd, IDC_CONTROLS),
  990. LB_SETCURSEL,
  991. nSelCtrl,
  992. 0L);
  993. }
  994. if(nActions)
  995. {
  996. SendMessageA(GetDlgItem(hwnd, IDC_ACTIONS),
  997. LB_SETCURSEL,
  998. 0,
  999. 0L);
  1000. }
  1001. // if there are no controls or no actions
  1002. //
  1003. // disable the map button
  1004. if(!nControls || !nActions)
  1005. {
  1006. EnableWindow(GetDlgItem(hwnd, IDC_STORE_MAPPING), FALSE);
  1007. }
  1008. // done
  1009. return FALSE;
  1010. } //*** end dmtcfgOnUpdateLists()
  1011. //===========================================================================
  1012. // dmtcfgSourceDlgProc
  1013. //
  1014. // Configure Device Mapping Source Code dialog processing function
  1015. //
  1016. // Parameters: (see SDK help for parameter details)
  1017. // HWND hwnd
  1018. // UINT uMsg
  1019. // WPARAM wparam
  1020. // LPARAM lparam
  1021. //
  1022. // Returns: (see SDK help for return value details)
  1023. // BOOL
  1024. //
  1025. // History:
  1026. // 08/31/1999 - davidkl - created
  1027. //===========================================================================
  1028. BOOL CALLBACK dmtcfgSourceDlgProc(HWND hwnd,
  1029. UINT uMsg,
  1030. WPARAM wparam,
  1031. LPARAM lparam)
  1032. {
  1033. switch(uMsg)
  1034. {
  1035. case WM_INITDIALOG:
  1036. return dmtcfgSourceOnInitDialog(hwnd,
  1037. (HWND)wparam,
  1038. lparam);
  1039. case WM_COMMAND:
  1040. return dmtcfgSourceOnCommand(hwnd,
  1041. LOWORD(wparam),
  1042. (HWND)lparam,
  1043. HIWORD(wparam));
  1044. case WM_DMT_UPDATE_LISTS:
  1045. return dmtcfgSourceOnUpdateLists(hwnd);
  1046. }
  1047. return FALSE;
  1048. } //*** end dmtcfgSourceDlgProc()
  1049. //===========================================================================
  1050. // dmtcfgSourceOnInitDialog
  1051. //
  1052. // Handle WM_INITDIALOG processing for the config source box
  1053. //
  1054. // Parameters:
  1055. // HWND hwnd - handle to property page
  1056. // HWND hwndFocus - handle of ctrl with focus
  1057. // LPARAM lparam - user data (in this case, PROPSHEETPAGE*)
  1058. //
  1059. // Returns: BOOL
  1060. //
  1061. // History:
  1062. // 08/31/1999 - davidkl - created
  1063. // 10/07/1999 - davidkl - reworked code to match UI change
  1064. //===========================================================================
  1065. BOOL dmtcfgSourceOnInitDialog(HWND hwnd,
  1066. HWND hwndFocus,
  1067. LPARAM lparam)
  1068. {
  1069. DMTSUBGENRE_NODE *pSubGenre = (DMTSUBGENRE_NODE*)lparam;
  1070. //LONG lPrev = 0L;
  1071. //JJ 64Bit Compat
  1072. LONG_PTR lPrev = 0;
  1073. int nIdx = 0;
  1074. char szBuf[MAX_PATH];
  1075. DPF(5, "dmtcfgSourceOnInitDialog");
  1076. // validate pSubGenre (lparam)
  1077. if(IsBadWritePtr((void*)pSubGenre, sizeof(DMTSUBGENRE_NODE)))
  1078. {
  1079. DPF(0, "dmtcfgOnInitDialog - invalid ppsp.ptp (%016Xh)",
  1080. pSubGenre);
  1081. return FALSE;
  1082. }
  1083. // set the window caption to include the subgenre name
  1084. wsprintfA(szBuf, "Configure Device Mapping Source Code - %s",
  1085. pSubGenre->szName);
  1086. SetWindowTextA(hwnd, szBuf);
  1087. // store the subgenre node in the window's user data
  1088. SetLastError(0);
  1089. //lPrev = SetWindowLong(hwnd,
  1090. // GWL_USERDATA,
  1091. // (LONG)pSubGenre);
  1092. //JJ 64Bit Compat
  1093. lPrev = SetWindowLongPtr(hwnd,
  1094. GWLP_USERDATA,
  1095. (LONG_PTR)pSubGenre);
  1096. if(!lPrev && GetLastError())
  1097. {
  1098. // serious app problem.
  1099. // we need to stop things right here and now
  1100. DPF(0, "dmtcfgSourceOnInitDialog - This is bad... "
  1101. "We failed to store pSubGenre");
  1102. DPF(0, "dmtcfgSourceOnInitDialog - Please find someone "
  1103. "to look at this right away");
  1104. DebugBreak();
  1105. return FALSE;
  1106. }
  1107. // populate the subgenre edit box
  1108. SetWindowTextA(GetDlgItem(hwnd, IDC_SUBGENRE),
  1109. pSubGenre->szName);
  1110. // display the subgenre description
  1111. SetWindowTextA(GetDlgItem(hwnd, IDC_DESCRIPTION),
  1112. pSubGenre->szDescription);
  1113. // select the axes radio button
  1114. CheckRadioButton(hwnd,
  1115. IDC_TYPE_POV,
  1116. IDC_TYPE_AXIS,
  1117. IDC_TYPE_AXIS);
  1118. // populate the actions list box
  1119. //
  1120. // store the ptr to the actions node in the listbox
  1121. // entry user data
  1122. SendMessageA(hwnd,
  1123. WM_DMT_UPDATE_LISTS,
  1124. 0,
  1125. 0L);
  1126. // done
  1127. return TRUE;
  1128. } //*** end dmtcfgSourceOnInitDialog()
  1129. //===========================================================================
  1130. // dmtcfgSourceOnCommand
  1131. //
  1132. // Handle WM_COMMAND processing for the config source box
  1133. //
  1134. // Parameters:
  1135. // HWND hwnd - handle to property page
  1136. // WORD wId - control identifier (LOWORD(wparam))
  1137. // HWND hwndCtrl - handle to control ((HWND)lparam)
  1138. // WORD wNotifyCode - notification code (HIWORD(wparam))
  1139. //
  1140. // Returns: BOOL
  1141. //
  1142. // History:
  1143. // 08/31/1999 - davidkl - created
  1144. //===========================================================================
  1145. BOOL dmtcfgSourceOnCommand(HWND hwnd,
  1146. WORD wId,
  1147. HWND hwndCtrl,
  1148. WORD wNotifyCode)
  1149. {
  1150. DMTGENRE_NODE *pGenre = NULL;
  1151. DPF(5, "dmtcfgOnCommand");
  1152. // get the genre from the window's user data
  1153. // ISSUE-2001/03/29-timgill config source box fails to handle many UI messages
  1154. // IDC_ADD_ACTION, IDC_REMOVE_ACTION, IDC_RENAME_ACTION, IDC_CUSTOM_ACTION all do nothing
  1155. // IDOK/IDCANCEL merely do default processing
  1156. switch(wId)
  1157. {
  1158. case IDOK:
  1159. EndDialog(hwnd, 0);
  1160. break;
  1161. case IDCANCEL:
  1162. EndDialog(hwnd, -1);
  1163. break;
  1164. case IDC_SUBGENRE:
  1165. // based on the selected subgenre
  1166. //
  1167. // display the objects/actions for the selected type
  1168. // (see type IDs below)
  1169. if(CBN_SELCHANGE == wNotifyCode)
  1170. {
  1171. // update the lists
  1172. SendMessageA(hwnd,
  1173. WM_DMT_UPDATE_LISTS,
  1174. 0,
  1175. 0L);
  1176. }
  1177. break;
  1178. case IDC_TYPE_AXIS:
  1179. case IDC_TYPE_BUTTON:
  1180. case IDC_TYPE_POV:
  1181. // update the lists
  1182. SendMessageA(hwnd,
  1183. WM_DMT_UPDATE_LISTS,
  1184. 0,
  1185. 0L);
  1186. break;
  1187. case IDC_ADD_ACTION:
  1188. break;
  1189. case IDC_REMOVE_ACTION:
  1190. break;
  1191. case IDC_RENAME_ACTION:
  1192. break;
  1193. case IDC_CUSTOM_ACTION:
  1194. break;
  1195. }
  1196. // done
  1197. return FALSE;
  1198. } //*** end dmtcfgSourceOnCommand()
  1199. //===========================================================================
  1200. // dmtcfgSourceOnUpdateLists
  1201. //
  1202. // Handle WM_DMT_UPDATE_LISTS message
  1203. //
  1204. // Parameters:
  1205. //
  1206. // Returns: BOOL
  1207. //
  1208. // History:
  1209. // 08/31/1999 - davidkl - created
  1210. // 10/07/1999 - davidkl - modified to match UI change
  1211. //===========================================================================
  1212. BOOL dmtcfgSourceOnUpdateLists(HWND hwnd)
  1213. {
  1214. //int nIdx = -1;
  1215. //JJ 64Bit Compat
  1216. INT_PTR nIdx = -1;
  1217. DWORD dwType = 0x0badbad0;
  1218. DMTSUBGENRE_NODE *pSubGenre = NULL;
  1219. DMTACTION_NODE *pAction = NULL;
  1220. char szBuf[MAX_PATH];
  1221. // get the subgenre node from the window's user data
  1222. //pSubGenre = (DMTSUBGENRE_NODE*)GetWindowLong(hwnd,
  1223. // GWL_USERDATA);
  1224. //JJ 64Bit Compat
  1225. pSubGenre = (DMTSUBGENRE_NODE*)GetWindowLongPtr(hwnd,
  1226. GWLP_USERDATA);
  1227. if(!pSubGenre)
  1228. {
  1229. // this is very bad
  1230. // ISSUE-2001/03/29-timgill Needs error case handling
  1231. DebugBreak();
  1232. return TRUE;
  1233. }
  1234. // clear the list box contents
  1235. SendMessageA(GetDlgItem(hwnd, IDC_ACTIONS),
  1236. LB_RESETCONTENT,
  1237. 0,
  1238. 0L);
  1239. // what control type is selected?
  1240. dwType = IDC_TYPE_AXIS - (dmtGetCheckedRadioButton(hwnd,
  1241. IDC_TYPE_POV,
  1242. IDC_TYPE_AXIS));
  1243. // populate the action list
  1244. pAction = pSubGenre->pActionList;
  1245. while(pAction)
  1246. {
  1247. // filter to the selected control type
  1248. if(dwType == pAction->dwType)
  1249. {
  1250. // filter actions that are already selected
  1251. /*
  1252. if(DMT_ACTION_NOTASSIGNED == pAction->dwDevObj)
  1253. {
  1254. */
  1255. // if the priority is NOT 1, append that info to the name string
  1256. //
  1257. // ISSUE-2001/03/29-timgill Should the priority 1 mapping display colour be different (eg. red)?
  1258. // Do game developers CARE about action priorities?
  1259. /*
  1260. if(1 < pAction->dwPriority)
  1261. {
  1262. wsprintfA(szBuf, "(Pri%d) %s",
  1263. pAction->dwPriority,
  1264. pAction->szName);
  1265. }
  1266. else
  1267. {
  1268. */
  1269. lstrcpyA(szBuf, pAction->szName);
  1270. // }
  1271. // add the action name
  1272. nIdx = SendMessageA(GetDlgItem(hwnd, IDC_ACTIONS),
  1273. LB_ADDSTRING,
  1274. 0,
  1275. (LPARAM)szBuf);
  1276. // add the extra data (action node)
  1277. SendMessageA(GetDlgItem(hwnd, IDC_ACTIONS),
  1278. LB_SETITEMDATA,
  1279. nIdx,
  1280. (LPARAM)&(pAction));
  1281. /*
  1282. } //* assigned action filter
  1283. */
  1284. } // control type filter
  1285. // next action
  1286. pAction = pAction->pNext;
  1287. }
  1288. // done
  1289. return FALSE;
  1290. } //*** end dmtcfgSourceOnUpdateLists()
  1291. //===========================================================================
  1292. // dmtcfgCreateGenreList
  1293. //
  1294. // Reads genres.ini and creates the genre list used to populate the
  1295. // Configure Device Action Map property sheet dialog. Returns the number of
  1296. // parent genres (NOT subgenres) found
  1297. //
  1298. // Parameters:
  1299. //
  1300. // Returns: HRESULT
  1301. //
  1302. // History:
  1303. // 08/23/1999 - davidkl - created
  1304. // 09/28/1999 - davidkl - modified to match new ini format
  1305. //===========================================================================
  1306. HRESULT dmtcfgCreateGenreList(DMTGENRE_NODE **ppdmtgList)
  1307. {
  1308. HRESULT hRes = S_OK;
  1309. UINT u = 0;
  1310. BOOL fFound = FALSE;
  1311. DMTGENRE_NODE *pCurrent = NULL;
  1312. DMTGENRE_NODE *pNew = NULL;
  1313. DMTGENRE_NODE *pHold = NULL;
  1314. char szItem[64];
  1315. char szBuf[MAX_PATH];
  1316. char szGroup[MAX_PATH];
  1317. // validate ppmdtgList
  1318. if(IsBadWritePtr((void*)ppdmtgList, sizeof(DMTGENRE_NODE*)))
  1319. {
  1320. DPF(0, "dmtcfgCreateGenreList - invalid ppdmtgList (%016Xh)",
  1321. ppdmtgList);
  1322. return E_POINTER;
  1323. }
  1324. // check to make sure we are not being asked
  1325. // to append to an existing list
  1326. //
  1327. // callers MUST pass a NULL list
  1328. if(*ppdmtgList)
  1329. {
  1330. DPF(0, "dmtcfgCreateGenreList - ppdmtgList points to "
  1331. "existing list! (%016Xh)", *ppdmtgList);
  1332. return E_INVALIDARG;
  1333. }
  1334. __try
  1335. {
  1336. // get the genre names from genres.ini
  1337. pCurrent = *ppdmtgList;
  1338. lstrcpyA(szBuf, "");
  1339. u = 0;
  1340. while(lstrcmpA("<<>>", szBuf))
  1341. {
  1342. // get the name of the genre
  1343. wsprintfA(szItem, "%d", u);
  1344. GetPrivateProfileStringA(szItem,
  1345. "N",
  1346. "<<>>",
  1347. szBuf,
  1348. MAX_PATH,
  1349. GENRES_INI);
  1350. if(!lstrcmpA("<<>>", szBuf))
  1351. {
  1352. DPF(3, "end of genre list");
  1353. continue;
  1354. }
  1355. DPF(3, "Genre name == %s", szBuf);
  1356. // extract the group name
  1357. hRes = dmtcfgGetGenreGroupName(szBuf,
  1358. szGroup);
  1359. if(FAILED(hRes))
  1360. {
  1361. // ISSUE-2001/03/29-timgill Needs error case handling
  1362. }
  1363. // walk the list
  1364. //
  1365. // make sure we did not get a duplicate name
  1366. fFound = FALSE;
  1367. pHold = pCurrent;
  1368. pCurrent = *ppdmtgList;
  1369. while(pCurrent)
  1370. {
  1371. if(!lstrcmpiA(pCurrent->szName,
  1372. szGroup))
  1373. {
  1374. // match found
  1375. fFound = TRUE;
  1376. break;
  1377. }
  1378. // next node
  1379. pCurrent = pCurrent->pNext;
  1380. }
  1381. if(!fFound)
  1382. {
  1383. // no match, allocate a new node
  1384. // allocate the genre node
  1385. pNew = (DMTGENRE_NODE*)LocalAlloc(LMEM_FIXED,
  1386. sizeof(DMTGENRE_NODE));
  1387. if(!pNew)
  1388. {
  1389. DPF(0, "dmtcfgCreateGenreList - insufficient memory to "
  1390. "allocate genre list node");
  1391. hRes = E_OUTOFMEMORY;
  1392. __leave;
  1393. }
  1394. // initialize the new node
  1395. ZeroMemory((void*)pNew, sizeof(DMTGENRE_NODE));
  1396. // set the name field
  1397. lstrcpyA(pNew->szName, szGroup);
  1398. // get the list of subgenres
  1399. hRes = dmtcfgCreateSubGenreList(pNew->szName,
  1400. &(pNew->pSubGenreList));
  1401. if(FAILED(hRes))
  1402. {
  1403. // ISSUE-2001/03/29-timgill Needs error case handling
  1404. }
  1405. // add it to the end of the list
  1406. pCurrent = pHold;
  1407. if(pCurrent)
  1408. {
  1409. // append the list
  1410. pCurrent->pNext = pNew;
  1411. // go to the next node
  1412. pCurrent = pCurrent->pNext;
  1413. }
  1414. else
  1415. {
  1416. // new list head
  1417. pCurrent = pNew;
  1418. *ppdmtgList = pCurrent;
  1419. }
  1420. }
  1421. // next genre
  1422. u++;
  1423. }
  1424. }
  1425. __finally
  1426. {
  1427. if(FAILED(hRes))
  1428. {
  1429. // cleanup allocations
  1430. DPF(1, "dmtcfgCreateGenreList - Failure occurred, "
  1431. "freeing genre list");
  1432. dmtcfgFreeGenreList(ppdmtgList);
  1433. *ppdmtgList = NULL;
  1434. }
  1435. }
  1436. // done
  1437. return hRes;
  1438. } //*** end dmtcfgCreateGenreList()
  1439. //===========================================================================
  1440. // dmtcfgFreeGenreList
  1441. //
  1442. // Frees the linked list (and sub-lists) created by dmtcfgCreateGenreList
  1443. //
  1444. // Parameters:
  1445. //
  1446. // Returns: HRESULT
  1447. //
  1448. // History:
  1449. // 08/23/1999 - davidkl - created
  1450. //===========================================================================
  1451. HRESULT dmtcfgFreeGenreList(DMTGENRE_NODE **ppdmtgList)
  1452. {
  1453. HRESULT hRes = S_OK;
  1454. DMTGENRE_NODE *pNode = NULL;
  1455. // validate ppdmtgList
  1456. if(IsBadWritePtr((void*)ppdmtgList, sizeof(PDMTGENRE_NODE)))
  1457. {
  1458. DPF(0, "dmtcfgFreeGenreList - Invalid ppdmtgList (%016Xh)",
  1459. ppdmtgList);
  1460. return E_POINTER;
  1461. }
  1462. // validate *ppdmtgList
  1463. if(IsBadReadPtr((void*)*ppdmtgList, sizeof(DMTGENRE_NODE)))
  1464. {
  1465. if(NULL != *ppdmtgList)
  1466. {
  1467. DPF(0, "dmtcfgFreeGenreList - Invalid *ppdmtgList (%016Xh)",
  1468. *ppdmtgList);
  1469. return E_POINTER;
  1470. }
  1471. else
  1472. {
  1473. // if NULL, then return "did nothing"
  1474. DPF(3, "dmtcfgFreeGenreList - Nothing to do....");
  1475. return S_FALSE;
  1476. }
  1477. }
  1478. // walk the list and free each object
  1479. while(*ppdmtgList)
  1480. {
  1481. pNode = *ppdmtgList;
  1482. *ppdmtgList = (*ppdmtgList)->pNext;
  1483. // first, free the action list
  1484. DPF(5, "dmtcfgFreeGenreList - "
  1485. "freeing subgenre list (%016Xh)",
  1486. pNode->pSubGenreList);
  1487. hRes = dmtcfgFreeSubGenreList(&(pNode->pSubGenreList));
  1488. if(FAILED(hRes))
  1489. {
  1490. // ISSUE-2001/03/29-timgill Needs error case handling
  1491. }
  1492. DPF(5, "dmtcfgFreeGenreList - Deleting Node (%016Xh)", pNode);
  1493. if(LocalFree((HLOCAL)pNode))
  1494. {
  1495. DPF(0, "dmtcfgFreeSubGenreList - MEMORY LEAK - "
  1496. "LocalFree() failed (%d)...",
  1497. GetLastError());
  1498. hRes = DMT_S_MEMORYLEAK;
  1499. }
  1500. DPF(5, "dmtcfgFreeGenreList - Node deleted");
  1501. }
  1502. // make sure that we set *ppdmtgList to NULL
  1503. *ppdmtgList = NULL;
  1504. // done
  1505. return hRes;
  1506. } //*** end dmtcfgFreeGenreList()
  1507. //===========================================================================
  1508. // dmtcfgCreateSubGenreList
  1509. //
  1510. // Reads genres.ini and creates the subgenre list used to populate the
  1511. // Configure Device Action Map property sheet dialog.
  1512. //
  1513. // Parameters:
  1514. //
  1515. // Returns: HRESULT
  1516. //
  1517. // History:
  1518. // 08/24/1999 - davidkl - created
  1519. // 09/29/1999 - davidkl - modified to match new ini format
  1520. //===========================================================================
  1521. HRESULT dmtcfgCreateSubGenreList(LPSTR szGenre,
  1522. DMTSUBGENRE_NODE **ppdmtsgList)
  1523. {
  1524. HRESULT hRes = S_OK;
  1525. UINT u = 0;
  1526. DMTSUBGENRE_NODE *pCurrent = NULL;
  1527. DMTSUBGENRE_NODE *pNew = NULL;
  1528. char szItem[64];
  1529. char szGroup[MAX_PATH];
  1530. char szBuf[MAX_PATH];
  1531. // validate ppmdtsgList
  1532. if(IsBadWritePtr((void*)ppdmtsgList, sizeof(DMTSUBGENRE_NODE*)))
  1533. {
  1534. return E_POINTER;
  1535. }
  1536. // check to make sure we are not being asked
  1537. // to append to an existing list
  1538. //
  1539. // callers MUST pass a NULL list
  1540. if(*ppdmtsgList)
  1541. {
  1542. return E_INVALIDARG;
  1543. }
  1544. __try
  1545. {
  1546. // get the subgenre names from genres.ini
  1547. pCurrent = *ppdmtsgList;
  1548. lstrcpyA(szBuf, "");
  1549. u = 0;
  1550. while(lstrcmpA("<<>>", szBuf))
  1551. {
  1552. // look for subgenres belonging to szGenre
  1553. wsprintfA(szItem, "%d", u);
  1554. GetPrivateProfileStringA(szItem,
  1555. "N",
  1556. "<<>>",
  1557. szBuf,
  1558. MAX_PATH,
  1559. GENRES_INI);
  1560. if(!lstrcmpA("<<>>", szBuf))
  1561. {
  1562. DPF(3, "end of subgenre list");
  1563. continue;
  1564. }
  1565. hRes = dmtcfgGetGenreGroupName(szBuf,
  1566. szGroup);
  1567. if(FAILED(hRes))
  1568. {
  1569. // ISSUE-2001/03/29-timgill Needs error case handling
  1570. }
  1571. // if we do not belong to the genre group
  1572. //
  1573. // make believe we found nothing
  1574. if(lstrcmpiA(szGenre, szGroup))
  1575. {
  1576. u++;
  1577. DPF(4, "bucket mismatch... skipping");
  1578. continue;
  1579. }
  1580. // we fit in the szGenre bucket
  1581. //
  1582. // allocate the genre node
  1583. pNew = (DMTSUBGENRE_NODE*)LocalAlloc(LMEM_FIXED,
  1584. sizeof(DMTSUBGENRE_NODE));
  1585. if(!pNew)
  1586. {
  1587. hRes = E_OUTOFMEMORY;
  1588. __leave;
  1589. }
  1590. // initialize the new node
  1591. ZeroMemory((void*)pNew, sizeof(DMTSUBGENRE_NODE));
  1592. // get the genreid
  1593. pNew->dwGenreId = GetPrivateProfileInt(szItem,
  1594. "AI0",
  1595. 0,
  1596. GENRES_INI);
  1597. pNew->dwGenreId &= DMT_GENRE_MASK;
  1598. DPF(4, "SubGenre ID == %08Xh", pNew->dwGenreId);
  1599. // get the "name" (Txt1)
  1600. GetPrivateProfileStringA(szItem,
  1601. "T1",
  1602. "<<>>",
  1603. pNew->szName,
  1604. MAX_PATH,
  1605. GENRES_INI);
  1606. DPF(3, "SubGenre name == %s", pNew->szName);
  1607. // get the description (Txt2)
  1608. GetPrivateProfileStringA(szItem,
  1609. "T2",
  1610. "<<>>",
  1611. pNew->szDescription,
  1612. MAX_PATH,
  1613. GENRES_INI);
  1614. DPF(4, "SubGenre description == %s", pNew->szDescription);
  1615. // get the list of actions
  1616. hRes = dmtcfgCreateActionList(szItem,
  1617. &(pNew->pActionList));
  1618. if(FAILED(hRes) || DMT_S_MEMORYLEAK == hRes)
  1619. {
  1620. // ISSUE-2001/03/29-timgill Needs error case handling
  1621. }
  1622. // add it to the end of the list
  1623. if(pCurrent)
  1624. {
  1625. // append the list
  1626. pCurrent->pNext = pNew;
  1627. // go to the next node
  1628. pCurrent = pCurrent->pNext;
  1629. }
  1630. else
  1631. {
  1632. // new list head
  1633. pCurrent = pNew;
  1634. *ppdmtsgList = pCurrent;
  1635. }
  1636. // next subgenre
  1637. u++;
  1638. }
  1639. }
  1640. __finally
  1641. {
  1642. // cleanup in failure case
  1643. if(FAILED(hRes))
  1644. {
  1645. DPF(1, "dmtcfgCreateSubGenreList - Failure occurred, "
  1646. "freeing subgenre list");
  1647. dmtcfgFreeSubGenreList(ppdmtsgList);
  1648. *ppdmtsgList = NULL;
  1649. }
  1650. }
  1651. //JJ_FIX
  1652. g_NumSubGenres = u;
  1653. // done
  1654. return S_OK;
  1655. } //*** end dmtcfgCreateSubGenreList()
  1656. //===========================================================================
  1657. // dmtcfgFreeSubGenreList
  1658. //
  1659. // Frees the linked list created by dmtcfgCreateSubGenreList
  1660. //
  1661. // Parameters:
  1662. //
  1663. // Returns: HRESULT
  1664. //
  1665. // History:
  1666. // 08/24/1999 - davidkl - created
  1667. // 08/25/1999 - davidkl - implemented
  1668. //===========================================================================
  1669. HRESULT dmtcfgFreeSubGenreList(DMTSUBGENRE_NODE **ppdmtsgList)
  1670. {
  1671. HRESULT hRes = S_OK;
  1672. DMTSUBGENRE_NODE *pNode = NULL;
  1673. // validate ppdmtaList
  1674. if(IsBadWritePtr((void*)ppdmtsgList, sizeof(PDMTSUBGENRE_NODE)))
  1675. {
  1676. DPF(0, "dmtcfgFreeSubGenreList - Invalid ppdmtsgList (%016Xh)",
  1677. ppdmtsgList);
  1678. return E_POINTER;
  1679. }
  1680. // validate *ppPortList
  1681. if(IsBadReadPtr((void*)*ppdmtsgList, sizeof(DMTSUBGENRE_NODE)))
  1682. {
  1683. if(NULL != *ppdmtsgList)
  1684. {
  1685. DPF(0, "dmtcfgFreeSubGenreList - Invalid *ppdmtsgList (%016Xh)",
  1686. *ppdmtsgList);
  1687. return E_POINTER;
  1688. }
  1689. else
  1690. {
  1691. // if NULL, then return "did nothing"
  1692. DPF(3, "dmtcfgFreeSubGenreList - Nothing to do....");
  1693. return S_FALSE;
  1694. }
  1695. }
  1696. // walk the list and free each object
  1697. while(*ppdmtsgList)
  1698. {
  1699. pNode = *ppdmtsgList;
  1700. *ppdmtsgList = (*ppdmtsgList)->pNext;
  1701. // first, free the action list
  1702. DPF(5, "dmtcfgFreeSubGenreList - "
  1703. "freeing action list (%016Xh)",
  1704. pNode->pActionList);
  1705. hRes = dmtcfgFreeActionList(&(pNode->pActionList));
  1706. if(FAILED(hRes))
  1707. {
  1708. hRes = DMT_S_MEMORYLEAK;
  1709. }
  1710. // then free the mapping list array
  1711. if(pNode->pMappingList)
  1712. {
  1713. hRes = dmtcfgFreeMappingList(&(pNode->pMappingList));
  1714. if(FAILED(hRes) || DMT_S_MEMORYLEAK == hRes)
  1715. {
  1716. hRes = DMT_S_MEMORYLEAK;
  1717. }
  1718. pNode->pMappingList = NULL;
  1719. }
  1720. // finally, free the node
  1721. DPF(5, "dmtcfgFreeSubGenreList - Deleting Node (%016Xh)", pNode);
  1722. if(LocalFree((HLOCAL)pNode))
  1723. {
  1724. DPF(0, "dmtcfgFreeSubGenreList - MEMORY LEAK - "
  1725. "LocalFree(Node) failed (%d)...",
  1726. GetLastError());
  1727. hRes = DMT_S_MEMORYLEAK;
  1728. }
  1729. DPF(5, "dmtcfgFreeSubGenreList - Node deleted");
  1730. }
  1731. // make sure that we set *ppdmtsgList to NULL
  1732. *ppdmtsgList = NULL;
  1733. // done
  1734. return hRes;
  1735. } //*** end dmtcfgFreeSubGenreList()
  1736. //===========================================================================
  1737. // dmtcfgCreateActionList
  1738. //
  1739. // Reads genres.ini and creates the action list used to populate the
  1740. // Configure Device Action Map property sheet dialog.
  1741. //
  1742. // Parameters:
  1743. //
  1744. // Returns: HRESULT
  1745. //
  1746. // History:
  1747. // 08/24/1999 - davidkl - created
  1748. // 09/07/1999 - davidkl - added DIACTION**
  1749. // 09/28/1999 - davidkl - updated to use info extraction macros
  1750. // 02/14/2000 - davidkl - started conversion to GetPrivateProfileSectionA
  1751. //===========================================================================
  1752. HRESULT dmtcfgCreateActionList(LPSTR szGenreSubgenre,
  1753. DMTACTION_NODE **ppdmtaList)
  1754. {
  1755. HRESULT hRes = S_OK;
  1756. UINT u = 0;
  1757. BYTE bTypeMask = 0x03;
  1758. DMTACTION_NODE *pCurrent = NULL;
  1759. DMTACTION_NODE *pNew = NULL;
  1760. char szItem[MAX_PATH];
  1761. char szBuf[MAX_PATH];
  1762. // validate ppmdtsgList
  1763. if(IsBadWritePtr((void*)ppdmtaList, sizeof(DMTACTION_NODE*)))
  1764. {
  1765. DPF(0, "dmtcfgCreateActionList - invalid ppdmtaList (%016Xh)",
  1766. ppdmtaList);
  1767. return E_POINTER;
  1768. }
  1769. // check to make sure we are not being asked
  1770. // to append to an existing list
  1771. //
  1772. // callers MUST pass a NULL list
  1773. if(*ppdmtaList)
  1774. {
  1775. DPF(0, "dmtcfgCreateActionList - ppdmtaList points to "
  1776. "existing list! (%016Xh)", *ppdmtaList);
  1777. return E_INVALIDARG;
  1778. }
  1779. __try
  1780. {
  1781. // get the action info from genres.ini
  1782. pCurrent = *ppdmtaList;
  1783. #ifdef BNW
  1784. char *pszSection = NULL;
  1785. char *pCurrent = NULL;
  1786. int nAlloc = 0;
  1787. // allocate space for the (Win9x) max size of an ini section
  1788. nAlloc = 32727;
  1789. pszSection = (char*)LocalAlloc(LMEM_FIXED,
  1790. sizeof(char) * nAlloc);
  1791. if(!pszSection)
  1792. {
  1793. // alloc failed,
  1794. // try ~1/2 of the max (that should still cover the
  1795. // fill size of the section)
  1796. nAlloc = 16386;
  1797. pszSection = (char*)LocalAlloc(LMEM_FIXED,
  1798. sizeof(char) * nAlloc);
  1799. if(!pszSection)
  1800. {
  1801. // alloc failed,
  1802. // try ~1/4 of the max (that should still cover the
  1803. // fill size of the section)
  1804. nAlloc = 8192;
  1805. pszSection = (char*)LocalAlloc(LMEM_FIXED,
  1806. sizeof(char) * nAlloc);
  1807. if(!pszSection)
  1808. {
  1809. // alloc failed,
  1810. // try ~1/8 of the max (that should still cover the
  1811. // fill size of the section)
  1812. nAlloc = 4096;
  1813. pszSection = (char*)LocalAlloc(LMEM_FIXED,
  1814. sizeof(char) * nAlloc);
  1815. if(!pszSection)
  1816. {
  1817. // alloc failed,
  1818. // try ~1/16 of the max (that should still cover the
  1819. // fill size of the section) - this is our last attempt
  1820. nAlloc = 2048;
  1821. pszSection = (char*)LocalAlloc(LMEM_FIXED,
  1822. sizeof(char) * nAlloc);
  1823. if(!pszSection)
  1824. {
  1825. // alloc failed, we give up
  1826. __leave;
  1827. }
  1828. }
  1829. }
  1830. }
  1831. }
  1832. DPF(2, "dmtcfgCreateActionList - section allocation: %d bytes", nAlloc);
  1833. // read the section specified by szGenreSubgenre
  1834. GetPrivateProfileSectionA(szGenreSubgenre,
  1835. pszSection,
  1836. nAlloc,
  1837. GENRES_INI);
  1838. /* the following code fragment does nothing - u is incremented and then never used again
  1839. // parse the action information from the section
  1840. for(u = 0; ; u++)
  1841. {
  1842. break;
  1843. }
  1844. */
  1845. #else
  1846. lstrcpyA(szBuf, "");
  1847. u = 0;
  1848. while(lstrcmpA("<<>>", szBuf))
  1849. {
  1850. // add the name of the action to the node
  1851. wsprintfA(szItem, "AN%d", u);
  1852. GetPrivateProfileStringA(szGenreSubgenre,
  1853. szItem,
  1854. "<<>>",
  1855. szBuf,
  1856. MAX_PATH,
  1857. GENRES_INI);
  1858. if(!lstrcmpA("<<>>", szBuf))
  1859. {
  1860. DPF(3, "end of action list");
  1861. continue;
  1862. }
  1863. DPF(3, "Action name == %s", szBuf);
  1864. // allocate the genre node
  1865. pNew = (DMTACTION_NODE*)LocalAlloc(LMEM_FIXED,
  1866. sizeof(DMTACTION_NODE));
  1867. if(!pNew)
  1868. {
  1869. hRes = E_OUTOFMEMORY;
  1870. __leave;
  1871. }
  1872. // initialize the new node
  1873. ZeroMemory((void*)pNew, sizeof(DMTACTION_NODE));
  1874. lstrcpyA(pNew->szName, szBuf);
  1875. // get the action id
  1876. wsprintfA(szItem, "AI%d", u);
  1877. pNew->dwActionId = GetPrivateProfileIntA(szGenreSubgenre,
  1878. szItem,
  1879. 0x0badbad0,
  1880. GENRES_INI);
  1881. DPF(4, "Action ID == %08Xh", pNew->dwActionId);
  1882. // get the action priority
  1883. pNew->dwPriority = dmtinputGetActionPri(pNew->dwActionId);
  1884. DPF(4, "Action priority == %d", pNew->dwPriority);
  1885. // get action type
  1886. pNew->dwType = dmtinputGetActionObjectType(pNew->dwActionId);
  1887. DPF(4, "Action type == %d", pNew->dwType);
  1888. // get the action type name
  1889. wsprintfA(szItem, "AIN%d", u);
  1890. GetPrivateProfileStringA(szGenreSubgenre,
  1891. szItem,
  1892. "<<>>",
  1893. pNew->szActionId,
  1894. MAX_ACTION_ID_STRING,
  1895. GENRES_INI);
  1896. DPF(4, "Action ID name == %s", pNew->szActionId);
  1897. // add it to the end of the list
  1898. if(pCurrent)
  1899. {
  1900. // append the list
  1901. pCurrent->pNext = pNew;
  1902. // go to the next node
  1903. pCurrent = pCurrent->pNext;
  1904. }
  1905. else
  1906. {
  1907. // new list head
  1908. pCurrent = pNew;
  1909. *ppdmtaList = pCurrent;
  1910. }
  1911. // net action
  1912. u++;
  1913. }
  1914. #endif // BNW
  1915. }
  1916. __finally
  1917. {
  1918. #ifdef BNW
  1919. // free the section memory we allocated
  1920. if(LocalFree((HLOCAL)pszSection))
  1921. {
  1922. // memory leak
  1923. DPF(0, "dmtcfgCreateActionList - !! MEMORY LEAK !! - LocalFree(section) failed");
  1924. }
  1925. #endif // BNW
  1926. // cleanup in failure case
  1927. if(FAILED(hRes))
  1928. {
  1929. // free action list
  1930. DPF(1, "dmtcfgCreateActionList - Failure occurred, "
  1931. "freeing action list");
  1932. dmtcfgFreeActionList(ppdmtaList);
  1933. *ppdmtaList = NULL;
  1934. }
  1935. }
  1936. // done
  1937. return S_OK;
  1938. } //*** end dmtCreateActionList()
  1939. //===========================================================================
  1940. // dmtcfgFreeActionList
  1941. //
  1942. // Frees the linked list created by dmtcfgCreateActionList
  1943. //
  1944. // Parameters:
  1945. //
  1946. // Returns: HRESULT
  1947. //
  1948. // History:
  1949. // 08/24/1999 - davidkl - created
  1950. // 08/25/1999 - davidkl - implemented
  1951. //===========================================================================
  1952. HRESULT dmtcfgFreeActionList(DMTACTION_NODE **ppdmtaList)
  1953. {
  1954. HRESULT hRes = S_OK;
  1955. DMTACTION_NODE *pNode = NULL;
  1956. // validate ppdmtaList
  1957. if(IsBadWritePtr((void*)ppdmtaList, sizeof(PDMTACTION_NODE)))
  1958. {
  1959. DPF(0, "dmtcfgFreeActionList - Invalid ppdmtaList (%016Xh)",
  1960. ppdmtaList);
  1961. return E_POINTER;
  1962. }
  1963. // validate *ppdmtaList
  1964. if(IsBadReadPtr((void*)*ppdmtaList, sizeof(DMTACTION_NODE)))
  1965. {
  1966. if(NULL != *ppdmtaList)
  1967. {
  1968. DPF(0, "dmtcfgFreeActionList - Invalid *ppdmtaList (%016Xh)",
  1969. *ppdmtaList);
  1970. return E_POINTER;
  1971. }
  1972. else
  1973. {
  1974. // if NULL, then return "did nothing"
  1975. DPF(3, "dmtcfgFreeActionList - Nothing to do....");
  1976. return S_FALSE;
  1977. }
  1978. }
  1979. // walk the list and free each object
  1980. while(*ppdmtaList)
  1981. {
  1982. pNode = *ppdmtaList;
  1983. *ppdmtaList = (*ppdmtaList)->pNext;
  1984. // free the node
  1985. DPF(5, "dmtcfgFreeActionList - deleting Node (%016Xh)", pNode);
  1986. if(LocalFree((HLOCAL)pNode))
  1987. {
  1988. DPF(0, "dmtcfgFreeActionList - MEMORY LEAK - "
  1989. "LocalFree(Node) failed (%d)...",
  1990. GetLastError());
  1991. hRes = DMT_S_MEMORYLEAK;
  1992. }
  1993. DPF(5, "dmtcfgFreeActionList - Node deleted");
  1994. }
  1995. // make sure that we set *ppObjList to NULL
  1996. *ppdmtaList = NULL;
  1997. // done
  1998. return hRes;
  1999. } //*** end dmtcfgFreeActionList()
  2000. //===========================================================================
  2001. // dmtcfgCreateMappingList
  2002. //
  2003. // Creates a device mapping list
  2004. //
  2005. // Parameters:
  2006. //
  2007. // Returns: HRESULT
  2008. //
  2009. // History:
  2010. // 09/23/1999 - davidkl - created
  2011. //===========================================================================
  2012. HRESULT dmtcfgCreateMappingList(DMTDEVICE_NODE *pDeviceList,
  2013. DMTACTION_NODE *pActions,
  2014. DMTMAPPING_NODE **ppdmtmList)
  2015. {
  2016. HRESULT hRes = S_OK;
  2017. UINT uActions = NULL;
  2018. DMTACTION_NODE *pActionNode = NULL;
  2019. DMTMAPPING_NODE *pNew = NULL;
  2020. DMTMAPPING_NODE *pCurrent = NULL;
  2021. DMTDEVICE_NODE *pDeviceNode = NULL;
  2022. // validate pDeviceList
  2023. if(IsBadReadPtr((void*)pDeviceList, sizeof(DMTDEVICE_NODE)))
  2024. {
  2025. DPF(0, "dmtcfgCreateMappingList - invalid pDeviceList (%016Xh)",
  2026. pDeviceList);
  2027. return E_POINTER;
  2028. }
  2029. // validate pActions
  2030. if(IsBadReadPtr((void*)pActions, sizeof(DMTACTION_NODE)))
  2031. {
  2032. if(NULL != pActions)
  2033. {
  2034. DPF(0, "dmtcfgCreateMappingList - invalid pActions (%016Xh)",
  2035. pActions);
  2036. return E_POINTER;
  2037. }
  2038. else
  2039. {
  2040. // no actions for this subgenre
  2041. DPF(3, "dmtcfgCreateMappingList - No actions for this subgenre, "
  2042. "nothing to do...");
  2043. return S_FALSE;
  2044. }
  2045. }
  2046. // validate ppdmtmList
  2047. if(IsBadWritePtr((void*)ppdmtmList, sizeof(DMTMAPPING_NODE)))
  2048. {
  2049. DPF(0, "dmtcfgCreateMappingList - invalid ppdmtmList (%016Xh)",
  2050. ppdmtmList);
  2051. return E_POINTER;
  2052. }
  2053. // check to make sure we are not being asked
  2054. // to append to an existing list
  2055. //
  2056. // callers MUST pass a NULL list
  2057. if(*ppdmtmList)
  2058. {
  2059. DPF(0, "dmtcfgCreateMappingList - ppdmtmList points to "
  2060. "existing list! (%016Xh)", *ppdmtmList);
  2061. return E_INVALIDARG;
  2062. }
  2063. __try
  2064. {
  2065. // count the actions
  2066. //
  2067. // this lets us know how much space to allocate for the
  2068. uActions = 0;
  2069. pActionNode = pActions;
  2070. while(pActionNode)
  2071. {
  2072. uActions++;
  2073. // next node
  2074. pActionNode = pActionNode->pNext;
  2075. }
  2076. // for each device
  2077. pDeviceNode = pDeviceList;
  2078. while(pDeviceNode)
  2079. {
  2080. // allocate the mapping node
  2081. pNew = (DMTMAPPING_NODE*)LocalAlloc(LMEM_FIXED,
  2082. sizeof(DMTMAPPING_NODE));
  2083. if(!pNew)
  2084. {
  2085. DPF(3, "dmtcfgCreateMappingList - Insufficient memory to "
  2086. "allocate mapping list node");
  2087. hRes = E_OUTOFMEMORY;
  2088. __leave;
  2089. }
  2090. // initialize the new node
  2091. ZeroMemory((void*)pNew, sizeof(DMTMAPPING_NODE));
  2092. // allocate the action array
  2093. pNew->pdia = (DIACTIONA*)LocalAlloc(LMEM_FIXED,
  2094. uActions * sizeof(DIACTIONA));
  2095. if(!(pNew->pdia))
  2096. {
  2097. hRes = E_OUTOFMEMORY;
  2098. __leave;
  2099. }
  2100. // initial population of the action array
  2101. hRes = dmtinputPopulateActionArray(pNew->pdia,
  2102. uActions,
  2103. pActions);
  2104. if(FAILED(hRes))
  2105. {
  2106. __leave;
  2107. }
  2108. // add the number of actions
  2109. pNew->uActions = uActions;
  2110. // add the device instance guid
  2111. pNew->guidInstance = pDeviceNode->guidInstance;
  2112. // add the new node to the list
  2113. if(pCurrent)
  2114. {
  2115. // append the list
  2116. pCurrent->pNext = pNew;
  2117. // go to the next node
  2118. pCurrent = pCurrent->pNext;
  2119. }
  2120. else
  2121. {
  2122. // new list head
  2123. pCurrent = pNew;
  2124. *ppdmtmList = pCurrent;
  2125. }
  2126. // next device
  2127. pDeviceNode = pDeviceNode->pNext;
  2128. }
  2129. }
  2130. __finally
  2131. {
  2132. // in case of error...
  2133. if(FAILED(hRes))
  2134. {
  2135. // free list
  2136. dmtcfgFreeMappingList(ppdmtmList);
  2137. *ppdmtmList = NULL;
  2138. }
  2139. }
  2140. // done
  2141. return hRes;
  2142. } //*** end dmtcfgCreateMappingList()
  2143. //===========================================================================
  2144. // dmtcfgFreeMappingList
  2145. //
  2146. // Completely frees a mapping list
  2147. //
  2148. // Parameters:
  2149. //
  2150. // Returns: HRESULT
  2151. //
  2152. // History:
  2153. // 09/23/1999 - davidkl - created
  2154. //===========================================================================
  2155. HRESULT dmtcfgFreeMappingList(DMTMAPPING_NODE **ppdmtmList)
  2156. {
  2157. HRESULT hRes = S_OK;
  2158. DMTMAPPING_NODE *pNode = NULL;
  2159. // validate ppdmtmList
  2160. if(IsBadWritePtr((void*)ppdmtmList, sizeof(DMTMAPPING_NODE*)))
  2161. {
  2162. return E_POINTER;
  2163. }
  2164. // validate *ppdmtmList
  2165. if(IsBadWritePtr((void*)*ppdmtmList, sizeof(DMTMAPPING_NODE)))
  2166. {
  2167. if(NULL != *ppdmtmList)
  2168. {
  2169. return E_POINTER;
  2170. }
  2171. else
  2172. {
  2173. // nothing to do
  2174. return S_FALSE;
  2175. }
  2176. }
  2177. // walk the list and free each object
  2178. while(*ppdmtmList)
  2179. {
  2180. pNode = *ppdmtmList;
  2181. *ppdmtmList = (*ppdmtmList)->pNext;
  2182. // first free the action array
  2183. if(LocalFree((HLOCAL)(pNode->pdia)))
  2184. {
  2185. DPF(0, "dmtcfgFreeMappingList - MEMORY LEAK - "
  2186. "LocalFree(pdia) failed (%d)...",
  2187. GetLastError());
  2188. hRes = DMT_S_MEMORYLEAK;
  2189. }
  2190. // lastly, free the node
  2191. DPF(5, "dmtcfgFreeMappingList - deleting Node (%016Xh)", pNode);
  2192. if(LocalFree((HLOCAL)pNode))
  2193. {
  2194. DPF(0, "dmtcfgFreeMappingList - MEMORY LEAK - "
  2195. "LocalFree(Node) failed (%d)...",
  2196. GetLastError());
  2197. hRes = DMT_S_MEMORYLEAK;
  2198. }
  2199. DPF(5, "dmtcfgFreeMappingList - Node deleted");
  2200. }
  2201. // make sure that we set *ppObjList to NULL
  2202. *ppdmtmList = NULL;
  2203. // done
  2204. return hRes;
  2205. } //*** end dmtcfgFreeMappingList
  2206. //===========================================================================
  2207. // dmtcfgCreateAllMappingLists
  2208. //
  2209. // Uses dmtcfgCreateMappingList to create mapping lists for each subgenre
  2210. // referenced by pdmtai->pGenreList for each device refereced by
  2211. // pdmtai->pDeviceList
  2212. //
  2213. // Parameters:
  2214. //
  2215. // Returns: HRESULT
  2216. //
  2217. // History:
  2218. // 09/23/1999 - davidkl - created
  2219. //===========================================================================
  2220. HRESULT dmtcfgCreateAllMappingLists(DMT_APPINFO *pdmtai)
  2221. {
  2222. HRESULT hRes = S_OK;
  2223. HRESULT hr = S_OK;
  2224. DMTGENRE_NODE *pGenreNode = NULL;
  2225. DMTSUBGENRE_NODE *pSubGenreNode = NULL;
  2226. // validate pdmtai
  2227. if(IsBadReadPtr((void*)pdmtai, sizeof(DMT_APPINFO)))
  2228. {
  2229. return E_POINTER;
  2230. }
  2231. // validate pdmtai->pGenreList
  2232. if(IsBadReadPtr((void*)(pdmtai->pGenreList), sizeof(DMTGENRE_NODE)))
  2233. {
  2234. return E_POINTER;
  2235. }
  2236. // validate pdmtai->pDeviceList
  2237. if(IsBadReadPtr((void*)(pdmtai->pDeviceList), sizeof(DMTDEVICE_NODE)))
  2238. {
  2239. return E_POINTER;
  2240. }
  2241. // for each genre
  2242. pGenreNode = pdmtai->pGenreList;
  2243. while(pGenreNode)
  2244. {
  2245. // for each subgenre of the genre
  2246. pSubGenreNode = pGenreNode->pSubGenreList;
  2247. while(pSubGenreNode)
  2248. {
  2249. // create the mapping list
  2250. hr = dmtcfgCreateMappingList(pdmtai->pDeviceList,
  2251. pSubGenreNode->pActionList,
  2252. &(pSubGenreNode->pMappingList));
  2253. if(FAILED(hr))
  2254. {
  2255. hRes = S_FALSE;
  2256. }
  2257. // next subgenre
  2258. pSubGenreNode = pSubGenreNode->pNext;
  2259. }
  2260. // next genre
  2261. pGenreNode = pGenreNode->pNext;
  2262. }
  2263. // done
  2264. return hRes;
  2265. } //*** end dmtcfgCreateAllMappingLists()
  2266. //===========================================================================
  2267. // dmtcfgFreeAllMappingLists
  2268. //
  2269. // Walks the provided genre list and frees the mapping list found in each
  2270. // subgenre node
  2271. //
  2272. // Parameters:
  2273. // DMTGENRE_NODE *pdmtgList - list of genres
  2274. //
  2275. // Returns: HRESULT
  2276. //
  2277. // History:
  2278. // 10/05/1999 - davidkl - created
  2279. //===========================================================================
  2280. HRESULT dmtcfgFreeAllMappingLists(DMTGENRE_NODE *pdmtgList)
  2281. {
  2282. HRESULT hRes = S_OK;
  2283. HRESULT hr = S_OK;
  2284. DMTGENRE_NODE *pGenre = NULL;
  2285. DMTSUBGENRE_NODE *pSubGenre = NULL;
  2286. // validate pdmtgList
  2287. if(IsBadReadPtr((void*)pdmtgList, sizeof(DMTGENRE_NODE)))
  2288. {
  2289. return E_POINTER;
  2290. }
  2291. // walk the genre list
  2292. pGenre = pdmtgList;
  2293. while(pGenre)
  2294. {
  2295. // walk each subgenre list
  2296. pSubGenre = pGenre->pSubGenreList;
  2297. while(pSubGenre)
  2298. {
  2299. // free the mapping list
  2300. hr = dmtcfgFreeMappingList(&(pSubGenre->pMappingList));
  2301. if(S_OK != hr)
  2302. {
  2303. hRes = hr;
  2304. }
  2305. // next subgenre
  2306. pSubGenre = pSubGenre->pNext;
  2307. }
  2308. // next genre
  2309. pGenre = pGenre->pNext;
  2310. }
  2311. // done
  2312. return hRes;
  2313. } //*** end dmtcfgFreeAllMappingLists()
  2314. //===========================================================================
  2315. // dmtcfgMapAction
  2316. //
  2317. // Connects the dots between an action (in the map config dialog) to a device
  2318. // object
  2319. //
  2320. // Parameters:
  2321. // HWND hwnd - handle to property page window
  2322. // REFGUID guidInstance - instance GUID of DirectInputDevice object
  2323. // DIACTIONA *pdia - ptr to array of DIACTIONA structuresfs
  2324. // UINT uActions - number of actions in pdia
  2325. //
  2326. // Returns: HRESULT
  2327. //
  2328. // History:
  2329. // 09/14/1999 - davidkl - created
  2330. //===========================================================================
  2331. HRESULT dmtcfgMapAction(HWND hwnd,
  2332. REFGUID guidInstance,
  2333. DIACTIONA *pdia,
  2334. UINT uActions)
  2335. {
  2336. HRESULT hRes = S_OK;
  2337. // UINT uObjectSel = 0;
  2338. //JJ 64Bit Compat
  2339. UINT_PTR uObjectSel = 0;
  2340. UINT_PTR uActionSel = 0;
  2341. // UINT uActionSel = 0;
  2342. UINT u = 0;
  2343. BOOL fFound = FALSE;
  2344. DMTDEVICEOBJECT_NODE *pObject = NULL;
  2345. DMTACTION_NODE *pAction = NULL;
  2346. // valudate pdia
  2347. if(IsBadWritePtr((void*)pdia, sizeof(DIACTION)))
  2348. {
  2349. DPF(0, "dmtinputMapAction - invalid pdia (%016Xh)",
  2350. pdia);
  2351. return E_POINTER;
  2352. }
  2353. __try
  2354. {
  2355. // get the object & it's data
  2356. uObjectSel = SendMessageA(GetDlgItem(hwnd, IDC_CONTROLS),
  2357. LB_GETCURSEL,
  2358. 0,
  2359. 0L);
  2360. pObject = (DMTDEVICEOBJECT_NODE*)SendMessageA(GetDlgItem(hwnd,
  2361. IDC_CONTROLS),
  2362. LB_GETITEMDATA,
  2363. (WPARAM)uObjectSel,
  2364. 0L);
  2365. if(!pObject)
  2366. {
  2367. hRes = E_UNEXPECTED;
  2368. __leave;
  2369. }
  2370. // get the action's data
  2371. uActionSel = SendMessageA(GetDlgItem(hwnd, IDC_ACTIONS),
  2372. LB_GETCURSEL,
  2373. 0,
  2374. 0L);
  2375. pAction = (DMTACTION_NODE*)SendMessageA(GetDlgItem(hwnd, IDC_ACTIONS),
  2376. LB_GETITEMDATA,
  2377. (WPARAM)uActionSel,
  2378. 0L);
  2379. if(!pAction)
  2380. {
  2381. hRes = E_UNEXPECTED;
  2382. __leave;
  2383. }
  2384. // find the appropriate action in the array
  2385. fFound = FALSE;
  2386. for(u = 0; u < uActions; u++)
  2387. {
  2388. // match based on the semantic / action id
  2389. if((pdia + u)->dwSemantic == pAction->dwActionId)
  2390. {
  2391. DPF(2, "dmtcfgMapAction - found matching action "
  2392. "pAction->dwActionId (%08Xh) == "
  2393. "(pdia+u)->dwSemantic (%08Xh)",
  2394. pAction->dwActionId,
  2395. (pdia + u)->dwSemantic);
  2396. fFound = TRUE;
  2397. break;
  2398. }
  2399. }
  2400. // did we find the action in the array?
  2401. if(!fFound)
  2402. {
  2403. // no. this is very bad!
  2404. //
  2405. // if this EVER happens,
  2406. // we have a serious bug in this app
  2407. hRes = E_FAIL;
  2408. // since this should NEVER happen,
  2409. // break into the debugger and alert the tester
  2410. DPF(0, "dmtcfgMapAction - action not found in pdia!");
  2411. DPF(0, "dmtcfgMapAction - we were looking for "
  2412. "%08Xh (%s)",
  2413. pAction->dwActionId,
  2414. pAction->szActionId);
  2415. DPF(0, "dmtcfgMapAction - CRITICAL failure. "
  2416. "This should have never happened!");
  2417. DPF(0, "dmtcfgMapAction - Please find someone "
  2418. "to look at this right away. ");
  2419. DebugBreak();
  2420. __leave;
  2421. }
  2422. // update the action array
  2423. (pdia + u)->dwObjID = pObject->dwObjectType;
  2424. (pdia + u)->guidInstance = guidInstance;
  2425. // HIWORD((DWORD)uAppData) == object type
  2426. // LOWORD((DWORD)uAppData) == pObject->wCtrlId
  2427. (pdia + u)->uAppData = (DIDFT_GETTYPE(pObject->dwObjectType) << 16) |
  2428. (pObject->wCtrlId);
  2429. // update the list boxes
  2430. SendMessageA(hwnd,
  2431. WM_DMT_UPDATE_LISTS,
  2432. 0,
  2433. 0L);
  2434. // enable the unmap & unmap all buttons
  2435. EnableWindow(GetDlgItem(hwnd, IDC_UNMAP_ALL), TRUE);
  2436. EnableWindow(GetDlgItem(hwnd, IDC_UNMAP), TRUE);
  2437. // disable the map button
  2438. EnableWindow(GetDlgItem(hwnd, IDC_STORE_MAPPING), FALSE);
  2439. }
  2440. __finally
  2441. {
  2442. // cleanup
  2443. // nothing to do... yet
  2444. }
  2445. // done
  2446. return hRes;
  2447. } //*** end dmtcfgMapAction()
  2448. //===========================================================================
  2449. // dmtcfgUnmapAction
  2450. //
  2451. // Disconnects the dots between an action (in the map config dialog) and a
  2452. // device object
  2453. //
  2454. // Parameters:
  2455. // HWND hwnd - handle to property page window
  2456. // DIACTIONA *pdia - ptr to DIACTIONA array
  2457. // UINNT uActions - number of elements in pdia
  2458. //
  2459. // Returns: HRESULT
  2460. //
  2461. // History:
  2462. // 09/15/1999 - davidkl - created
  2463. //===========================================================================
  2464. HRESULT dmtcfgUnmapAction(HWND hwnd,
  2465. DIACTIONA *pdia,
  2466. UINT uActions)
  2467. {
  2468. HRESULT hRes = S_OK;
  2469. UINT u = 0;
  2470. // UINT uSel = 0;
  2471. //JJ 64Bit Compat
  2472. UINT_PTR uSel = 0;
  2473. BOOL fFound = FALSE;
  2474. DMTSUBGENRE_NODE *pSubGenre = NULL;
  2475. DMTDEVICEOBJECT_NODE *pObject = NULL;
  2476. // validate pdia
  2477. if(IsBadWritePtr((void*)pdia, uActions * sizeof(DIACTIONA)))
  2478. {
  2479. return E_POINTER;
  2480. }
  2481. __try
  2482. {
  2483. // get the current control selection
  2484. uSel = SendMessageA(GetDlgItem(hwnd, IDC_CONTROLS),
  2485. LB_GETCURSEL,
  2486. 0,
  2487. 0L);
  2488. pObject = (DMTDEVICEOBJECT_NODE*)SendMessageA(GetDlgItem(hwnd, IDC_CONTROLS),
  2489. LB_GETITEMDATA,
  2490. (WPARAM)uSel,
  2491. 0L);
  2492. if(!pObject)
  2493. {
  2494. // this is bad
  2495. hRes = E_UNEXPECTED;
  2496. __leave;
  2497. }
  2498. // spin through pdia
  2499. // look for an action with our object's offset
  2500. fFound = FALSE;
  2501. for(u = 0; u < uActions; u++)
  2502. {
  2503. // first check the guid
  2504. if(IsEqualGUID(pObject->guidDeviceInstance, (pdia+u)->guidInstance))
  2505. {
  2506. // then compare the offset
  2507. if((pdia+u)->dwObjID == pObject->dwObjectType)
  2508. {
  2509. fFound = TRUE;
  2510. break;
  2511. }
  2512. }
  2513. }
  2514. // if nothing is found,
  2515. // the selected object is not mapped
  2516. //
  2517. // (non-critical internal error condition)
  2518. if(!fFound)
  2519. {
  2520. hRes = S_FALSE;
  2521. __leave;
  2522. }
  2523. // reset the guidInstance and dwSemantic fields
  2524. (pdia + u)->guidInstance = GUID_NULL;
  2525. (pdia + u)->dwObjID = 0;
  2526. (pdia + u)->uAppData = 0;
  2527. // update the lists
  2528. SendMessageA(hwnd,
  2529. WM_DMT_UPDATE_LISTS,
  2530. 0,
  2531. 0L);
  2532. // enable the map button
  2533. EnableWindow(GetDlgItem(hwnd, IDC_STORE_MAPPING), TRUE);
  2534. // disable the unmap button
  2535. EnableWindow(GetDlgItem(hwnd, IDC_UNMAP), FALSE);
  2536. // if no other actions are mapped,
  2537. // disable the unmap all button
  2538. fFound = FALSE;
  2539. for(u = 0; u < uActions; u++)
  2540. {
  2541. if(!IsEqualGUID(GUID_NULL, (pdia+u)->guidInstance))
  2542. {
  2543. fFound = TRUE;
  2544. }
  2545. }
  2546. if(!fFound)
  2547. {
  2548. EnableWindow(GetDlgItem(hwnd, IDC_UNMAP_ALL), FALSE);
  2549. }
  2550. }
  2551. __finally
  2552. {
  2553. // cleanup
  2554. // nothing to do... yet
  2555. }
  2556. // done
  2557. return hRes;
  2558. } //*** end dmtcfgUnmapAction()
  2559. //===========================================================================
  2560. // dmtcfgUnmapAllActions
  2561. //
  2562. // Disconnects the all connections between an action (in the map config
  2563. // dialog) and a device object
  2564. //
  2565. // Parameters:
  2566. // HWND hwnd - handle to property page window
  2567. // DIACTIONA *pdia - ptr to DIACTIONA array
  2568. // UINNT uActions - number of elements in pdia
  2569. //
  2570. // Returns: HRESULT
  2571. //
  2572. // History:
  2573. // 09/15/1999 - davidkl - created
  2574. //===========================================================================
  2575. HRESULT dmtcfgUnmapAllActions(HWND hwnd,
  2576. DIACTIONA *pdia,
  2577. UINT uActions)
  2578. {
  2579. UINT u = 0;
  2580. // validate pdia
  2581. if(IsBadWritePtr((void*)pdia, uActions * sizeof(DIACTIONA)))
  2582. {
  2583. return E_POINTER;
  2584. }
  2585. // spin through pdia
  2586. // reset the guidInstance and dwSemantic fields
  2587. for(u = 0; u < uActions; u++)
  2588. {
  2589. (pdia + u)->guidInstance = GUID_NULL;
  2590. (pdia + u)->dwObjID = 0;
  2591. (pdia + u)->uAppData = 0;
  2592. }
  2593. // update the lists
  2594. SendMessageA(hwnd,
  2595. WM_DMT_UPDATE_LISTS,
  2596. 0,
  2597. 0L);
  2598. // disable the unmap & unmap all buttons
  2599. EnableWindow(GetDlgItem(hwnd, IDC_UNMAP), FALSE);
  2600. EnableWindow(GetDlgItem(hwnd, IDC_UNMAP_ALL), FALSE);
  2601. // enable the map button
  2602. EnableWindow(GetDlgItem(hwnd, IDC_STORE_MAPPING), TRUE);
  2603. // done
  2604. return S_OK;
  2605. } //*** end dmtcfgUnmapAllActions()
  2606. //===========================================================================
  2607. // dmtcfgIsControlMapped
  2608. //
  2609. // Checks to see if a control is mapped to an action
  2610. //
  2611. // Parameters:
  2612. //
  2613. // Returns:
  2614. //
  2615. // History:
  2616. // 09/15/1999 - davidkl - created
  2617. //===========================================================================
  2618. BOOL dmtcfgIsControlMapped(HWND hwnd,
  2619. DIACTIONA *pdia,
  2620. UINT uActions)
  2621. {
  2622. BOOL fMapped = FALSE;
  2623. UINT u = 0;
  2624. // UINT uSel = 0;
  2625. //JJ 64Bit Compat
  2626. UINT_PTR uSel = 0;
  2627. DMTDEVICEOBJECT_NODE *pObject = NULL;
  2628. // validate pdia
  2629. if(IsBadReadPtr((void*)pdia, uActions * sizeof(pdia)))
  2630. {
  2631. DPF(0, "dmtcfgIsControlMapped - invalid pdia (%016Xh)",
  2632. pdia);
  2633. SetLastError(ERROR_INVALID_DATA);
  2634. return FALSE;
  2635. }
  2636. // get the currently selected control
  2637. uSel = SendMessageA(GetDlgItem(hwnd, IDC_CONTROLS),
  2638. LB_GETCURSEL,
  2639. 0,
  2640. 0L);
  2641. pObject = (DMTDEVICEOBJECT_NODE*)SendMessageA(GetDlgItem(hwnd, IDC_CONTROLS),
  2642. LB_GETITEMDATA,
  2643. (WPARAM)uSel,
  2644. 0L);
  2645. if(!pObject)
  2646. {
  2647. // this is bad
  2648. //
  2649. // (serious internal app error)
  2650. SetLastError(ERROR_GEN_FAILURE);
  2651. DebugBreak();
  2652. return FALSE;
  2653. }
  2654. // check the array,
  2655. // see if this control is mapped to anything
  2656. fMapped = FALSE;
  2657. for(u = 0; u < uActions; u++)
  2658. {
  2659. // first check the guid
  2660. if(IsEqualGUID(pObject->guidDeviceInstance, (pdia+u)->guidInstance))
  2661. {
  2662. // then compare the offset
  2663. if((pdia+u)->dwObjID == pObject->dwObjectType)
  2664. // if((pdia+u)->dwObjID == pObject->dwObjectOffset)
  2665. {
  2666. fMapped = TRUE;
  2667. break;
  2668. }
  2669. }
  2670. }
  2671. // done
  2672. SetLastError(ERROR_SUCCESS);
  2673. return fMapped;
  2674. } //*** end dmtcfgIsControlMapped()
  2675. //===========================================================================
  2676. // dmtcfgAreAnyControlsMapped
  2677. //
  2678. // Checks to see if any controls are mapped to an action.
  2679. //
  2680. // Parameters:
  2681. //
  2682. // Returns:
  2683. //
  2684. // History:
  2685. // 11/01/1999 - davidkl - created
  2686. //===========================================================================
  2687. BOOL dmtcfgAreAnyControlsMapped(HWND hwnd,
  2688. DIACTIONA *pdia,
  2689. UINT uActions)
  2690. {
  2691. BOOL fMapped = FALSE;
  2692. UINT u = 0;
  2693. // validate pdia
  2694. if(IsBadReadPtr((void*)pdia, uActions * sizeof(pdia)))
  2695. {
  2696. DPF(0, "dmtcfgAreAnyControlsMapped - invalid pdia (%016Xh)",
  2697. pdia);
  2698. SetLastError(ERROR_INVALID_DATA);
  2699. return FALSE;
  2700. }
  2701. // check the array,
  2702. // see if this control is mapped to anything
  2703. fMapped = FALSE;
  2704. for(u = 0; u < uActions; u++)
  2705. {
  2706. // check guid
  2707. //
  2708. // if not GUID_NULL, this action is mapped
  2709. if(!IsEqualGUID(GUID_NULL, (pdia+u)->guidInstance))
  2710. {
  2711. fMapped = TRUE;
  2712. break;
  2713. }
  2714. }
  2715. // done
  2716. SetLastError(ERROR_SUCCESS);
  2717. return fMapped;
  2718. } //*** end dmtcfgAreAnyControlsMapped()
  2719. //===========================================================================
  2720. // dmtcfgGetGenreGroupName
  2721. //
  2722. // Extracts the genre group name from the genres.ini entry
  2723. //
  2724. // Paramters:
  2725. //
  2726. // Returns: HRESULT
  2727. //
  2728. // History:
  2729. // 09/28/1999 - davidkl - created
  2730. // 09/29/1999 - davidkl - modified "buckets"
  2731. //===========================================================================
  2732. HRESULT dmtcfgGetGenreGroupName(PSTR szGenreName,
  2733. PSTR szGenreGroupName)
  2734. {
  2735. HRESULT hRes = S_OK;
  2736. char *pcFirst = NULL;
  2737. char *pcCurrent = NULL;
  2738. // find the first '_'
  2739. pcFirst = strchr(szGenreName, '_');
  2740. // copy the characters between pcFirst and pcLast
  2741. pcCurrent = pcFirst+1; // skip past the first '_'
  2742. while((*pcCurrent != '_') && (*pcCurrent != '\0'))
  2743. {
  2744. *szGenreGroupName = *pcCurrent;
  2745. // next character
  2746. pcCurrent++;
  2747. szGenreGroupName++;
  2748. }
  2749. *szGenreGroupName = '\0';
  2750. // done
  2751. return hRes;
  2752. } //*** end dmtcfgGetGenreGroupName()
  2753. //===========================================================================
  2754. //===========================================================================