//=========================================================================== // dmtcfg.cpp // // File / code creation functionality // // Functions: // dmtcfgCreatePropertySheet // dmtcfgDlgProc // dmtcfgOnInitDialog // dmtcfgOnClose // dmtcfgOnCommand // dmtcfgOnNotify // dmtcfgCreateGenreList // dmtcfgFreeGenreList // dmtcfgCreateSubGenreList // dmtcfgFreeSubGenreList // dmtcfgCreateActionList // dmtcfgFreeActionList // // History: // 08/20/1999 - davidkl - created //=========================================================================== #include "dimaptst.h" #include "dmtinput.h" //#include "dmtwrite.h" #include "dmtcfg.h" //--------------------------------------------------------------------------- //=========================================================================== // dmtcfgCreatePropertySheet // // Create property sheet dialog for device action map configuration // // Parameters: // HINSTANCE hinst - app instance handle // HWND hwndParent - parent window handle // LPSTR szSelectedGenre // DMTGENRE_NODE* pGenreList // DMTGENRE_NODE* pDeviceNode // BOOL fStartWithDefaults // // Returns: HRESULT // // History: // 08/23/1999 - davidkl - created // 09/08/1999 - davidkl - changed param list //=========================================================================== HRESULT dmtcfgCreatePropertySheet(HINSTANCE hinst, HWND hwndParent, LPSTR szSelectedGenre, DMTGENRE_NODE *pGenreList, DMTDEVICE_NODE *pDeviceNode, BOOL fStartWithDefaults) { HRESULT hRes = S_OK; UINT u = 0; UINT uSel = 0; DMTGENRE_NODE *pNode = NULL; PROPSHEETPAGEA *pPages = NULL; PROPSHEETHEADERA psh; char szCaption[MAX_PATH]; DMT_APPINFO *pdmtai = NULL; DMTDEVICE_NODE dmtd; // validate pGenreList if(IsBadReadPtr((void*)pGenreList, sizeof(DMTGENRE_NODE))) { DPF(0, "dmtcfgCreatePropertySheet - invalid pGenreList (%016Xh)", pGenreList); return E_POINTER; } // validate pDeviceNode if(IsBadReadPtr((void*)pDeviceNode, sizeof(DMTDEVICE_NODE))) { DPF(0, "dmtcfgCreatePropertySheet - invalid pDeviceNode (%016Xh)", pDeviceNode); return E_POINTER; } __try { // count the genres // // find the node we care about u = 0; pNode = pGenreList; while(pNode) { // if we find our genre, start on that page if(!lstrcmpiA(szSelectedGenre, pNode->szName)) { uSel = u; } // increment the number of genres u++; pNode = pNode->pNext; } // allocate the page array (dw pages) pPages = (PROPSHEETPAGEA*)LocalAlloc(LMEM_FIXED, sizeof(PROPSHEETPAGEA) * u); if(!pPages) { DPF(0, "dmtcfgCreatePropertySheet - insufficient mempory to " "allocate pPages array"); hRes = E_OUTOFMEMORY; __leave; } // add device name to caption wsprintfA(szCaption, "Configure Device Action Map - %s", pDeviceNode->szName); // strip the next ptr from the selected device node CopyMemory((void*)&dmtd, (void*)pDeviceNode, sizeof(DMTDEVICE_NODE)); dmtd.pNext = NULL; // allocate app info data struct for pages pdmtai = (DMT_APPINFO*)LocalAlloc(LMEM_FIXED, u * sizeof(DMT_APPINFO)); if(!pdmtai) { hRes = E_OUTOFMEMORY; __leave; } ZeroMemory((void*)pdmtai, u * sizeof(DMT_APPINFO)); // prepare property sheet header psh.dwSize = sizeof(PROPSHEETHEADERA); psh.dwFlags = PSH_PROPSHEETPAGE | PSP_USETITLE | PSH_NOAPPLYNOW; psh.hwndParent = hwndParent; psh.hInstance = hinst; psh.pszCaption = szCaption; psh.nPages = u; psh.nStartPage = uSel; psh.ppsp = pPages; // describe sheets pNode = pGenreList; for(u = 0; u < (DWORD)(psh.nPages); u++) { if(!pNode) { DPF(0, "dmtcfgCreatePropertySheet - we messed up! " "we allocated less than %d pages", psh.nPages); DPF(0, "PLEASE find someone to look at this NOW"); hRes = E_UNEXPECTED; DebugBreak(); __leave; } // populate the app info for the page (pdmtai + u)->pGenreList = pNode; (pdmtai + u)->pDeviceList = &dmtd; (pdmtai + u)->fStartWithDefaults = fStartWithDefaults; (pdmtai + u)->fLaunchCplEditMode = FALSE; // populate the page array entry ZeroMemory((void*)(pPages + u), sizeof(PROPSHEETPAGEA)); (pPages + u)->dwSize = sizeof(PROPSHEETPAGEA); (pPages + u)->dwFlags = PSP_USETITLE; (pPages + u)->hInstance = hinst; (pPages + u)->pszTemplate = MAKEINTRESOURCEA(IDD_CONFIGURE_MAPPING_PAGE); (pPages + u)->pfnDlgProc = (DLGPROC)dmtcfgDlgProc; (pPages + u)->pszTitle = pNode->szName; (pPages + u)->lParam = (LPARAM)(pdmtai + u); // next node pNode = pNode->pNext; } // create this thing if(0 > PropertySheetA(&psh)) { DPF(0, "dmtcfgCreatePropertySheet - dialog creation failed (%08Xh)", GetLastError()); hRes = E_UNEXPECTED; __leave; } } __finally { // free the app info array if(pdmtai) { if(LocalFree((HLOCAL)pdmtai)) { DPF(0, "dmtcfgCreaatePropertySheet - !!!MEMORY LEAK!!! " "LocalFree(pdmtai) failed (%08X)", GetLastError()); hRes = S_FALSE; } pdmtai = NULL; } // free the page array if(pPages) { if(LocalFree((HLOCAL)pPages)) { DPF(0, "dmtcfgCreaatePropertySheet - !!!MEMORY LEAK!!! " "LocalFree(pPages) failed (%08X)", GetLastError()); hRes = S_FALSE; } pPages = NULL; } } // done return hRes; } //*** end dmtcfgCreatePropertySheet() //=========================================================================== // dmtcfgDlgProc // // Configure Device Action Map dialog processing function // // Parameters: (see SDK help for parameter details) // HWND hwnd // UINT uMsg // WPARAM wparam // LPARAM lparam // // Returns: (see SDK help for return value details) // BOOL // // History: // 08/20/1999 - davidkl - created //=========================================================================== BOOL CALLBACK dmtcfgDlgProc(HWND hwnd, UINT uMsg, WPARAM wparam, LPARAM lparam) { switch(uMsg) { case WM_INITDIALOG: return dmtcfgOnInitDialog(hwnd, (HWND)wparam, lparam); case WM_COMMAND: return dmtcfgOnCommand(hwnd, LOWORD(wparam), (HWND)lparam, HIWORD(wparam)); case WM_NOTIFY: return dmtcfgOnNotify(hwnd, (PSHNOTIFY *)lparam); case WM_DMT_UPDATE_LISTS: return dmtcfgOnUpdateLists(hwnd); } return FALSE; } //*** end dmtcfgDlgProc() //=========================================================================== // dmtcfgOnInitDialog // // Handle WM_INITDIALOG processing for the config device box // // Parameters: // HWND hwnd - handle to property page // HWND hwndFocus - handle of ctrl with focus // LPARAM lparam - user data (in this case, PROPSHEETPAGE*) // // Returns: BOOL // // History: // 08/20/1999 - davidkl - created //=========================================================================== BOOL dmtcfgOnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lparam) { HRESULT hRes = S_OK; PROPSHEETPAGEA *ppsp = (PROPSHEETPAGEA*)lparam; DMTGENRE_NODE *pGenre = NULL; DMTSUBGENRE_NODE *pSubNode = NULL; DMTMAPPING_NODE *pMapNode = NULL; //LONG lPrev = 0L; //JJ 64Bit Compat LONG_PTR lPrev = 0; // int nIdx = 0; LONG_PTR nIdx = 0; DMTDEVICE_NODE *pDevice = NULL; DMT_APPINFO *pdmtai = NULL; UINT u = 0; WORD wTypeCtrl = 0; DIACTIONFORMATA diaf; DPF(5, "dmtcfgOnInitDialog"); // validate ppsp (lparam) if(IsBadWritePtr((void*)ppsp, sizeof(PROPSHEETPAGEA))) { DPF(0, "dmtcfgOnInitDialog - invalid lParam (%016Xh)", ppsp); return FALSE; } // pdmtai == ppsp->lParam pdmtai = (DMT_APPINFO*)(ppsp->lParam); // validate pdmtai if(IsBadWritePtr((void*)pdmtai, sizeof(DMT_APPINFO))) { DPF(0, "dmtcfgOnInitDialog - invalid ppsp.ptp (%016Xh)", pdmtai); return FALSE; } // pGenre == pdmtai->pGenreList pGenre = pdmtai->pGenreList; // valdiate pGenre if(IsBadWritePtr((void*)pGenre, sizeof(DMTGENRE_NODE))) { DPF(0, "dmtcfgOnInitDialog - invalid pGenre (%016Xh)", pGenre); return FALSE; } // pDevice == pdmtai->pDeviceList pDevice = pdmtai->pDeviceList; // valdiate pGenre if(IsBadWritePtr((void*)pDevice, sizeof(DMTDEVICE_NODE))) { DPF(0, "dmtcfgOnInitDialog - invalid pDevice (%016Xh)", pDevice); return FALSE; } // change the property sheet dialog button text // Ok -> Save SetWindowTextA(GetDlgItem(GetParent(hwnd), IDOK), "&Save"); // Apply -> Load //SetWindowTextA(GetDlgItem(GetParent(hwnd), IDC_PS_APPLY), // "Load"); // Cancel -> Close SetWindowTextA(GetDlgItem(GetParent(hwnd), IDCANCEL), "&Close"); __try { // store the app info in the property page's user data SetLastError(0); //lPrev = SetWindowLong(hwnd, // GWL_USERDATA, // (LONG)pdmtai); //JJ 64Bit Compat lPrev = SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pdmtai); if(!lPrev && GetLastError()) { // serious app problem. // we need to stop things right here and now DPF(0, "dmtcfgOnInitDialog - This is bad... " "We failed to store pdmtai"); DPF(0, "dmtcfgOnInitDialog - Please find someone " "to look at this right away"); DebugBreak(); hRes = E_FAIL; __leave; } // walk the list and populate the subgenre list box // // store the ptr to the subgenre node in the listbox // entry user data pSubNode = pGenre->pSubGenreList; while(pSubNode) { // add the subgenre name to the list nIdx = SendMessageA(GetDlgItem(hwnd, IDC_SUBGENRE), CB_ADDSTRING, 0, (LPARAM)(pSubNode->szName)); // store the subgenre node in the list entry SendMessageA(GetDlgItem(hwnd, IDC_SUBGENRE), CB_SETITEMDATA, nIdx, (LPARAM)pSubNode); // if the user has requested default mappings // get them for the specified device if(pdmtai->fStartWithDefaults) { // walk the mappings list until the selected // device is found pMapNode = pSubNode->pMappingList; while(pMapNode) { // try to match on guidInstance if(IsEqualGUID(pDevice->guidInstance, pMapNode->guidInstance)) { // match found break; } // next mapping pMapNode = pMapNode->pNext; } if(pMapNode) { ZeroMemory((void*)&diaf, sizeof(DIACTIONFORMATA)); diaf.dwSize = sizeof(DIACTIONFORMATA); diaf.dwActionSize = sizeof(DIACTIONA); diaf.dwNumActions = (DWORD)(pMapNode->uActions); diaf.rgoAction = pMapNode->pdia; diaf.dwDataSize = 4 * diaf.dwNumActions; diaf.guidActionMap = GUID_DIMapTst; diaf.dwGenre = pSubNode->dwGenreId; diaf.dwBufferSize = DMTINPUT_BUFFERSIZE; lstrcpyA(diaf.tszActionMap, DMT_APP_CAPTION); // get the default mappings hRes = (pDevice->pdid)->BuildActionMap(&diaf, (LPCSTR)NULL, DIDBAM_HWDEFAULTS); if(FAILED(hRes)) { // ISSUE-2001/03/29-timgill Needs error case handling } } else { // ISSUE-2001/03/29-timgill needs error handling } } // next subgenre pSubNode = pSubNode->pNext; } // set the subgenre list selection SendMessageA(GetDlgItem(hwnd, IDC_SUBGENRE), CB_SETCURSEL, 0, 0); // selectively disable axis/button/pov radio buttons // // this is done if the selected device does not // actually have one of these objects // // since axes are our "prefered" initial display // option, check them last if(dmtinputDeviceHasObject(pDevice->pObjectList, DMTA_TYPE_POV)) { EnableWindow(GetDlgItem(hwnd, IDC_TYPE_POV), TRUE); wTypeCtrl = IDC_TYPE_POV; } if(dmtinputDeviceHasObject(pDevice->pObjectList, DMTA_TYPE_BUTTON)) { EnableWindow(GetDlgItem(hwnd, IDC_TYPE_BUTTON), TRUE); wTypeCtrl = IDC_TYPE_BUTTON; } if(dmtinputDeviceHasObject(pDevice->pObjectList, DMTA_TYPE_AXIS)) { EnableWindow(GetDlgItem(hwnd, IDC_TYPE_AXIS), TRUE); wTypeCtrl = IDC_TYPE_AXIS; } // select the axes radio button if(0 == wTypeCtrl) { // we have a "device" that has no objects... // // this is very bad DebugBreak(); return TRUE; } CheckRadioButton(hwnd, IDC_TYPE_POV, IDC_TYPE_AXIS, wTypeCtrl); // for the default subgenre, walk the list and populate // the actions list box // // store the ptr to the actions node in the listbox // entry user data pSubNode = (DMTSUBGENRE_NODE*)SendMessageA(GetDlgItem(hwnd, IDC_SUBGENRE), CB_GETITEMDATA, 0, 0L); // update the lists SendMessageA(hwnd, WM_DMT_UPDATE_LISTS, 0, 0L); // select the first entry in each list SendMessageA(GetDlgItem(hwnd, IDC_CONTROLS), LB_SETCURSEL, 0, 0L); SendMessageA(GetDlgItem(hwnd, IDC_ACTIONS), LB_SETCURSEL, 0, 0L); // display the subgenre description SetDlgItemTextA(hwnd, IDC_DESCRIPTION, pSubNode->szDescription); // make sure the map/unmap buttons are enabled correctly SendMessageA(hwnd, WM_COMMAND, IDC_CONTROLS, 0L); } __finally { // if failure case, clean house if(FAILED(hRes)) { // ISSUE-2001/03/29-timgill Needs error case handling } } // done return TRUE; } //*** end dmtcfgOnInitDialog() //=========================================================================== // dmtcfgOnCommand // // Handle WM_COMMAND processing for the config device box // // Parameters: // HWND hwnd - handle to property page // WORD wId - control identifier (LOWORD(wparam)) // HWND hwndCtrl - handle to control ((HWND)lparam) // WORD wNotifyCode - notification code (HIWORD(wparam)) // // Returns: BOOL // // History: // 08/20/1999 - davidkl - created //=========================================================================== BOOL dmtcfgOnCommand(HWND hwnd, WORD wId, HWND hwndCtrl, WORD wNotifyCode) { HRESULT hRes = S_OK; // UINT uSel = 0; //JJ 64Bit Compat UINT_PTR uSel = 0; UINT uActions = 0; BOOL fEnable = FALSE; DMT_APPINFO *pdmtai = NULL; DMTSUBGENRE_NODE *pSubGenre = NULL; DMTMAPPING_NODE *pMapping = NULL; DIACTIONA *pdia = NULL; DPF(5, "dmtcfgOnCommand"); // get the window data //pdmtai = (DMT_APPINFO*)GetWindowLong(hwnd, GWL_USERDATA); //JJ 64Bit Compat pdmtai = (DMT_APPINFO*)GetWindowLongPtr(hwnd, GWLP_USERDATA); if(!pdmtai) { // big problem // // this should NEVER happen // ISSUE-2001/03/29-timgill Needs error case handling } // what is the currently selected subgenre? uSel = SendMessageA(GetDlgItem(hwnd, IDC_SUBGENRE), CB_GETCURSEL, 0, 0L); pSubGenre = (DMTSUBGENRE_NODE*)SendMessageA(GetDlgItem(hwnd, IDC_SUBGENRE), CB_GETITEMDATA, uSel, 0L); if(!pSubGenre) { // big problem // // this should NEVER happen // ISSUE-2001/03/29-timgill Needs error case handling } // get the active DIACTION array pMapping = pSubGenre->pMappingList; while(pMapping) { // match pdmtai->pDeviceList->guidInstance with // pMapping->guidInstance if(IsEqualGUID(pdmtai->pDeviceList->guidInstance, pMapping->guidInstance)) { break; } // next mapping pMapping = pMapping->pNext; } if(pMapping) { pdia = pMapping->pdia; uActions = pMapping->uActions; } // update genre description SetDlgItemTextA(hwnd, IDC_DESCRIPTION, pSubGenre->szDescription); switch(wId) { case IDC_SUBGENRE: // based on the selected subgenre // // display the objects/actions for the selected type // (see type IDs below) if(CBN_SELCHANGE == wNotifyCode) { // update the lists SendMessageA(hwnd, WM_DMT_UPDATE_LISTS, 0, 0L); } break; case IDC_TYPE_AXIS: case IDC_TYPE_BUTTON: case IDC_TYPE_POV: // update the lists SendMessageA(hwnd, WM_DMT_UPDATE_LISTS, 0, 0L); // make sure the unmap button is selected as appropriate SendMessageA(hwnd, WM_COMMAND, IDC_CONTROLS, 0L); break; case IDC_CONTROLS: // if a mapped action is selected // enable the "Unmap action" button fEnable = dmtcfgIsControlMapped(hwnd, pdia, uActions); EnableWindow(GetDlgItem(hwnd, IDC_UNMAP), fEnable); // do NOT enable the map button if there are no // more actions if(!SendMessage(GetDlgItem(hwnd, IDC_ACTIONS), LB_GETCOUNT, 0, 0L)) { EnableWindow(GetDlgItem(hwnd, IDC_STORE_MAPPING), FALSE); } else { EnableWindow(GetDlgItem(hwnd, IDC_STORE_MAPPING), !fEnable); } // if >any< controls are mapped // enable the "Unmap all" button fEnable = dmtcfgAreAnyControlsMapped(hwnd, pdia, uActions); EnableWindow(GetDlgItem(hwnd, IDC_UNMAP_ALL), fEnable); break; case IDC_STORE_MAPPING: // "Map action" // map it hRes = dmtcfgMapAction(hwnd, pdmtai->pDeviceList->guidInstance, pdia, uActions); if(FAILED(hRes)) { // ISSUE-2001/03/29-timgill Needs error case handling } // set the changed flag pMapping->fChanged = TRUE; break; case IDC_UNMAP: // "Unmap action" // unmap it hRes = dmtcfgUnmapAction(hwnd, pdia, uActions); if(FAILED(hRes)) { // ISSUE-2001/03/29-timgill Needs error case handling } // set the changed flag pMapping->fChanged = TRUE; break; case IDC_UNMAP_ALL: // "Unmap all" hRes = dmtcfgUnmapAllActions(hwnd, pdia, uActions); if(FAILED(hRes)) { // ISSUE-2001/03/29-timgill Needs error case handling } // set the changed flag pMapping->fChanged = TRUE; break; } // done return FALSE; } //*** end dmtcfgOnCommand() //=========================================================================== // dmtcfgOnNotify // // Handle WM_NOTIFY processing for the config device box // // Parameters: // HWND hwnd - handle to property page // PSHNOTIFY *ppsh - PSHNOTIFY ptr // // Returns: BOOL // // History: // 08/20/1999 - davidkl - created // 10/14/1999 - davidkl - implemented save calls //=========================================================================== BOOL dmtcfgOnNotify(HWND hwnd, PSHNOTIFY *pNotify) { //int n = 0; //JJ 64Bit Compat INT_PTR n = 0; BOOL fSave = FALSE; DMT_APPINFO *pdmtai = NULL; // 7/19/2000(a-JiTay): IA64: Use %p format specifier for 32/64-bit pointers. DPF(5, "dmtcfgOnNotify: hwnd == %Ph", hwnd); // get the window data //pdmtai = (DMT_APPINFO*)GetWindowLong(hwnd, GWL_USERDATA); //JJ 64Bit Compat pdmtai = (DMT_APPINFO*)GetWindowLongPtr(hwnd, GWLP_USERDATA); if(!pdmtai) { // bad news // ISSUE-2001/03/29-timgill Needs error case handling } switch(pNotify->hdr.code) { case PSN_SETACTIVE: DPF(5, "PSN_SETACTIVE"); // force the apply button to be enabled SendMessageA(GetParent(hwnd), PSM_CHANGED, (WPARAM)hwnd, 0L); break; case PSN_KILLACTIVE: DPF(5, "PSN_KILLACTIVE"); // make sure we get a PSN_APPLY message //SetWindowLong(hwnd, DWL_MSGRESULT, (LONG)FALSE); SetWindowLong(hwnd, DWLP_MSGRESULT, (LONG)FALSE); break; case PSN_APPLY: DPF(5, "PSN_APPLY - %s", (pNotify->lParam) ? "Ok" : "Apply"); // save/load mapping data // // OK == Save // Apply == Load // which button was clicked? if(pNotify->lParam) { // save mapping data SendMessage(hwnd, WM_DMT_FILE_SAVE, 0,0L); } else { // load mapping data // ISSUE-2001/03/29-timgill Load Mapping Data not yet implemented MessageBoxA(hwnd, "Load - Not Yet Implemented", pdmtai->pDeviceList->szName, MB_OK); } // DO NOT allow the dialog to close //SetWindowLong(hwnd, // DWL_MSGRESULT, // (LONG)PSNRET_INVALID_NOCHANGEPAGE); //JJ 64Bit Compat SetWindowLongPtr(hwnd, DWLP_MSGRESULT, (LONG_PTR)PSNRET_INVALID_NOCHANGEPAGE); break; } // done return TRUE; } //*** end dmtcfgOnNotify() //=========================================================================== // dmtcfgOnUpdateLists // // Handle WM_DMT_UPDATE_LISTS message // // Parameters: // // Returns: BOOL // // History: // 08/25/1999 - davidkl - created // 11/12/1999 - dvaidkl - fixed problem with control selection setting //=========================================================================== BOOL dmtcfgOnUpdateLists(HWND hwnd) { //int nIdx = -1; //int nSelCtrl = -1; //JJ 64Bit Compat INT_PTR nSelCtrl = -1; INT_PTR nIdx = -1; int n = 0; INT_PTR nControls = 0; INT_PTR nActions = 0; //int nControls = 0; //int nActions = 0; DWORD dwType = DMTA_TYPE_UNKNOWN; DWORD dwObjType = DMTA_TYPE_UNKNOWN; DMTSUBGENRE_NODE *pSubGenre = NULL; DMTACTION_NODE *pAction = NULL; DMTMAPPING_NODE *pMapping = NULL; DMTDEVICEOBJECT_NODE *pObjectList = NULL; DMTDEVICEOBJECT_NODE *pObjectNode = NULL; DMT_APPINFO *pdmtai = NULL; DIACTION *pdia = NULL; BOOL fFound = FALSE; char szBuf[MAX_PATH]; DPF(5, "dmtcfgOnUpdateLists"); // get the window data //pdmtai = (DMT_APPINFO*)GetWindowLong(hwnd, GWL_USERDATA); //JJ 64Bit Compat pdmtai = (DMT_APPINFO*)GetWindowLongPtr(hwnd, GWLP_USERDATA); if(!pdmtai) { // bad news // ISSUE-2001/03/29-timgill Needs error case handling } // device object list pObjectList = pdmtai->pDeviceList->pObjectList; // get the currently selected control nSelCtrl = SendMessageA(GetDlgItem(hwnd, IDC_CONTROLS), LB_GETCURSEL, 0, 0L); // clear the list box contents // actions SendMessageA(GetDlgItem(hwnd, IDC_ACTIONS), LB_RESETCONTENT, 0, 0L); // controls SendMessageA(GetDlgItem(hwnd, IDC_CONTROLS), LB_RESETCONTENT, 0, 0L); // get the current selection nIdx = SendMessageA(GetDlgItem(hwnd, IDC_SUBGENRE), CB_GETCURSEL, 0, 0L); // get the item data pSubGenre = (DMTSUBGENRE_NODE*)SendMessageA(GetDlgItem(hwnd, IDC_SUBGENRE), CB_GETITEMDATA, nIdx, 0L); // get the DIACTION array specific to the current device pMapping = pSubGenre->pMappingList; while(pMapping) { // match pdmtai->pDeviceList->guidInstance // with pMapping->guidInstance if(IsEqualGUID(pdmtai->pDeviceList->guidInstance, pMapping->guidInstance)) { break; } // next mapping pMapping = pMapping->pNext; } if(!pMapping) { // this is very bad and should NEVER happen // ISSUE-2001/03/29-timgill Needs error case handling DebugBreak(); } pdia = pMapping->pdia; nActions = (int)pMapping->uActions; // what control type is selected? dwType = IDC_TYPE_AXIS - (dmtGetCheckedRadioButton(hwnd, IDC_TYPE_POV, IDC_TYPE_AXIS)); // populate the action list nIdx = 0; pAction = pSubGenre->pActionList; while(pAction) { // filter to the selected control type if(dwType == pAction->dwType) { // filter actions that are already assigned // first, find a matching action in the array fFound = FALSE; for(n = 0; n < nActions; n++) { // match based on the semantic / action id if((pdia+n)->dwSemantic == pAction->dwActionId) { DPF(2, "dmtcfgOnUpdateLists- found matching action " "pAction->dwActionId (%08Xh) == " "(pdia+u)->dwSemantic (%08Xh)", pAction->dwActionId, (pdia+n)->dwSemantic); fFound = TRUE; break; } } // next, read the action array entry, // if GUID_NULL == guidInstance, add the entry if(!fFound || IsEqualGUID(GUID_NULL, (pdia+n)->guidInstance)) { // prepend the action priority wsprintfA(szBuf, "(Pri%d) %s", pAction->dwPriority, pAction->szName); // add the action name nIdx = SendMessageA(GetDlgItem(hwnd, IDC_ACTIONS), LB_ADDSTRING, 0, (LPARAM)szBuf); // add the item data (action node) SendMessageA(GetDlgItem(hwnd, IDC_ACTIONS), LB_SETITEMDATA, nIdx, (LPARAM)pAction); } //* assigned action filter } //* control type filter // next action pAction = pAction->pNext; } // populate the control list nIdx = 0; pObjectNode = pObjectList; while(pObjectNode) { // convert dinput's DIDFT to our // internal control type if(FAILED(dmtinputXlatDIDFTtoInternalType(pObjectNode->dwObjectType, &dwObjType))) { // ISSUE-2001/03/29-timgill Needs error case handling } DPF(3, "dmtcfgOnUpdateLists - %s : DIDFT type %08Xh, internal type %d", pObjectNode->szName, pObjectNode->dwObjectType, dwObjType); // filter on control type // // dwType populated above if(dwType == dwObjType) { // check to if mapped // // we do this by scanning the DIACTION array, looking // for actions that contain our device's guidInstance // and our object's offset // if so, put the mapping info in () wsprintfA(szBuf, "%s", pObjectNode->szName); for(n = 0; n < nActions; n++) { if(IsEqualGUID((pdia+n)->guidInstance, pdmtai->pDeviceList->guidInstance) && ((pdia+n)->dwObjID == pObjectNode->dwObjectType)) { wsprintfA(szBuf, "%s (%s)", pObjectNode->szName, (pdia+n)->lptszActionName); break; } } // add the control name nIdx = SendMessageA(GetDlgItem(hwnd, IDC_CONTROLS), LB_ADDSTRING, 0, (LPARAM)szBuf); // add the item data (object node) SendMessageA(GetDlgItem(hwnd, IDC_CONTROLS), LB_SETITEMDATA, nIdx, (LPARAM)pObjectNode); } //* control type filter // next control pObjectNode = pObjectNode->pNext; } // count the number of entries in each list nControls = SendMessage(GetDlgItem(hwnd, IDC_CONTROLS), LB_GETCOUNT, 0, 0L); nActions = SendMessage(GetDlgItem(hwnd, IDC_ACTIONS), LB_GETCOUNT, 0, 0L); // set the selected entry in each list // // only do this if there are entries in the lists if(nControls) { if(nSelCtrl > nControls) { nSelCtrl = 0; } SendMessageA(GetDlgItem(hwnd, IDC_CONTROLS), LB_SETCURSEL, nSelCtrl, 0L); } if(nActions) { SendMessageA(GetDlgItem(hwnd, IDC_ACTIONS), LB_SETCURSEL, 0, 0L); } // if there are no controls or no actions // // disable the map button if(!nControls || !nActions) { EnableWindow(GetDlgItem(hwnd, IDC_STORE_MAPPING), FALSE); } // done return FALSE; } //*** end dmtcfgOnUpdateLists() //=========================================================================== // dmtcfgSourceDlgProc // // Configure Device Mapping Source Code dialog processing function // // Parameters: (see SDK help for parameter details) // HWND hwnd // UINT uMsg // WPARAM wparam // LPARAM lparam // // Returns: (see SDK help for return value details) // BOOL // // History: // 08/31/1999 - davidkl - created //=========================================================================== BOOL CALLBACK dmtcfgSourceDlgProc(HWND hwnd, UINT uMsg, WPARAM wparam, LPARAM lparam) { switch(uMsg) { case WM_INITDIALOG: return dmtcfgSourceOnInitDialog(hwnd, (HWND)wparam, lparam); case WM_COMMAND: return dmtcfgSourceOnCommand(hwnd, LOWORD(wparam), (HWND)lparam, HIWORD(wparam)); case WM_DMT_UPDATE_LISTS: return dmtcfgSourceOnUpdateLists(hwnd); } return FALSE; } //*** end dmtcfgSourceDlgProc() //=========================================================================== // dmtcfgSourceOnInitDialog // // Handle WM_INITDIALOG processing for the config source box // // Parameters: // HWND hwnd - handle to property page // HWND hwndFocus - handle of ctrl with focus // LPARAM lparam - user data (in this case, PROPSHEETPAGE*) // // Returns: BOOL // // History: // 08/31/1999 - davidkl - created // 10/07/1999 - davidkl - reworked code to match UI change //=========================================================================== BOOL dmtcfgSourceOnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lparam) { DMTSUBGENRE_NODE *pSubGenre = (DMTSUBGENRE_NODE*)lparam; //LONG lPrev = 0L; //JJ 64Bit Compat LONG_PTR lPrev = 0; int nIdx = 0; char szBuf[MAX_PATH]; DPF(5, "dmtcfgSourceOnInitDialog"); // validate pSubGenre (lparam) if(IsBadWritePtr((void*)pSubGenre, sizeof(DMTSUBGENRE_NODE))) { DPF(0, "dmtcfgOnInitDialog - invalid ppsp.ptp (%016Xh)", pSubGenre); return FALSE; } // set the window caption to include the subgenre name wsprintfA(szBuf, "Configure Device Mapping Source Code - %s", pSubGenre->szName); SetWindowTextA(hwnd, szBuf); // store the subgenre node in the window's user data SetLastError(0); //lPrev = SetWindowLong(hwnd, // GWL_USERDATA, // (LONG)pSubGenre); //JJ 64Bit Compat lPrev = SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pSubGenre); if(!lPrev && GetLastError()) { // serious app problem. // we need to stop things right here and now DPF(0, "dmtcfgSourceOnInitDialog - This is bad... " "We failed to store pSubGenre"); DPF(0, "dmtcfgSourceOnInitDialog - Please find someone " "to look at this right away"); DebugBreak(); return FALSE; } // populate the subgenre edit box SetWindowTextA(GetDlgItem(hwnd, IDC_SUBGENRE), pSubGenre->szName); // display the subgenre description SetWindowTextA(GetDlgItem(hwnd, IDC_DESCRIPTION), pSubGenre->szDescription); // select the axes radio button CheckRadioButton(hwnd, IDC_TYPE_POV, IDC_TYPE_AXIS, IDC_TYPE_AXIS); // populate the actions list box // // store the ptr to the actions node in the listbox // entry user data SendMessageA(hwnd, WM_DMT_UPDATE_LISTS, 0, 0L); // done return TRUE; } //*** end dmtcfgSourceOnInitDialog() //=========================================================================== // dmtcfgSourceOnCommand // // Handle WM_COMMAND processing for the config source box // // Parameters: // HWND hwnd - handle to property page // WORD wId - control identifier (LOWORD(wparam)) // HWND hwndCtrl - handle to control ((HWND)lparam) // WORD wNotifyCode - notification code (HIWORD(wparam)) // // Returns: BOOL // // History: // 08/31/1999 - davidkl - created //=========================================================================== BOOL dmtcfgSourceOnCommand(HWND hwnd, WORD wId, HWND hwndCtrl, WORD wNotifyCode) { DMTGENRE_NODE *pGenre = NULL; DPF(5, "dmtcfgOnCommand"); // get the genre from the window's user data // ISSUE-2001/03/29-timgill config source box fails to handle many UI messages // IDC_ADD_ACTION, IDC_REMOVE_ACTION, IDC_RENAME_ACTION, IDC_CUSTOM_ACTION all do nothing // IDOK/IDCANCEL merely do default processing switch(wId) { case IDOK: EndDialog(hwnd, 0); break; case IDCANCEL: EndDialog(hwnd, -1); break; case IDC_SUBGENRE: // based on the selected subgenre // // display the objects/actions for the selected type // (see type IDs below) if(CBN_SELCHANGE == wNotifyCode) { // update the lists SendMessageA(hwnd, WM_DMT_UPDATE_LISTS, 0, 0L); } break; case IDC_TYPE_AXIS: case IDC_TYPE_BUTTON: case IDC_TYPE_POV: // update the lists SendMessageA(hwnd, WM_DMT_UPDATE_LISTS, 0, 0L); break; case IDC_ADD_ACTION: break; case IDC_REMOVE_ACTION: break; case IDC_RENAME_ACTION: break; case IDC_CUSTOM_ACTION: break; } // done return FALSE; } //*** end dmtcfgSourceOnCommand() //=========================================================================== // dmtcfgSourceOnUpdateLists // // Handle WM_DMT_UPDATE_LISTS message // // Parameters: // // Returns: BOOL // // History: // 08/31/1999 - davidkl - created // 10/07/1999 - davidkl - modified to match UI change //=========================================================================== BOOL dmtcfgSourceOnUpdateLists(HWND hwnd) { //int nIdx = -1; //JJ 64Bit Compat INT_PTR nIdx = -1; DWORD dwType = 0x0badbad0; DMTSUBGENRE_NODE *pSubGenre = NULL; DMTACTION_NODE *pAction = NULL; char szBuf[MAX_PATH]; // get the subgenre node from the window's user data //pSubGenre = (DMTSUBGENRE_NODE*)GetWindowLong(hwnd, // GWL_USERDATA); //JJ 64Bit Compat pSubGenre = (DMTSUBGENRE_NODE*)GetWindowLongPtr(hwnd, GWLP_USERDATA); if(!pSubGenre) { // this is very bad // ISSUE-2001/03/29-timgill Needs error case handling DebugBreak(); return TRUE; } // clear the list box contents SendMessageA(GetDlgItem(hwnd, IDC_ACTIONS), LB_RESETCONTENT, 0, 0L); // what control type is selected? dwType = IDC_TYPE_AXIS - (dmtGetCheckedRadioButton(hwnd, IDC_TYPE_POV, IDC_TYPE_AXIS)); // populate the action list pAction = pSubGenre->pActionList; while(pAction) { // filter to the selected control type if(dwType == pAction->dwType) { // filter actions that are already selected /* if(DMT_ACTION_NOTASSIGNED == pAction->dwDevObj) { */ // if the priority is NOT 1, append that info to the name string // // ISSUE-2001/03/29-timgill Should the priority 1 mapping display colour be different (eg. red)? // Do game developers CARE about action priorities? /* if(1 < pAction->dwPriority) { wsprintfA(szBuf, "(Pri%d) %s", pAction->dwPriority, pAction->szName); } else { */ lstrcpyA(szBuf, pAction->szName); // } // add the action name nIdx = SendMessageA(GetDlgItem(hwnd, IDC_ACTIONS), LB_ADDSTRING, 0, (LPARAM)szBuf); // add the extra data (action node) SendMessageA(GetDlgItem(hwnd, IDC_ACTIONS), LB_SETITEMDATA, nIdx, (LPARAM)&(pAction)); /* } //* assigned action filter */ } // control type filter // next action pAction = pAction->pNext; } // done return FALSE; } //*** end dmtcfgSourceOnUpdateLists() //=========================================================================== // dmtcfgCreateGenreList // // Reads genres.ini and creates the genre list used to populate the // Configure Device Action Map property sheet dialog. Returns the number of // parent genres (NOT subgenres) found // // Parameters: // // Returns: HRESULT // // History: // 08/23/1999 - davidkl - created // 09/28/1999 - davidkl - modified to match new ini format //=========================================================================== HRESULT dmtcfgCreateGenreList(DMTGENRE_NODE **ppdmtgList) { HRESULT hRes = S_OK; UINT u = 0; BOOL fFound = FALSE; DMTGENRE_NODE *pCurrent = NULL; DMTGENRE_NODE *pNew = NULL; DMTGENRE_NODE *pHold = NULL; char szItem[64]; char szBuf[MAX_PATH]; char szGroup[MAX_PATH]; // validate ppmdtgList if(IsBadWritePtr((void*)ppdmtgList, sizeof(DMTGENRE_NODE*))) { DPF(0, "dmtcfgCreateGenreList - invalid ppdmtgList (%016Xh)", ppdmtgList); return E_POINTER; } // check to make sure we are not being asked // to append to an existing list // // callers MUST pass a NULL list if(*ppdmtgList) { DPF(0, "dmtcfgCreateGenreList - ppdmtgList points to " "existing list! (%016Xh)", *ppdmtgList); return E_INVALIDARG; } __try { // get the genre names from genres.ini pCurrent = *ppdmtgList; lstrcpyA(szBuf, ""); u = 0; while(lstrcmpA("<<>>", szBuf)) { // get the name of the genre wsprintfA(szItem, "%d", u); GetPrivateProfileStringA(szItem, "N", "<<>>", szBuf, MAX_PATH, GENRES_INI); if(!lstrcmpA("<<>>", szBuf)) { DPF(3, "end of genre list"); continue; } DPF(3, "Genre name == %s", szBuf); // extract the group name hRes = dmtcfgGetGenreGroupName(szBuf, szGroup); if(FAILED(hRes)) { // ISSUE-2001/03/29-timgill Needs error case handling } // walk the list // // make sure we did not get a duplicate name fFound = FALSE; pHold = pCurrent; pCurrent = *ppdmtgList; while(pCurrent) { if(!lstrcmpiA(pCurrent->szName, szGroup)) { // match found fFound = TRUE; break; } // next node pCurrent = pCurrent->pNext; } if(!fFound) { // no match, allocate a new node // allocate the genre node pNew = (DMTGENRE_NODE*)LocalAlloc(LMEM_FIXED, sizeof(DMTGENRE_NODE)); if(!pNew) { DPF(0, "dmtcfgCreateGenreList - insufficient memory to " "allocate genre list node"); hRes = E_OUTOFMEMORY; __leave; } // initialize the new node ZeroMemory((void*)pNew, sizeof(DMTGENRE_NODE)); // set the name field lstrcpyA(pNew->szName, szGroup); // get the list of subgenres hRes = dmtcfgCreateSubGenreList(pNew->szName, &(pNew->pSubGenreList)); if(FAILED(hRes)) { // ISSUE-2001/03/29-timgill Needs error case handling } // add it to the end of the list pCurrent = pHold; if(pCurrent) { // append the list pCurrent->pNext = pNew; // go to the next node pCurrent = pCurrent->pNext; } else { // new list head pCurrent = pNew; *ppdmtgList = pCurrent; } } // next genre u++; } } __finally { if(FAILED(hRes)) { // cleanup allocations DPF(1, "dmtcfgCreateGenreList - Failure occurred, " "freeing genre list"); dmtcfgFreeGenreList(ppdmtgList); *ppdmtgList = NULL; } } // done return hRes; } //*** end dmtcfgCreateGenreList() //=========================================================================== // dmtcfgFreeGenreList // // Frees the linked list (and sub-lists) created by dmtcfgCreateGenreList // // Parameters: // // Returns: HRESULT // // History: // 08/23/1999 - davidkl - created //=========================================================================== HRESULT dmtcfgFreeGenreList(DMTGENRE_NODE **ppdmtgList) { HRESULT hRes = S_OK; DMTGENRE_NODE *pNode = NULL; // validate ppdmtgList if(IsBadWritePtr((void*)ppdmtgList, sizeof(PDMTGENRE_NODE))) { DPF(0, "dmtcfgFreeGenreList - Invalid ppdmtgList (%016Xh)", ppdmtgList); return E_POINTER; } // validate *ppdmtgList if(IsBadReadPtr((void*)*ppdmtgList, sizeof(DMTGENRE_NODE))) { if(NULL != *ppdmtgList) { DPF(0, "dmtcfgFreeGenreList - Invalid *ppdmtgList (%016Xh)", *ppdmtgList); return E_POINTER; } else { // if NULL, then return "did nothing" DPF(3, "dmtcfgFreeGenreList - Nothing to do...."); return S_FALSE; } } // walk the list and free each object while(*ppdmtgList) { pNode = *ppdmtgList; *ppdmtgList = (*ppdmtgList)->pNext; // first, free the action list DPF(5, "dmtcfgFreeGenreList - " "freeing subgenre list (%016Xh)", pNode->pSubGenreList); hRes = dmtcfgFreeSubGenreList(&(pNode->pSubGenreList)); if(FAILED(hRes)) { // ISSUE-2001/03/29-timgill Needs error case handling } DPF(5, "dmtcfgFreeGenreList - Deleting Node (%016Xh)", pNode); if(LocalFree((HLOCAL)pNode)) { DPF(0, "dmtcfgFreeSubGenreList - MEMORY LEAK - " "LocalFree() failed (%d)...", GetLastError()); hRes = DMT_S_MEMORYLEAK; } DPF(5, "dmtcfgFreeGenreList - Node deleted"); } // make sure that we set *ppdmtgList to NULL *ppdmtgList = NULL; // done return hRes; } //*** end dmtcfgFreeGenreList() //=========================================================================== // dmtcfgCreateSubGenreList // // Reads genres.ini and creates the subgenre list used to populate the // Configure Device Action Map property sheet dialog. // // Parameters: // // Returns: HRESULT // // History: // 08/24/1999 - davidkl - created // 09/29/1999 - davidkl - modified to match new ini format //=========================================================================== HRESULT dmtcfgCreateSubGenreList(LPSTR szGenre, DMTSUBGENRE_NODE **ppdmtsgList) { HRESULT hRes = S_OK; UINT u = 0; DMTSUBGENRE_NODE *pCurrent = NULL; DMTSUBGENRE_NODE *pNew = NULL; char szItem[64]; char szGroup[MAX_PATH]; char szBuf[MAX_PATH]; // validate ppmdtsgList if(IsBadWritePtr((void*)ppdmtsgList, sizeof(DMTSUBGENRE_NODE*))) { return E_POINTER; } // check to make sure we are not being asked // to append to an existing list // // callers MUST pass a NULL list if(*ppdmtsgList) { return E_INVALIDARG; } __try { // get the subgenre names from genres.ini pCurrent = *ppdmtsgList; lstrcpyA(szBuf, ""); u = 0; while(lstrcmpA("<<>>", szBuf)) { // look for subgenres belonging to szGenre wsprintfA(szItem, "%d", u); GetPrivateProfileStringA(szItem, "N", "<<>>", szBuf, MAX_PATH, GENRES_INI); if(!lstrcmpA("<<>>", szBuf)) { DPF(3, "end of subgenre list"); continue; } hRes = dmtcfgGetGenreGroupName(szBuf, szGroup); if(FAILED(hRes)) { // ISSUE-2001/03/29-timgill Needs error case handling } // if we do not belong to the genre group // // make believe we found nothing if(lstrcmpiA(szGenre, szGroup)) { u++; DPF(4, "bucket mismatch... skipping"); continue; } // we fit in the szGenre bucket // // allocate the genre node pNew = (DMTSUBGENRE_NODE*)LocalAlloc(LMEM_FIXED, sizeof(DMTSUBGENRE_NODE)); if(!pNew) { hRes = E_OUTOFMEMORY; __leave; } // initialize the new node ZeroMemory((void*)pNew, sizeof(DMTSUBGENRE_NODE)); // get the genreid pNew->dwGenreId = GetPrivateProfileInt(szItem, "AI0", 0, GENRES_INI); pNew->dwGenreId &= DMT_GENRE_MASK; DPF(4, "SubGenre ID == %08Xh", pNew->dwGenreId); // get the "name" (Txt1) GetPrivateProfileStringA(szItem, "T1", "<<>>", pNew->szName, MAX_PATH, GENRES_INI); DPF(3, "SubGenre name == %s", pNew->szName); // get the description (Txt2) GetPrivateProfileStringA(szItem, "T2", "<<>>", pNew->szDescription, MAX_PATH, GENRES_INI); DPF(4, "SubGenre description == %s", pNew->szDescription); // get the list of actions hRes = dmtcfgCreateActionList(szItem, &(pNew->pActionList)); if(FAILED(hRes) || DMT_S_MEMORYLEAK == hRes) { // ISSUE-2001/03/29-timgill Needs error case handling } // add it to the end of the list if(pCurrent) { // append the list pCurrent->pNext = pNew; // go to the next node pCurrent = pCurrent->pNext; } else { // new list head pCurrent = pNew; *ppdmtsgList = pCurrent; } // next subgenre u++; } } __finally { // cleanup in failure case if(FAILED(hRes)) { DPF(1, "dmtcfgCreateSubGenreList - Failure occurred, " "freeing subgenre list"); dmtcfgFreeSubGenreList(ppdmtsgList); *ppdmtsgList = NULL; } } //JJ_FIX g_NumSubGenres = u; // done return S_OK; } //*** end dmtcfgCreateSubGenreList() //=========================================================================== // dmtcfgFreeSubGenreList // // Frees the linked list created by dmtcfgCreateSubGenreList // // Parameters: // // Returns: HRESULT // // History: // 08/24/1999 - davidkl - created // 08/25/1999 - davidkl - implemented //=========================================================================== HRESULT dmtcfgFreeSubGenreList(DMTSUBGENRE_NODE **ppdmtsgList) { HRESULT hRes = S_OK; DMTSUBGENRE_NODE *pNode = NULL; // validate ppdmtaList if(IsBadWritePtr((void*)ppdmtsgList, sizeof(PDMTSUBGENRE_NODE))) { DPF(0, "dmtcfgFreeSubGenreList - Invalid ppdmtsgList (%016Xh)", ppdmtsgList); return E_POINTER; } // validate *ppPortList if(IsBadReadPtr((void*)*ppdmtsgList, sizeof(DMTSUBGENRE_NODE))) { if(NULL != *ppdmtsgList) { DPF(0, "dmtcfgFreeSubGenreList - Invalid *ppdmtsgList (%016Xh)", *ppdmtsgList); return E_POINTER; } else { // if NULL, then return "did nothing" DPF(3, "dmtcfgFreeSubGenreList - Nothing to do...."); return S_FALSE; } } // walk the list and free each object while(*ppdmtsgList) { pNode = *ppdmtsgList; *ppdmtsgList = (*ppdmtsgList)->pNext; // first, free the action list DPF(5, "dmtcfgFreeSubGenreList - " "freeing action list (%016Xh)", pNode->pActionList); hRes = dmtcfgFreeActionList(&(pNode->pActionList)); if(FAILED(hRes)) { hRes = DMT_S_MEMORYLEAK; } // then free the mapping list array if(pNode->pMappingList) { hRes = dmtcfgFreeMappingList(&(pNode->pMappingList)); if(FAILED(hRes) || DMT_S_MEMORYLEAK == hRes) { hRes = DMT_S_MEMORYLEAK; } pNode->pMappingList = NULL; } // finally, free the node DPF(5, "dmtcfgFreeSubGenreList - Deleting Node (%016Xh)", pNode); if(LocalFree((HLOCAL)pNode)) { DPF(0, "dmtcfgFreeSubGenreList - MEMORY LEAK - " "LocalFree(Node) failed (%d)...", GetLastError()); hRes = DMT_S_MEMORYLEAK; } DPF(5, "dmtcfgFreeSubGenreList - Node deleted"); } // make sure that we set *ppdmtsgList to NULL *ppdmtsgList = NULL; // done return hRes; } //*** end dmtcfgFreeSubGenreList() //=========================================================================== // dmtcfgCreateActionList // // Reads genres.ini and creates the action list used to populate the // Configure Device Action Map property sheet dialog. // // Parameters: // // Returns: HRESULT // // History: // 08/24/1999 - davidkl - created // 09/07/1999 - davidkl - added DIACTION** // 09/28/1999 - davidkl - updated to use info extraction macros // 02/14/2000 - davidkl - started conversion to GetPrivateProfileSectionA //=========================================================================== HRESULT dmtcfgCreateActionList(LPSTR szGenreSubgenre, DMTACTION_NODE **ppdmtaList) { HRESULT hRes = S_OK; UINT u = 0; BYTE bTypeMask = 0x03; DMTACTION_NODE *pCurrent = NULL; DMTACTION_NODE *pNew = NULL; char szItem[MAX_PATH]; char szBuf[MAX_PATH]; // validate ppmdtsgList if(IsBadWritePtr((void*)ppdmtaList, sizeof(DMTACTION_NODE*))) { DPF(0, "dmtcfgCreateActionList - invalid ppdmtaList (%016Xh)", ppdmtaList); return E_POINTER; } // check to make sure we are not being asked // to append to an existing list // // callers MUST pass a NULL list if(*ppdmtaList) { DPF(0, "dmtcfgCreateActionList - ppdmtaList points to " "existing list! (%016Xh)", *ppdmtaList); return E_INVALIDARG; } __try { // get the action info from genres.ini pCurrent = *ppdmtaList; #ifdef BNW char *pszSection = NULL; char *pCurrent = NULL; int nAlloc = 0; // allocate space for the (Win9x) max size of an ini section nAlloc = 32727; pszSection = (char*)LocalAlloc(LMEM_FIXED, sizeof(char) * nAlloc); if(!pszSection) { // alloc failed, // try ~1/2 of the max (that should still cover the // fill size of the section) nAlloc = 16386; pszSection = (char*)LocalAlloc(LMEM_FIXED, sizeof(char) * nAlloc); if(!pszSection) { // alloc failed, // try ~1/4 of the max (that should still cover the // fill size of the section) nAlloc = 8192; pszSection = (char*)LocalAlloc(LMEM_FIXED, sizeof(char) * nAlloc); if(!pszSection) { // alloc failed, // try ~1/8 of the max (that should still cover the // fill size of the section) nAlloc = 4096; pszSection = (char*)LocalAlloc(LMEM_FIXED, sizeof(char) * nAlloc); if(!pszSection) { // alloc failed, // try ~1/16 of the max (that should still cover the // fill size of the section) - this is our last attempt nAlloc = 2048; pszSection = (char*)LocalAlloc(LMEM_FIXED, sizeof(char) * nAlloc); if(!pszSection) { // alloc failed, we give up __leave; } } } } } DPF(2, "dmtcfgCreateActionList - section allocation: %d bytes", nAlloc); // read the section specified by szGenreSubgenre GetPrivateProfileSectionA(szGenreSubgenre, pszSection, nAlloc, GENRES_INI); /* the following code fragment does nothing - u is incremented and then never used again // parse the action information from the section for(u = 0; ; u++) { break; } */ #else lstrcpyA(szBuf, ""); u = 0; while(lstrcmpA("<<>>", szBuf)) { // add the name of the action to the node wsprintfA(szItem, "AN%d", u); GetPrivateProfileStringA(szGenreSubgenre, szItem, "<<>>", szBuf, MAX_PATH, GENRES_INI); if(!lstrcmpA("<<>>", szBuf)) { DPF(3, "end of action list"); continue; } DPF(3, "Action name == %s", szBuf); // allocate the genre node pNew = (DMTACTION_NODE*)LocalAlloc(LMEM_FIXED, sizeof(DMTACTION_NODE)); if(!pNew) { hRes = E_OUTOFMEMORY; __leave; } // initialize the new node ZeroMemory((void*)pNew, sizeof(DMTACTION_NODE)); lstrcpyA(pNew->szName, szBuf); // get the action id wsprintfA(szItem, "AI%d", u); pNew->dwActionId = GetPrivateProfileIntA(szGenreSubgenre, szItem, 0x0badbad0, GENRES_INI); DPF(4, "Action ID == %08Xh", pNew->dwActionId); // get the action priority pNew->dwPriority = dmtinputGetActionPri(pNew->dwActionId); DPF(4, "Action priority == %d", pNew->dwPriority); // get action type pNew->dwType = dmtinputGetActionObjectType(pNew->dwActionId); DPF(4, "Action type == %d", pNew->dwType); // get the action type name wsprintfA(szItem, "AIN%d", u); GetPrivateProfileStringA(szGenreSubgenre, szItem, "<<>>", pNew->szActionId, MAX_ACTION_ID_STRING, GENRES_INI); DPF(4, "Action ID name == %s", pNew->szActionId); // add it to the end of the list if(pCurrent) { // append the list pCurrent->pNext = pNew; // go to the next node pCurrent = pCurrent->pNext; } else { // new list head pCurrent = pNew; *ppdmtaList = pCurrent; } // net action u++; } #endif // BNW } __finally { #ifdef BNW // free the section memory we allocated if(LocalFree((HLOCAL)pszSection)) { // memory leak DPF(0, "dmtcfgCreateActionList - !! MEMORY LEAK !! - LocalFree(section) failed"); } #endif // BNW // cleanup in failure case if(FAILED(hRes)) { // free action list DPF(1, "dmtcfgCreateActionList - Failure occurred, " "freeing action list"); dmtcfgFreeActionList(ppdmtaList); *ppdmtaList = NULL; } } // done return S_OK; } //*** end dmtCreateActionList() //=========================================================================== // dmtcfgFreeActionList // // Frees the linked list created by dmtcfgCreateActionList // // Parameters: // // Returns: HRESULT // // History: // 08/24/1999 - davidkl - created // 08/25/1999 - davidkl - implemented //=========================================================================== HRESULT dmtcfgFreeActionList(DMTACTION_NODE **ppdmtaList) { HRESULT hRes = S_OK; DMTACTION_NODE *pNode = NULL; // validate ppdmtaList if(IsBadWritePtr((void*)ppdmtaList, sizeof(PDMTACTION_NODE))) { DPF(0, "dmtcfgFreeActionList - Invalid ppdmtaList (%016Xh)", ppdmtaList); return E_POINTER; } // validate *ppdmtaList if(IsBadReadPtr((void*)*ppdmtaList, sizeof(DMTACTION_NODE))) { if(NULL != *ppdmtaList) { DPF(0, "dmtcfgFreeActionList - Invalid *ppdmtaList (%016Xh)", *ppdmtaList); return E_POINTER; } else { // if NULL, then return "did nothing" DPF(3, "dmtcfgFreeActionList - Nothing to do...."); return S_FALSE; } } // walk the list and free each object while(*ppdmtaList) { pNode = *ppdmtaList; *ppdmtaList = (*ppdmtaList)->pNext; // free the node DPF(5, "dmtcfgFreeActionList - deleting Node (%016Xh)", pNode); if(LocalFree((HLOCAL)pNode)) { DPF(0, "dmtcfgFreeActionList - MEMORY LEAK - " "LocalFree(Node) failed (%d)...", GetLastError()); hRes = DMT_S_MEMORYLEAK; } DPF(5, "dmtcfgFreeActionList - Node deleted"); } // make sure that we set *ppObjList to NULL *ppdmtaList = NULL; // done return hRes; } //*** end dmtcfgFreeActionList() //=========================================================================== // dmtcfgCreateMappingList // // Creates a device mapping list // // Parameters: // // Returns: HRESULT // // History: // 09/23/1999 - davidkl - created //=========================================================================== HRESULT dmtcfgCreateMappingList(DMTDEVICE_NODE *pDeviceList, DMTACTION_NODE *pActions, DMTMAPPING_NODE **ppdmtmList) { HRESULT hRes = S_OK; UINT uActions = NULL; DMTACTION_NODE *pActionNode = NULL; DMTMAPPING_NODE *pNew = NULL; DMTMAPPING_NODE *pCurrent = NULL; DMTDEVICE_NODE *pDeviceNode = NULL; // validate pDeviceList if(IsBadReadPtr((void*)pDeviceList, sizeof(DMTDEVICE_NODE))) { DPF(0, "dmtcfgCreateMappingList - invalid pDeviceList (%016Xh)", pDeviceList); return E_POINTER; } // validate pActions if(IsBadReadPtr((void*)pActions, sizeof(DMTACTION_NODE))) { if(NULL != pActions) { DPF(0, "dmtcfgCreateMappingList - invalid pActions (%016Xh)", pActions); return E_POINTER; } else { // no actions for this subgenre DPF(3, "dmtcfgCreateMappingList - No actions for this subgenre, " "nothing to do..."); return S_FALSE; } } // validate ppdmtmList if(IsBadWritePtr((void*)ppdmtmList, sizeof(DMTMAPPING_NODE))) { DPF(0, "dmtcfgCreateMappingList - invalid ppdmtmList (%016Xh)", ppdmtmList); return E_POINTER; } // check to make sure we are not being asked // to append to an existing list // // callers MUST pass a NULL list if(*ppdmtmList) { DPF(0, "dmtcfgCreateMappingList - ppdmtmList points to " "existing list! (%016Xh)", *ppdmtmList); return E_INVALIDARG; } __try { // count the actions // // this lets us know how much space to allocate for the uActions = 0; pActionNode = pActions; while(pActionNode) { uActions++; // next node pActionNode = pActionNode->pNext; } // for each device pDeviceNode = pDeviceList; while(pDeviceNode) { // allocate the mapping node pNew = (DMTMAPPING_NODE*)LocalAlloc(LMEM_FIXED, sizeof(DMTMAPPING_NODE)); if(!pNew) { DPF(3, "dmtcfgCreateMappingList - Insufficient memory to " "allocate mapping list node"); hRes = E_OUTOFMEMORY; __leave; } // initialize the new node ZeroMemory((void*)pNew, sizeof(DMTMAPPING_NODE)); // allocate the action array pNew->pdia = (DIACTIONA*)LocalAlloc(LMEM_FIXED, uActions * sizeof(DIACTIONA)); if(!(pNew->pdia)) { hRes = E_OUTOFMEMORY; __leave; } // initial population of the action array hRes = dmtinputPopulateActionArray(pNew->pdia, uActions, pActions); if(FAILED(hRes)) { __leave; } // add the number of actions pNew->uActions = uActions; // add the device instance guid pNew->guidInstance = pDeviceNode->guidInstance; // add the new node to the list if(pCurrent) { // append the list pCurrent->pNext = pNew; // go to the next node pCurrent = pCurrent->pNext; } else { // new list head pCurrent = pNew; *ppdmtmList = pCurrent; } // next device pDeviceNode = pDeviceNode->pNext; } } __finally { // in case of error... if(FAILED(hRes)) { // free list dmtcfgFreeMappingList(ppdmtmList); *ppdmtmList = NULL; } } // done return hRes; } //*** end dmtcfgCreateMappingList() //=========================================================================== // dmtcfgFreeMappingList // // Completely frees a mapping list // // Parameters: // // Returns: HRESULT // // History: // 09/23/1999 - davidkl - created //=========================================================================== HRESULT dmtcfgFreeMappingList(DMTMAPPING_NODE **ppdmtmList) { HRESULT hRes = S_OK; DMTMAPPING_NODE *pNode = NULL; // validate ppdmtmList if(IsBadWritePtr((void*)ppdmtmList, sizeof(DMTMAPPING_NODE*))) { return E_POINTER; } // validate *ppdmtmList if(IsBadWritePtr((void*)*ppdmtmList, sizeof(DMTMAPPING_NODE))) { if(NULL != *ppdmtmList) { return E_POINTER; } else { // nothing to do return S_FALSE; } } // walk the list and free each object while(*ppdmtmList) { pNode = *ppdmtmList; *ppdmtmList = (*ppdmtmList)->pNext; // first free the action array if(LocalFree((HLOCAL)(pNode->pdia))) { DPF(0, "dmtcfgFreeMappingList - MEMORY LEAK - " "LocalFree(pdia) failed (%d)...", GetLastError()); hRes = DMT_S_MEMORYLEAK; } // lastly, free the node DPF(5, "dmtcfgFreeMappingList - deleting Node (%016Xh)", pNode); if(LocalFree((HLOCAL)pNode)) { DPF(0, "dmtcfgFreeMappingList - MEMORY LEAK - " "LocalFree(Node) failed (%d)...", GetLastError()); hRes = DMT_S_MEMORYLEAK; } DPF(5, "dmtcfgFreeMappingList - Node deleted"); } // make sure that we set *ppObjList to NULL *ppdmtmList = NULL; // done return hRes; } //*** end dmtcfgFreeMappingList //=========================================================================== // dmtcfgCreateAllMappingLists // // Uses dmtcfgCreateMappingList to create mapping lists for each subgenre // referenced by pdmtai->pGenreList for each device refereced by // pdmtai->pDeviceList // // Parameters: // // Returns: HRESULT // // History: // 09/23/1999 - davidkl - created //=========================================================================== HRESULT dmtcfgCreateAllMappingLists(DMT_APPINFO *pdmtai) { HRESULT hRes = S_OK; HRESULT hr = S_OK; DMTGENRE_NODE *pGenreNode = NULL; DMTSUBGENRE_NODE *pSubGenreNode = NULL; // validate pdmtai if(IsBadReadPtr((void*)pdmtai, sizeof(DMT_APPINFO))) { return E_POINTER; } // validate pdmtai->pGenreList if(IsBadReadPtr((void*)(pdmtai->pGenreList), sizeof(DMTGENRE_NODE))) { return E_POINTER; } // validate pdmtai->pDeviceList if(IsBadReadPtr((void*)(pdmtai->pDeviceList), sizeof(DMTDEVICE_NODE))) { return E_POINTER; } // for each genre pGenreNode = pdmtai->pGenreList; while(pGenreNode) { // for each subgenre of the genre pSubGenreNode = pGenreNode->pSubGenreList; while(pSubGenreNode) { // create the mapping list hr = dmtcfgCreateMappingList(pdmtai->pDeviceList, pSubGenreNode->pActionList, &(pSubGenreNode->pMappingList)); if(FAILED(hr)) { hRes = S_FALSE; } // next subgenre pSubGenreNode = pSubGenreNode->pNext; } // next genre pGenreNode = pGenreNode->pNext; } // done return hRes; } //*** end dmtcfgCreateAllMappingLists() //=========================================================================== // dmtcfgFreeAllMappingLists // // Walks the provided genre list and frees the mapping list found in each // subgenre node // // Parameters: // DMTGENRE_NODE *pdmtgList - list of genres // // Returns: HRESULT // // History: // 10/05/1999 - davidkl - created //=========================================================================== HRESULT dmtcfgFreeAllMappingLists(DMTGENRE_NODE *pdmtgList) { HRESULT hRes = S_OK; HRESULT hr = S_OK; DMTGENRE_NODE *pGenre = NULL; DMTSUBGENRE_NODE *pSubGenre = NULL; // validate pdmtgList if(IsBadReadPtr((void*)pdmtgList, sizeof(DMTGENRE_NODE))) { return E_POINTER; } // walk the genre list pGenre = pdmtgList; while(pGenre) { // walk each subgenre list pSubGenre = pGenre->pSubGenreList; while(pSubGenre) { // free the mapping list hr = dmtcfgFreeMappingList(&(pSubGenre->pMappingList)); if(S_OK != hr) { hRes = hr; } // next subgenre pSubGenre = pSubGenre->pNext; } // next genre pGenre = pGenre->pNext; } // done return hRes; } //*** end dmtcfgFreeAllMappingLists() //=========================================================================== // dmtcfgMapAction // // Connects the dots between an action (in the map config dialog) to a device // object // // Parameters: // HWND hwnd - handle to property page window // REFGUID guidInstance - instance GUID of DirectInputDevice object // DIACTIONA *pdia - ptr to array of DIACTIONA structuresfs // UINT uActions - number of actions in pdia // // Returns: HRESULT // // History: // 09/14/1999 - davidkl - created //=========================================================================== HRESULT dmtcfgMapAction(HWND hwnd, REFGUID guidInstance, DIACTIONA *pdia, UINT uActions) { HRESULT hRes = S_OK; // UINT uObjectSel = 0; //JJ 64Bit Compat UINT_PTR uObjectSel = 0; UINT_PTR uActionSel = 0; // UINT uActionSel = 0; UINT u = 0; BOOL fFound = FALSE; DMTDEVICEOBJECT_NODE *pObject = NULL; DMTACTION_NODE *pAction = NULL; // valudate pdia if(IsBadWritePtr((void*)pdia, sizeof(DIACTION))) { DPF(0, "dmtinputMapAction - invalid pdia (%016Xh)", pdia); return E_POINTER; } __try { // get the object & it's data uObjectSel = SendMessageA(GetDlgItem(hwnd, IDC_CONTROLS), LB_GETCURSEL, 0, 0L); pObject = (DMTDEVICEOBJECT_NODE*)SendMessageA(GetDlgItem(hwnd, IDC_CONTROLS), LB_GETITEMDATA, (WPARAM)uObjectSel, 0L); if(!pObject) { hRes = E_UNEXPECTED; __leave; } // get the action's data uActionSel = SendMessageA(GetDlgItem(hwnd, IDC_ACTIONS), LB_GETCURSEL, 0, 0L); pAction = (DMTACTION_NODE*)SendMessageA(GetDlgItem(hwnd, IDC_ACTIONS), LB_GETITEMDATA, (WPARAM)uActionSel, 0L); if(!pAction) { hRes = E_UNEXPECTED; __leave; } // find the appropriate action in the array fFound = FALSE; for(u = 0; u < uActions; u++) { // match based on the semantic / action id if((pdia + u)->dwSemantic == pAction->dwActionId) { DPF(2, "dmtcfgMapAction - found matching action " "pAction->dwActionId (%08Xh) == " "(pdia+u)->dwSemantic (%08Xh)", pAction->dwActionId, (pdia + u)->dwSemantic); fFound = TRUE; break; } } // did we find the action in the array? if(!fFound) { // no. this is very bad! // // if this EVER happens, // we have a serious bug in this app hRes = E_FAIL; // since this should NEVER happen, // break into the debugger and alert the tester DPF(0, "dmtcfgMapAction - action not found in pdia!"); DPF(0, "dmtcfgMapAction - we were looking for " "%08Xh (%s)", pAction->dwActionId, pAction->szActionId); DPF(0, "dmtcfgMapAction - CRITICAL failure. " "This should have never happened!"); DPF(0, "dmtcfgMapAction - Please find someone " "to look at this right away. "); DebugBreak(); __leave; } // update the action array (pdia + u)->dwObjID = pObject->dwObjectType; (pdia + u)->guidInstance = guidInstance; // HIWORD((DWORD)uAppData) == object type // LOWORD((DWORD)uAppData) == pObject->wCtrlId (pdia + u)->uAppData = (DIDFT_GETTYPE(pObject->dwObjectType) << 16) | (pObject->wCtrlId); // update the list boxes SendMessageA(hwnd, WM_DMT_UPDATE_LISTS, 0, 0L); // enable the unmap & unmap all buttons EnableWindow(GetDlgItem(hwnd, IDC_UNMAP_ALL), TRUE); EnableWindow(GetDlgItem(hwnd, IDC_UNMAP), TRUE); // disable the map button EnableWindow(GetDlgItem(hwnd, IDC_STORE_MAPPING), FALSE); } __finally { // cleanup // nothing to do... yet } // done return hRes; } //*** end dmtcfgMapAction() //=========================================================================== // dmtcfgUnmapAction // // Disconnects the dots between an action (in the map config dialog) and a // device object // // Parameters: // HWND hwnd - handle to property page window // DIACTIONA *pdia - ptr to DIACTIONA array // UINNT uActions - number of elements in pdia // // Returns: HRESULT // // History: // 09/15/1999 - davidkl - created //=========================================================================== HRESULT dmtcfgUnmapAction(HWND hwnd, DIACTIONA *pdia, UINT uActions) { HRESULT hRes = S_OK; UINT u = 0; // UINT uSel = 0; //JJ 64Bit Compat UINT_PTR uSel = 0; BOOL fFound = FALSE; DMTSUBGENRE_NODE *pSubGenre = NULL; DMTDEVICEOBJECT_NODE *pObject = NULL; // validate pdia if(IsBadWritePtr((void*)pdia, uActions * sizeof(DIACTIONA))) { return E_POINTER; } __try { // get the current control selection uSel = SendMessageA(GetDlgItem(hwnd, IDC_CONTROLS), LB_GETCURSEL, 0, 0L); pObject = (DMTDEVICEOBJECT_NODE*)SendMessageA(GetDlgItem(hwnd, IDC_CONTROLS), LB_GETITEMDATA, (WPARAM)uSel, 0L); if(!pObject) { // this is bad hRes = E_UNEXPECTED; __leave; } // spin through pdia // look for an action with our object's offset fFound = FALSE; for(u = 0; u < uActions; u++) { // first check the guid if(IsEqualGUID(pObject->guidDeviceInstance, (pdia+u)->guidInstance)) { // then compare the offset if((pdia+u)->dwObjID == pObject->dwObjectType) { fFound = TRUE; break; } } } // if nothing is found, // the selected object is not mapped // // (non-critical internal error condition) if(!fFound) { hRes = S_FALSE; __leave; } // reset the guidInstance and dwSemantic fields (pdia + u)->guidInstance = GUID_NULL; (pdia + u)->dwObjID = 0; (pdia + u)->uAppData = 0; // update the lists SendMessageA(hwnd, WM_DMT_UPDATE_LISTS, 0, 0L); // enable the map button EnableWindow(GetDlgItem(hwnd, IDC_STORE_MAPPING), TRUE); // disable the unmap button EnableWindow(GetDlgItem(hwnd, IDC_UNMAP), FALSE); // if no other actions are mapped, // disable the unmap all button fFound = FALSE; for(u = 0; u < uActions; u++) { if(!IsEqualGUID(GUID_NULL, (pdia+u)->guidInstance)) { fFound = TRUE; } } if(!fFound) { EnableWindow(GetDlgItem(hwnd, IDC_UNMAP_ALL), FALSE); } } __finally { // cleanup // nothing to do... yet } // done return hRes; } //*** end dmtcfgUnmapAction() //=========================================================================== // dmtcfgUnmapAllActions // // Disconnects the all connections between an action (in the map config // dialog) and a device object // // Parameters: // HWND hwnd - handle to property page window // DIACTIONA *pdia - ptr to DIACTIONA array // UINNT uActions - number of elements in pdia // // Returns: HRESULT // // History: // 09/15/1999 - davidkl - created //=========================================================================== HRESULT dmtcfgUnmapAllActions(HWND hwnd, DIACTIONA *pdia, UINT uActions) { UINT u = 0; // validate pdia if(IsBadWritePtr((void*)pdia, uActions * sizeof(DIACTIONA))) { return E_POINTER; } // spin through pdia // reset the guidInstance and dwSemantic fields for(u = 0; u < uActions; u++) { (pdia + u)->guidInstance = GUID_NULL; (pdia + u)->dwObjID = 0; (pdia + u)->uAppData = 0; } // update the lists SendMessageA(hwnd, WM_DMT_UPDATE_LISTS, 0, 0L); // disable the unmap & unmap all buttons EnableWindow(GetDlgItem(hwnd, IDC_UNMAP), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_UNMAP_ALL), FALSE); // enable the map button EnableWindow(GetDlgItem(hwnd, IDC_STORE_MAPPING), TRUE); // done return S_OK; } //*** end dmtcfgUnmapAllActions() //=========================================================================== // dmtcfgIsControlMapped // // Checks to see if a control is mapped to an action // // Parameters: // // Returns: // // History: // 09/15/1999 - davidkl - created //=========================================================================== BOOL dmtcfgIsControlMapped(HWND hwnd, DIACTIONA *pdia, UINT uActions) { BOOL fMapped = FALSE; UINT u = 0; // UINT uSel = 0; //JJ 64Bit Compat UINT_PTR uSel = 0; DMTDEVICEOBJECT_NODE *pObject = NULL; // validate pdia if(IsBadReadPtr((void*)pdia, uActions * sizeof(pdia))) { DPF(0, "dmtcfgIsControlMapped - invalid pdia (%016Xh)", pdia); SetLastError(ERROR_INVALID_DATA); return FALSE; } // get the currently selected control uSel = SendMessageA(GetDlgItem(hwnd, IDC_CONTROLS), LB_GETCURSEL, 0, 0L); pObject = (DMTDEVICEOBJECT_NODE*)SendMessageA(GetDlgItem(hwnd, IDC_CONTROLS), LB_GETITEMDATA, (WPARAM)uSel, 0L); if(!pObject) { // this is bad // // (serious internal app error) SetLastError(ERROR_GEN_FAILURE); DebugBreak(); return FALSE; } // check the array, // see if this control is mapped to anything fMapped = FALSE; for(u = 0; u < uActions; u++) { // first check the guid if(IsEqualGUID(pObject->guidDeviceInstance, (pdia+u)->guidInstance)) { // then compare the offset if((pdia+u)->dwObjID == pObject->dwObjectType) // if((pdia+u)->dwObjID == pObject->dwObjectOffset) { fMapped = TRUE; break; } } } // done SetLastError(ERROR_SUCCESS); return fMapped; } //*** end dmtcfgIsControlMapped() //=========================================================================== // dmtcfgAreAnyControlsMapped // // Checks to see if any controls are mapped to an action. // // Parameters: // // Returns: // // History: // 11/01/1999 - davidkl - created //=========================================================================== BOOL dmtcfgAreAnyControlsMapped(HWND hwnd, DIACTIONA *pdia, UINT uActions) { BOOL fMapped = FALSE; UINT u = 0; // validate pdia if(IsBadReadPtr((void*)pdia, uActions * sizeof(pdia))) { DPF(0, "dmtcfgAreAnyControlsMapped - invalid pdia (%016Xh)", pdia); SetLastError(ERROR_INVALID_DATA); return FALSE; } // check the array, // see if this control is mapped to anything fMapped = FALSE; for(u = 0; u < uActions; u++) { // check guid // // if not GUID_NULL, this action is mapped if(!IsEqualGUID(GUID_NULL, (pdia+u)->guidInstance)) { fMapped = TRUE; break; } } // done SetLastError(ERROR_SUCCESS); return fMapped; } //*** end dmtcfgAreAnyControlsMapped() //=========================================================================== // dmtcfgGetGenreGroupName // // Extracts the genre group name from the genres.ini entry // // Paramters: // // Returns: HRESULT // // History: // 09/28/1999 - davidkl - created // 09/29/1999 - davidkl - modified "buckets" //=========================================================================== HRESULT dmtcfgGetGenreGroupName(PSTR szGenreName, PSTR szGenreGroupName) { HRESULT hRes = S_OK; char *pcFirst = NULL; char *pcCurrent = NULL; // find the first '_' pcFirst = strchr(szGenreName, '_'); // copy the characters between pcFirst and pcLast pcCurrent = pcFirst+1; // skip past the first '_' while((*pcCurrent != '_') && (*pcCurrent != '\0')) { *szGenreGroupName = *pcCurrent; // next character pcCurrent++; szGenreGroupName++; } *szGenreGroupName = '\0'; // done return hRes; } //*** end dmtcfgGetGenreGroupName() //=========================================================================== //===========================================================================