/****************************************************************************** * * dimap.cpp * * Copyright (c) 1999, 2000 Microsoft Corporation. All Rights Reserved. * * Abstract: * * Contents: * *****************************************************************************/ #include "dimapp.h" #include "objbase.h" #include "stdio.h" #include "shlwapi.h" #include "shlobj.h" #include "lmcons.h" #include "dimap.h" #include "dinputp.h" #include "string" #include "list" #include "algorithm" #include "dinputd.h" /****************************************************************************** * * Definitions * *****************************************************************************/ using namespace std; #undef STRICT_DEV_DEF //MAKE SURE THIS SIX ARE CONSISTENT #define MAP_DIR _T("\\DirectX\\DirectInput\\User Maps") #define MAP_DIR_NT _T("\\Microsoft\\DirectX\\DirectInput\\User Maps") #define MS_NAME _T("\\Microsoft") #define DIRECTX _T("\\DirectX") #define DIRECTINPUT _T("\\DirectInput") #define USER_MAPS _T("\\User Maps") #define DEFAULT_USER_NAME _T("X") #define NAME _T("Name") #define RESERVED_STRING _T("Error") #define DIRECT_INPUT _T("DirectInput") #define DIRECTX_VERSION _T("DirectXVersion") #define DEVICES _T("Devices") #define DEVICE _T("Device") #define VENDORID _T("VID") #define PRODUCTID _T("PID") #define CONTROLS _T("Controls") #define CONTROL _T("Control") #define USAGE _T("Usage") #define USAGEPAGE _T("UsagePage") #define GENRE _T("Genre") #define MAPEXISTS _T("MapExists") #define APPLICATION _T("Application") #define IMAGE_FILENAME _T("ImageFileName") #define OVERLAY_FILENAME _T("OverlayFileName") #define SELECTION_FILENAME _T("SelectionFileName") #define VIEWSELECT_FILENAME _T("ViewSelectFileName") #define IMAGE_FORMAT _T("ImageFormat") #define OVERLAY_FORMAT _T("OverlayFormat") #define SELECTION_FORMAT _T("SelectionFormat") #define VIEWSELECT_FORMAT _T("ViewSelectFormat") #define OVERLAY_RECT _T("OverlayRect") #define CONTROL_STRING_ALIGN _T("Align") #define CONTROL_VISIBLE _T("Visible") #define STRING_POS _T("StringPos") #define LINE_DATA _T("LineData") #define CALLOUTMAX _T("CallOutMax") #define OVERLAYRECT _T("OverlayRect") #define OFFSET _T("Type") #define TIMESTAMPHIGH _T("TimestampHigh") #define TIMESTAMPLOW _T("TimestampLow") #define NUMACTIONS _T("NumActions") #define SEPARATOR _T(',') #define RESERVED_DX_VER 0xffffffff #define RESERVED_VENDORID 0 #define RESERVED_PRODUCTID 0 #define RESERVED_OFFSET 0xffffffff #define RESERVED_USAGE 0 #define RESERVED_USAGEPAGE 0 #define RESERVED_ACTION 0xffffffff #define _MAX_SECTION_NAME 64 #define _MAX_KEY_NAME 64 GUID NULLGUID; #ifdef UNICODE #define String wstring #define IsSpace iswspace #else #define String string #define IsSpace isspace #endif // !UNICODE typedef String::iterator StrIter; class CS:public String{}; typedef list STRINGLIST; /****************************************************************************** * * Classes * *****************************************************************************/ template class AutoRelease { p m_p; public: AutoRelease(){m_p=NULL;}; ~AutoRelease(){if(m_p){m_p->Release();m_p=NULL;};}; inline LPVOID* Addr() { return (LPVOID*) &m_p;}; operator p(){return m_p;}; operator p*(){return &m_p;}; p P(){return m_p;}; }; typedef AutoRelease LPDIRECTINPUT_AR; typedef AutoRelease LPDIRECTINPUTDEVICE_AR; struct DeviceObjData; struct ControlData { DeviceObjData *pDevObj; String ControlName;//Name in .ini file String Name; DWORD dwUsage; DWORD dwUsagePage; DWORD dwAction;//<---workspace for mapping... DWORD dwOffset; }; typedef list CONTROLLIST; struct DeviceObjData { ControlData *pUCtrlData; ControlData *pVCtrlData; String Name;//Name for device object returned by DInput DWORD dwUsage; DWORD dwUsagePage; DWORD dwOffset; DWORD dwType; DWORD dwFlags; bool bMapped;//<---workspace for mapping... }; typedef list DEVICEOBJLIST; struct DEVCNT { LPDIDEVICEINSTANCE pDIDI; int *m_pnCnt; }; class IDirectInputMapperTrA: public IDirectInputMapperA,public IDirectInputMapperVendorA { virtual HRESULT InitializeI( LPCGUID lpThisGUIDInstance, LPCTSTR lpcstrFileName, DWORD dwFlags)=0; HRESULT STDMETHODCALLTYPE Initialize( LPCGUID lpThisGUIDInstance, LPCSTR lpcstrFileName, DWORD dwFlags); virtual HRESULT GetActionMapI( LPDIACTIONFORMAT lpDiActionFormat, LPCTSTR lpctstrUserName, FILETIME *pTimestamp,DWORD dwFlags)=0; HRESULT STDMETHODCALLTYPE GetActionMap( LPDIACTIONFORMATA lpDiActionFormat, LPCSTR lpctstrUserName, FILETIME *pTimestamp,DWORD dwFlags); virtual HRESULT SaveActionMapI( LPDIACTIONFORMAT lpDiActionFormat, LPCTSTR lpctstrUserName, DWORD dwFlags)=0; HRESULT STDMETHODCALLTYPE SaveActionMap( LPDIACTIONFORMATA lpDiActionFormat, LPCSTR lpctstrUserName, DWORD dwFlags); virtual HRESULT GetImageInfoI( LPDIDEVICEIMAGEINFOHEADER lpdiDevImageInfoHeader)=0; HRESULT STDMETHODCALLTYPE GetImageInfo( LPDIDEVICEIMAGEINFOHEADERA lpdiDevImageInfoHeader); virtual HRESULT WriteVendorFileI( LPDIACTIONFORMAT lpDiActionFormat, LPDIDEVICEIMAGEINFOHEADER lpdiDevImageInfoHeader, DWORD dwFlags)=0; HRESULT STDMETHODCALLTYPE WriteVendorFile( LPDIACTIONFORMATA lpDiActionFormat, LPDIDEVICEIMAGEINFOHEADERA lpdiDevImageInfoHeader, DWORD dwFlags); }; class IDirectInputMapperTrW: public IDirectInputMapperW,public IDirectInputMapperVendorW { virtual HRESULT InitializeI( LPCGUID lpThisGUIDInstance, LPCTSTR lpcstrFileName, DWORD dwFlags)=0; HRESULT STDMETHODCALLTYPE Initialize( LPCGUID lpThisGUIDInstance, LPCWSTR lpcstrFileName, DWORD dwFlags); virtual HRESULT GetActionMapI( LPDIACTIONFORMAT lpDiActionFormat, LPCTSTR lpctstrUserName, FILETIME *pTimestamp,DWORD dwFlags)=0; HRESULT STDMETHODCALLTYPE GetActionMap( LPDIACTIONFORMATW lpDiActionFormat, LPCWSTR lpctstrUserName, FILETIME *pTimestamp,DWORD dwFlags); virtual HRESULT SaveActionMapI( LPDIACTIONFORMAT lpDiActionFormat, LPCTSTR lpctstrUserName, DWORD dwFlags)=0; HRESULT STDMETHODCALLTYPE SaveActionMap( LPDIACTIONFORMATW lpDiActionFormat, LPCWSTR lpctstrUserName, DWORD dwFlags); virtual HRESULT GetImageInfoI( LPDIDEVICEIMAGEINFOHEADER lpdiDevImageInfoHeader)=0; HRESULT STDMETHODCALLTYPE GetImageInfo( LPDIDEVICEIMAGEINFOHEADERW lpdiDevImageInfoHeader); virtual HRESULT WriteVendorFileI( LPDIACTIONFORMAT lpDiActionFormat, LPDIDEVICEIMAGEINFOHEADER lpdiDevImageInfoHeader, DWORD dwFlags)=0; HRESULT STDMETHODCALLTYPE WriteVendorFile( LPDIACTIONFORMATW lpDiActionFormat, LPDIDEVICEIMAGEINFOHEADERW lpdiDevImageInfoHeader, DWORD dwFlags); }; class CDIMapObj:public IDirectInputMapperTrA,public IDirectInputMapperTrW { #ifdef _CHECKED static int m_DeviceCount; int m_DeviceNo; #endif ULONG m_ulRefCnt; bool m_bInitialized; DWORD m_dwThisVendorID; DWORD m_dwThisProductID; String m_DeviceName; GUID m_DeviceGuid; int m_nDeviceInstanceNo; //Vendor file name data String m_VFileName; LPCTSTR m_lpVFileName; String m_VFileDevName; CONTROLLIST m_VCtrlData; bool m_bVLoaded; //User file name data String m_UName; LPCTSTR m_lpUName; String m_UFileName; String m_UserDir; String m_UFileDevName; CONTROLLIST m_UCtrlData; bool m_bULoaded; FILETIME m_UTimestamp; bool m_bImageBufferSize; DWORD m_dwImageBufferSize; HRESULT InitializeI( LPCGUID lpThisGUIDInstance, LPCTSTR lpcstrFileName, DWORD dwFlags); HRESULT GetActionMapI( LPDIACTIONFORMAT lpDiActionFormat, LPCTSTR lpctstrUserName, FILETIME *pTimestamp,DWORD dwFlags); HRESULT SaveActionMapI( LPDIACTIONFORMAT lpDiActionFormat, LPCTSTR lpctstrUserName, DWORD dwFlags); HRESULT GetImageInfoI( LPDIDEVICEIMAGEINFOHEADER lpdiDevImageInfoHeader); HRESULT WriteVendorFileI( LPDIACTIONFORMAT lpDiActionFormat, LPDIDEVICEIMAGEINFOHEADER lpdiDevImageInfoHeader, DWORD dwFlags); HRESULT GetImageInfoInternal( LPDIDEVICEIMAGEINFOHEADER lpdiDevImageInfoHeader, bool bGettingSize); void SaveActionMapUV( LPDIACTIONFORMAT lpDiActionFormat, bool bDevInFileLoaded, LPCTSTR pFileName, String &FileDevName, CONTROLLIST &ControlsData, LPDIDEVICEIMAGEINFOHEADER lpdiDevImageInfoHeader, DWORD dwHow1,DWORD dwHow2,bool bUserFile); void WriteImageInfo(LPCTSTR lpFileKeyName,LPCTSTR lpFormatKeyName, LPCTSTR lpSectionName,LPDIDEVICEIMAGEINFO lpImageInfo, bool bAddIndex,bool bDelete); void MakeNewControlName(String &CtrlName, DEVICEOBJLIST::iterator DevObjIt, CONTROLLIST &ControlsData, String &FileDevName, STRINGLIST &ControlsAllDevs, STRINGLIST &Controls); void Resinc(LPDIACTIONFORMAT lpDiActionFormat); HRESULT GetImageInfo( DeviceObjData *pDevObj, DWORD dwIndex, LPDIDEVICEIMAGEINFO lpImageInfo, DWORD dwImageType); bool GetImageInfoFileName(LPCTSTR lpKeyName,LPCTSTR lpSectionName, DWORD dwIndex,LPDIDEVICEIMAGEINFO lpImageInfo); //keep flags for a while just in case we change our minds again #if 0 void GetImageInfoFormat(LPCTSTR lpKeyName,LPCTSTR lpSectionName, DWORD dwIndex,LPDIDEVICEIMAGEINFO lpImageInfo); #endif void LoadFileData(LPCTSTR lpFileName,LPCTSTR lpThisName, DWORD dwThisVendorID,DWORD dwThisProductID, String &FileDeviceName,CONTROLLIST &ControlsData, bool &bLoaded,FILETIME *pT,LPDIACTIONFORMAT lpDiActionFormat); void LoadUserData(LPCTSTR lpctstrUserName, LPDIACTIONFORMAT lpDiActionFormat, bool bForceReload=false, bool bCreateDir=false); void Clear(); bool IsVIDPID(){if(m_dwThisVendorID&&m_dwThisProductID) return true;return false;}; bool CompareData(DeviceObjData &DOD,ControlData &CD); bool GetOffset(ControlData &CD,DEVICEOBJLIST &DevObjList,DWORD dwSemantic, DEVICEOBJLIST::iterator &DevObjItOut); void MapGenre(LPDIACTIONFORMAT lpDiActionFormat,CONTROLLIST &ControlsData, LPCTSTR lpGenreName,LPCTSTR lpFileName, LPCGUID lpThisGUIDInstance, DEVICEOBJLIST &DevObjList,DWORD dwHow, DWORD &dwNOfMappedActions); void MapDevice(LPDIACTIONFORMAT lpDiActionFormat, LPCTSTR lpFileName, LPCTSTR lpFileDevName,LPCGUID lpThisGUIDInstance, DEVICEOBJLIST &DevObjList,CONTROLLIST &ControlsData, DWORD dwHow,DWORD dwHowApp,DWORD &dwNOfMappedActions, bool *pbMapExists,bool bUserFile); public: #ifdef _CHECKED int GetDeviceNo(){return m_DeviceNo;}; #endif DEVICEOBJLIST m_DevObjList; CDIMapObj(); ~CDIMapObj(); ULONG STDMETHODCALLTYPE AddRef() {DllAddRef();m_ulRefCnt++;return m_ulRefCnt;}; ULONG STDMETHODCALLTYPE Release(); HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID * ppvObj); }; /****************************************************************************** * * Debug code * *****************************************************************************/ #ifdef _CHECKED #include #include #include enum BlockType{ eObjectEntryBT, eFunctionBT, eSubBT, eException, }; enum ObjectEntry{ eInitialize=1, eGetActionMap=2, eSaveActionMap=4, eGetImageInfo=8, eWriteVendorFile=16, eCDIMapObj=32, e_CDIMapObj=64, eAddRef=128, eRelease=256, eUnknownMethod=4096 }; class CAdvancedTracer { static DWORD s_dwFlags; static DWORD s_dwFlagsEx; static DWORD s_dwObjNo; static DWORD s_dwObjNoEx; static int s_nDeviceNo; static DWORD s_dwLevels; static String s_ExceptionBuffer; static LPCTSTR s_lpMethodName; static ObjectEntry s_eObjectEntry; static CDIMapObj* s_lpMapObj; static FILE *s_pLogFile; // File handle used for outputing to file static bool s_bException; static bool ExProcessing(){return s_bException;}; BlockType m_eBlockType; int m_nExceptionBufferPos; static bool DumpFlagEx(); static bool DumpFlag(bool bInfoEx); public: CAdvancedTracer( BlockType eBlockType=eSubBT, LPCTSTR pMethodName=NULL, ObjectEntry eObjectEntry=eUnknownMethod, CDIMapObj*lpMapObj=NULL); CAdvancedTracer(LPCTSTR lpSourceFile,DWORD dwLine,HRESULT hRes); ~CAdvancedTracer(); static void OutputTraceString(LPCTSTR szFmt, ...); static void OutputTraceStringInfoEx(LPCTSTR szFmt, ...); static void OutputTraceStringI(bool bInfoEx,LPCTSTR szFmt, va_list argptr); static void Dump(LPCTSTR szName,DWORD dwVal); static void Dump(LPCTSTR szName,int nVal); static void Dump(LPCTSTR szName,bool bVal); static void Dump(LPCTSTR szName,LPDIACTIONFORMAT lpVal); static void Dump(LPCTSTR szName,LPDIDEVICEIMAGEINFOHEADER lpVal); static void Dump(LPCTSTR szName,LPCTSTR lpVal); static void Dump(LPCTSTR szName,LPTSTR lpVal); static void Dump(LPCTSTR szName,LPCGUID lpVal); static void Dump(LPCTSTR szName,LPCDIDEVICEOBJECTINSTANCE lpVal); static void Dump(LPCTSTR szName,const GUID &guid); static void Dump(LPCTSTR szName,String &Val); static void Dump(LPCTSTR szName,DEVICEOBJLIST &Val); }; // Initialize to 0 implicitly DWORD CAdvancedTracer::s_dwFlags; DWORD CAdvancedTracer::s_dwFlagsEx; DWORD CAdvancedTracer::s_dwObjNo; DWORD CAdvancedTracer::s_dwObjNoEx; int CAdvancedTracer::s_nDeviceNo; DWORD CAdvancedTracer::s_dwLevels; String CAdvancedTracer::s_ExceptionBuffer; LPCTSTR CAdvancedTracer::s_lpMethodName=_T(""); ObjectEntry CAdvancedTracer::s_eObjectEntry=eUnknownMethod; CDIMapObj* CAdvancedTracer::s_lpMapObj; FILE *CAdvancedTracer::s_pLogFile; bool CAdvancedTracer::s_bException; #define USETRACER() \ CAdvancedTracer \ There_can_be_only_one_USETRACER_macro_per_block; #define METHOD_ENTRY(MethodName) \ CAdvancedTracer \ There_can_be_only_one_USETRACER_macro_per_block\ (eFunctionBT,_T(#MethodName)); #define OBJECT_ENTRY(MethodName,MethodID) \ CAdvancedTracer \ There_can_be_only_one_USETRACER_macro_per_block\ (eObjectEntryBT,MethodName,MethodID,this); #define EXCEPTION(lpSourceFile,dwLine,hRes) \ CAdvancedTracer \ There_can_be_only_one_USETRACER_macro_per_block\ (lpSourceFile,dwLine,hRes); #define CDIMAPOBJ_ENTERED OBJECT_ENTRY\ (_T("CDIMapObj"),eCDIMapObj); #define _CDIMAPOBJ_ENTERED OBJECT_ENTRY\ (_T("~CDIMapObj"),e_CDIMapObj); #define ADDREF_ENTERED OBJECT_ENTRY\ (_T("AddRef"),eAddRef); #define RELEASE_ENTERED OBJECT_ENTRY\ (_T("Release"),eRelease); #define INITIALIZE_ENTERED OBJECT_ENTRY\ (_T("Initialize"),eInitialize); #define GETACTIONMAP_ENTERED OBJECT_ENTRY\ (_T("GetActionMap"),eGetActionMap); #define SAVEACTIONMAP_ENTERED OBJECT_ENTRY\ (_T("SaveActionMap"),eSaveActionMap); #define GETIMAGEINFO_ENTERED OBJECT_ENTRY\ (_T("GetImageInfo"),eGetImageInfo); #define WRITEVENDORFILE_ENTERED OBJECT_ENTRY\ (_T("WriteVendorFile"),eWriteVendorFile); #define TRACE CAdvancedTracer::OutputTraceString #define TRACEI CAdvancedTracer::OutputTraceStringInfoEx #define DUMP(P) CAdvancedTracer::Dump(_T(#P),P) #define DUMPN(N,V) CAdvancedTracer::Dump(N,V) #define TRACEGUID OutputDebugGuid void OutputDebugGuid(const GUID &guid); #define MAP_EXCEPTION(A) MapException(_T(__FILE__),__LINE__,A) #else //_CHECKED #define TRACE 1 ? 0 : #define TRACEI 1 ? 0 : #define DUMP(a) #define DUMPN(a,b) #define USETRACER() #define METHOD_ENTRY(a) #define OBJECT_ENTRY(a,b) #define EXCEPTION(a,b,c) #define CDIMAPOBJ_ENTERED #define _CDIMAPOBJ_ENTERED #define ADDREF_ENTERED #define RELEASE_ENTERED #define INITIALIZE_ENTERED #define GETACTIONMAP_ENTERED #define SAVEACTIONMAP_ENTERED #define GETIMAGEINFO_ENTERED #define WRITEVENDORFILE_ENTERED #define TRACEGUID 0 ? 1 : (DWORD)& #define MAP_EXCEPTION(A) MapException(A) #endif //_CHECKED #ifdef _CHECKED CAdvancedTracer::CAdvancedTracer( BlockType eBlockType, LPCTSTR pMethodName, ObjectEntry eObjectEntry, CDIMapObj*lpMapObj) { m_eBlockType=eBlockType; switch(m_eBlockType) { case eObjectEntryBT: s_bException=false; //default - no method is dumped s_dwFlags=GetProfileInt(_T("DEBUG"),_T("dinput.map"),0); //default - all methods are dumped during exception s_dwFlagsEx=GetProfileInt(_T("DEBUG"),_T("dinput.mapex"),-1); //default - all objects are dumped s_dwObjNo=GetProfileInt(_T("DEBUG"),_T("dinput.mapobj"),-1); //default - all objects are dumped during exception s_dwObjNoEx=GetProfileInt(_T("DEBUG"),_T("dinput.mapobjex"),-1); s_nDeviceNo=lpMapObj->GetDeviceNo(); s_dwLevels=0; s_ExceptionBuffer.resize(0); s_lpMethodName=pMethodName; s_eObjectEntry=eObjectEntry; s_lpMapObj=lpMapObj; s_pLogFile=NULL; // File handle used for outputing to file m_nExceptionBufferPos=0; TCHAR F[1024]; if((GetProfileString(_T("DEBUG"), _T("dinput.maplogfile"),_T(""), F,1024)!=1023)&&F[0]) { F[1023]=0; s_pLogFile=_tfopen(F,_T("a+")); } TRACE(_T("____________________________________\ ___________________________________________\n")); TRACE(_T("%s() entered, dump method id=%u, dump object id=%u\n"), s_lpMethodName,s_eObjectEntry,s_nDeviceNo); TRACE(_T("{\n")); break; case eFunctionBT: m_nExceptionBufferPos=s_ExceptionBuffer.size(); TRACE(_T("%s()\n"),pMethodName); TRACE(_T("{\n")); break; case eSubBT: m_nExceptionBufferPos=s_ExceptionBuffer.size(); break; } s_dwLevels++; } CAdvancedTracer::CAdvancedTracer( LPCTSTR lpSourceFile, DWORD dwLine, HRESULT hRes) { m_eBlockType=eException; s_bException=true; DWORD dwOldLevels=s_dwLevels; s_dwLevels=0; TRACE(_T("MAPPER ERROR ******************************\n")); TRACE(_T("ERROR IN FILE: %s\n"),lpSourceFile); TRACE(_T("ERROR ON LINE: %d\n"),dwLine); TRACE(_T("hRes=0x%x\n"),hRes); switch(hRes) { case E_SYNTAX_ERROR: TRACE(_T("hRes=E_SYNTAX_ERROR\n")); break; case E_DEFINITION_NOT_FOUND: TRACE(_T("hRes=E_DEFINITION_NOT_FOUND\n")); break; case E_LINE_TO_LONG: TRACE(_T("hRes=E_LINE_TO_LONG\n")); break; case E_ACTION_NOT_DEFINED: TRACE(_T("hRes=E_ACTION_NOT_DEFINED\n")); break; case E_DEVICE_NOT_DEFINED: TRACE(_T("hRes=E_DEVICE_NOT_DEFINED\n")); break; case E_VENDORID_NOT_FOUND: TRACE(_T("hRes=E_VENDORID_NOT_FOUND\n")); break; case E_PRODUCTID_NOT_FOUND: TRACE(_T("hRes=E_PRODUCTID_NOT_FOUND\n")); break; case E_USAGE_NOT_FOUND: TRACE(_T("hRes=E_USAGE_NOT_FOUND\n")); break; case E_USAGEPAGE_NOT_FOUND: TRACE(_T("hRes=E_USAGEPAGE_NOT_FOUND\n")); break; case E_DEVICE_NOT_FOUND: TRACE(_T("hRes=E_DEVICE_NOT_FOUND\n")); break; case E_BAD_VERSION: TRACE(_T("hRes=E_BAD_VERSION\n")); break; case E_DEVICE_MISSING_CONTROL: TRACE(_T("hRes=E_DEVICE_MISSING_CONTROL\n")); break; case E_DEV_OBJ_NOT_FOUND: TRACE(_T("hRes=E_DEV_OBJ_NOT_FOUND\n")); break; case E_CTRL_W_OFFSET_NOTFOUND: TRACE(_T("hRes=E_CTRL_W_OFFSET_NOTFOUND\n")); break; case E_FILENAME_TO_LONG: TRACE(_T("hRes=E_FILENAME_TO_LONG\n")); break; case E_WRONG_ALIGN_DATA: TRACE(_T("hRes=E_WRONG_ALIGN_DATA\n")); break; case E_CORRUPT_IMAGE_DATA: TRACE(_T("hRes=E_CORRUPT_IMAGE_DATA\n")); break; case E_OUTOFMEMORY: TRACE(_T("hRes=E_OUTOFMEMORY\n")); break; case E_INVALIDARG: TRACE(_T("hRes=E_INVALIDARG\n")); break; case DIERR_NOTINITIALIZED: TRACE(_T("hRes=DIERR_NOTINITIALIZED\n")); break; case E_FAIL: TRACE(_T("hRes=E_FAIL\n")); break; default : TRACE(_T("hRes=UNKNOWN ERROR.\n")); break; } TRACE(_T("ERROR INFO:\n")); if(DumpFlagEx()) { if(s_ExceptionBuffer.data()) { LPCTSTR p=s_ExceptionBuffer.data(); TCHAR C[2]; C[1]=0; while(*p) { C[0]=*p; OutputDebugString(C); Sleep(0); p++; }; //OutputDebugString(s_ExceptionBuffer.data()); if (s_pLogFile) { _ftprintf(s_pLogFile,s_ExceptionBuffer.data()); } } } TRACE(_T("ERROR HAPPENED HERE -->\n")); s_ExceptionBuffer.resize(0); s_dwLevels=dwOldLevels+1; } CAdvancedTracer::~CAdvancedTracer() { --s_dwLevels; switch(m_eBlockType) { case eObjectEntryBT: TRACE(_T("}\n")); TRACE(_T("%s leaving\n"),s_lpMethodName); TRACE(_T("____________________________________\ ___________________________________________\n")); s_dwFlags=0; s_dwFlagsEx=-1; s_dwObjNo=-1; s_dwObjNoEx=-1; s_nDeviceNo=-1; s_dwLevels=0; s_ExceptionBuffer.resize(0); s_lpMethodName=_T(""); s_eObjectEntry=eUnknownMethod; s_lpMapObj=NULL; if(s_pLogFile) fclose(s_pLogFile); s_pLogFile=NULL; break; case eFunctionBT: TRACE(_T("}\n")); break; case eSubBT: break; case eException: break; } if((m_eBlockType!=eObjectEntryBT)&& (m_eBlockType!=eSubBT)) { if(!ExProcessing()) s_ExceptionBuffer.resize(m_nExceptionBufferPos); } } bool CAdvancedTracer::DumpFlag(bool bInfoEx) { if((s_dwObjNo==-1)||(s_dwObjNo==s_nDeviceNo)) if(s_dwFlags&s_eObjectEntry) return true; if(bInfoEx) if((s_dwObjNoEx==-1)||(s_dwObjNoEx==s_nDeviceNo)) if(s_dwFlagsEx&s_eObjectEntry) return true; return false; } bool CAdvancedTracer::DumpFlagEx() { if((s_dwObjNoEx==-1)||(s_dwObjNoEx==s_nDeviceNo)) if(s_dwFlagsEx&s_eObjectEntry) return true; return false; } void CAdvancedTracer::OutputTraceString(LPCTSTR szFmt, ...) { va_list argptr; va_start(argptr, szFmt); OutputTraceStringI(false,szFmt,argptr); va_end(argptr); } void CAdvancedTracer::OutputTraceStringInfoEx(LPCTSTR szFmt, ...) { va_list argptr; va_start(argptr, szFmt); OutputTraceStringI(true,szFmt,argptr); va_end(argptr); } // Warning: This function is not thread safe. void CAdvancedTracer::OutputTraceStringI(bool bInfoEx, LPCTSTR szFmt,va_list argptr) { const cBufSize=1024; TCHAR szBuf[cBufSize]; szBuf[cBufSize-1]=0; // Print the identation first int nCnt=s_dwLevels; if(nCnt>cBufSize-1)nCnt=cBufSize-1; for (DWORD i = 0; i < nCnt; ++i) { szBuf[i]=_T(' '); } szBuf[i]=0; // Then print the content #ifdef WIN95 { char *psz = NULL; char szDfs[1024]={0}; strcpy(szDfs,szFmt); // make a local copy of format string while (psz = strstr(szDfs,"%p")) // find each %p *(psz+1) = 'x'; // replace each %p with %x _vsntprintf(&szBuf[i], cBufSize-1-i, szDfs, argptr); // use the local format string } #else { _vsntprintf(&szBuf[i], cBufSize-1-i, szFmt, argptr); } #endif szBuf[cBufSize-1]=0; if((!ExProcessing())&&DumpFlagEx()) s_ExceptionBuffer+=szBuf; if(DumpFlag(bInfoEx)||(ExProcessing()&&DumpFlagEx())) { OutputDebugString(szBuf); if (s_pLogFile) { _ftprintf(s_pLogFile, szBuf); } } } void CAdvancedTracer::Dump(LPCTSTR szName,DWORD dwVal) { TRACE(_T("%s=%u\n"),szName,(unsigned int)dwVal); } void CAdvancedTracer::Dump(LPCTSTR szName,int nVal) { TRACE(_T("%s=%d\n"),szName,(unsigned int)nVal); } void CAdvancedTracer::Dump(LPCTSTR szName,String &Val) { if(Val.data()) TRACE(_T("%s=%s\n"),szName,Val.data()); else TRACE(_T("%s=NULL\n"),szName); } void CAdvancedTracer::Dump(LPCTSTR szName,bool bVal) { TRACE(_T("%s=%u\n"),szName,(unsigned int)bVal); } void CAdvancedTracer::Dump(LPCTSTR szName,DEVICEOBJLIST &Val) { TRACE(_T("%s:\n"),szName); USETRACER(); TRACE(_T("UsagePage\tUsage\tType\tFlags\tName\n")); DEVICEOBJLIST::iterator DevObjIt; for(DevObjIt=Val.begin();DevObjIt!=Val.end();DevObjIt++) { TRACE(_T("%u\t%u\t0x%x\t0x%x\t%s\n"), DevObjIt->dwUsagePage, DevObjIt->dwUsage, DevObjIt->dwType, DevObjIt->dwFlags, DevObjIt->Name.data()); } } void CAdvancedTracer::Dump(LPCTSTR szName,LPDIACTIONFORMAT lpVal) { // 7/18/2000(a-JiTay): IA64: Use %p format specifier for 32/64-bit pointers. TRACE(_T("%s=0x%p\n"),szName,lpVal); if(lpVal) { USETRACER(); TRACE(_T("dwSize=%u\tdwActionSize=%u\n"), (unsigned int)lpVal->dwSize, (unsigned int)lpVal->dwActionSize); TRACE(_T("guidActionMap="));TRACEGUID(lpVal->guidActionMap); TRACE(_T("dwGenre=0x%x\tGenre=%u\n"), (unsigned int)lpVal->dwGenre, (unsigned int)DISEM_GENRE_GET(lpVal->dwGenre)); TRACE(_T("dwNumActions=%u\trgoAction=0x%x\n"), (unsigned int)lpVal->dwNumActions, lpVal->rgoAction); TRACE(_T("ftTimeStamp.dwHighDateTime=0x%x\t"), (unsigned int)lpVal->ftTimeStamp.dwHighDateTime); TRACE(_T("ftTimeStamp.dwLowDateTime=0x%x\n"), (unsigned int)lpVal->ftTimeStamp.dwLowDateTime); // 7/18/2000(a-JiTay): IA64: Use %p format specifier for 32/64-bit pointers. TRACE(_T("rgoAction=0x%p\n"),lpVal); if(lpVal->rgoAction) { USETRACER(); TRACE(_T("Action No\tdwSemantic\tSemantic\tSemantic type\tdwFlags\t\ dwObjID\tdwHow\tguidInstance\n")); for(DWORD i=0;idwNumActions;i++) { LPCTSTR p; if(DISEM_TYPE_GET(lpVal->rgoAction[i].dwSemantic)== DISEM_TYPE_GET(DISEM_TYPE_AXIS)) p=_T("DISEM_TYPE_AXIS"); else if(DISEM_TYPE_GET(lpVal->rgoAction[i].dwSemantic)== DISEM_TYPE_GET(DISEM_TYPE_BUTTON)) p=_T("DISEM_TYPE_BUTTON"); else if(DISEM_TYPE_GET(lpVal->rgoAction[i].dwSemantic)== DISEM_TYPE_GET(DISEM_TYPE_POV)) p=_T("DISEM_TYPE_POV"); else p=_T(""); TRACE(_T("%u\t0x%x\t%u\t%u %s\t0x%x\t0x%x\t0x%x\t"), i, (unsigned int)lpVal->rgoAction[i].dwSemantic, (unsigned int)DISEM_INDEX_GET (lpVal->rgoAction[i].dwSemantic), (unsigned int)DISEM_TYPE_GET (lpVal->rgoAction[i].dwSemantic),p, (unsigned int)lpVal->rgoAction[i].dwFlags, (unsigned int)lpVal->rgoAction[i].dwObjID, (unsigned int)lpVal->rgoAction[i].dwHow); TRACEGUID(lpVal->rgoAction[i].guidInstance); } } } } void CAdvancedTracer::Dump(LPCTSTR szName,LPDIDEVICEIMAGEINFOHEADER lpVal) { // 7/18/2000(a-JiTay): IA64: Use %p format specifier for 32/64-bit pointers. TRACE(_T("%s=0x%p\n"),szName,lpVal); if(lpVal) { USETRACER(); TRACE(_T("dwSize=%u\tdwSizeImageInfo=%u\n"), (unsigned int)lpVal->dwSize, (unsigned int)lpVal->dwSizeImageInfo); TRACE(_T("dwcViews=%u\tdwcButtons=%u\n"), (unsigned int)lpVal->dwcViews, (unsigned int)lpVal->dwcButtons); TRACE(_T("dwcAxes=%u\tdwcPOVs=%u\n"), (unsigned int)lpVal->dwcAxes, (unsigned int)lpVal->dwcPOVs); TRACE(_T("dwBufferSize=%u\tdwBufferUsed=%u\n"), (unsigned int)lpVal->dwBufferSize, (unsigned int)lpVal->dwBufferUsed); // 7/18/2000(a-JiTay): IA64: Use %p format specifier for 32/64-bit pointers. TRACE(_T("lprgImageInfoArray=0x%p\n"),lpVal->lprgImageInfoArray); if(lpVal->lprgImageInfoArray) { USETRACER(); TRACE(_T("tszImagePath\ndwFlags\tdwViewID\trcOverlay\tdwObjID\t\ dwcValidPts\trcCalloutRect\tdwTextAlign\n")); for(DWORD i=0;i<(lpVal->dwBufferSize/ sizeof(lpVal->lprgImageInfoArray[0]));i++) { TCHAR tszImagePath[MAX_PATH]; memcpy(&tszImagePath, &lpVal->lprgImageInfoArray[i].tszImagePath, sizeof(tszImagePath)); tszImagePath[MAX_PATH-1]=0; TRACE(_T("%s\n"),&tszImagePath); TRACE(_T("0x%x\t"),lpVal->lprgImageInfoArray[i].dwFlags); TRACE(_T("%u\t"),lpVal->lprgImageInfoArray[i].dwViewID); TRACE(_T("[%u,%u],[%u,%u]\t"), lpVal->lprgImageInfoArray[i].rcOverlay.left, lpVal->lprgImageInfoArray[i].rcOverlay.top, lpVal->lprgImageInfoArray[i].rcOverlay.right, lpVal->lprgImageInfoArray[i].rcOverlay.bottom); TRACE(_T("0x%x\t"),lpVal->lprgImageInfoArray[i].dwObjID); TRACE(_T("%u\t"),lpVal->lprgImageInfoArray[i].dwcValidPts); const int nPnts= sizeof(lpVal->lprgImageInfoArray[i].rgptCalloutLine)/ sizeof(lpVal->lprgImageInfoArray[i].rgptCalloutLine[0]); TRACE(_T("[%u,%u],[%u,%u]\t"), lpVal->lprgImageInfoArray[i].rcCalloutRect.left, lpVal->lprgImageInfoArray[i].rcCalloutRect.top, lpVal->lprgImageInfoArray[i].rcCalloutRect.right, lpVal->lprgImageInfoArray[i].rcCalloutRect.bottom); TRACE(_T("0x%x\n"),lpVal->lprgImageInfoArray[i].dwTextAlign); } } } } void CAdvancedTracer::Dump(LPCTSTR szName,LPCTSTR lpVal) { if(lpVal) TRACE(_T("%s=%s\n"),szName,lpVal); else TRACE(_T("%s=NULL\n"),szName); } void CAdvancedTracer::Dump(LPCTSTR szName,LPTSTR lpVal) { Dump(szName,(LPCTSTR)lpVal); } void CAdvancedTracer::Dump(LPCTSTR szName,LPCDIDEVICEOBJECTINSTANCE lpVal) { // 7/18/2000(a-JiTay): IA64: Use %p format specifier for 32/64-bit pointers. TRACE(_T("%s=0x%p\n"),szName,lpVal); if(lpVal) { USETRACER(); // 7/18/2000(a-JiTay): IA64: Use %p format specifier for 32/64-bit pointers. TRACE(_T("tszName=0x%p\n"),lpVal->tszName); if(lpVal->tszName) { USETRACER(); TRACE(_T("%s\n"),lpVal->tszName); } TRACE(_T("dwOfs=%u\n"),(unsigned int)lpVal->dwOfs); TRACE(_T("wUsagePage=%u\n"),(unsigned int)lpVal->wUsagePage); TRACE(_T("wUsage=%u\n"),(unsigned int)lpVal->wUsage); TRACE(_T("dwType=%u\n"),(unsigned int)lpVal->dwType); if(lpVal->dwType&DIDFT_RELAXIS) TRACE(_T("dwType&=DIDFT_RELAXIS\n")); if(lpVal->dwType&DIDFT_ABSAXIS) TRACE(_T("dwType&=DIDFT_ABSAXIS\n")); if(lpVal->dwType&DIDFT_PSHBUTTON) TRACE(_T("dwType&=DIDFT_PSHBUTTON\n")); if(lpVal->dwType&DIDFT_TGLBUTTON) TRACE(_T("dwType&=DIDFT_TGLBUTTON\n")); if(lpVal->dwType&DIDFT_POV) TRACE(_T("dwType&=DIDFT_POV\n")); } } void CAdvancedTracer::Dump(LPCTSTR szName,const GUID &guid) { TRACE(_T("%s="),szName); OutputDebugGuid(guid); } void CAdvancedTracer::Dump(LPCTSTR szName,LPCGUID lpVal) { if(lpVal) { TRACE(_T("%s="),szName); OutputDebugGuid(*lpVal); } else TRACE(_T("%s=NULL\n"),szName); } void OutputDebugGuid(const GUID &guid) { TRACE(_T("{%08X-%04hX-%04hX-%02hX%02hX-%02X%02X%02X%02X%02X%02X}\n"), guid.Data1, guid.Data2, guid.Data3, (WORD)guid.Data4[0], (WORD)guid.Data4[1], (WORD)guid.Data4[2], (WORD)guid.Data4[3], (WORD)guid.Data4[4], (WORD)guid.Data4[5], (WORD)guid.Data4[6], (WORD)guid.Data4[7]); } #endif //_CHECKED /****************************************************************************** * * Exception Handler * *****************************************************************************/ MapException::MapException( #ifdef _CHECKED LPCTSTR lpSourceFile,DWORD dwLine, #endif HRESULT hRes) { m_hRes=hRes; EXCEPTION(lpSourceFile,dwLine,hRes); } /****************************************************************************** * * String Processing * *****************************************************************************/ void ToUpper(String &S) { CharUpperBuff((LPTSTR)S.data(),S.size()); for(StrIter B=S.begin();BS.begin();E--) { if(!(IsSpace(*(E-1))||(0==*(E-1))))break; } String R; while(Bleft)+_T(",")+N2Str(pR->top)+ _T("),(")+N2Str(pR->right)+_T(",")+N2Str(pR->bottom)+_T(")"); if(!WritePrivateProfileString(pSection,pKey,Rect.data(),pFile)) { TRACE(_T("Error writing ini file.\n")); throw MAP_EXCEPTION(HRESULT_FROM_WIN32(GetLastError())); } } void WritePointArray(LPCTSTR pSection,LPCTSTR pKey,LPPOINT pP, int N,LPCTSTR pFile) { METHOD_ENTRY(WritePointArray); DUMP(pFile); DUMP(pSection); DUMP(pKey); String LineData; for(DWORD i=0;i>12); GetHexCode(Ret,(*p)>>8); GetHexCode(Ret,(*p)>>4); GetHexCode(Ret,*p); break; } } } void MakeUniqueDeviceName(String &Ret, LPCWSTR pIn/*This is hardcoded in dinput to WSTR*/) { Ret=_T(""); for(LPCWCH p=pIn;*p!=0;p++) { switch(*p) { case L'A': case L'a':Ret+=_T('A');break; case L'B': case L'b':Ret+=_T('B');break; case L'C': case L'c':Ret+=_T('C');break; case L'D': case L'd':Ret+=_T('D');break; case L'E': case L'e':Ret+=_T('E');break; case L'F': case L'f':Ret+=_T('F');break; case L'G': case L'g':Ret+=_T('G');break; case L'H': case L'h':Ret+=_T('H');break; case L'I': case L'i':Ret+=_T('I');break; case L'J': case L'j':Ret+=_T('J');break; case L'K': case L'k':Ret+=_T('K');break; case L'L': case L'l':Ret+=_T('L');break; case L'M': case L'm':Ret+=_T('M');break; case L'N': case L'n':Ret+=_T('N');break; case L'O': case L'o':Ret+=_T('O');break; case L'P': case L'p':Ret+=_T('P');break; case L'Q': case L'q':Ret+=_T('Q');break; case L'R': case L'r':Ret+=_T('R');break; case L'S': case L's':Ret+=_T('S');break; case L'T': case L't':Ret+=_T('T');break; case L'U': case L'u':Ret+=_T('U');break; case L'V': case L'v':Ret+=_T('V');break; case L'W': case L'w':Ret+=_T('W');break; //X: Special case. Make sure it is consistent //with special case elsewhere. case L'X': case L'x':Ret+=_T("XX");break; case L'Y': case L'y':Ret+=_T('Y');break; case L'Z': case L'z':Ret+=_T('Z');break; case L'1':Ret+=_T('1');break; case L'2':Ret+=_T('2');break; case L'3':Ret+=_T('3');break; case L'4':Ret+=_T('4');break; case L'5':Ret+=_T('5');break; case L'6':Ret+=_T('6');break; case L'7':Ret+=_T('7');break; case L'8':Ret+=_T('8');break; case L'9':Ret+=_T('9');break; case L'0':Ret+=_T('0');break; case L' ':Ret+=_T(' ');break; case L'(':Ret+=_T('(');break; case L')':Ret+=_T(')');break; case L'.':Ret+=_T('.');break; case L'_':Ret+=_T('_');break; case L'-':Ret+=_T('-');break; case L'&':Ret+=_T('&');break; default: //X: Special case. Make sure it is consistent //with special case elsewhere. Ret+=_T("X"); GetHexCode(Ret,(*p)>>12); GetHexCode(Ret,(*p)>>8); GetHexCode(Ret,(*p)>>4); GetHexCode(Ret,*p); break; } } } void MakeSubDir(LPCTSTR lpDir) { String DirCreationString=lpDir; DirCreationString+=_T("\\"); LPTSTR lpPos=_tcschr(DirCreationString.data(),_T('\\')); if(!lpPos) { TRACE(_T("Error creating user directory. Invalid parent directory.\n")); throw MAP_EXCEPTION(E_FAIL); } lpPos=_tcschr(lpPos+1,_T('\\')); if(!lpPos) { TRACE(_T("Error creating user directory. Invalid parent directory.\n")); throw MAP_EXCEPTION(E_FAIL); } while(lpPos) { *lpPos=0; if(!CreateDirectory(DirCreationString.data(),NULL)) { DWORD dwErr=GetLastError(); if(dwErr!=ERROR_ALREADY_EXISTS) { TRACE(_T("Error creating user directory.\n")); throw MAP_EXCEPTION(HRESULT_FROM_WIN32(dwErr)); } } *lpPos=_T('\\'); lpPos=_tcschr(lpPos+1,_T('\\')); } } void GetMapFileName(LPCTSTR lpctstrUserName,LPCTSTR lpctstrDeviceName, int nDeviceInstanceNo, LPTSTR szFileName/*_MAX_PATH*/,bool bCreateDir=false, String *lpUserDir=NULL) { HRESULT hRes=S_OK; #ifdef WINNT //Allocate a pointer to an Item ID list LPITEMIDLIST pidl; hRes=SHGetSpecialFolderLocation(NULL,CSIDL_APPDATA,&pidl); if(FAILED(hRes)) { TRACE(_T("Error calling SHGetSpecialFolderLocation().\n")); throw MAP_EXCEPTION(hRes); } //Convert the item ID list's binary //representation into a file system path if(!SHGetPathFromIDList(pidl,szFileName)) { TRACE(_T("Error calling SHGetPathFromIDList().\n")); } szFileName[_MAX_PATH-1]=0; //Allocate a pointer to an IMalloc interface LPMALLOC pMalloc=NULL; //Get the address of our task allocator's IMalloc interface hRes=SHGetMalloc(&pMalloc); if((hRes==NOERROR)&&pMalloc) { //Free the item ID list allocated by SHGetSpecialFolderLocation pMalloc->Free(pidl); //Free our task allocator pMalloc->Release(); } #ifdef _CHECKED else { TRACE(_T("RESOURCE LEAK! SHGetMalloc failed, can not free resource.\n")); } #endif hRes=S_OK;//Could not release resource. Continue anyways. //There is nothing we can do. //Create directories if necessary. String DirCreationString=szFileName; //Check if directory name is too long if((_tcslen(szFileName)+_tcslen(MAP_DIR_NT)+1)>_MAX_PATH) { TRACE(_T("User dir name too long.\n")); throw MAP_EXCEPTION(E_FAIL); } _tcscat(szFileName,MAP_DIR_NT); if(lpUserDir)*lpUserDir=szFileName; //Create directory for map files if(bCreateDir) { //Create subdirs one by one TRACE(_T("Creating user directory %s.\n"),szFileName); DirCreationString+=MS_NAME; if(!CreateDirectory(DirCreationString.data(),NULL)) { DWORD dwErr=GetLastError(); if(dwErr!=ERROR_ALREADY_EXISTS) { TRACE(_T("Error creating user directory.\n")); throw MAP_EXCEPTION(HRESULT_FROM_WIN32(dwErr)); } } DirCreationString+=DIRECTX; if(!CreateDirectory(DirCreationString.data(),NULL)) { DWORD dwErr=GetLastError(); if(dwErr!=ERROR_ALREADY_EXISTS) { TRACE(_T("Error creating user directory.\n")); throw MAP_EXCEPTION(HRESULT_FROM_WIN32(dwErr)); } } DirCreationString+=DIRECTINPUT; if(!CreateDirectory(DirCreationString.data(),NULL)) { DWORD dwErr=GetLastError(); if(dwErr!=ERROR_ALREADY_EXISTS) { TRACE(_T("Error creating user directory.\n")); throw MAP_EXCEPTION(HRESULT_FROM_WIN32(dwErr)); } } DirCreationString+=USER_MAPS; if(!CreateDirectory(DirCreationString.data(),NULL)) { DWORD dwErr=GetLastError(); if(dwErr!=ERROR_ALREADY_EXISTS) { TRACE(_T("Error creating user directory.\n")); throw MAP_EXCEPTION(HRESULT_FROM_WIN32(dwErr)); } } } //Get user name if(!lpctstrUserName) { lpctstrUserName=DEFAULT_USER_NAME; } #else//WINNT //For win9x get directory name from the registry HKEY Key=0; if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion"), (DWORD)0, KEY_QUERY_VALUE, &Key)!=ERROR_SUCCESS) { TRACE(_T("Error calling RegOpenKeyEx(HKEY_LOCAL_MACHINE\ \\SOFTWARE\\Microsoft\\Windows\\CurrentVersion).\n")); throw MAP_EXCEPTION(E_FAIL); } DWORD dwType=REG_SZ; DWORD dwSize=MAX_PATH*sizeof(TCHAR); if(RegQueryValueEx(Key,_T("CommonFilesDir"), NULL,&dwType,(LPBYTE)szFileName,&dwSize)!=ERROR_SUCCESS) { TRACE(_T("Error calling RegQueryValueEx(CommonFilesDir).\n")); throw MAP_EXCEPTION(E_FAIL); } RegCloseKey(Key); //Create directories if necessary. String DirCreationString=szFileName; //Check if directory name is too long if((_tcslen(szFileName)+_tcslen(MAP_DIR)+1)>_MAX_PATH) { TRACE(_T("User dir name too long.\n")); throw MAP_EXCEPTION(E_FAIL); } _tcscat(szFileName,MAP_DIR); if(lpUserDir)*lpUserDir=szFileName; //Create directory for map files if(bCreateDir) { //Create subdirs one by one TRACE(_T("Creating user directory %s.\n"),szFileName); DirCreationString+=DIRECTX; if(!CreateDirectory(DirCreationString.data(),NULL)) { DWORD dwErr=GetLastError(); if(dwErr!=ERROR_ALREADY_EXISTS) { //could be that Win95 Gold does not have "Common Files" dir MakeSubDir(DirCreationString.data()); } } DirCreationString+=DIRECTINPUT; if(!CreateDirectory(DirCreationString.data(),NULL)) { DWORD dwErr=GetLastError(); if(dwErr!=ERROR_ALREADY_EXISTS) { TRACE(_T("Error creating user directory.\n")); throw MAP_EXCEPTION(HRESULT_FROM_WIN32(dwErr)); } } DirCreationString+=USER_MAPS; if(!CreateDirectory(DirCreationString.data(),NULL)) { DWORD dwErr=GetLastError(); if(dwErr!=ERROR_ALREADY_EXISTS) { TRACE(_T("Error creating user directory.\n")); throw MAP_EXCEPTION(HRESULT_FROM_WIN32(dwErr)); } } } //Get user name TCHAR UN[UNLEN+1]; if(!lpctstrUserName) { DWORD dwLen=UNLEN+1; GetUserName(UN,&dwLen); lpctstrUserName=UN; } #endif //WINNT //Create full path filename //Unique user name String UniqueUserName; MakeUniqueUserName(UniqueUserName,lpctstrUserName); //Device instance string String DevInst; DevInst=N2Str(nDeviceInstanceNo); if((_tcslen(szFileName)+1+_tcslen(UniqueUserName.data())+2+ _tcslen(lpctstrDeviceName)+2+ _tcslen(DevInst.data())+4+1)>_MAX_PATH) { TRACE(_T("User path file name too long.\n")); throw MAP_EXCEPTION(E_FAIL); } _tcscat(szFileName,_T("\\")); _tcscat(szFileName,UniqueUserName.data()); //X: Special case. Make sure it is consistent //with special case elsewhere. _tcscat(szFileName,_T("X_")); _tcscat(szFileName,lpctstrDeviceName); //X: Special case. Make sure it is consistent //with special case elsewhere. _tcscat(szFileName,_T("X_")); _tcscat(szFileName,DevInst.data()); _tcscat(szFileName,_T(".INI")); } /****************************************************************************** * * ANSI/UNICODE parameter translation templates * *****************************************************************************/ int TrCopy(LPCSTR pszA,size_t nCharacters,LPWSTR pszW,size_t nSizeW) {return MultiByteToWideChar(CP_ACP,0,pszA,nCharacters,pszW,nSizeW);}; int TrCopy(LPCOLESTR pszW,size_t nCharacters,LPSTR pszA,size_t nSizeA) {return WideCharToMultiByte(CP_ACP,0,pszW,nCharacters, pszA,nSizeA,NULL,NULL);}; size_t TrSize(LPCSTR pszA,size_t nSizeA){return nSizeA;}; size_t TrSize(LPCWSTR pszW,size_t nSizeW){return nSizeW*2;}; size_t TrStrLen(LPCSTR pszA){return strlen(pszA);}; size_t TrStrLen(LPCWSTR pszW){return wcslen(pszW);}; template void Tr(StrTypeFrom *pszFrom,size_t nSizeFrom, StrTypeTo* pszTo,size_t nSizeTo) { if(!TrCopy(pszFrom,TrStrLen(pszFrom)+1,pszTo,nSizeTo)) throw MAP_EXCEPTION(HRESULT_FROM_WIN32(GetLastError())); pszTo[nSizeTo-1]=0; }; template class C2Base { protected: StrTypeTo *m_pszStrTo; size_t m_nSizeTo; StrTypeFrom *m_pszStrFrom; size_t m_nSizeFrom; bool m_bReturn; public: C2Base(){m_pszStrTo=NULL;}; ~C2Base(){delete m_pszStrTo;}; operator StrTypeTo*(){return m_pszStrTo;}; size_t Size(){return m_nSizeTo;}; void Set(const StrTypeFrom *pszStrFrom=NULL,size_t nSizeFrom=-1) { //Delete old buffer delete m_pszStrTo; //Initialize members m_pszStrTo=NULL; m_nSizeTo=0; m_pszStrFrom=(StrTypeFrom*)pszStrFrom; m_nSizeFrom=nSizeFrom; m_bReturn=false; //Check if in string is 0 if((!m_pszStrFrom)||(!nSizeFrom)) { m_nSizeFrom=0; return; } //Get len of the in string if(m_nSizeFrom==-1) m_nSizeFrom=TrStrLen(m_pszStrFrom)+1; //Allocate buffer for translated string m_nSizeTo=TrSize(m_pszStrFrom,m_nSizeFrom); m_pszStrTo=new StrTypeTo[m_nSizeTo]; if(m_nSizeTo) m_pszStrTo[0]=0; //Check if this is in or out param if((nSizeFrom!=-1)) m_bReturn=true; //Translate if(!m_bReturn) Tr(m_pszStrFrom,m_nSizeFrom,m_pszStrTo,m_nSizeTo); } }; template class C2: public C2Base { public: C2(const StrTypeFrom *pszStrFrom=NULL,size_t nSizeFrom=-1) {Set(pszStrFrom,nSizeFrom);}; ~C2(){if(m_bReturn) Tr(m_pszStrTo,m_nSizeTo,m_pszStrFrom,m_nSizeFrom);}; }; //This template translates between DIACTIONFORMATA and DIACTIONFORMATW template class CTrDIACTIONFORMAT:public IDTo { IDTo* m_pIDTo; IDFrom* m_pIDFrom; public: CTrDIACTIONFORMAT(IDFrom *pIn) { m_pIDTo=NULL; m_pIDFrom=pIn; if(pIn) { dwSize=sizeof(IDTo); dwActionSize=pIn->dwActionSize; dwDataSize=0; dwNumActions=pIn->dwNumActions; guidActionMap=pIn->guidActionMap; dwGenre=pIn->dwGenre; rgoAction=(Act*)(pIn->rgoAction); dwBufferSize=0; lAxisMin=0; lAxisMax=0; hInstString=0; tszActionMap[0]=0; ftTimeStamp.dwLowDateTime= pIn->ftTimeStamp.dwLowDateTime; ftTimeStamp.dwHighDateTime= pIn->ftTimeStamp.dwHighDateTime; m_pIDTo=(IDTo*)this; } }; ~CTrDIACTIONFORMAT() { if(m_pIDFrom&&m_pIDTo) { m_pIDFrom->ftTimeStamp.dwLowDateTime= m_pIDTo->ftTimeStamp.dwLowDateTime; m_pIDFrom->ftTimeStamp.dwHighDateTime= m_pIDTo->ftTimeStamp.dwHighDateTime; } } operator IDTo*(){return m_pIDTo;}; }; //This templates translate between DIDEVICEIMAGEINFOHEADERA and //DIDEVICEIMAGEINFOHEADERW template class CTrDIDEVICEIMAGEINFOHEADERB:public IDTo { public: CTrDIDEVICEIMAGEINFOHEADERB(){lprgImageInfoArray=NULL;}; ~CTrDIDEVICEIMAGEINFOHEADERB(){delete lprgImageInfoArray;}; }; template void TrDIDEVICEIMAGEINFO(StrTypeFrom *pszFrom,StrTypeTo* pszTo) { Tr(pszFrom->tszImagePath, sizeof(pszFrom->tszImagePath)/sizeof(pszFrom->tszImagePath[0]), pszTo->tszImagePath, sizeof(pszTo->tszImagePath)/sizeof(pszTo->tszImagePath[0])); pszTo->dwFlags=pszFrom->dwFlags; pszTo->dwViewID=pszFrom->dwViewID; pszTo->rcOverlay=pszFrom->rcOverlay; pszTo->dwObjID=pszFrom->dwObjID; pszTo->rgptCalloutLine[0]=pszFrom->rgptCalloutLine[0]; pszTo->rgptCalloutLine[1]=pszFrom->rgptCalloutLine[1]; pszTo->rgptCalloutLine[2]=pszFrom->rgptCalloutLine[2]; pszTo->rgptCalloutLine[3]=pszFrom->rgptCalloutLine[3]; pszTo->rgptCalloutLine[4]=pszFrom->rgptCalloutLine[4]; pszTo->dwcValidPts=pszFrom->dwcValidPts; pszTo->rcCalloutRect=pszFrom->rcCalloutRect; pszTo->dwTextAlign=pszFrom->dwTextAlign; } template class CTrDIDEVICEIMAGEINFOHEADER:public CTrDIDEVICEIMAGEINFOHEADERB { IDTo* m_pIDTo; IDFrom* m_pIDFrom; bool m_bGet; public: CTrDIDEVICEIMAGEINFOHEADER(IDFrom *pIn,bool bGet=true) { m_pIDTo=NULL; m_pIDFrom=pIn; m_bGet=bGet; if(pIn) { memset((IDTo*)this,0,sizeof(IDTo)); if(pIn->dwSize==sizeof(IDFrom)) dwSize=sizeof(IDTo); else dwSize=0; if(pIn->dwSizeImageInfo==sizeof(IDFromImgInfo)) dwSizeImageInfo=sizeof(IDToImgInfo); else dwSizeImageInfo=0; //dwcViews=pIn->dwcViews; //dwcButtons=pIn->dwcButtons; //dwcAxes=pIn->dwcAxes; dwBufferSize=(pIn->dwBufferSize/ sizeof(IDFromImgInfo))*sizeof(IDToImgInfo); dwBufferUsed=(pIn->dwBufferUsed/ sizeof(IDFromImgInfo))*sizeof(IDToImgInfo); if(dwBufferSize&&pIn->lprgImageInfoArray) { lprgImageInfoArray=(IDToImgInfo*)new char[dwBufferSize]; //PREFIX #171787 new does not return NULL. Instead, exception is thrown and //handled properly inside of catch block. memset(lprgImageInfoArray,0,dwBufferSize); for(int i=0;i<(dwBufferSize/sizeof(IDToImgInfo));i++) { //PREFIX #34520 I do not see how m_pIDFrom or m_pIDFrom->lprgImageInfoArray //can be NULL at this point. if(!m_bGet) { TrDIDEVICEIMAGEINFO( &m_pIDFrom->lprgImageInfoArray[i], &lprgImageInfoArray[i]); } } } m_pIDTo=(IDTo*)this; } }; ~CTrDIDEVICEIMAGEINFOHEADER() { if(m_pIDFrom) { m_pIDFrom->dwcViews=dwcViews; //m_pIDFrom->dwcButtons=dwcButtons; //m_pIDFrom->dwcAxes=dwcAxes; m_pIDFrom->dwBufferUsed=(dwBufferUsed/ sizeof(IDToImgInfo))*sizeof(IDFromImgInfo); if(m_pIDFrom->dwBufferSize) { for(int i=0;i<(dwBufferSize/sizeof(IDToImgInfo));i++) { if(m_bGet) { TrDIDEVICEIMAGEINFO(&lprgImageInfoArray[i], &m_pIDFrom->lprgImageInfoArray[i]); } } } delete lprgImageInfoArray; lprgImageInfoArray=NULL; } }; operator IDTo*(){return m_pIDTo;}; }; /* template class CDIAFAUBase { protected: Str m_ApplicationName; ActionFormat *m_pDIAF; ActionFormat m_DIAF; Action* m_lpDIA; Str *m_pA2U; public: CDIAFAUBase() { m_pDIAF=NULL; m_lpDIA=NULL; m_pA2U=NULL; }; ~CDIAFAUBase() { delete[] m_lpDIA; delete[] m_pA2U; }; operator ActionFormat*(){return m_pDIAF;}; }; template class CDIAFAU: public CDIAFAUBase { public: CDIAFAU(ActionFormatFrom lpDiActionFormat) { if(!lpDiActionFormat)return; memcpy(&m_DIAF,lpDiActionFormat,sizeof(m_DIAF)); m_ApplicationName.Set(lpDiActionFormat->lptszActionMap); m_DIAF.lptszActionMap=m_ApplicationName; if(!(m_DIAF.dwNumActions&&m_DIAF.rgoAction))return; m_lpDIA=new Action[m_DIAF.dwNumActions]; m_DIAF.rgoAction=m_lpDIA; m_pA2U=new Str[m_DIAF.dwNumActions]; for(DWORD i=0;irgoAction[i], sizeof(m_lpDIA[i])); m_pA2U[i].Set(lpDiActionFormat->rgoAction[i].lptszActionName); m_lpDIA[i].lptszActionName=m_pA2U[i]; } m_pDIAF=&m_DIAF; }; }; */ #define STARTTR try{ #define ENDTR }catch(MapException E){return E.GetResult();}\ catch(exception){return E_OUTOFMEMORY;} #ifdef UNICODE #define U2A(P) P #define DIAFU2A(P) P #define IDW(P) P typedef C2 CA2U; #define A2U(P) CA2U(P) #define STARTTRA STARTTR #define ENDTRA ENDTR #define STARTTRW #define ENDTRW //DIACTIONFORMAT translation typedef CTrDIACTIONFORMAT CDIACTIONFORMAT; #define AFA(P) CDIACTIONFORMAT(P) #define AFW(P) P //DIDEVICEIMAGEINFOHEADER translation typedef CTrDIDEVICEIMAGEINFOHEADER CDIDEVICEIMAGEINFOHEADER; #define DIIHA(P) CDIDEVICEIMAGEINFOHEADER(P) #define DIIHW(P) P #define SETDIIHA(P) CDIDEVICEIMAGEINFOHEADER(P,false) #define SETDIIHW(P) P #else //ANSI #define A2U(P) P #define DIAFA2U(P) P #define IDA(P) P typedef C2 CU2A; #define U2A(P) CU2A(P) #define STARTTRA #define ENDTRA #define STARTTRW STARTTR #define ENDTRW ENDTR //DIACTIONFORMAT translation typedef CTrDIACTIONFORMAT CDIACTIONFORMAT; #define AFA(P) P #define AFW(P) CDIACTIONFORMAT(P) //DIDEVICEIMAGEINFOHEADER translation typedef CTrDIDEVICEIMAGEINFOHEADER CDIDEVICEIMAGEINFOHEADER; #define DIIHA(P) P #define DIIHW(P) CDIDEVICEIMAGEINFOHEADER(P) #define SETDIIHA(P) P #define SETDIIHW(P) CDIDEVICEIMAGEINFOHEADER(P,false) #endif //ANSI /****************************************************************************** * * ANSI/UNICODE parameter translation * *****************************************************************************/ HRESULT STDMETHODCALLTYPE IDirectInputMapperTrA:: Initialize( LPCGUID lpThisGUIDInstance, LPCSTR lpcstrFileName, DWORD dwFlags) { STARTTRA return InitializeI(lpThisGUIDInstance,A2U(lpcstrFileName),dwFlags); ENDTRA } HRESULT STDMETHODCALLTYPE IDirectInputMapperTrA:: GetActionMap( LPDIACTIONFORMATA lpDiActionFormat, LPCSTR lpcstrUserName, FILETIME *pTimestamp,DWORD dwFlags) { STARTTRA return GetActionMapI(AFA(lpDiActionFormat),A2U(lpcstrUserName), pTimestamp,dwFlags); ENDTRA } HRESULT STDMETHODCALLTYPE IDirectInputMapperTrA:: SaveActionMap( LPDIACTIONFORMATA lpDiActionFormat, LPCSTR lpcstrUserName, DWORD dwFlags) { STARTTRA return SaveActionMapI(AFA(lpDiActionFormat),A2U(lpcstrUserName), dwFlags); ENDTRA } HRESULT STDMETHODCALLTYPE IDirectInputMapperTrA:: GetImageInfo( LPDIDEVICEIMAGEINFOHEADERA lpdiDevImageInfoHeader) { STARTTRA return GetImageInfoI(DIIHA(lpdiDevImageInfoHeader)); ENDTRA } HRESULT STDMETHODCALLTYPE IDirectInputMapperTrA:: WriteVendorFile( LPDIACTIONFORMATA lpDiActionFormat, LPDIDEVICEIMAGEINFOHEADERA lpdiDevImageInfoHeader, DWORD dwFlags) { STARTTRA return WriteVendorFileI(AFA(lpDiActionFormat), SETDIIHA(lpdiDevImageInfoHeader),dwFlags); ENDTRA } HRESULT STDMETHODCALLTYPE IDirectInputMapperTrW:: Initialize( LPCGUID lpThisGUIDInstance, LPCWSTR lpcwstrFileName, DWORD dwFlags) { STARTTRA return InitializeI(lpThisGUIDInstance,U2A(lpcwstrFileName),dwFlags); ENDTRA } HRESULT STDMETHODCALLTYPE IDirectInputMapperTrW:: GetActionMap( LPDIACTIONFORMATW lpDiActionFormat, LPCWSTR lpcwstrUserName, FILETIME *pTimestamp,DWORD dwFlags) { STARTTRW return GetActionMapI(AFW(lpDiActionFormat),U2A(lpcwstrUserName), pTimestamp,dwFlags); ENDTRW } HRESULT STDMETHODCALLTYPE IDirectInputMapperTrW:: SaveActionMap( LPDIACTIONFORMATW lpDiActionFormat, LPCWSTR lpcwstrUserName, DWORD dwFlags) { STARTTRW return SaveActionMapI(AFW(lpDiActionFormat),U2A(lpcwstrUserName), dwFlags); ENDTRW } HRESULT STDMETHODCALLTYPE IDirectInputMapperTrW:: GetImageInfo( LPDIDEVICEIMAGEINFOHEADERW lpdiDevImageInfoHeader) { STARTTRW return GetImageInfoI(DIIHW(lpdiDevImageInfoHeader)); ENDTRW } HRESULT STDMETHODCALLTYPE IDirectInputMapperTrW:: WriteVendorFile( LPDIACTIONFORMATW lpDiActionFormat, LPDIDEVICEIMAGEINFOHEADERW lpdiDevImageInfoHeader, DWORD dwFlags) { STARTTRW return WriteVendorFileI(AFW(lpDiActionFormat), SETDIIHW(lpdiDevImageInfoHeader),dwFlags); ENDTRW } /****************************************************************************** * * Mapper object implementation * *****************************************************************************/ BOOL CALLBACK DIEnumDeviceObjectsProcC(LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pvRef) { //Read offset, usage page, usage and name and store into private list DEVICEOBJLIST *pDevObjList=&(((CDIMapObj*)pvRef)->m_DevObjList); DeviceObjData D; /* We decided to use dwType (ObjID) instead of dwOffset. This place and exports are the only places where this data enters into the module so there should not be problem. Latter rename the code from dwOffset. Also, it is valid to use 0xffffffff value of dwType for special purposes. */ //D.dwOffset=lpddoi->dwOfs; D.dwOffset=lpddoi->dwType; D.dwUsage=lpddoi->wUsage; D.dwUsagePage=lpddoi->wUsagePage; D.dwType=lpddoi->dwType; D.dwFlags=lpddoi->dwFlags; D.Name=lpddoi->tszName; ToUpper(D.Name); pDevObjList->push_back(D); return DIENUM_CONTINUE; } void MakeGenreName(String &S,LPCTSTR lpDeviceName, DWORD dwGenre,LPCGUID lpAppGUID=NULL) { S=lpDeviceName; S+=_T("."); //If application genre if(lpAppGUID) { S=S+APPLICATION+_T(".")+GUID2String(*lpAppGUID)+_T("."); } S=S+GENRE+_T(".")+N2Str(DISEM_GENRE_GET(dwGenre)); DUMPN(_T("Genre section name"),S); } bool CompareTypeObjAct(DWORD dwObjType,DWORD dwActType) { if((dwObjType&DIDFT_AXIS)&& (DISEM_TYPE_GET(dwActType)==DISEM_TYPE_GET(DISEM_TYPE_AXIS))) return true; if((dwObjType&DIDFT_BUTTON)&& (DISEM_TYPE_GET(dwActType)==DISEM_TYPE_GET(DISEM_TYPE_BUTTON))) return true; if((dwObjType&DIDFT_POV)&& (DISEM_TYPE_GET(dwActType)==DISEM_TYPE_GET(DISEM_TYPE_POV))) return true; return false; } bool CDIMapObj::CompareData(DeviceObjData &DOD,ControlData &CD) { if(IsVIDPID()) { //Assume for now that the DOD.dwOffset and DOD.dwType fields are //both always set as they are actually the same thing //under W2K. If this isn't the case we need to work out //which one to check against CD.dwOffset #ifdef _CHECKED if (DOD.dwOffset!=DOD.dwType) DUMP(_T("CDIMapObj::CompareData. Problem - DeviceObjData has differing dwOffset and dwType fields should not differ!")); #endif if((DOD.dwUsagePage==CD.dwUsagePage)&& (DOD.dwUsage==CD.dwUsage) && (DIDFT_FINDMASK&DOD.dwOffset)==(DIDFT_FINDMASK&CD.dwOffset)) //Device object found return true; } else { //Ignore FF bits since some drivers do not report properly. //Also, this way same ini file can be used for both FF and //non-FF device. if((DIDFT_FINDMASK&DOD.dwOffset)==(DIDFT_FINDMASK&CD.dwOffset)) //Device object found return true; } return false; } bool CDIMapObj::GetOffset(ControlData &CD, DEVICEOBJLIST &DevObjList,DWORD dwSemantic, DEVICEOBJLIST::iterator &DevObjItOut) { METHOD_ENTRY(GetOffset); bool bFoundDevice=false; //Find DI device object with usage/usage page or name DEVICEOBJLIST::iterator DevObjIt; for(DevObjIt=DevObjList.begin();DevObjIt!=DevObjList.end();DevObjIt++) { if(CompareData(*DevObjIt,CD)) { bFoundDevice=true; if(CompareTypeObjAct(DevObjIt->dwType,dwSemantic)&& !(DevObjIt->bMapped)) { DevObjItOut=DevObjIt; return true; } } } if(!bFoundDevice) { TRACE(_T("Control with filename '%s' does not exist in device.\n"), CD.ControlName.data()); throw MAP_EXCEPTION(E_DEVICE_MISSING_CONTROL); } return false; } /*This three functions TBD*/ //Use when writing DWORD GetFileSemantic(DWORD dwSemantic,DWORD dwHow) { if(dwHow==DIAH_USERCONFIG) return dwSemantic; return DISEM_INDEX_SET(DISEM_INDEX_GET(dwSemantic)); } //Use to get value from file DWORD GetCmpFileGenreSemantic(DWORD dwSemantic,DWORD dwHow,DWORD dwGenre) { if(dwHow==DIAH_USERCONFIG) return dwSemantic; return DISEM_INDEX_SET(DISEM_INDEX_GET(dwSemantic))| DISEM_GENRE_SET(DISEM_GENRE_GET(dwGenre)); } //Use to get value from action array DWORD GetCmpActionGenreSemantic(DWORD dwSemantic,DWORD dwHow) { if(dwHow==DIAH_USERCONFIG) return dwSemantic; return DISEM_INDEX_SET(DISEM_INDEX_GET(dwSemantic))| DISEM_GENRE_SET(DISEM_GENRE_GET(dwSemantic)); } /**/ void WhichDeviceObjectIsMapped(LPDIACTIONFORMAT lpDiActionFormat, DEVICEOBJLIST &DevObjList, LPCGUID lpThisGUIDInstance) { DEVICEOBJLIST::iterator DevObjIt; for(DevObjIt=DevObjList.begin();DevObjIt!=DevObjList.end();DevObjIt++) { DevObjIt->bMapped=false; for(DWORD i=0;idwNumActions;i++) { if((lpDiActionFormat->rgoAction[i].guidInstance!= *lpThisGUIDInstance)|| (lpDiActionFormat->rgoAction[i].dwHow==DIAH_UNMAPPED)|| ((DIDFT_FINDMASK&lpDiActionFormat->rgoAction[i].dwObjID)!= (DIDFT_FINDMASK&DevObjIt->dwOffset))) continue; else { DevObjIt->bMapped=true; break; } } } } void CDIMapObj::MapGenre(LPDIACTIONFORMAT lpDiActionFormat, CONTROLLIST &ControlsData, LPCTSTR lpGenreName,LPCTSTR lpFileName, LPCGUID lpThisGUIDInstance, DEVICEOBJLIST &DevObjList,DWORD dwHow, DWORD &dwNOfMappedActions) { METHOD_ENTRY(MapGenre); //For all file control names, read the genre action mapping CONTROLLIST::iterator CtrlIt; for(CtrlIt=ControlsData.begin();CtrlIt!=ControlsData.end();CtrlIt++) { DWORD dwAction=GetPrivateProfileInt(lpGenreName, CtrlIt->ControlName.data(),RESERVED_ACTION,lpFileName); CtrlIt->dwAction=dwAction; } //Find actions which are not mapped yet TRACE(_T("Iterate through action array and controls in ini file.\n")); for(DWORD i=0;idwNumActions;i++) { if(((lpDiActionFormat->rgoAction[i].guidInstance!=NULLGUID) &&(lpDiActionFormat->rgoAction[i].guidInstance!=*lpThisGUIDInstance))|| (lpDiActionFormat->rgoAction[i].dwFlags&DIA_APPNOMAP)|| (lpDiActionFormat->rgoAction[i].dwHow!=DIAH_UNMAPPED)) continue; //Find control which maps to this action for(CtrlIt=ControlsData.begin();CtrlIt!=ControlsData.end();CtrlIt++) { if(GetCmpFileGenreSemantic(CtrlIt->dwAction,dwHow, lpDiActionFormat->dwGenre)== GetCmpActionGenreSemantic( lpDiActionFormat->rgoAction[i].dwSemantic,dwHow)) { //Find offset and initialize it in the action structure DEVICEOBJLIST::iterator DevObjIt; if(GetOffset(*CtrlIt,DevObjList, lpDiActionFormat->rgoAction[i].dwSemantic,DevObjIt)) { if((lpDiActionFormat->rgoAction[i].dwFlags& DIA_FORCEFEEDBACK)&& !((DevObjIt->dwFlags&DIDOI_FFEFFECTTRIGGER)|| (DevObjIt->dwFlags&DIDOI_FFACTUATOR))) { TRACE(_T("Action array %u has DIA_FORCEFEEDBACK set but devobj \ does not have DIDOI_FFEFFECTTRIGGER or DIDOI_FFACTUATOR set. Not mapped.\n"),i); continue; } TRACE(_T("Action array %u mapped to ini file \ control and devobj with dwObjID 0x%x\n"),i,DevObjIt->dwOffset); lpDiActionFormat->rgoAction[i].dwObjID=DevObjIt->dwOffset; DevObjIt->bMapped=true; dwNOfMappedActions++; lpDiActionFormat->rgoAction[i].guidInstance= *lpThisGUIDInstance; lpDiActionFormat->rgoAction[i].dwHow=dwHow; break; } else { TRACE(_T("Action array %u related to ini file \ control but devobj not found. Not mapping.\n"),i); } } } } } void WriteTimestamp(LPCTSTR lpFileName,LPCTSTR lpDeviceName, GUID &AppGUID,LPDIACTIONFORMAT lpDiActionFormat) { String S,SH,SL; S=GUID2String(AppGUID)+_T("."); SH=S+TIMESTAMPHIGH; SL=S+TIMESTAMPLOW; FILETIME T; if((lpDiActionFormat->ftTimeStamp.dwLowDateTime==DIAFTS_NEWDEVICELOW)&& (lpDiActionFormat->ftTimeStamp.dwHighDateTime==DIAFTS_NEWDEVICEHIGH)) { T.dwHighDateTime=DIAFTS_UNUSEDDEVICEHIGH; T.dwLowDateTime=DIAFTS_UNUSEDDEVICELOW; } else { GetSystemTimeAsFileTime(&T); } WritePrivateProfileIntX(lpDeviceName,SH.data(), T.dwHighDateTime,lpFileName); WritePrivateProfileIntX(lpDeviceName,SL.data(), T.dwLowDateTime,lpFileName); } void ReadTimestamp(FILETIME &T,LPCTSTR lpFileName, LPCTSTR lpDeviceName,GUID &AppGUID) { String S,SH,SL; S=GUID2String(AppGUID)+_T("."); SH=S+TIMESTAMPHIGH; SL=S+TIMESTAMPLOW; T.dwHighDateTime=GetPrivateProfileInt(lpDeviceName,SH.data(), DIAFTS_NEWDEVICELOW,lpFileName); T.dwLowDateTime=GetPrivateProfileInt(lpDeviceName,SL.data(), DIAFTS_NEWDEVICEHIGH,lpFileName); } #ifdef _CHECKED int CDIMapObj::m_DeviceCount=0; #endif CDIMapObj::CDIMapObj() { #ifdef _CHECKED m_DeviceNo=m_DeviceCount++; #endif m_ulRefCnt=0; Clear(); } void CDIMapObj::Clear() { //m_ulRefCnt must not be set here, only in constructor bool m_bInitialized=false; m_dwThisVendorID=0; m_dwThisProductID=0; m_DeviceName=_T(""); memset(&m_DeviceGuid,0,sizeof(m_DeviceGuid)); //Vendor file name data m_VFileName=_T(""); m_lpVFileName=NULL; m_VFileDevName=_T(""); m_VCtrlData.clear(); m_bVLoaded=false; //User file name data m_UName=_T(""); m_lpUName=NULL; m_UFileName=_T(""); m_UserDir=_T(""); m_UFileDevName=_T(""); m_UCtrlData.clear(); m_bULoaded=false; m_UTimestamp.dwHighDateTime=0; m_UTimestamp.dwLowDateTime=0; m_bImageBufferSize=false; m_dwImageBufferSize=0; } CDIMapObj::~CDIMapObj() { } void CDIMapObj::LoadFileData(LPCTSTR lpFileName,LPCTSTR lpThisName, DWORD dwThisVendorID,DWORD dwThisProductID, String &FileDeviceName,CONTROLLIST &ControlsData, bool &bLoaded,FILETIME *pT, LPDIACTIONFORMAT lpDiActionFormat) { METHOD_ENTRY(LoadFileData); DUMPN(_T("Filename"),lpFileName); bLoaded=false; FileDeviceName=_T(""); ControlsData.clear(); //Clear DevObj pointers to controls for(DEVICEOBJLIST::iterator DevObjIt=m_DevObjList.begin();DevObjIt!= m_DevObjList.end();DevObjIt++) { if(&ControlsData==&m_UCtrlData) DevObjIt->pUCtrlData=NULL; else DevObjIt->pVCtrlData=NULL; } if(pT) { pT->dwLowDateTime=DIAFTS_NEWDEVICELOW; pT->dwHighDateTime=DIAFTS_NEWDEVICEHIGH; } //Read file version and choose file parser DWORD dwVersion=GetPrivateProfileInt(DIRECT_INPUT,DIRECTX_VERSION, RESERVED_DX_VER,lpFileName); if(dwVersion==0x800) { //Load all file device names STRINGLIST Devices; LoadListOfStrings(lpFileName,DIRECT_INPUT,DEVICES,Devices); BOOL bDeviceFound=FALSE; //Iterate through all file device names STRINGLIST::iterator DevIt=Devices.begin(); while(DevIt!=Devices.end()) { String DeviceName=(*DevIt); DUMPN(_T("Trying to match device with ini file name"), DeviceName); //Read VID, PID and type name. String NameCur; DWORD dwVendorIDCur=GetPrivateProfileInt(DeviceName.data(), VENDORID,RESERVED_VENDORID,lpFileName); DWORD dwProductIDCur=GetPrivateProfileInt(DeviceName.data(), PRODUCTID,RESERVED_PRODUCTID,lpFileName); LoadString(NameCur,lpFileName,DeviceName.data(),NAME); if((IsVIDPID()&& ((dwVendorIDCur==dwThisVendorID)&& (dwProductIDCur==dwThisProductID)))|| ((!IsVIDPID())&& (NameCur==lpThisName))) { TRACE(_T("Device found in ini file!\n")); //Definition of a device is found in the file bDeviceFound=TRUE; FileDeviceName=DeviceName; if(pT&&lpDiActionFormat) ReadTimestamp(*pT,lpFileName,FileDeviceName.data(), lpDiActionFormat->guidActionMap); //Load all file control names STRINGLIST Controls; LoadListOfStrings(lpFileName,DeviceName.data(),CONTROLS, Controls,true); //Iterate through all file control names for this device STRINGLIST::iterator CtrlIt=Controls.begin(); while(CtrlIt!=Controls.end()) { DUMPN(_T("Read control data with ini file name"), CtrlIt->data()); String ControlSectionName=*CtrlIt; ControlData ControlDataCur; ControlDataCur.pDevObj=NULL; ControlDataCur.ControlName=*CtrlIt; ControlDataCur.dwOffset=RESERVED_OFFSET; ControlDataCur.dwUsagePage=RESERVED_USAGEPAGE; ControlDataCur.dwUsage=RESERVED_USAGE; //Read offset, Usage and UsagePage for a file control name ControlDataCur.dwOffset= GetPrivateProfileInt(ControlSectionName.data(), OFFSET,RESERVED_OFFSET,lpFileName); ControlDataCur.dwUsage= GetPrivateProfileInt(ControlSectionName.data(), USAGE,RESERVED_USAGE,lpFileName); ControlDataCur.dwUsagePage= GetPrivateProfileInt( ControlSectionName.data(), USAGEPAGE,RESERVED_USAGEPAGE, lpFileName); // LoadString(ControlDataCur.Name,lpFileName, // ControlSectionName.data(),NAME); #ifdef STRICT_DEV_DEF //Store data for this control into the list ControlsData.push_back(ControlDataCur); #endif STRICT_DEV_DEF //Here bind device obj and control data //Find DI device object with usage/usage page or name for(DEVICEOBJLIST::iterator DevObjIt=m_DevObjList.begin(); DevObjIt!=m_DevObjList.end();DevObjIt++) { if(CompareData(*DevObjIt,ControlDataCur)) { #ifndef STRICT_DEV_DEF //Store data for this control into the list ControlsData.push_back(ControlDataCur); #endif STRICT_DEV_DEF ControlsData.back().pDevObj=&(*DevObjIt); if(&ControlsData==&m_UCtrlData) DevObjIt->pUCtrlData=&ControlsData.back(); else DevObjIt->pVCtrlData=&ControlsData.back(); } } #ifdef STRICT_DEV_DEF if(!ControlsData.back().pDevObj) { TRACE(_T("Could not match control in file with device object.\n")); throw MAP_EXCEPTION(E_DEVICE_MISSING_CONTROL); } #endif STRICT_DEV_DEF CtrlIt++; } break; } DevIt++; } if(!bDeviceFound) { TRACE(_T("Device description not present in this file!!!!!!!!!!!!!\n")); //throw MAP_EXCEPTION(E_DEVICE_NOT_FOUND); Currently this is legal } else { TRACE(_T("Device data loaded from ini file.\n")); bLoaded=true; } } else if(dwVersion!=RESERVED_DX_VER) { TRACE(_T("Bad file version\n")); throw MAP_EXCEPTION(E_BAD_VERSION); } else { TRACE(_T("File not found, or no version info. Continuing...\n")); } } void CDIMapObj::LoadUserData(LPCTSTR lpctstrUserName, LPDIACTIONFORMAT lpDiActionFormat, bool bForceReload/*=false*/,bool bCreateDir/*=false*/) { METHOD_ENTRY(LoadUserData); String UserName; if(bForceReload) lpctstrUserName=m_lpUName; if(lpctstrUserName) UserName=lpctstrUserName; if((m_UFileName==_T(""))||//first run (UserName!=m_UName)||//different user name bForceReload) { TRACE(_T("First run or new user or forced reload of user data.\n")); m_UName=_T(""); m_lpUName=NULL; m_UFileName=_T(""); m_UserDir=_T(""); m_UFileDevName=_T(""); m_UCtrlData.clear(); m_bULoaded=false; m_UTimestamp.dwHighDateTime; m_UTimestamp.dwLowDateTime; if(lpctstrUserName)//just used as logic operation { m_UName=UserName; m_lpUName=m_UName.data(); } TCHAR lpctstrUserFileName[_MAX_PATH]; GetMapFileName(m_UName.data(),m_DeviceName.data(), m_nDeviceInstanceNo, lpctstrUserFileName,false,&m_UserDir); m_UFileName=lpctstrUserFileName; DUMPN(_T("User File Name"),lpctstrUserFileName); LoadFileData(m_UFileName.data(),m_DeviceName.data(), m_dwThisVendorID,m_dwThisProductID,m_UFileDevName,m_UCtrlData, m_bULoaded,&m_UTimestamp,lpDiActionFormat); } if(bCreateDir) { TCHAR lpctstrUserFileName[_MAX_PATH]; GetMapFileName(m_UName.data(),m_DeviceName.data(), m_nDeviceInstanceNo, lpctstrUserFileName,true,&m_UserDir); } } BOOL CALLBACK DIEnumDevicesProc( const DIDEVICEINSTANCE * lpddi,LPVOID pvRef) { DEVCNT *pDevCnt=(DEVCNT*)pvRef; if(!memcmp(&lpddi->guidProduct, &pDevCnt->pDIDI->guidProduct, sizeof(lpddi->guidProduct))) { if(0guidInstance, &pDevCnt->pDIDI->guidInstance, sizeof(lpddi->guidInstance))) (*(pDevCnt->m_pnCnt))++; } return DIENUM_CONTINUE; } HRESULT CDIMapObj::InitializeI( LPCGUID lpThisGUIDInstance, LPCTSTR lpctstrFileName, DWORD dwFlags) { try { INITIALIZE_ENTERED; TRACE(_T("Parameters:\n")); DUMP(lpThisGUIDInstance); DUMP(lpctstrFileName); TRACE(_T("\n")); //Check parameters //Check guid pointer if(!lpThisGUIDInstance) { TRACE(_T("lpThisGUIDInstance is NULL\n")); throw MAP_EXCEPTION(E_INVALIDARG); } HRESULT hRes=S_OK; Clear(); m_DeviceGuid=*lpThisGUIDInstance; //Create DInput device and get info LPDIRECTINPUT_AR lpDI; HMODULE hM=GetModuleHandle(NULL); if(!hM) { TRACE(_T("ERROR, GetModuleHandle failed\n")); throw MAP_EXCEPTION(E_FAIL); } hRes=DirectInput8Create(hM, DIRECTINPUT_VERSION, IID_IDirectInput8, lpDI.Addr(),NULL); if(FAILED(hRes)) { TRACE(_T("ERROR, DirectInput8Create failed\n")); throw MAP_EXCEPTION(hRes); } LPDIRECTINPUTDEVICE_AR lpDID; hRes=lpDI.P()->CreateDevice(*lpThisGUIDInstance,lpDID,NULL); if(FAILED(hRes)) { TRACE(_T("ERROR, CreateDeviceEx failed\n")); throw MAP_EXCEPTION(hRes); } DIDEVICEINSTANCE DIDI; DIDI.dwSize=sizeof(DIDI); hRes=lpDID.P()->GetDeviceInfo(&DIDI); if(FAILED(hRes)) { TRACE(_T("ERROR, GetDeviceInfo failed\n")); throw MAP_EXCEPTION(hRes); } //find device instance number m_nDeviceInstanceNo=0; DEVCNT DevCnt; DevCnt.m_pnCnt=&m_nDeviceInstanceNo; DevCnt.pDIDI=&DIDI; if(DI_OK!=lpDI.P()->EnumDevices (0,DIEnumDevicesProc,&DevCnt,DIEDFL_ATTACHEDONLY)) { TRACE(_T("ERROR, EnumDevices failed\n")); throw MAP_EXCEPTION(hRes); } DUMP(m_nDeviceInstanceNo); // Code block added by MarcAnd { DIPROPDWORD dipdw; dipdw.diph.dwSize = sizeof( dipdw ); dipdw.diph.dwHeaderSize = sizeof( dipdw.diph ); dipdw.diph.dwObj = 0; dipdw.diph.dwHow = DIPH_DEVICE; if(FAILED(lpDID.P()->GetProperty(DIPROP_VIDPID,&dipdw.diph))) { m_dwThisVendorID=0; m_dwThisProductID=0; } else { m_dwThisVendorID=LOWORD( dipdw.dwData ); m_dwThisProductID=HIWORD( dipdw.dwData ); } } DUMP(m_dwThisVendorID); DUMP(m_dwThisProductID); DIPROPSTRING dipwsz; dipwsz.diph.dwSize=sizeof(dipwsz); dipwsz.diph.dwHeaderSize=sizeof(dipwsz.diph); dipwsz.diph.dwObj=0; dipwsz.diph.dwHow=DIPH_DEVICE; if(FAILED(lpDID.P()->GetProperty(DIPROP_TYPENAME,&dipwsz.diph))) { //keyboard, mouse... m_DeviceName=DIDI.tszInstanceName; } else { MakeUniqueDeviceName(m_DeviceName,dipwsz.wsz); } ToUpper(m_DeviceName); DUMP(DIDI.tszInstanceName); DUMP(m_DeviceName); //Enumerate DI device objects and get info. //Must go before LoadFileData file control data //can be binded to object data hRes=lpDID.P()->EnumObjects(DIEnumDeviceObjectsProcC,this, DIDFT_AXIS|DIDFT_BUTTON|DIDFT_POV); if(FAILED(hRes)) { TRACE(_T("ERROR, EnumObjects failed\n")); throw MAP_EXCEPTION(hRes); } if(!m_DevObjList.size()) { TRACE(_T("ERROR, No dev objects found\n")); throw MAP_EXCEPTION(E_DEV_OBJ_NOT_FOUND); } DUMP(m_DevObjList); m_lpVFileName=NULL; if(lpctstrFileName) { m_VFileName=lpctstrFileName; m_lpVFileName=m_VFileName.data(); LoadFileData(m_lpVFileName,m_DeviceName.data(),m_dwThisVendorID, m_dwThisProductID,m_VFileDevName, m_VCtrlData,m_bVLoaded,NULL,NULL); } m_bInitialized=true; TRACE(_T("hRes=0x%x\n"),S_OK); return S_OK; } catch(MapException E) { return E.GetResult(); } catch(exception) { USETRACER(); TRACE(_T("Internal error, hRes=0x%x\n"),E_FAIL); return E_FAIL; } } ULONG STDMETHODCALLTYPE CDIMapObj::Release() { m_ulRefCnt--; if(m_ulRefCnt)return m_ulRefCnt; delete this; DllRelease(); return 0; } HRESULT STDMETHODCALLTYPE CDIMapObj::QueryInterface(REFIID riid, LPVOID * ppvOut) { if(IsEqualIID(riid,IID_IDirectInputMapIW)) { AddRef(); *ppvOut=(IDirectInputMapperW*)this; return S_OK; } else if(IsEqualIID(riid,IID_IDirectInputMapIA)) { AddRef(); *ppvOut=(IDirectInputMapperA*)this; return S_OK; } else if(IsEqualIID(riid,IID_IUnknown)) { AddRef(); *ppvOut=(IUnknown*)(IDirectInputMapperA*)this; return S_OK; } else if(IsEqualIID(riid,IID_IDirectInputMapVendorIW)) { AddRef(); *ppvOut=(IDirectInputMapperVendorW*)this; return S_OK; } else if(IsEqualIID(riid,IID_IDirectInputMapVendorIA)) { AddRef(); *ppvOut=(IDirectInputMapperVendorA*)this; return S_OK; } *ppvOut = 0; return E_NOINTERFACE; } void CDIMapObj::MapDevice(LPDIACTIONFORMAT lpDiActionFormat, LPCTSTR lpFileName, LPCTSTR lpFileDevName,LPCGUID lpThisGUIDInstance, DEVICEOBJLIST &DevObjList,CONTROLLIST &ControlsData, DWORD dwHow,DWORD dwHowApp,DWORD &dwNOfMappedActions, bool *pbMapExists,bool bUserFile) { METHOD_ENTRY(MapDevice); DUMPN(_T("Filename"),lpFileName); DUMPN(_T("Device name file"),lpFileDevName); //Map genre overrides for a particular game String ApplicationGenreName; MakeGenreName(ApplicationGenreName,lpFileDevName, lpDiActionFormat->dwGenre, &lpDiActionFormat->guidActionMap); if(GetPrivateProfileInt(ApplicationGenreName.data(), MAPEXISTS,0,lpFileName)) { if(pbMapExists) { *pbMapExists=true; } if(lpDiActionFormat->dwNumActions!= GetPrivateProfileInt( ApplicationGenreName.data(),NUMACTIONS, -1,lpFileName)) { TRACEI(_T("WARNING! Action map changed!\n")); TRACEI(_T("File name=%s\n"),lpFileName); TRACEI(_T("Genre section name=%s\n"),ApplicationGenreName.data()); } } TRACE(_T("Process application specific genre.\n")); DUMPN(_T("Section name"),ApplicationGenreName.data()); MapGenre(lpDiActionFormat,ControlsData, ApplicationGenreName.data(),lpFileName,lpThisGUIDInstance, DevObjList,dwHowApp,dwNOfMappedActions); //Map remainder of semantics of a genre if(!bUserFile)//only app. specific maps in user file { String GenreName; MakeGenreName(GenreName,lpFileDevName, lpDiActionFormat->dwGenre); if(pbMapExists) { if(GetPrivateProfileInt(GenreName.data(), MAPEXISTS,0,lpFileName)) *pbMapExists=true; } TRACE(_T("Process genre.\n")); DUMPN(_T("Section name"),GenreName.data()); MapGenre(lpDiActionFormat,ControlsData,GenreName.data(), lpFileName,lpThisGUIDInstance,DevObjList, dwHow,dwNOfMappedActions); } } bool IsImageInfoFull(DIDEVICEIMAGEINFOHEADER *lpdiDevImageInfoHeader, DWORD dwImages) { if((lpdiDevImageInfoHeader->dwBufferSize!=0)&& (((dwImages+1)*sizeof(DIDEVICEIMAGEINFO))> lpdiDevImageInfoHeader->dwBufferSize)) return true; return false; } DIDEVICEIMAGEINFO *GetImageInfoAdr( DIDEVICEIMAGEINFOHEADER *lpdiDevImageInfoHeader,DWORD dwImages) { if(lpdiDevImageInfoHeader->dwBufferSize==0) return NULL; return &lpdiDevImageInfoHeader->lprgImageInfoArray[dwImages]; } HRESULT CDIMapObj::GetImageInfoI( LPDIDEVICEIMAGEINFOHEADER lpdiDevImageInfoHeader) { try { GETIMAGEINFO_ENTERED; return GetImageInfoInternal(lpdiDevImageInfoHeader,false); } catch(MapException E) { return E.GetResult(); } catch(exception) { USETRACER(); TRACE(_T("Internal error, hRes=0x%x\n"),E_FAIL); return E_FAIL; } } HRESULT CDIMapObj::GetImageInfoInternal( LPDIDEVICEIMAGEINFOHEADER lpdiDevImageInfoHeader, bool bGettingSize) { METHOD_ENTRY(GetImageInfoInternal); TRACE(_T("Parameters:\n")); // DUMP(lpdiDevImageInfoHeader);Instead of dumping entire struct // dump only input params // 7/18/2000(a-JiTay): IA64: Use %p format specifier for 32/64-bit pointers. TRACE(_T("lpdiDevImageInfoHeader=0x%p\n"),lpdiDevImageInfoHeader); if(lpdiDevImageInfoHeader) { USETRACER(); TRACE(_T("dwSize=%u\tdwSizeImageInfo=%u\n"), (unsigned int)lpdiDevImageInfoHeader->dwSize, (unsigned int)lpdiDevImageInfoHeader->dwSizeImageInfo); TRACE(_T("dwBufferSize=%u\tdwBufferUsed=%u\n"), (unsigned int)lpdiDevImageInfoHeader->dwBufferSize, (unsigned int)lpdiDevImageInfoHeader->dwBufferUsed); // 7/18/2000(a-JiTay): IA64: Use %p format specifier for 32/64-bit pointers. TRACE(_T("lprgImageInfoArray=0x%p\n"), lpdiDevImageInfoHeader->lprgImageInfoArray); } TRACE(_T("\n")); //Check if initialized if(!m_bInitialized) { TRACE(_T("Object not initialized\n")); throw MAP_EXCEPTION(DIERR_NOTINITIALIZED); } //Check parameters if(!lpdiDevImageInfoHeader) { TRACE(_T("lpdiDevImageInfoHeader is NULL\n")); throw MAP_EXCEPTION(E_INVALIDARG); } //Check structure sizes if(lpdiDevImageInfoHeader->dwSize!=sizeof(DIDEVICEIMAGEINFOHEADER)) { TRACE(_T("lpdiDevImageInfoHeader->dwSize is wrong size\n")); throw MAP_EXCEPTION(E_INVALIDARG); } if(lpdiDevImageInfoHeader->dwBufferSize&& lpdiDevImageInfoHeader->dwSizeImageInfo!= sizeof(DIDEVICEIMAGEINFO)) { TRACE(_T("lpdiDevImageInfoHeader->dwSizeImageInfo is wrong size\n")); throw MAP_EXCEPTION(E_INVALIDARG); } //Check buffer size if(lpdiDevImageInfoHeader->dwBufferSize&& !lpdiDevImageInfoHeader->lprgImageInfoArray) { TRACE(_T("lpdiDevImageInfoHeader->\ dwBufferSize is not 0 and lpdiDevImageInfoHeader->\ lprgImageInfo is NULL\n")); throw MAP_EXCEPTION(E_INVALIDARG); } DUMPN(_T("Vendor filename"),m_VFileName); DUMPN(_T("Device name in vendor file"),m_VFileDevName); HRESULT hRes=S_OK; if((!m_bImageBufferSize)&&(!bGettingSize)&& lpdiDevImageInfoHeader->dwBufferSize) { TRACE(_T("User forgot to inquire about buffer size.\n")); DIDEVICEIMAGEINFOHEADER DIIH; DIIH.dwSize=sizeof(DIIH); DIIH.dwSizeImageInfo=sizeof(DIDEVICEIMAGEINFO); DIIH.dwcViews=0; DIIH.dwcButtons=0; DIIH.dwcAxes=0; DIIH.dwcPOVs=0; DIIH.dwBufferSize=0; DIIH.dwBufferUsed=0; hRes=GetImageInfoInternal(&DIIH,true); if(hRes!=S_OK) return hRes; } //check if image info buffer is big enough if(lpdiDevImageInfoHeader->dwBufferSize&& (lpdiDevImageInfoHeader->dwBufferSize< m_dwImageBufferSize)) { TRACE(_T("lpdiDevImageInfoHeader->dwBufferSize is too small.\n")); throw MAP_EXCEPTION(DIERR_MOREDATA ); } //process configuration images TRACE(_T("Processing DIDIFT_CONFIGURATION images.\n")); lpdiDevImageInfoHeader->dwcViews=0; DWORD dwImages=0; do { if(IsImageInfoFull(lpdiDevImageInfoHeader,dwImages))break; hRes=GetImageInfo((DeviceObjData*)NULL, lpdiDevImageInfoHeader->dwcViews, GetImageInfoAdr(lpdiDevImageInfoHeader,dwImages), DIDIFT_CONFIGURATION); if(hRes==S_OK) { lpdiDevImageInfoHeader->dwcViews++; dwImages++; } } while(hRes==S_OK); #if 0 //process view select images TRACE(_T("Processing DIDIFT_VIEWSELECT images.\n")); for(int i=0;idwcViews;i++) { if(IsImageInfoFull(lpdiDevImageInfoHeader,dwImages))break; if(GetImageInfo((DeviceObjData*)NULL,i, GetImageInfoAdr(lpdiDevImageInfoHeader,dwImages), DIDIFT_VIEWSELECT)==S_OK) dwImages++; } //process device selection image TRACE(_T("Processing DIDIFT_SELECTION images.\n")); if(!IsImageInfoFull(lpdiDevImageInfoHeader,dwImages)) { if(GetImageInfo((DeviceObjData*)NULL,-1, GetImageInfoAdr(lpdiDevImageInfoHeader,dwImages), DIDIFT_SELECTION)==S_OK) dwImages++; } #endif //process control data TRACE(_T("Processing DIDIFT_OVERLAY images.\n")); DEVICEOBJLIST::iterator DevObjIt; for(DevObjIt=m_DevObjList.begin(); DevObjIt!=m_DevObjList.end();DevObjIt++) { if(IsImageInfoFull(lpdiDevImageInfoHeader,dwImages))break; for(int i=0;idwcViews;i++) { if(IsImageInfoFull(lpdiDevImageInfoHeader,dwImages))break; if(GetImageInfo(&(*DevObjIt),i, GetImageInfoAdr(lpdiDevImageInfoHeader,dwImages), DIDIFT_OVERLAY)==S_OK) dwImages++; } } lpdiDevImageInfoHeader->dwBufferUsed= dwImages*sizeof(DIDEVICEIMAGEINFO); if((!lpdiDevImageInfoHeader->dwBufferSize)&&(!m_bImageBufferSize)) { m_bImageBufferSize=true; m_dwImageBufferSize=lpdiDevImageInfoHeader->dwBufferUsed; } TRACE(_T("hRes=0x%x\n"),S_OK); DUMP(lpdiDevImageInfoHeader); return S_OK; } bool CDIMapObj:: GetImageInfoFileName(LPCTSTR lpKeyName,LPCTSTR lpSectionName, DWORD dwIndex,LPDIDEVICEIMAGEINFO lpImageInfo) { METHOD_ENTRY(GetImageInfoFileName); DUMP(lpSectionName); DUMP(lpKeyName); DUMP(dwIndex); String KeyName=lpKeyName; if(dwIndex!=-1) KeyName+=_T(".")+N2Str(dwIndex); String ImageFileName; if(lpImageInfo) lpImageInfo->tszImagePath[0]=0; if(!LoadString(ImageFileName,m_VFileName.data(), lpSectionName,KeyName.data(),true)) return false; String Dir; GetDirectory(m_VFileName.data(),Dir); Dir+=ImageFileName; if(Dir.size()> (sizeof(lpImageInfo->tszImagePath)/ sizeof(lpImageInfo->tszImagePath[0]))) { TRACE(_T("Image filename too long.\n")); throw MAP_EXCEPTION(E_FILENAME_TO_LONG); } if(lpImageInfo) _tcscpy(lpImageInfo->tszImagePath,Dir.data()); return true; } //keep flags for a while just in case we change our minds again #if 0 void CDIMapObj:: GetImageInfoFormat(LPCTSTR lpKeyName,LPCTSTR lpSectionName, DWORD dwIndex,LPDIDEVICEIMAGEINFO lpImageInfo) { if(lpImageInfo) { METHOD_ENTRY(GetImageInfoFormat); DUMP(lpSectionName); DUMP(lpKeyName); DUMP(dwIndex); String ImageFileFormatKeyName=lpKeyName; if(dwIndex!=-1) ImageFileFormatKeyName+=_T(".")+N2Str(dwIndex); String ImageFileFormat; if(!LoadString(ImageFileFormat,m_VFileName.data(), lpSectionName,ImageFileFormatKeyName.data(),true)) lpImageInfo->dwFlags|=DIDIFT_IMAGE2D_BMP; else { if(ImageFileFormat==_T("BMP")) lpImageInfo->dwFlags|=DIDIFT_IMAGE2D_BMP; else if(ImageFileFormat==_T("PNG")) lpImageInfo->dwFlags|=DIDIFT_IMAGE2D_PNG; else { TRACE(_T("Corrupt image type.\n")); throw MAP_EXCEPTION(E_CORRUPT_IMAGE_DATA); } } } } #endif bool ImageDataPresent(DWORD dwIndex,LPCTSTR pControlName, LPCTSTR pVFileName) { TCHAR Ret[2]; String VisibleKeyName; VisibleKeyName=OVERLAY_FILENAME; VisibleKeyName+=_T(".")+N2Str(dwIndex); if(GetPrivateProfileString(pControlName,VisibleKeyName.data(), _T(""),Ret,2,pVFileName)) return true; VisibleKeyName=OVERLAY_FORMAT; VisibleKeyName+=_T(".")+N2Str(dwIndex); if(GetPrivateProfileString(pControlName,VisibleKeyName.data(), _T(""),Ret,2,pVFileName)) return true; VisibleKeyName=OVERLAY_RECT; VisibleKeyName+=_T(".")+N2Str(dwIndex); if(GetPrivateProfileString(pControlName,VisibleKeyName.data(), _T(""),Ret,2,pVFileName)) return true; VisibleKeyName=CONTROL_STRING_ALIGN; VisibleKeyName+=_T(".")+N2Str(dwIndex); if(GetPrivateProfileString(pControlName,VisibleKeyName.data(), _T(""),Ret,2,pVFileName)) return true; VisibleKeyName=CALLOUTMAX; VisibleKeyName+=_T(".")+N2Str(dwIndex); if(GetPrivateProfileString(pControlName,VisibleKeyName.data(), _T(""),Ret,2,pVFileName)) return true; VisibleKeyName=LINE_DATA; VisibleKeyName+=_T(".")+N2Str(dwIndex); if(GetPrivateProfileString(pControlName,VisibleKeyName.data(), _T(""),Ret,2,pVFileName)) return true; return false; } HRESULT CDIMapObj::GetImageInfo( DeviceObjData *pDevObj, DWORD dwIndex, LPDIDEVICEIMAGEINFO lpImageInfo, DWORD dwImageType) { METHOD_ENTRY(GetImageInfo); DUMPN(_T("Image index"),dwIndex); HRESULT hRes=S_OK; //There must be vendor file when getting image data if(!m_bVLoaded) { TRACE(_T("No vendor file or error in Initialize().\n")); throw MAP_EXCEPTION(E_CORRUPT_IMAGE_DATA); } switch(dwImageType) { case DIDIFT_CONFIGURATION: if(GetImageInfoFileName(IMAGE_FILENAME,m_VFileDevName.data(), dwIndex,lpImageInfo)) { if(lpImageInfo)//we are not only counting { lpImageInfo->dwFlags=dwImageType; lpImageInfo->dwViewID=dwIndex; //keep flags for a while just in case we change our minds again #if 0 GetImageInfoFormat(IMAGE_FORMAT,m_VFileDevName.data(), dwIndex,lpImageInfo); #endif } return S_OK; } else { if(dwIndex) return S_FALSE; else { //there must be at least one device view TRACE(_T("There must be at least one device view, with index 0.\n")); throw MAP_EXCEPTION(E_CORRUPT_IMAGE_DATA); } } break; #if 0 case DIDIFT_SELECTION: if(GetImageInfoFileName(SELECTION_FILENAME,m_VFileDevName.data(), -1,lpImageInfo)) { if(lpImageInfo)//we are not only counting { lpImageInfo->dwFlags=dwImageType; //keep flags for a while just in case we change our minds again #if 0 GetImageInfoFormat(SELECTION_FORMAT,m_VFileDevName.data(), -1,lpImageInfo); #endif } return S_OK; } else return S_FALSE; break; case DIDIFT_VIEWSELECT: if(GetImageInfoFileName(VIEWSELECT_FILENAME,m_VFileDevName.data(), dwIndex,lpImageInfo)) { if(lpImageInfo)//we are not only counting { lpImageInfo->dwFlags=dwImageType; lpImageInfo->dwViewID=dwIndex; //keep flags for a while just in case we change our minds again #if 0 GetImageInfoFormat(VIEWSELECT_FORMAT,m_VFileDevName.data(), dwIndex,lpImageInfo); #endif } return S_OK; } else return S_FALSE; break; #endif case DIDIFT_OVERLAY: { //Get control section name CONTROLLIST::iterator VCtrlDataIt=m_VCtrlData.begin(); while(VCtrlDataIt!=m_VCtrlData.end()) { if(CompareData(*pDevObj,*VCtrlDataIt))break; VCtrlDataIt++; } if(VCtrlDataIt==m_VCtrlData.end()) { TRACE(_T("No control with obj ID in file.\n")); return S_FALSE;//control with offset not found } //Section=VCtrlDataIt->ControlName.data(); DUMPN(_T("Control name in ini file"),VCtrlDataIt->ControlName); //Is there ctrl image data String VisibleKeyName=CONTROL_VISIBLE; VisibleKeyName+=_T(".")+N2Str(dwIndex); if(!GetPrivateProfileInt(VCtrlDataIt->ControlName.data(), VisibleKeyName.data(),1,m_VFileName.data())) { TRACE(_T("No image data for this control.\n")); return S_FALSE;//No control data } if(!ImageDataPresent(dwIndex,VCtrlDataIt->ControlName.data(), m_VFileName.data())) { TRACE(_T("No image data for this control.\n")); return S_FALSE;//No control data } if(!lpImageInfo) return S_OK;//Just counting data... lpImageInfo->dwFlags=dwImageType; lpImageInfo->dwViewID=dwIndex; lpImageInfo->dwObjID=pDevObj->dwType; //Get overlay image data if(GetImageInfoFileName(OVERLAY_FILENAME, VCtrlDataIt->ControlName.data(),dwIndex,lpImageInfo)) { TRACE(_T("There is image file name, reading rest.\n")); //keep flags for a while just in case we change our minds again #if 0 GetImageInfoFormat(OVERLAY_FORMAT, VCtrlDataIt->ControlName.data(),dwIndex,lpImageInfo); #endif //Get overlay rect DWORD dwOverlayRectCnt; String OverlayRectKeyName=OVERLAY_RECT; OverlayRectKeyName+=_T(".")+N2Str(dwIndex); POINT OverlayRect[2]; if(LoadPointArray(m_VFileName.data(), VCtrlDataIt->ControlName.data(), OverlayRectKeyName.data(),OverlayRect, dwOverlayRectCnt,2)) { if(dwOverlayRectCnt!=2) { TRACE(_T("Corrupt overlay rect data.\n")); throw MAP_EXCEPTION(E_CORRUPT_IMAGE_DATA); } lpImageInfo->rcOverlay.left=OverlayRect[0].x; lpImageInfo->rcOverlay.top=OverlayRect[0].y; lpImageInfo->rcOverlay.right=OverlayRect[1].x; lpImageInfo->rcOverlay.bottom=OverlayRect[1].y; } else { lpImageInfo->rcOverlay.left=0; lpImageInfo->rcOverlay.top=0; lpImageInfo->rcOverlay.right=100; lpImageInfo->rcOverlay.bottom=20; } } //Get string alignment String KeyName=CONTROL_STRING_ALIGN; KeyName+=_T(".")+N2Str(dwIndex); String Align; if(!LoadString(Align,m_VFileName.data(), VCtrlDataIt->ControlName.data(),KeyName.data(),true)) lpImageInfo->dwTextAlign=DIDAL_CENTERED|DIDAL_MIDDLE; else { if(Align==_T("C")) lpImageInfo->dwTextAlign= DIDAL_CENTERED|DIDAL_MIDDLE; else if(Align==_T("L")) lpImageInfo->dwTextAlign= DIDAL_LEFTALIGNED|DIDAL_MIDDLE; else if(Align==_T("R")) lpImageInfo->dwTextAlign= DIDAL_RIGHTALIGNED|DIDAL_MIDDLE; else if(Align==_T("T")) lpImageInfo->dwTextAlign= DIDAL_CENTERED|DIDAL_TOPALIGNED; else if(Align==_T("B")) lpImageInfo->dwTextAlign= DIDAL_CENTERED|DIDAL_BOTTOMALIGNED; else if(Align==_T("TL")) lpImageInfo->dwTextAlign= DIDAL_LEFTALIGNED|DIDAL_TOPALIGNED; else if(Align==_T("TR")) lpImageInfo->dwTextAlign= DIDAL_RIGHTALIGNED|DIDAL_TOPALIGNED; else if(Align==_T("BL")) lpImageInfo->dwTextAlign= DIDAL_LEFTALIGNED|DIDAL_BOTTOMALIGNED; else if(Align==_T("BR")) lpImageInfo->dwTextAlign= DIDAL_RIGHTALIGNED|DIDAL_BOTTOMALIGNED; else { TRACE(_T("Corrupt align data.\n")); throw MAP_EXCEPTION(E_WRONG_ALIGN_DATA); } } //Get call out rect DWORD dwCallOutMaxCnt; String CallOutMaxKeyName=CALLOUTMAX; CallOutMaxKeyName+=_T(".")+N2Str(dwIndex); POINT Callout[2]; if(LoadPointArray(m_VFileName.data(), VCtrlDataIt->ControlName.data(), CallOutMaxKeyName.data(),Callout, dwCallOutMaxCnt,2)) { if(dwCallOutMaxCnt!=2) { TRACE(_T("Corrupt callout rect data.\n")); throw MAP_EXCEPTION(E_CORRUPT_IMAGE_DATA); } lpImageInfo->rcCalloutRect.left=Callout[0].x; lpImageInfo->rcCalloutRect.top=Callout[0].y; lpImageInfo->rcCalloutRect.right=Callout[1].x; lpImageInfo->rcCalloutRect.bottom=Callout[1].y; } else { lpImageInfo->rcCalloutRect.left=0; lpImageInfo->rcCalloutRect.top=0; lpImageInfo->rcCalloutRect.right=100; lpImageInfo->rcCalloutRect.bottom=20; } //Get line data String PointArrayKeyName=LINE_DATA; PointArrayKeyName+=_T(".")+N2Str(dwIndex); LoadPointArray(m_VFileName.data(), VCtrlDataIt->ControlName.data(), PointArrayKeyName.data(), lpImageInfo->rgptCalloutLine, lpImageInfo->dwcValidPts, sizeof(lpImageInfo->rgptCalloutLine)/ sizeof(lpImageInfo->rgptCalloutLine[0])); return S_OK; } break; default: TRACE(_T("Internal error!!!!\n")); throw MAP_EXCEPTION(E_INVALIDARG);break; } return S_FALSE; } HRESULT CDIMapObj::GetActionMapI( LPDIACTIONFORMAT lpDiActionFormat, LPCTSTR lpctstrUserName, FILETIME *pTimestamp,DWORD dwFlags) { try { GETACTIONMAP_ENTERED; TRACE(_T("Parameters:\n")); DUMP(lpDiActionFormat); DUMP(lpctstrUserName); TRACE(_T("\n")); //Check if initialized if(!m_bInitialized) { TRACE(_T("Object not initialized\n")); throw MAP_EXCEPTION(DIERR_NOTINITIALIZED); } //Check parameters if(!lpDiActionFormat) { TRACE(_T("lpDiActionFormat is NULL\n")); throw MAP_EXCEPTION(E_INVALIDARG); } //Check structure sizes if(lpDiActionFormat->dwSize!=sizeof(*lpDiActionFormat)) { TRACE(_T("lpDiActionFormat->\ dwSize is wrong size\n")); throw MAP_EXCEPTION(E_INVALIDARG); } if(lpDiActionFormat->dwActionSize!= sizeof(*(lpDiActionFormat->rgoAction))) { TRACE(_T("lpDiActionFormat->\ dwActionSize is wrong size\n")); throw MAP_EXCEPTION(E_INVALIDARG); } //Check how many actions, should be more than 0 if(!lpDiActionFormat->dwNumActions) { TRACE(_T("lpDiActionFormat->dwNumActions is 0\n")); throw MAP_EXCEPTION(E_INVALIDARG); } //Check ptr to the action array if(!lpDiActionFormat->rgoAction) { TRACE(_T("lpDiActionFormat->rgoAction is NULL\n")); throw MAP_EXCEPTION(E_INVALIDARG); } DWORD dwNOfMappedActions=0; bool bDoNotMapControl=false;//is this per control or action??? bool bDoNotMapGenre=false; WhichDeviceObjectIsMapped( lpDiActionFormat,m_DevObjList,&m_DeviceGuid); bool bMapExists=false;//sticky flag, must set to false if(!(DIDBAM_HWDEFAULTS&dwFlags)) { TRACE(_T("No DIDBAM_HWDEFAULTS flag, map user file first.")); //Map the user file first LoadUserData(lpctstrUserName,lpDiActionFormat); DUMPN(_T("User File Name"),m_UFileName.data()); lpDiActionFormat->ftTimeStamp=m_UTimestamp; if(m_bULoaded)//file was sucessfully preloaded... { TRACE(_T("User file loaded.\n")); MapDevice(lpDiActionFormat,m_UFileName.data(), m_UFileDevName.data(), &m_DeviceGuid,m_DevObjList,m_UCtrlData, DIAH_USERCONFIG,DIAH_USERCONFIG, dwNOfMappedActions,&bMapExists,true); } } if(m_lpVFileName&&m_bVLoaded&& ((DIDBAM_HWDEFAULTS&dwFlags)||!bMapExists)) { TRACE(_T("Vendor file loaded.\n")); //Check if there are unmapped entries for(DWORD i=0;idwNumActions;i++) { if((lpDiActionFormat->rgoAction[i].guidInstance==NULLGUID) ||((lpDiActionFormat->rgoAction[i].guidInstance==m_DeviceGuid) &&(lpDiActionFormat->rgoAction[i].dwHow==DIAH_UNMAPPED) &&((lpDiActionFormat->rgoAction[i].dwFlags&DIA_APPNOMAP)==0))) { TRACE(_T("Unmapped action found, mapping vendor file.\n")); //If there are unmapped entries, map manufacturer file DUMPN(_T("Vendor file name"),m_lpVFileName); MapDevice(lpDiActionFormat,m_lpVFileName, m_VFileDevName.data(),&m_DeviceGuid,m_DevObjList, m_VCtrlData,DIAH_HWDEFAULT,DIAH_HWAPP, dwNOfMappedActions,NULL,false); break; } } } if(dwNOfMappedActions) { DUMP(dwNOfMappedActions); TRACE(_T("hRes=0x%x\n"),S_OK); DUMP(lpDiActionFormat); return S_OK; } if((!(DIDBAM_HWDEFAULTS&dwFlags))&&bMapExists) { TRACE(_T("hRes=0x%x\n"),S_FALSE); return S_FALSE; } TRACE(_T("hRes=0x%x\n"),S_NOMAP); return S_NOMAP; } catch(MapException E) { return E.GetResult(); } catch(exception) { USETRACER(); TRACE(_T("Internal error, hRes=0x%x\n"),E_FAIL); return E_FAIL; } } void CDIMapObj::Resinc(LPDIACTIONFORMAT lpDiActionFormat) { TRACE(_T("Resincing object after writing.\n")); LoadUserData(NULL,lpDiActionFormat,true); } HRESULT CDIMapObj::SaveActionMapI( LPDIACTIONFORMAT lpDiActionFormat, LPCTSTR lpctstrUserName, DWORD dwFlags) { try { SAVEACTIONMAP_ENTERED; TRACE(_T("Parameters:\n")); DUMP(lpDiActionFormat); DUMP(lpctstrUserName); TRACE(_T("\n")); //Check if initialized if(!m_bInitialized) { TRACE(_T("Object not initialized\n")); throw MAP_EXCEPTION(DIERR_NOTINITIALIZED); } //Check parameters if(!lpDiActionFormat) { TRACE(_T("lpDiActionFormat is NULL\n")); throw MAP_EXCEPTION(E_INVALIDARG); } //Check structure sizes if(lpDiActionFormat->dwSize!=sizeof(*lpDiActionFormat)) { TRACE(_T("lpDiActionFormat->\ dwSize is wrong size\n")); throw MAP_EXCEPTION(E_INVALIDARG); } if(lpDiActionFormat->dwActionSize!= sizeof(*(lpDiActionFormat->rgoAction))) { TRACE(_T("lpDiActionFormat->\ dwActionSize is wrong size\n")); throw MAP_EXCEPTION(E_INVALIDARG); } //Check how many actions, should be more than 0 if(!lpDiActionFormat->dwNumActions) { TRACE(_T("lpDiActionFormat->dwNumActions is 0\n")); throw MAP_EXCEPTION(E_INVALIDARG); } //Check ptr to the action array if(!lpDiActionFormat->rgoAction) { TRACE(_T("lpDiActionFormat->rgoAction is NULL\n")); throw MAP_EXCEPTION(E_INVALIDARG); } //this also creates directory if necessary LoadUserData(lpctstrUserName,lpDiActionFormat,false,true); SaveActionMapUV( lpDiActionFormat, m_bULoaded, m_UFileName.data(), m_UFileDevName, m_UCtrlData, NULL, DIAH_USERCONFIG,DIAH_USERCONFIG,true); Resinc(lpDiActionFormat); TRACE(_T("hRes=0x%x\n"),S_OK); return S_OK; } catch(MapException E) { return E.GetResult(); } catch(exception) { USETRACER(); TRACE(_T("Internal error, hRes=0x%x\n"),E_FAIL); return E_FAIL; } } void CDIMapObj::WriteImageInfo(LPCTSTR lpFileKeyName, LPCTSTR lpFormatKeyName, LPCTSTR lpSectionName, LPDIDEVICEIMAGEINFO lpImageInfo, bool bAddIndex, bool bDelete) { if(lpImageInfo->tszImagePath[0]||bDelete) { String FileKeyName=lpFileKeyName; if(bAddIndex) FileKeyName+=_T(".")+N2Str(lpImageInfo->dwViewID); String ImageFileName; LPCTSTR pImageFileName=NULL; if(!bDelete) { StripDirectory(lpImageInfo->tszImagePath,ImageFileName); pImageFileName=ImageFileName.data(); } if(!WritePrivateProfileString(lpSectionName,FileKeyName.data(), pImageFileName,m_VFileName.data())) throw MAP_EXCEPTION(HRESULT_FROM_WIN32(GetLastError())); //keep flags for a while just in case we change our minds again #if 0 String FormatKeyName=lpFormatKeyName; if(bAddIndex) FormatKeyName+=_T(".")+N2Str(lpImageInfo->dwViewID); String ImageFileFormat; LPCTSTR pImageFileFormat=NULL; if(!bDelete) { if(lpImageInfo->dwFlags&DIDIFT_IMAGE2D_PNG) ImageFileFormat=_T("PNG"); else ImageFileFormat=_T("BMP"); pImageFileFormat=ImageFileFormat.data(); } if(!WritePrivateProfileString(lpSectionName,FormatKeyName.data(), pImageFileFormat,m_VFileName.data())) throw MAP_EXCEPTION(HRESULT_FROM_WIN32(GetLastError())); #endif } } void CDIMapObj::MakeNewControlName(String &CtrlName, DEVICEOBJLIST::iterator DevObjIt, CONTROLLIST &ControlsData, String &FileDevName, STRINGLIST &ControlsAllDevs, STRINGLIST &Controls) { ControlData *pCtrlData=NULL; if(&ControlsData==&m_UCtrlData) pCtrlData=DevObjIt->pUCtrlData; else pCtrlData=DevObjIt->pVCtrlData; //Was control data allready in the file if(!pCtrlData) { //No control data in the file //Make unique control name for the file ControlData ControlDataCur; ControlDataCur.ControlName=_T("Ctrl"); ControlDataCur.ControlName+=N2Str(DevObjIt->dwOffset); //ControlDataCur.ControlName+=FileDevName; ToUpper(ControlDataCur.ControlName); MakeUniqueName(ControlDataCur.ControlName,ControlsAllDevs); //Now add this control name into the list CS S; S.assign(ControlDataCur.ControlName); Controls.push_back(S); //Store data for this control into the list ControlsData.push_back(ControlDataCur); //Here bind device obj and control data ControlsData.back().pDevObj=&(*DevObjIt); if(&ControlsData==&m_UCtrlData) pCtrlData=DevObjIt->pUCtrlData=&ControlsData.back(); else pCtrlData=DevObjIt->pVCtrlData=&ControlsData.back(); } CtrlName=pCtrlData->ControlName; } void WriteCtrlData(DEVICEOBJLIST::iterator DevObjIt, LPCTSTR pCtrlName,LPCTSTR pFileName) { //Write offset WritePrivateProfileIntX(pCtrlName,OFFSET, DevObjIt->dwOffset,pFileName); //Write USB usage/usagepage if available if(DevObjIt->dwUsage&&DevObjIt->dwUsagePage) { WritePrivateProfileIntX(pCtrlName,USAGEPAGE, DevObjIt->dwUsagePage,pFileName); WritePrivateProfileIntX(pCtrlName,USAGE, DevObjIt->dwUsage,pFileName); } //Write control name if(!WritePrivateProfileString(pCtrlName,NAME, DevObjIt->Name.data(),pFileName)) { TRACE(_T("Error writing ini file.\n")); throw MAP_EXCEPTION(HRESULT_FROM_WIN32(GetLastError())); } } void CDIMapObj:: SaveActionMapUV( LPDIACTIONFORMAT lpDiActionFormat, bool bDevInFileLoaded, LPCTSTR pFileName, String &FileDevName, CONTROLLIST &ControlsData, LPDIDEVICEIMAGEINFOHEADER lpdiDevImageInfoHeader, DWORD dwHowDev,DWORD dwHowApp,bool bUserFile) { METHOD_ENTRY(SaveActionMapUV); DUMPN(_T("Filename"),pFileName); //Write allways ,just to update name with lattest. WritePrivateProfileIntX(DIRECT_INPUT,DIRECTX_VERSION, 0x800,pFileName); //Load list of devices in the file STRINGLIST Devices; LoadListOfStrings(pFileName,DIRECT_INPUT,DEVICES,Devices,true); if(!bDevInFileLoaded) { TRACE(_T("Device not in file.\n")); FileDevName=m_DeviceName; //Find unique device name and add the list MakeUniqueName(FileDevName,Devices); //Write list of devices WriteListOfStrings(DIRECT_INPUT,DEVICES,Devices,pFileName); //Write VID and PID if(m_dwThisVendorID&&m_dwThisProductID) { WritePrivateProfileIntX(FileDevName.data(),VENDORID, m_dwThisVendorID,pFileName); WritePrivateProfileIntX(FileDevName.data(),PRODUCTID, m_dwThisProductID,pFileName); } //Write device name. if(!WritePrivateProfileString(FileDevName.data(),NAME, m_DeviceName.data(),pFileName)) { TRACE(_T("Error writing ini file.\n")); throw MAP_EXCEPTION(HRESULT_FROM_WIN32(GetLastError())); } } DUMPN(_T("Device name in file"),FileDevName); //write timestamp, but only if we are processing user file if(&ControlsData==&m_UCtrlData) WriteTimestamp(pFileName,FileDevName.data(), lpDiActionFormat->guidActionMap,lpDiActionFormat); //Load list of controls for this device in the file STRINGLIST Controls; LoadListOfStrings(pFileName,FileDevName.data(),CONTROLS,Controls,true); //Load list of controls for all devices in the file STRINGLIST ControlsAllDevs; for(STRINGLIST::iterator DevIt=Devices.begin(); DevIt!=Devices.end();DevIt++) LoadListOfStrings(pFileName,DevIt->data(),CONTROLS, ControlsAllDevs,true); // bool bOtherAppFirst=true; // bool bUserConfig=true; //Delete old sections and create empty mapping String GenreName; //Game specific section //Get section name MakeGenreName(GenreName,FileDevName.data(), lpDiActionFormat->dwGenre,&lpDiActionFormat->guidActionMap); //Find out if this is first writting bool bFirstWrite=!GetPrivateProfileInt(GenreName.data(), MAPEXISTS,0,pFileName); UINT nNoOfMappings=-1; if(!bFirstWrite) { nNoOfMappings=GetPrivateProfileInt(GenreName.data(), NUMACTIONS,-1,pFileName); } //Delete section if(!WritePrivateProfileString(GenreName.data(),NULL, NULL,pFileName)) { TRACE(_T("Error writing ini file.\n")); throw MAP_EXCEPTION( HRESULT_FROM_WIN32(GetLastError())); } //Write numbet of actions if(bUserFile) { if(bFirstWrite) WritePrivateProfileInt(GenreName.data(),NUMACTIONS, lpDiActionFormat->dwNumActions,pFileName); else WritePrivateProfileInt(GenreName.data(),NUMACTIONS, nNoOfMappings,pFileName); } //Mark that section exists WritePrivateProfileInt(GenreName.data(), MAPEXISTS,1,pFileName); //General section (not game specific) //Delete section MakeGenreName(GenreName,FileDevName.data(), lpDiActionFormat->dwGenre,NULL); if(!WritePrivateProfileString(GenreName.data(),NULL, NULL,pFileName)) { TRACE(_T("Error writing ini file.\n")); throw MAP_EXCEPTION( HRESULT_FROM_WIN32(GetLastError())); } //Mark that section exist if(!bUserFile) WritePrivateProfileInt(GenreName.data(), MAPEXISTS,1,pFileName); TRACE(_T("Looking for action to write.\n")); //Iterate through all the actions and store control data for(DWORD dwAct=0;dwActdwNumActions;dwAct++) { DWORD dwHow=lpDiActionFormat->rgoAction[dwAct].dwHow; if(!(lpDiActionFormat->rgoAction[dwAct].guidInstance== m_DeviceGuid)) continue; if(bUserFile) { if(!(dwHow& (DIAH_USERCONFIG|DIAH_APPREQUESTED|DIAH_HWAPP| DIAH_HWDEFAULT|DIAH_DEFAULT))) continue; } else { if(!(dwHow&(DIAH_HWAPP|DIAH_HWDEFAULT))) continue; } if(bUserFile) dwHow=DIAH_HWAPP; String CtrlName; #ifdef _CHECKED int nObjIndex=-1; #endif //Find device object with same offset for(DEVICEOBJLIST::iterator DevObjIt=m_DevObjList.begin(); DevObjIt!=m_DevObjList.end();DevObjIt++) { #ifdef _CHECKED nObjIndex++; #endif if((DIDFT_FINDMASK&DevObjIt->dwOffset)!= (DIDFT_FINDMASK&lpDiActionFormat->rgoAction[dwAct].dwObjID)) continue; if(((DIDFT_FINDMASK&DevObjIt->dwOffset)== (DIDFT_FINDMASK&lpDiActionFormat->rgoAction[dwAct].dwObjID))&& CompareTypeObjAct(DevObjIt->dwType, lpDiActionFormat->rgoAction[dwAct].dwSemantic)) { #ifdef _CHECKED TRACE(_T("To write found action %u matched with devobj %u\n"), dwAct,nObjIndex); #endif //Device object found //Now find file control name MakeNewControlName(CtrlName,DevObjIt, ControlsData,FileDevName,ControlsAllDevs,Controls); DUMPN(_T("control name in file"),CtrlName); WriteCtrlData(DevObjIt,CtrlName.data(),pFileName); //Make section genre name String GenreName; LPCGUID lpAppGUID=NULL; if(dwHow&DIAH_HWAPP) lpAppGUID=&lpDiActionFormat->guidActionMap; MakeGenreName(GenreName,FileDevName.data(), lpDiActionFormat->dwGenre,lpAppGUID); /* bool bDelSect=false; if(bOtherAppFirst&&(dwHow&DIAH_HWAPP)) { bOtherAppFirst=false; bDelSect=true; } if(bUserConfig&&(dwHow&DIAH_HWDEFAULT)) { bUserConfig=false; bDelSect=true; } //Delete section if necessary if(bDelSect) { TRACE(_T("First write to this section, deleting section.")); if(!WritePrivateProfileString(GenreName.data(),NULL, NULL,pFileName)) { TRACE(_T("Error writing ini file.\n")); throw MAP_EXCEPTION( HRESULT_FROM_WIN32(GetLastError())); } //Put flag that this mapping exists WritePrivateProfileInt(GenreName.data(), MAPEXISTS,1,pFileName); } */ //Now update genre mapping WritePrivateProfileIntX(GenreName.data(),CtrlName.data(), GetFileSemantic( lpDiActionFormat->rgoAction[dwAct].dwSemantic, dwHowDev), pFileName); break; } } } if(lpdiDevImageInfoHeader) { m_bImageBufferSize=false; m_dwImageBufferSize=0; for(int i=0;i<(lpdiDevImageInfoHeader->dwBufferUsed/ lpdiDevImageInfoHeader->dwSizeImageInfo);i++) { LPDIDEVICEIMAGEINFO lpImageInfo= &lpdiDevImageInfoHeader->lprgImageInfoArray[i]; DWORD dwFlags=lpImageInfo->dwFlags; if(dwFlags&DIDIFT_CONFIGURATION) { WriteImageInfo(IMAGE_FILENAME,IMAGE_FORMAT, FileDevName.data(), lpImageInfo,true,(dwFlags&DIDIFT_DELETE)?true:false); } #if 0 else if(dwFlags&DIDIFT_SELECTION) { WriteImageInfo(SELECTION_FILENAME,SELECTION_FORMAT, FileDevName.data(), lpImageInfo,false,(dwFlags&DIDIFT_DELETE)?true:false); } else if(dwFlags&DIDIFT_VIEWSELECT) { WriteImageInfo(VIEWSELECT_FILENAME,VIEWSELECT_FORMAT, FileDevName.data(), lpImageInfo,true,(dwFlags&DIDIFT_DELETE)?true:false); } #endif else if(dwFlags&DIDIFT_OVERLAY) { String CtrlName; //Find device object with same offset for(DEVICEOBJLIST::iterator DevObjIt=m_DevObjList.begin(); DevObjIt!=m_DevObjList.end();DevObjIt++) { if((DIDFT_FINDMASK&lpImageInfo->dwObjID) ==(DIDFT_FINDMASK&DevObjIt->dwType)) { //Device object found //Now find file control name String CtrlName; MakeNewControlName(CtrlName,DevObjIt, ControlsData,FileDevName, ControlsAllDevs,Controls); WriteCtrlData(DevObjIt,CtrlName.data(),pFileName); //Write file name and format WriteImageInfo(OVERLAY_FILENAME, OVERLAY_FORMAT,CtrlName.data(), lpImageInfo,true, (dwFlags&DIDIFT_DELETE)?true:false); //Write overlay rect if(lpImageInfo->tszImagePath[0]|| (dwFlags&DIDIFT_DELETE)) { //Get overlay rect String OverlayRectKeyName=OVERLAY_RECT; OverlayRectKeyName+= _T(".")+N2Str(lpImageInfo->dwViewID); if(dwFlags&DIDIFT_DELETE) { if(!WritePrivateProfileString( CtrlName.data(), OverlayRectKeyName.data(), NULL, m_VFileName.data())) throw MAP_EXCEPTION( HRESULT_FROM_WIN32( GetLastError())); } else WriteRect(CtrlName.data(), OverlayRectKeyName.data(), &lpImageInfo->rcOverlay, m_VFileName.data()); } //Write string alignment String AlignKeyName=CONTROL_STRING_ALIGN; AlignKeyName+= _T(".")+N2Str(lpImageInfo->dwViewID); String Align; LPCTSTR pAlign=NULL; if(!(dwFlags&DIDIFT_DELETE)) { if(lpImageInfo->dwTextAlign& DIDAL_TOPALIGNED) Align=_T("T"); else if(lpImageInfo->dwTextAlign& DIDAL_BOTTOMALIGNED) Align=_T("B"); if(lpImageInfo->dwTextAlign& DIDAL_LEFTALIGNED) Align+=_T("L"); else if(lpImageInfo->dwTextAlign& DIDAL_RIGHTALIGNED) Align+=_T("R"); if(Align==_T("")) Align=_T("C"); pAlign=Align.data(); } if(!WritePrivateProfileString( CtrlName.data(), AlignKeyName.data(), pAlign, m_VFileName.data())) throw MAP_EXCEPTION( HRESULT_FROM_WIN32(GetLastError())); //Write call out rect String CallOutMaxKeyName=CALLOUTMAX; CallOutMaxKeyName+= _T(".")+N2Str(lpImageInfo->dwViewID); if(dwFlags&DIDIFT_DELETE) { if(!WritePrivateProfileString( CtrlName.data(), CallOutMaxKeyName.data(), NULL, m_VFileName.data())) throw MAP_EXCEPTION( HRESULT_FROM_WIN32( GetLastError())); } else WriteRect(CtrlName.data(), CallOutMaxKeyName.data(), &lpImageInfo->rcCalloutRect, m_VFileName.data()); //Write line data String PointArrayKeyName=LINE_DATA; PointArrayKeyName+= _T(".")+N2Str(lpImageInfo->dwViewID); if(dwFlags&DIDIFT_DELETE) { if(!WritePrivateProfileString( CtrlName.data(), PointArrayKeyName.data(), NULL, m_VFileName.data())) throw MAP_EXCEPTION( HRESULT_FROM_WIN32( GetLastError())); } else WritePointArray( CtrlName.data(), PointArrayKeyName.data(), lpImageInfo->rgptCalloutLine, lpImageInfo->dwcValidPts, m_VFileName.data()); break; } } } else throw MAP_EXCEPTION(E_CORRUPT_IMAGE_DATA); } } //Write new list of controls into the file if(Controls.size()) WriteListOfStrings(FileDevName.data(),CONTROLS,Controls,pFileName); } HRESULT CDIMapObj:: WriteVendorFileI( LPDIACTIONFORMAT lpDiActionFormat, LPDIDEVICEIMAGEINFOHEADER lpdiDevImageInfoHeader, DWORD dwFlags) { try { WRITEVENDORFILE_ENTERED; TRACE(_T("Parameters:\n")); DUMP(lpDiActionFormat); DUMP(lpdiDevImageInfoHeader); //DUMP(lpdiDevImageInfoHeader); TRACE(_T("\n")); //Check if initialized if(!m_bInitialized) { TRACE(_T("Object not initialized\n")); throw MAP_EXCEPTION(DIERR_NOTINITIALIZED); } //Check lpDiActionFormat structure //Check structure sizes if(lpDiActionFormat&&(lpDiActionFormat->dwSize!= sizeof(*lpDiActionFormat))) { TRACE(_T("lpDiActionFormat->dwSize is wrong size\n")); throw MAP_EXCEPTION(E_INVALIDARG); } if(lpDiActionFormat&&(lpDiActionFormat->dwActionSize!= sizeof(*(lpDiActionFormat->rgoAction)))) { TRACE(_T("lpDiActionFormat->dwActionSize is wrong size\n")); throw MAP_EXCEPTION(E_INVALIDARG); } //Check how many actions, should be more than 0 if(lpDiActionFormat&&!lpDiActionFormat->dwNumActions) { TRACE(_T("lpDiActionFormat->dwNumActions is 0\n")); throw MAP_EXCEPTION(E_INVALIDARG); } //Check ptr to the action array if(lpDiActionFormat&&!lpDiActionFormat->rgoAction) { TRACE(_T("lpDiActionFormat->rgoAction is NULL\n")); throw MAP_EXCEPTION(E_INVALIDARG); } //Check lpdiDevImageInfoHeader structure //Check structure sizes if(lpdiDevImageInfoHeader&& (lpdiDevImageInfoHeader->dwSize!= sizeof(*lpdiDevImageInfoHeader))) { TRACE(_T("lpdiDevImageInfoHeader->dwSize is wrong size\n")); throw MAP_EXCEPTION(E_INVALIDARG); } if(lpdiDevImageInfoHeader&& (lpdiDevImageInfoHeader->dwSizeImageInfo!= sizeof(*(lpdiDevImageInfoHeader->lprgImageInfoArray)))) { TRACE(_T("lpdiDevImageInfoHeader->dwSizeImageInfo is wrong size\n")); throw MAP_EXCEPTION(E_INVALIDARG); } //Check how many images, should be more than 0 if(lpdiDevImageInfoHeader&&!lpdiDevImageInfoHeader->dwBufferSize) { TRACE(_T("lpdiDevImageInfoHeader->dwBufferSize is 0\n")); throw MAP_EXCEPTION(E_INVALIDARG); } //Check how many images, should be more than 0 if(lpdiDevImageInfoHeader&&!lpdiDevImageInfoHeader->dwBufferUsed) { TRACE(_T("lpdiDevImageInfoHeader->dwBufferUsed is 0\n")); throw MAP_EXCEPTION(E_INVALIDARG); } //Check ptr to the image array if(lpdiDevImageInfoHeader&& !lpdiDevImageInfoHeader->lprgImageInfoArray) { TRACE(_T("lpdiDevImageInfoHeader->lprgImageInfoArray is NULL\n")); throw MAP_EXCEPTION(E_INVALIDARG); } SaveActionMapUV( lpDiActionFormat, m_bVLoaded, m_VFileName.data(), m_VFileDevName, m_VCtrlData, lpdiDevImageInfoHeader, DIAH_HWDEFAULT,DIAH_HWAPP,false); LoadFileData(m_VFileName.data(),m_DeviceName.data(), m_dwThisVendorID,m_dwThisProductID, m_VFileDevName,m_VCtrlData,m_bVLoaded,NULL,NULL); TRACE(_T("hRes=0x%x\n"),S_OK); return S_OK; } catch(MapException E) { return E.GetResult(); } catch(exception) { USETRACER(); TRACE(_T("Internal error, hRes=0x%x\n"),E_FAIL); return E_FAIL; } } HRESULT Map_New(REFIID riid,LPVOID *ppvOut) { CDIMapObj *lpDIMapObj=NULL; try { HRESULT hRes=S_OK; *ppvOut=NULL; lpDIMapObj=new CDIMapObj; hRes=lpDIMapObj->QueryInterface(riid,ppvOut); if(hRes!=S_OK) throw MAP_EXCEPTION(hRes); return S_OK; } catch(MapException E) { delete lpDIMapObj; return E.GetResult(); } catch(exception) { delete lpDIMapObj; USETRACER(); TRACE(_T("Internal error, hRes=0x%x\n"),E_FAIL); return E_FAIL; } }