3159 lines
92 KiB
C++
3159 lines
92 KiB
C++
//===========================================================================
|
|
// 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()
|
|
|
|
|
|
//===========================================================================
|
|
//===========================================================================
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|