Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2731 lines
80 KiB

  1. /****************************************************************************
  2. *
  3. * Copyright (C) 2000, 2001 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * Author: Tomislav Markoc, (tmarkoc), SDE
  6. *
  7. ****************************************************************************/
  8. #include <windows.h>
  9. #include <commctrl.h>//UI only
  10. #include <shfusion.h>//UI only
  11. #define _INC_MMSYSTEM
  12. #define WINMMAPI DECLSPEC_IMPORT
  13. typedef UINT MMRESULT; /* error return code, 0 means no error */
  14. /* call as if(err=xxxx(...)) Error(err); else */
  15. // end of hack to avoid including mmsystem.h!!!
  16. #include <gameport.h>
  17. #include <dinput.h>
  18. #include <dinputd.h>
  19. #include <list>
  20. #include <exception>
  21. #include <string>
  22. #include <algorithm>
  23. #include <tchar.h>
  24. #include <windowsx.h>
  25. #include <regstr.h>
  26. #include <new.h>
  27. #include "resource.h"
  28. #include "ifacesvr.h"
  29. #include "joyarray.h"
  30. using namespace std;
  31. #define NUMJOYDEVS 16//Max joy id-s. Why is this hardcoded?
  32. #define MAX_DEVICES 75
  33. #define IDC_WHATSTHIS 400
  34. #ifdef UNICODE
  35. #define String wstring
  36. #else
  37. #define String string
  38. #endif // !UNICODE
  39. #ifdef _CHECKED
  40. #define JOY_EXCEPTION(A) JoyException(_T(__FILE__),__LINE__,A)
  41. #else
  42. #define JOY_EXCEPTION(A) JoyException(A)
  43. #endif
  44. #define cA(a) (sizeof(a)/sizeof(a[0]))
  45. class JoyException:public exception
  46. {
  47. HRESULT m_hRes;
  48. #ifdef _CHECKED
  49. String m_SourceFile;
  50. DWORD m_dwLine;
  51. #endif
  52. public:
  53. HRESULT GetResult(){return m_hRes;};
  54. JoyException(
  55. #ifdef _CHECKED
  56. LPCTSTR lpSourceFile,DWORD dwLine,
  57. #endif
  58. HRESULT hRes);
  59. };
  60. JoyException::JoyException(
  61. #ifdef _CHECKED
  62. LPCTSTR lpSourceFile,DWORD dwLine,
  63. #endif
  64. HRESULT hRes)
  65. {
  66. m_hRes=hRes;
  67. #ifdef _CHECKED
  68. m_SourceFile=lpSourceFile;
  69. m_dwLine=dwLine;
  70. #endif
  71. }
  72. int __cdecl my_new_handler(size_t) {
  73. throw JOY_EXCEPTION(E_OUTOFMEMORY);
  74. return 0;
  75. }
  76. template <class p> class AutoRelease
  77. {
  78. p m_p;
  79. public:
  80. AutoRelease(){m_p=NULL;};
  81. ~AutoRelease(){Clear();};
  82. void Clear(){
  83. ULONG nRef=-1;
  84. if(m_p)
  85. {
  86. nRef=m_p->Release();//If last ptr, nRef falls to 0.
  87. };
  88. m_p=NULL;};
  89. AutoRelease(const AutoRelease<p> &R)
  90. {m_p=R.m_p;m_p->AddRef();};
  91. AutoRelease<p> &operator=(const AutoRelease<p> &R)
  92. {m_p=R.m_p;m_p->AddRef();return *this;};
  93. AutoRelease<p> &operator=(p ptr)
  94. {m_p=ptr;if(m_p)m_p->AddRef();return *this;};
  95. p operator->(){return m_p;};
  96. operator p&(){return m_p;};
  97. operator p*(){return &m_p;};
  98. };
  99. typedef AutoRelease<LPDIRECTINPUT8> LPDIRECTINPUT_AR;
  100. typedef AutoRelease<LPDIRECTINPUTDEVICE8> LPDIRECTINPUTDEVICE_AR;
  101. typedef AutoRelease<LPDIRECTINPUTJOYCONFIG8> LPDIRECTINPUTJOYCONFIG_AR;
  102. template <class p> class AutoDeleteArray
  103. {
  104. p m_p;
  105. public:
  106. AutoDeleteArray(){m_p=NULL;};
  107. AutoDeleteArray(const p P){m_p=P;};
  108. ~AutoDeleteArray(){delete[] m_p;};
  109. p operator=(const p P){m_p=P;return m_p;};
  110. p operator->(){return m_p;};
  111. operator p&(){return m_p;};
  112. operator p*(){return &m_p;};
  113. };
  114. enum EStatus{EConnected,ENotConnected,EUnknown};
  115. //ISSUE-2001/03/29-timgill Should use predefined NULLGUID
  116. const GUID NULLGUID;
  117. class CCore;
  118. class CDIDev
  119. {
  120. friend BOOL CALLBACK DIEnumDevicesProc(
  121. const DIDEVICEINSTANCE * lpddi,LPVOID pvRef);
  122. LPDIRECTINPUTDEVICE_AR m_pDID;
  123. DIDEVICEINSTANCE m_DIDevInst;
  124. DIDEVCAPS_DX3 m_DIDevCaps;
  125. DIJOYCONFIG m_DIJoyCfg;
  126. DWORD m_dwId;
  127. bool m_bInitialized;
  128. CCore *m_pCore;
  129. public:
  130. CDIDev(){m_bInitialized=false;};
  131. DWORD Id(){return m_dwId;};
  132. const GUID &InstGUID(){return m_DIDevInst.guidInstance;};
  133. const GUID &PortGUID(){return m_DIJoyCfg.guidGameport;};
  134. LPCTSTR InstName(){return m_DIDevInst.tszInstanceName;};
  135. EStatus Status(){if(m_DIDevCaps.dwFlags&DIDC_ATTACHED)return EConnected;return ENotConnected;};
  136. void Update(LPDIRECTINPUTJOYCONFIG8 pJoyCfg);
  137. HRESULT Rename(LPCTSTR pName);
  138. bool operator==(const GUID &G){if(InstGUID()==G)return true;return false;};
  139. };
  140. class CGprtDev
  141. {
  142. friend BOOL CALLBACK DIEnumJoyTypePr(LPCWSTR pwszTypeName,LPVOID pvRef);
  143. friend class CCore;
  144. String m_Name;
  145. DIJOYTYPEINFO m_Info;
  146. public:
  147. LPCTSTR TypeName(){return m_Name.data();};
  148. LPCTSTR Name(){return m_Info.wszDisplayName;};
  149. bool operator==(LPCTSTR pTypeName){if(m_Name==pTypeName)return true;return false;};
  150. bool Rudder(){if(m_Info.hws.dwFlags&JOY_HWS_HASR)return true;return false;};
  151. };
  152. typedef list<CDIDev> LISTDIDEV;
  153. typedef list<String> LISTSTRING;
  154. typedef list<CGprtDev> LISTGPRTDEV;
  155. class CCore
  156. {
  157. friend HRESULT Properties(HMODULE hMod,HWND hWnd,CCore *pCore,DWORD dwId);
  158. friend BOOL CALLBACK DIEnumJoyTypePr(LPCWSTR pwszTypeName,LPVOID pvRef);
  159. friend class CDIDev;
  160. friend BOOL CALLBACK DIEnumDevicesProc(const DIDEVICEINSTANCE *lpddi,LPVOID pvRef);
  161. bool m_bAccess;
  162. bool m_bInitialized;
  163. virtual void UIUpdate(){};
  164. LPDIRECTINPUT_AR m_pDI;
  165. LPDIRECTINPUTJOYCONFIG_AR m_pDIJoyCfg;
  166. int GetNextAvailableId();
  167. bool FullJoyOemAccess();
  168. public:
  169. LISTDIDEV m_ListDIDev;
  170. LISTSTRING m_GprtDrv;
  171. LISTGPRTDEV m_GprtBus;
  172. LISTGPRTDEV m_GprtDev;
  173. CCore();
  174. void Initialize(HWND hWnd);
  175. void Update();
  176. void UpdateType();
  177. bool Access(){return m_bAccess;};
  178. CDIDev *FindDIDev(GUID &G);
  179. HRESULT Remove(GUID &G);
  180. void Preferred(GUID &G);
  181. HRESULT AddDevice
  182. (LPCTSTR pTypeName,bool bRudder,LPCTSTR pGprtId,GUID &GOccupied);
  183. bool IsAutoDetectGprt();
  184. bool IsAvailableVIDPID(String &VIDPIDName);
  185. bool DuplicateDeviceName(LPCTSTR pName);
  186. void AddCustomDevice(bool bJoy,bool bPad,bool bYoke,bool bCar,
  187. int nAxes,bool bZAxis,int nButtons,bool bHasPov,LPCTSTR pName,
  188. LPCTSTR pVIDPIDName);
  189. bool IsCustomDevice(LPCTSTR pTypeName);
  190. bool IsDeviceActive(LPCTSTR pTypeName);
  191. void DeleteType(LPCTSTR pTypeName);
  192. CGprtDev *FindGprtDev(LPCTSTR pTypeName);
  193. };
  194. struct SEnumDev
  195. {
  196. LPDIRECTINPUT8 m_pDI;
  197. CCore *m_pCore;
  198. SEnumDev(LISTDIDEV &ListDIDev,LPDIRECTINPUT8 pDI,CCore *pCore)
  199. {m_pDI=pDI;m_pCore=pCore;};
  200. };
  201. /******************************************************************************
  202. End of header
  203. ******************************************************************************/
  204. /******************************************************************************
  205. CDIDev
  206. ******************************************************************************/
  207. HRESULT CDIDev::Rename(LPCTSTR pName)
  208. {
  209. if(!m_bInitialized)
  210. {
  211. throw JOY_EXCEPTION(E_FAIL);
  212. }
  213. if(!m_pCore->Access())return DIERR_INSUFFICIENTPRIVS;
  214. DIPROPSTRING DIPropString;
  215. ZeroMemory(&DIPropString,sizeof(DIPROPSTRING));
  216. DIPropString.diph.dwSize=sizeof(DIPROPSTRING);
  217. DIPropString.diph.dwHeaderSize=sizeof(DIPROPHEADER);
  218. DIPropString.diph.dwHow=DIPH_DEVICE;
  219. wcsncpy(DIPropString.wsz,pName,MAX_PATH-1);
  220. DIPropString.wsz[MAX_PATH-1]=0;
  221. HRESULT hRes=m_pDID->SetProperty(DIPROP_INSTANCENAME,&DIPropString.diph);
  222. Update(m_pCore->m_pDIJoyCfg);
  223. return hRes;
  224. }
  225. void CDIDev::Update(LPDIRECTINPUTJOYCONFIG8 pJoyCfg)
  226. {
  227. HRESULT hRes=S_OK;
  228. ZeroMemory(&m_DIDevInst,sizeof(m_DIDevInst));
  229. m_DIDevInst.dwSize=sizeof(m_DIDevInst);
  230. hRes=m_pDID->GetDeviceInfo(&m_DIDevInst);
  231. if(FAILED(hRes))
  232. {
  233. throw JOY_EXCEPTION(hRes);
  234. }
  235. ZeroMemory(&m_DIDevCaps,sizeof(m_DIDevCaps));
  236. m_DIDevCaps.dwSize=sizeof(m_DIDevCaps);
  237. hRes=m_pDID->GetCapabilities((LPDIDEVCAPS)&m_DIDevCaps);
  238. if(FAILED(hRes))
  239. {
  240. throw JOY_EXCEPTION(hRes);
  241. }
  242. //Get Id.
  243. m_dwId=-1;
  244. DIPROPDWORD DIPropDW;
  245. ZeroMemory(&DIPropDW,sizeof(DIPropDW));
  246. DIPropDW.diph.dwSize=sizeof(DIPROPDWORD);
  247. DIPropDW.diph.dwHeaderSize=sizeof(DIPROPHEADER);
  248. DIPropDW.diph.dwHow=DIPH_DEVICE;
  249. hRes=m_pDID->GetProperty(DIPROP_JOYSTICKID,&DIPropDW.diph);
  250. if(FAILED(hRes))
  251. {
  252. throw JOY_EXCEPTION(hRes);
  253. }
  254. m_dwId=DIPropDW.dwData;
  255. //Get gameport.
  256. ZeroMemory(&m_DIJoyCfg,sizeof(m_DIJoyCfg));
  257. m_DIJoyCfg.dwSize=sizeof(m_DIJoyCfg);
  258. hRes=pJoyCfg->GetConfig(m_dwId,&m_DIJoyCfg,DIJC_WDMGAMEPORT);
  259. if(FAILED(hRes))
  260. {
  261. //throw JOY_EXCEPTION(hRes);
  262. }
  263. }
  264. /******************************************************************************
  265. CCore
  266. ******************************************************************************/
  267. BOOL CALLBACK DIEnumDevicesProc(
  268. const DIDEVICEINSTANCE *lpddi,LPVOID pvRef)
  269. {
  270. try
  271. {
  272. SEnumDev &ED=*(SEnumDev*)pvRef;
  273. CDIDev Dev;
  274. Dev.m_pCore=ED.m_pCore;
  275. HRESULT hRes=ED.m_pDI->CreateDevice(lpddi->guidInstance,Dev.m_pDID,NULL);
  276. if(FAILED(hRes))
  277. {
  278. throw JOY_EXCEPTION(hRes);
  279. }
  280. Dev.Update(ED.m_pCore->m_pDIJoyCfg);
  281. Dev.m_bInitialized=true;
  282. ED.m_pCore->m_ListDIDev.push_back(Dev);
  283. }
  284. catch(JoyException E)
  285. {
  286. }
  287. catch(exception)
  288. {
  289. }
  290. return DIENUM_CONTINUE;
  291. }
  292. BOOL CALLBACK DIEnumJoyTypePr(LPCWSTR pwszTypeName,LPVOID pvRef)
  293. {
  294. try
  295. {
  296. HRESULT hRes=S_OK;
  297. String TN=pwszTypeName;
  298. SEnumDev &ED=*(SEnumDev*)pvRef;
  299. DIJOYTYPEINFO JoyInfo;
  300. ZeroMemory(&JoyInfo,sizeof(JoyInfo));
  301. JoyInfo.dwSize=sizeof(JoyInfo);
  302. switch(ED.m_pCore->m_pDIJoyCfg->GetTypeInfo(pwszTypeName,&JoyInfo,DITC_REGHWSETTINGS))
  303. {
  304. //Errors to continue with.
  305. case DIERR_NOTFOUND:
  306. return DIENUM_CONTINUE;
  307. //Errors to stop with.
  308. case DIERR_INVALIDPARAM:
  309. case DIERR_NOMOREITEMS:
  310. return DIENUM_STOP;
  311. }
  312. if(JoyInfo.hws.dwFlags&JOY_HWS_ISGAMEPORTBUS)
  313. {
  314. CGprtDev D;
  315. D.m_Name=TN;
  316. ZeroMemory(&D.m_Info,sizeof(D.m_Info));
  317. D.m_Info.dwSize=sizeof(D.m_Info);
  318. DWORD dwFlags=DITC_CLSIDCONFIG|DITC_DISPLAYNAME;
  319. if(FAILED(ED.m_pCore->m_pDIJoyCfg->GetTypeInfo(D.m_Name.data(),&D.m_Info,dwFlags)))
  320. {
  321. throw JOY_EXCEPTION(hRes);
  322. }
  323. ED.m_pCore->m_GprtBus.push_back(D);
  324. }
  325. else if(!(JoyInfo.hws.dwFlags&JOY_HWS_AUTOLOAD))
  326. {
  327. CGprtDev D;
  328. D.m_Name=TN;
  329. ZeroMemory(&D.m_Info,sizeof(D.m_Info));
  330. D.m_Info.dwSize=sizeof(D.m_Info);
  331. DWORD dwFlags=DITC_REGHWSETTINGS|DITC_FLAGS1|DITC_HARDWAREID|DITC_CALLOUT|DITC_DISPLAYNAME;
  332. if(FAILED(ED.m_pCore->m_pDIJoyCfg->GetTypeInfo(D.m_Name.data(),&D.m_Info,dwFlags)))
  333. {
  334. throw JOY_EXCEPTION(hRes);
  335. }
  336. ED.m_pCore->m_GprtDev.push_back(D);
  337. }
  338. }
  339. catch(JoyException E)
  340. {
  341. }
  342. catch(exception)
  343. {
  344. }
  345. return DIENUM_CONTINUE;
  346. }
  347. CCore::CCore()
  348. {
  349. m_bAccess=false;
  350. m_bInitialized=false;
  351. }
  352. bool CCore::IsAutoDetectGprt()
  353. {
  354. if(!m_GprtDev.size())return false;
  355. if(m_GprtDev.front().m_Info.dwFlags1&
  356. JOYTYPE_NOAUTODETECTGAMEPORT)return false;
  357. return true;
  358. }
  359. int CCore::GetNextAvailableId()
  360. {
  361. if(!m_bInitialized)return -1;
  362. DIJOYCONFIG JoyCfg;
  363. ZeroMemory(&JoyCfg,sizeof(JoyCfg));
  364. JoyCfg.dwSize=sizeof(JoyCfg);
  365. for(int i=0;i<NUMJOYDEVS;i++)
  366. {
  367. switch(m_pDIJoyCfg->GetConfig(i,&JoyCfg,DIJC_REGHWCONFIGTYPE))
  368. {
  369. case S_FALSE:
  370. case DIERR_NOMOREITEMS:
  371. case DIERR_NOTFOUND:
  372. case E_FAIL:
  373. return i;
  374. }
  375. }
  376. return -1;
  377. }
  378. bool CCore::FullJoyOemAccess()
  379. {
  380. LONG lRc;
  381. HKEY hk;
  382. bool bRc;
  383. lRc = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  384. REGSTR_PATH_JOYOEM,
  385. 0,
  386. KEY_ALL_ACCESS & ~WRITE_DAC & ~WRITE_OWNER,
  387. &hk);
  388. if( lRc == ERROR_SUCCESS ) {
  389. bRc = true;
  390. RegCloseKey(hk);
  391. } else {
  392. bRc = false;
  393. }
  394. return bRc;
  395. }
  396. HRESULT CCore::AddDevice(LPCTSTR pTypeName,bool bRudder,LPCTSTR pGprtId,GUID &GOccupied)
  397. {
  398. HRESULT hRes=S_OK;
  399. GOccupied=NULLGUID;
  400. if(!m_bInitialized)return E_FAIL;
  401. if(m_GprtDev.size()>=MAX_DEVICES)return E_FAIL;
  402. LISTGPRTDEV::iterator It;
  403. It=find(m_GprtDev.begin(),m_GprtDev.end(),pTypeName);
  404. if(It==m_GprtDev.end())return E_FAIL;
  405. CGprtDev *pGprtDev=&*It;
  406. int nId=GetNextAvailableId();
  407. if(nId==-1)return DIERR_NOTFOUND;
  408. DIJOYCONFIG JoyCfg;
  409. ZeroMemory(&JoyCfg,sizeof(JoyCfg));
  410. JoyCfg.dwSize=sizeof(JoyCfg);
  411. JoyCfg.hwc.hws=pGprtDev->m_Info.hws;
  412. JoyCfg.hwc.hws.dwFlags|=JOY_HWS_ISANALOGPORTDRIVER;
  413. if(bRudder)
  414. {
  415. JoyCfg.hwc.hws.dwFlags|=JOY_HWS_HASR;
  416. JoyCfg.hwc.dwUsageSettings|=JOY_US_HASRUDDER;
  417. }
  418. JoyCfg.hwc.dwUsageSettings|=JOY_US_PRESENT;
  419. //JoyCfg.hwc.dwType=nArrayID;WHY is this beeing set to index?????????????????????????????????????????????????????????????????????????????????
  420. wcsncpy(JoyCfg.wszCallout,pGprtDev->m_Info.wszCallout,sizeof(JoyCfg.wszCallout)/sizeof(JoyCfg.wszCallout[0])-1);
  421. wcsncpy(JoyCfg.wszType,pGprtDev->m_Name.data(),sizeof(JoyCfg.wszType)/sizeof(JoyCfg.wszType[0])-1);
  422. if(SUCCEEDED(hRes=m_pDIJoyCfg->Acquire()))
  423. {
  424. if(m_GprtBus.size())
  425. {
  426. if(m_GprtBus.size()>1)
  427. {
  428. if(pGprtId)
  429. {
  430. String GId=pGprtId;
  431. LISTGPRTDEV::iterator It;
  432. It=find(m_GprtBus.begin(),m_GprtBus.end(),GId.data());
  433. if(It!=m_GprtDev.end())
  434. {
  435. JoyCfg.guidGameport=It->m_Info.clsidConfig;
  436. }
  437. }
  438. }
  439. else
  440. {
  441. JoyCfg.guidGameport=m_GprtBus.front().m_Info.clsidConfig;
  442. }
  443. }
  444. if(FAILED(hRes=m_pDIJoyCfg->SetConfig(nId,&JoyCfg,DIJC_REGHWCONFIGTYPE|DIJC_CALLOUT)))
  445. {
  446. m_pDIJoyCfg->Unacquire();
  447. if(hRes==E_ACCESSDENIED)
  448. GOccupied=JoyCfg.guidGameport;
  449. return hRes;
  450. }
  451. else
  452. {
  453. //Fix #55524.
  454. if(SUCCEEDED(m_pDIJoyCfg->GetConfig(nId,&JoyCfg,DIJC_REGHWCONFIGTYPE)))
  455. {
  456. if(!(JoyCfg.hwc.dwUsageSettings&JOY_US_PRESENT))
  457. {
  458. JoyCfg.hwc.dwUsageSettings|=JOY_US_PRESENT;
  459. JoyCfg.hwc.hwv.dwCalFlags|=0x80000000;
  460. JoyCfg.hwc.hws.dwFlags|=JOY_HWS_ISANALOGPORTDRIVER;
  461. m_pDIJoyCfg->SetConfig(nId,&JoyCfg,DIJC_REGHWCONFIGTYPE);
  462. }
  463. }
  464. //End of fix #55524.
  465. }
  466. m_pDIJoyCfg->Unacquire();
  467. }
  468. Update();
  469. UpdateType();
  470. return hRes;
  471. }
  472. void CCore::Initialize(HWND hWnd)
  473. {
  474. if((LPDIRECTINPUTJOYCONFIG8)m_pDIJoyCfg)
  475. m_pDIJoyCfg->Release();
  476. m_pDIJoyCfg=NULL;
  477. if((LPDIRECTINPUT8)m_pDI)
  478. m_pDI->Release();
  479. m_pDI=NULL;
  480. HMODULE hM=GetModuleHandle(NULL);
  481. if(!hM)
  482. {
  483. throw JOY_EXCEPTION(E_FAIL);
  484. }
  485. HRESULT hRes=DirectInput8Create(hM,DIRECTINPUT_VERSION,
  486. IID_IDirectInput8,(LPVOID*)&m_pDI,NULL);
  487. if(FAILED(hRes))
  488. {
  489. throw JOY_EXCEPTION(hRes);
  490. }
  491. hRes=m_pDI->QueryInterface(IID_IDirectInputJoyConfig8,(LPVOID*)&m_pDIJoyCfg);
  492. if(hRes!=DI_OK)
  493. {
  494. throw JOY_EXCEPTION(hRes);
  495. }
  496. hRes=m_pDIJoyCfg->SetCooperativeLevel(hWnd,DISCL_EXCLUSIVE|DISCL_BACKGROUND);
  497. if(hRes!=DI_OK)
  498. {
  499. throw JOY_EXCEPTION(hRes);
  500. }
  501. m_bAccess = FullJoyOemAccess();
  502. m_bInitialized=true;
  503. }
  504. void CCore::Update()
  505. {
  506. HRESULT hRes;
  507. if(!m_bInitialized)
  508. {
  509. throw JOY_EXCEPTION(E_FAIL);
  510. }
  511. m_ListDIDev.clear();
  512. SEnumDev ED(m_ListDIDev,m_pDI,this);
  513. hRes=m_pDI->EnumDevices(DI8DEVCLASS_GAMECTRL,DIEnumDevicesProc,&ED,DIEDFL_ALLDEVICES);
  514. if(FAILED(hRes))
  515. {
  516. //EnumDevices goes wrong
  517. ; //throw JOY_EXCEPTION(hRes);
  518. }
  519. UIUpdate();
  520. }
  521. void CCore::UpdateType()
  522. {
  523. if(!m_bInitialized)
  524. {
  525. throw JOY_EXCEPTION(E_FAIL);
  526. }
  527. m_GprtDrv.clear();
  528. m_GprtBus.clear();
  529. m_GprtDev.clear();
  530. HRESULT hRes=S_OK;
  531. SEnumDev ED(m_ListDIDev,m_pDI,this);
  532. hRes=m_pDIJoyCfg->EnumTypes(DIEnumJoyTypePr,&ED);
  533. if(FAILED(hRes))
  534. {
  535. throw JOY_EXCEPTION(hRes);
  536. }
  537. UIUpdate();
  538. }
  539. CDIDev *CCore::FindDIDev(GUID &Guid)
  540. {
  541. LISTDIDEV::iterator It;
  542. It=find(m_ListDIDev.begin(),m_ListDIDev.end(),Guid);
  543. if(It==m_ListDIDev.end())return NULL;
  544. return &*It;
  545. }
  546. HRESULT CCore::Remove(GUID &Guid)
  547. {
  548. if(!m_bInitialized)
  549. {
  550. throw JOY_EXCEPTION(E_FAIL);
  551. }
  552. CDIDev *pDev=FindDIDev(Guid);
  553. if(!pDev)return E_FAIL;
  554. HRESULT hRes;
  555. if(FAILED(hRes=m_pDIJoyCfg->Acquire()))return hRes;
  556. if(FAILED(hRes=m_pDIJoyCfg->DeleteConfig(pDev->Id())))
  557. {
  558. m_pDIJoyCfg->Unacquire();
  559. return hRes;
  560. }
  561. m_pDIJoyCfg->SendNotify();
  562. m_pDIJoyCfg->Unacquire();
  563. return S_OK;
  564. }
  565. #define DIJC_ALL DIJC_REGHWCONFIGTYPE|DIJC_CALLOUT|DIJC_WDMGAMEPORT|DIJC_GAIN|DIJC_GUIDINSTANCE
  566. void CCore::Preferred(GUID &G)
  567. {
  568. if(!m_bInitialized)
  569. {
  570. throw JOY_EXCEPTION(E_FAIL);
  571. }
  572. //Set Id of preferred device to 0.
  573. //Find Id of device to be set to 0.
  574. CDIDev *pDev=FindDIDev(G);
  575. if(!pDev)return;
  576. int nId=pDev->Id();
  577. if(nId==0)//Already preferred.
  578. return;
  579. if(SUCCEEDED(m_pDIJoyCfg->Acquire()))
  580. {
  581. //We could call SetConfig only once and DInput on NT or Whistler should
  582. //swap Id-s of two devices. However, it will not work if gameport device
  583. //is unplugged, so we still must swap by salling SetConfig twice.
  584. DIJOYCONFIG OldId0;
  585. ZeroMemory(&OldId0,sizeof(OldId0));
  586. OldId0.dwSize=sizeof(OldId0);
  587. bool bOldId0=true;
  588. HRESULT hRes = m_pDIJoyCfg->GetConfig(0,&OldId0,DIJC_ALL);
  589. if(hRes==DIERR_NOTFOUND||hRes==S_FALSE)
  590. bOldId0=false;
  591. DIJOYCONFIG NewId0;
  592. ZeroMemory(&NewId0,sizeof(NewId0));
  593. NewId0.dwSize=sizeof(NewId0);
  594. bool bNewId0=true;
  595. hRes=m_pDIJoyCfg->GetConfig(nId,&NewId0,DIJC_ALL);
  596. if(hRes==DIERR_NOTFOUND||hRes==S_FALSE)
  597. bNewId0=false;
  598. if(bOldId0)
  599. m_pDIJoyCfg->SetConfig(nId,&OldId0,DIJC_ALL);
  600. else
  601. //We must still delete because GetConfig could fail for other
  602. //reasons than device with Id 0 not present.
  603. m_pDIJoyCfg->DeleteConfig(0);
  604. if(bNewId0)
  605. m_pDIJoyCfg->SetConfig(0,&NewId0,DIJC_ALL);
  606. m_pDIJoyCfg->SendNotify();
  607. m_pDIJoyCfg->Unacquire();
  608. }
  609. Update();
  610. }
  611. //Partialy copied from old joy.cpl.
  612. //I strongly suspect this is not documented anywhere.
  613. bool CCore::IsAvailableVIDPID(String &VIDPIDName)
  614. {
  615. if(!m_bInitialized)
  616. {
  617. throw JOY_EXCEPTION(E_FAIL);
  618. }
  619. HRESULT hRes=m_pDIJoyCfg->Acquire();
  620. if(FAILED(hRes))throw JOY_EXCEPTION(hRes);
  621. //Make the VID/PID to compare from the following formula:
  622. //VID_045e&PID_100+JOY_HW_LASTENTRY to 100+JOY_HW_LASTENTRY+0xf
  623. TCHAR Type[18];
  624. _tcsncpy(Type,_T("VID_045E&PID_0100"),18);
  625. Type[17] = 0;
  626. const WCHAR Lookup[]=_T("0123456789ABCDEF");
  627. int i=JOY_HW_LASTENTRY;
  628. do
  629. {
  630. if(i<0x10)
  631. {
  632. Type[16]=Lookup[i];
  633. }
  634. else
  635. {
  636. Type[15]=Lookup[1];
  637. Type[16]=Lookup[i%0x10];
  638. }
  639. i++;
  640. HKEY hKey;
  641. if(FAILED(m_pDIJoyCfg->OpenTypeKey(Type,KEY_READ,&hKey)))
  642. break;
  643. RegCloseKey(hKey);
  644. }
  645. while(i<(JOY_HW_LASTENTRY+0x11));
  646. m_pDIJoyCfg->Unacquire();
  647. if(i<0x1d)
  648. {
  649. VIDPIDName=Type;
  650. return true;
  651. }
  652. return false;
  653. }
  654. CGprtDev *CCore::FindGprtDev(LPCTSTR pTypeName)
  655. {
  656. if(!pTypeName)return NULL;
  657. if(!m_bInitialized)
  658. {
  659. throw JOY_EXCEPTION(E_FAIL);
  660. }
  661. for(LISTGPRTDEV::iterator It=m_GprtDev.begin();
  662. It!=m_GprtDev.end();It++)
  663. {
  664. if(It->m_Name==pTypeName)
  665. return &(*It);
  666. }
  667. return NULL;
  668. }
  669. bool CCore::IsCustomDevice(LPCTSTR pTypeName)
  670. {
  671. if(!pTypeName)return false;
  672. if(!m_bInitialized)
  673. {
  674. throw JOY_EXCEPTION(E_FAIL);
  675. }
  676. if(pTypeName[0]==_T('#'))return false;//Standard type.
  677. CGprtDev *pDevType=FindGprtDev(pTypeName);
  678. if(!pDevType)
  679. //This should never happend, but just in case.
  680. throw JOY_EXCEPTION(E_FAIL);
  681. if(!pDevType->m_Info.wszHardwareId[0])
  682. {
  683. if(!pDevType->m_Info.wszCallout[0])
  684. return true;
  685. }
  686. else
  687. {
  688. TCHAR AnalogRoot[]=_T("gameport\\vid_045e&pid_01");
  689. //Test if it is predefined custom. Do not delete.
  690. TCHAR C=pDevType->m_Info.wszHardwareId[(sizeof(AnalogRoot)/
  691. sizeof(AnalogRoot[0]))-1];
  692. if((C==_T('f'))||(C==_T('F')))
  693. return false;
  694. //Now test if it is custom.
  695. if(!_tcsnicmp(pDevType->m_Info.wszHardwareId,AnalogRoot,
  696. (sizeof(AnalogRoot)/sizeof(AnalogRoot[0]))-1))
  697. return true;
  698. }
  699. return false;
  700. }
  701. void CCore::DeleteType(LPCTSTR pTypeName)
  702. {
  703. if(!pTypeName)return;
  704. if(!m_bInitialized)
  705. {
  706. throw JOY_EXCEPTION(E_FAIL);
  707. }
  708. HRESULT hRes=m_pDIJoyCfg->Acquire();
  709. if(FAILED(hRes))throw JOY_EXCEPTION(hRes);
  710. m_pDIJoyCfg->DeleteType(pTypeName);
  711. m_pDIJoyCfg->Unacquire();
  712. UpdateType();
  713. }
  714. bool CCore::IsDeviceActive(LPCTSTR pTypeName)
  715. {
  716. if(!pTypeName)return false;
  717. if(!m_bInitialized)
  718. {
  719. throw JOY_EXCEPTION(E_FAIL);
  720. }
  721. for(LISTDIDEV::iterator It=m_ListDIDev.begin();
  722. It!=m_ListDIDev.end();It++)
  723. {
  724. DIJOYCONFIG JoyCfg;
  725. ZeroMemory(&JoyCfg,sizeof(JoyCfg));
  726. JoyCfg.dwSize=sizeof(JoyCfg);
  727. if(SUCCEEDED(m_pDIJoyCfg->GetConfig(It->Id(),&JoyCfg,
  728. DIJC_REGHWCONFIGTYPE)))
  729. {
  730. if(!_tcscmp(JoyCfg.wszType,pTypeName))
  731. return true;
  732. }
  733. }
  734. return false;
  735. }
  736. bool CCore::DuplicateDeviceName(LPCTSTR pName)
  737. {
  738. if(!m_bInitialized)
  739. {
  740. throw JOY_EXCEPTION(E_FAIL);
  741. }
  742. for(LISTGPRTDEV::iterator It=m_GprtDev.begin();
  743. It!=m_GprtDev.end();It++)
  744. {
  745. if(!_tcsncmp(pName,It->Name(),
  746. (sizeof(It->m_Info.wszDisplayName)/
  747. sizeof(It->m_Info.wszDisplayName[0]))-1))
  748. return true;
  749. }
  750. return false;
  751. }
  752. void CCore::AddCustomDevice(bool bJoy,bool bPad,bool bYoke,bool bCar,
  753. int nAxes,bool bZAxis,int nButtons,bool bHasPov,LPCTSTR pName,
  754. LPCTSTR pVIDPIDName)
  755. {
  756. if(!m_bInitialized)
  757. {
  758. throw JOY_EXCEPTION(E_FAIL);
  759. }
  760. String VIDPIDName=_T("GamePort\\");
  761. VIDPIDName+=pVIDPIDName;
  762. HRESULT hRes=m_pDIJoyCfg->Acquire();
  763. if(FAILED(hRes))throw JOY_EXCEPTION(hRes);
  764. DIJOYTYPEINFO JTI;
  765. ZeroMemory(&JTI,sizeof(JTI));
  766. JTI.dwSize=sizeof(JTI);
  767. int nCh=sizeof(JTI.wszDisplayName)/
  768. sizeof(JTI.wszDisplayName[0]);
  769. _tcsncpy(JTI.wszDisplayName,pName,nCh);
  770. JTI.wszDisplayName[nCh-1]=0;
  771. JTI.hws.dwNumButtons=nButtons;
  772. if(nAxes==3)
  773. {
  774. if(bZAxis)
  775. JTI.hws.dwFlags|=JOY_HWS_HASZ;
  776. else
  777. JTI.hws.dwFlags|=JOY_HWS_HASR;
  778. }
  779. else if(nAxes==4)
  780. {
  781. JTI.hws.dwFlags|=JOY_HWS_HASR|JOY_HWS_HASZ;
  782. }
  783. if(bHasPov)
  784. JTI.hws.dwFlags|=JOY_HWS_HASPOV|JOY_HWS_POVISBUTTONCOMBOS;
  785. if(!bJoy)
  786. {
  787. if(bPad)
  788. {
  789. JTI.hws.dwFlags|=JOY_HWS_ISGAMEPAD;
  790. }
  791. else if(bCar)
  792. {
  793. JTI.hws.dwFlags|=JOY_HWS_ISCARCTRL;
  794. }
  795. else
  796. {
  797. JTI.hws.dwFlags|=JOY_HWS_ISYOKE;
  798. }
  799. }
  800. nCh=sizeof(JTI.wszHardwareId)/
  801. sizeof(JTI.wszHardwareId[0]);
  802. _tcsncpy(JTI.wszHardwareId,VIDPIDName.data(),nCh);
  803. JTI.wszDisplayName[nCh-1]=0;
  804. hRes=m_pDIJoyCfg->SetTypeInfo(pVIDPIDName,&JTI,
  805. DITC_DISPLAYNAME|DITC_CLSIDCONFIG|
  806. DITC_REGHWSETTINGS|DITC_HARDWAREID,NULL);
  807. m_pDIJoyCfg->Unacquire();
  808. if(FAILED(hRes))throw JOY_EXCEPTION(hRes);
  809. UpdateType();
  810. }
  811. /******************************************************************************
  812. UI
  813. ******************************************************************************/
  814. /******************************************************************************
  815. UI header
  816. ******************************************************************************/
  817. class CDlgProcHandler//this is not in CDlg because we want to reuse for property sheets...
  818. {
  819. protected:
  820. HWND m_hWnd;
  821. HMODULE m_hModule;
  822. static INT_PTR CALLBACK DialogProc
  823. (HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam);
  824. virtual INT_PTR DialogProc(UINT uMsg,WPARAM wParam,LPARAM lParam);
  825. virtual BOOL InitDialog(HWND hFocus,LPARAM lParam){return TRUE;};
  826. virtual BOOL Timer(WPARAM wTimerID){return FALSE;};
  827. virtual INT_PTR Command(WORD wNotifyCode,WORD wID,HWND hwndCtl);
  828. virtual INT_PTR Notify(int idCtrl,LPNMHDR pnmh){return 0;};
  829. HWND HDlgItem(int nIDDlgItem){return GetDlgItem(m_hWnd,nIDDlgItem);};
  830. public:
  831. CDlgProcHandler(){m_hWnd=NULL;m_hModule=NULL;};
  832. };
  833. class CDlg:public CDlgProcHandler
  834. {
  835. protected:
  836. virtual INT_PTR DialogProc(UINT uMsg,WPARAM wParam,LPARAM lParam);
  837. virtual INT_PTR Command(WORD wNotifyCode,WORD wID,HWND hwndCtl);
  838. public:
  839. int Dlg(WORD wID,HMODULE hModule,HWND hParent);
  840. };
  841. int CDlg::Dlg(WORD wID,HMODULE hModule,HWND hParent)
  842. {
  843. m_hModule=hModule;
  844. return DialogBoxParam(hModule,MAKEINTRESOURCE(wID),hParent,
  845. CDlgProcHandler::DialogProc,(LPARAM)this);
  846. }
  847. typedef list<GUID> LISTGUID;
  848. class CMainDlg;
  849. class CPreferredDlg:public CDlg
  850. {
  851. LISTGUID m_ListCtrl;
  852. bool m_bBlockUpdate;
  853. CCore *m_pCore;
  854. CMainDlg *m_pMainDlg;
  855. virtual BOOL InitDialog(HWND hFocus,LPARAM lParam);
  856. virtual INT_PTR Command(WORD wNotifyCode,WORD wID,HWND hwndCtl);
  857. void Preferred();
  858. INT_PTR Notify(int idCtrl,LPNMHDR pnmh);
  859. public:
  860. CPreferredDlg(CMainDlg *pMainDlg,CCore *pCore)
  861. {m_pMainDlg=pMainDlg;m_pCore=pCore;m_bBlockUpdate=false;};
  862. void Update();
  863. };
  864. class CAddDlg:public CDlg
  865. {
  866. CCore *m_pCore;
  867. // CMainDlg *m_pMainDlg;
  868. LISTSTRING m_ListCtrl;
  869. LISTSTRING m_GprtListCtrl;
  870. bool m_bBlockUpdate;
  871. BOOL InitDialog(HWND hFocus,LPARAM lParam);
  872. INT_PTR Command(WORD wNotifyCode,WORD wID,HWND hwndCtl);
  873. void AddDev();
  874. INT_PTR DialogProc(UINT uMsg,WPARAM wParam,LPARAM lParam);
  875. public:
  876. CAddDlg(/*CMainDlg *pMainDlg,*/CCore *pCore)
  877. {/*m_pMainDlg=pMainDlg;*/m_pCore=pCore;m_bBlockUpdate=false;};
  878. void Update();
  879. };
  880. class CCustomDlg:public CDlg
  881. {
  882. CCore *m_pCore;
  883. String m_VIDPIDName;
  884. BOOL InitDialog(HWND hFocus,LPARAM lParam);
  885. INT_PTR Command(WORD wNotifyCode,WORD wID,HWND hwndCtl);
  886. public:
  887. CCustomDlg(CCore *pCore){m_pCore=pCore;};
  888. LPCTSTR GetVIDPIDName(){return m_VIDPIDName.data();};
  889. };
  890. class CMainDlg:public CDlg
  891. {
  892. LISTGUID m_ListCtrl;
  893. bool m_bBlockUpdate;
  894. CCore *m_pCore;
  895. CPreferredDlg *m_pPrefDlg;
  896. CAddDlg *m_pAddDlg;
  897. bool m_bEditingName;
  898. virtual BOOL InitDialog(HWND hFocus,LPARAM lParam);
  899. virtual BOOL Timer(WPARAM wTimerID);
  900. virtual INT_PTR Command(WORD wNotifyCode,WORD wID,HWND hwndCtl);
  901. INT_PTR DialogProc(UINT uMsg,WPARAM wParam,LPARAM lParam);
  902. INT_PTR Notify(int idCtrl,LPNMHDR pnmh);
  903. void Remove();
  904. void Prop();
  905. protected:
  906. CMainDlg(){m_pCore=NULL;m_bBlockUpdate=false;m_pPrefDlg=NULL;m_pAddDlg=NULL;m_bEditingName=false;};
  907. void ConnectUI(CCore *pCore){m_pCore=pCore;};
  908. void Update();
  909. void CoreUpdate();
  910. };
  911. class CUpdate
  912. {
  913. bool *m_pbBlockUpdate;
  914. public:
  915. CUpdate(bool *pbBlockUpdate)
  916. {m_pbBlockUpdate=pbBlockUpdate;*m_pbBlockUpdate=true;};
  917. ~CUpdate(){*m_pbBlockUpdate=false;};
  918. };
  919. /******************************************************************************
  920. End of UI header
  921. ******************************************************************************/
  922. #define DEVICE_COLUMN 0
  923. #define STATUS_COLUMN 1
  924. LPTSTR Insert1String(LPCTSTR pS,LPCTSTR pI)
  925. {
  926. LPTSTR pR=new TCHAR[_tcslen(pS)+_tcslen(pI)+1];
  927. wsprintf(pR,pS,pI);
  928. return pR;
  929. }
  930. LPTSTR Insert2Strings(LPCTSTR pS,LPCTSTR pI1,LPCTSTR pI2)
  931. {
  932. LPTSTR pR=new TCHAR[_tcslen(pS)+_tcslen(pI1)+_tcslen(pI2)+1];
  933. wsprintf(pR,pS,pI1,pI2);
  934. return pR;
  935. }
  936. void MessageBox(HWND hWnd,HINSTANCE hInstance,UINT uTitleID,UINT uMsgID)
  937. {
  938. TCHAR Title[128];
  939. TCHAR Msg[256];
  940. LoadString(hInstance,uTitleID, Title, cA(Title));
  941. LoadString(hInstance,uMsgID, Msg, cA(Msg));
  942. UINT uRTL = (GetWindowLongPtr(hWnd,GWL_EXSTYLE) & WS_EX_LAYOUTRTL) ? MB_RTLREADING : 0;
  943. MessageBox(hWnd,Msg,Title,MB_ICONHAND|MB_OK|MB_APPLMODAL|uRTL);
  944. }
  945. void LVSetItem(HWND hCtrl,int nItem,int nSubItem, LPCTSTR lpStr)
  946. {
  947. LVITEM Item;
  948. ZeroMemory(&Item,sizeof(Item));
  949. Item.mask=LVIF_TEXT;
  950. Item.iItem=nItem;
  951. Item.iSubItem=nSubItem;
  952. Item.cchTextMax=lstrlen(lpStr);
  953. Item.pszText=(LPTSTR)lpStr;
  954. SendMessage(hCtrl,LVM_SETITEM,0,(LPARAM)(const LPLVITEM)&Item);
  955. }
  956. void LVInsertItem(HWND hCtrl,int nItem,int nSubItem,LPCTSTR lpStr,LPARAM lData)
  957. {
  958. LVITEM Item;
  959. ZeroMemory(&Item,sizeof(Item));
  960. Item.mask=LVIF_TEXT|LVIF_PARAM;
  961. Item.iItem=nItem;
  962. Item.cchTextMax=lstrlen(lpStr);
  963. Item.pszText=(LPTSTR)lpStr;
  964. Item.lParam=lData;
  965. SendMessage(hCtrl,LVM_INSERTITEM,0,(LPARAM)(const LPLVITEM)&Item);
  966. }
  967. void *LVGetItemDataPtr(HWND hCtrl,int nItem)
  968. {
  969. LVITEM Item;
  970. ZeroMemory(&Item,sizeof(LVITEM));
  971. Item.mask=LVIF_PARAM;
  972. Item.iItem=nItem;
  973. if(SendMessage(hCtrl,LVM_GETITEM,0,(LPARAM)(LPLVITEM)&Item))
  974. return(void*)Item.lParam;
  975. return NULL;
  976. }
  977. const GUID &LVGetItemGUID(HWND hCtrl,int nItem)
  978. {
  979. if(nItem<0)return NULLGUID;
  980. GUID *pG=(GUID*)LVGetItemDataPtr(hCtrl,nItem);
  981. if(pG)return *pG;
  982. return NULLGUID;
  983. }
  984. int LVFindGUIDIndex(HWND hCtrl,GUID &G)
  985. {
  986. int nCnt=ListView_GetItemCount(hCtrl);
  987. for(int i=0;i<nCnt;i++)
  988. if(G==LVGetItemGUID(hCtrl,i))return i;
  989. return -1;
  990. }
  991. int LVGetSel(HWND hCtrl)
  992. {
  993. return ListView_GetNextItem(hCtrl,-1,LVNI_SELECTED);
  994. }
  995. void LVSetSel(HWND hCtrl,int nItem,bool bSel=true)
  996. {
  997. if(bSel)
  998. ListView_SetItemState(hCtrl,nItem,
  999. LVIS_FOCUSED|LVIS_SELECTED,0x000F)
  1000. else
  1001. ListView_SetItemState(hCtrl,nItem,
  1002. 0,0x000F);
  1003. }
  1004. void LVInsertColumn (HWND hCtrl,int nColumn,UINT uID,int nWidth,HINSTANCE hInstance)
  1005. {
  1006. LVCOLUMN Col;
  1007. ZeroMemory(&Col,sizeof(Col));
  1008. Col.mask=LVCF_FMT|LVCF_TEXT|LVCF_WIDTH;
  1009. Col.fmt=LVCFMT_CENTER;
  1010. Col.cx=nWidth;
  1011. TCHAR S[128];
  1012. LoadString(hInstance,uID, S, cA(S));
  1013. Col.pszText=(LPTSTR)S;
  1014. SendMessage(hCtrl,LVM_INSERTCOLUMN,(WPARAM)(int)nColumn,(LPARAM)(const LPLVCOLUMN)&Col);
  1015. }
  1016. INT_PTR CDlgProcHandler::DialogProc(UINT uMsg,WPARAM wParam,LPARAM lParam)
  1017. {
  1018. switch(uMsg)
  1019. {
  1020. case WM_INITDIALOG:
  1021. return InitDialog((HWND)wParam,lParam);
  1022. case WM_TIMER:
  1023. return Timer(wParam);
  1024. case WM_COMMAND:
  1025. return Command(HIWORD(wParam),LOWORD(wParam),(HWND)lParam);
  1026. case WM_NOTIFY:
  1027. return Notify((int)wParam,(LPNMHDR)lParam);
  1028. case WM_CONTEXTMENU:
  1029. {
  1030. TCHAR HelpFileName[128];
  1031. LoadString(m_hModule,IDS_HELPFILENAME, HelpFileName, cA(HelpFileName));
  1032. WinHelp((HWND)wParam,HelpFileName,HELP_CONTEXTMENU,(ULONG_PTR)gaHelpIDs);
  1033. }
  1034. //Undocumented in msdn but otherwise
  1035. //problem rightclicking title to close.
  1036. return TRUE;
  1037. default:
  1038. return FALSE;
  1039. }
  1040. return FALSE;
  1041. }
  1042. INT_PTR CDlgProcHandler::Command(WORD wNotifyCode,WORD wID,HWND hwndCtl)
  1043. {
  1044. switch(wID)
  1045. {
  1046. case IDC_WHATSTHIS:
  1047. {
  1048. TCHAR HelpFileName[128];
  1049. LoadString(m_hModule,IDS_HELPFILENAME, HelpFileName, cA(HelpFileName));
  1050. WinHelp(hwndCtl,HelpFileName,HELP_WM_HELP,(ULONG_PTR)gaHelpIDs);
  1051. }
  1052. return 0;
  1053. }
  1054. return 0;
  1055. };
  1056. INT_PTR CALLBACK CDlgProcHandler::DialogProc
  1057. (HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
  1058. {
  1059. CDlgProcHandler* pH=NULL;
  1060. try
  1061. {
  1062. if(uMsg==WM_INITDIALOG)
  1063. {
  1064. SetLastError(0);
  1065. LONG lRet=SetWindowLongPtr(hwndDlg,GWLP_USERDATA,lParam);
  1066. if(GetLastError()&&!lRet) {
  1067. EndDialog(hwndDlg,E_FAIL);
  1068. }
  1069. }
  1070. pH=(CDlgProcHandler*)GetWindowLongPtr(hwndDlg,GWLP_USERDATA);
  1071. if(pH && !IsBadReadPtr(pH, sizeof(CDlgProcHandler)))
  1072. {
  1073. if(uMsg==WM_INITDIALOG) {
  1074. pH->m_hWnd=hwndDlg;
  1075. }
  1076. if( pH->m_hWnd == hwndDlg ) {
  1077. return pH->DialogProc(uMsg,wParam,lParam);
  1078. }
  1079. }
  1080. return FALSE;
  1081. }
  1082. catch(JoyException E)
  1083. {
  1084. if(pH)
  1085. {
  1086. if(uMsg==WM_INITDIALOG) {
  1087. EndDialog(pH->m_hWnd,IDCANCEL);
  1088. }
  1089. }
  1090. }
  1091. catch(...)
  1092. {
  1093. if(pH && !IsBadReadPtr(pH, sizeof(CDlgProcHandler))) {
  1094. EndDialog(pH->m_hWnd, IDCANCEL);
  1095. }
  1096. //should report error here, and keep going.
  1097. }
  1098. if(uMsg==WM_INITDIALOG) {
  1099. return TRUE;
  1100. }
  1101. return FALSE;
  1102. }
  1103. /******************************************************************************
  1104. CDlg
  1105. ******************************************************************************/
  1106. INT_PTR CDlg::Command(WORD wNotifyCode,WORD wID,HWND hwndCtl)
  1107. {
  1108. switch(wID)
  1109. {
  1110. case IDOK:
  1111. if(!(wNotifyCode&~1))
  1112. EndDialog(m_hWnd,IDOK);
  1113. return 0;
  1114. case IDCANCEL:
  1115. if(!(wNotifyCode&~1))
  1116. EndDialog(m_hWnd,IDCANCEL);
  1117. return 0;
  1118. }
  1119. return CDlgProcHandler::Command(wNotifyCode,wID,hwndCtl);
  1120. };
  1121. INT_PTR CDlg::DialogProc(UINT uMsg,WPARAM wParam,LPARAM lParam)
  1122. {
  1123. switch(uMsg)
  1124. {
  1125. case WM_CLOSE:
  1126. EndDialog(m_hWnd,0);
  1127. return 0;
  1128. }
  1129. return CDlgProcHandler::DialogProc(uMsg,wParam,lParam);
  1130. }
  1131. /******************************************************************************
  1132. Main dialog CMainDlg
  1133. ******************************************************************************/
  1134. void CMainDlg::Remove()
  1135. {
  1136. {
  1137. if(!m_pCore->Access())
  1138. {
  1139. MessageBox(m_hWnd,m_hModule,IDS_USER_MODE_TITLE,IDS_USER_MODE);
  1140. return;
  1141. }
  1142. HWND hListCtrl=HDlgItem(IDC_LIST_DEVICE);
  1143. if(hListCtrl)
  1144. {
  1145. int nSelDev=LVGetSel(hListCtrl);
  1146. if(nSelDev<0)return;
  1147. GUID G=LVGetItemGUID(hListCtrl,nSelDev);
  1148. CDIDev *pDev=m_pCore->FindDIDev(G);
  1149. if(!pDev) {
  1150. return;
  1151. }
  1152. TCHAR AreSure[256];
  1153. LoadString(m_hModule,IDS_GEN_AREYOUSURE, AreSure, cA(AreSure));
  1154. LPTSTR pT = Insert1String(AreSure,pDev->InstName());
  1155. lstrcpy(AreSure, pT);
  1156. delete[] pT;
  1157. TCHAR Title[128];
  1158. LoadString(m_hModule,IDS_GEN_AREYOUSURE_TITLE, Title, cA(Title));
  1159. UINT uRTL = (GetWindowLongPtr(m_hWnd,GWL_EXSTYLE) & WS_EX_LAYOUTRTL) ? MB_RTLREADING : 0;
  1160. if(IDYES!=MessageBox(m_hWnd,AreSure,Title,MB_ICONQUESTION|MB_YESNO|MB_APPLMODAL|uRTL)) {
  1161. return;
  1162. }
  1163. if(m_pCore->Remove(G)==DIERR_UNSUPPORTED) {
  1164. MessageBox(m_hWnd,m_hModule,IDS_GEN_AREYOUSURE_TITLE,IDS_GEN_NO_REMOVE_USB);
  1165. }
  1166. }
  1167. }
  1168. CoreUpdate();
  1169. }
  1170. void OnHelp(LPHELPINFO pHelpInfo,HINSTANCE hInstance)
  1171. {
  1172. TCHAR FileName[256];
  1173. LoadString(hInstance,IDS_HELPFILENAME, FileName, cA(FileName));
  1174. if(pHelpInfo->iContextType==HELPINFO_WINDOW)
  1175. WinHelp((HWND)pHelpInfo->hItemHandle,FileName,HELP_WM_HELP,(ULONG_PTR)gaHelpIDs);
  1176. }
  1177. INT_PTR CMainDlg::DialogProc(UINT uMsg,WPARAM wParam,LPARAM lParam)
  1178. {
  1179. switch(uMsg)
  1180. {
  1181. case WM_ACTIVATEAPP:
  1182. CoreUpdate();
  1183. return 0;
  1184. /* case WM_POWERBROADCAST:
  1185. switch( wParam )
  1186. {
  1187. return 0;
  1188. case PBT_APMSUSPEND:
  1189. // Suspend operation!
  1190. KillTimer(hDlg, ID_MYTIMER);
  1191. break;
  1192. case PBT_APMRESUMESUSPEND:
  1193. case PBT_APMRESUMECRITICAL:
  1194. // Resume operation!
  1195. SetActive(hDlg);
  1196. break;
  1197. }
  1198. break;return 0;*/
  1199. case WM_DEVICECHANGE:
  1200. CoreUpdate();
  1201. return 0;
  1202. case WM_HELP:
  1203. OnHelp((LPHELPINFO)lParam,m_hModule);
  1204. return 0;
  1205. /* nFlags &= ~ON_PAGE;
  1206. KillTimer(hDlg, ID_MYTIMER);
  1207. OnContextMenu(wParam, lParam);
  1208. nFlags |= ON_PAGE;
  1209. SetTimer(hDlg, ID_MYTIMER, POLLRATE, 0);
  1210. return(1); return 0;???
  1211. */
  1212. case WM_SYSCOLORCHANGE:
  1213. {
  1214. HWND hListCtrl=HDlgItem(IDC_LIST_DEVICE);
  1215. if(hListCtrl)
  1216. {
  1217. SendMessage(hListCtrl,WM_SYSCOLORCHANGE,0,0);
  1218. }
  1219. }
  1220. return 0;
  1221. }
  1222. return CDlg::DialogProc(uMsg,wParam,lParam);
  1223. }
  1224. void CMainDlg::Prop()
  1225. {
  1226. HWND hListCtrl=HDlgItem(IDC_LIST_DEVICE);
  1227. if(hListCtrl)
  1228. {
  1229. int nSelDev=LVGetSel(hListCtrl);
  1230. if(nSelDev<0)return;
  1231. GUID G=LVGetItemGUID(hListCtrl,nSelDev);
  1232. CDIDev *pDev=m_pCore->FindDIDev(G);
  1233. //ISSUE-2001/03/29-timgill internal error;SHOULD ASSERT HERE
  1234. if(!pDev)return;
  1235. //need to kill the timer before launching property sheet - see Whistler bug 260145 for details
  1236. KillTimer(m_hWnd,1);
  1237. switch(Properties(m_hModule,m_hWnd,m_pCore,pDev->Id()))
  1238. {
  1239. case E_NOINTERFACE:
  1240. MessageBox(m_hWnd,m_hModule,IDS_INTERNAL_ERROR,IDS_NO_DIJOYCONFIG);
  1241. break;
  1242. default://Not handled for now or ever?
  1243. break;
  1244. };
  1245. //now update and re-set the timer
  1246. m_pCore->Update();
  1247. SetTimer(m_hWnd,1,5000,NULL);
  1248. }
  1249. }
  1250. INT_PTR CMainDlg::Command(WORD wNotifyCode,WORD wID,HWND hwndCtl)
  1251. {
  1252. switch(wID)
  1253. {
  1254. case IDC_BTN_ADV:
  1255. if(!m_pCore->Access()) {
  1256. MessageBox(m_hWnd,m_hModule,IDS_USER_MODE_TITLE,IDS_USER_MODE);
  1257. } else {
  1258. if(!m_pPrefDlg)
  1259. {
  1260. CPreferredDlg PrefDlg(this,m_pCore);
  1261. m_pPrefDlg=&PrefDlg;
  1262. PrefDlg.Dlg(IDD_ADV_CHANGE,m_hModule,m_hWnd);
  1263. m_pPrefDlg=NULL;
  1264. }
  1265. }
  1266. return 0;
  1267. case IDC_BTN_REMOVE:
  1268. Remove();
  1269. return 0;
  1270. case IDC_BTN_ADD:
  1271. if(!m_pCore->Access()) {
  1272. MessageBox(m_hWnd,m_hModule,IDS_USER_MODE_TITLE,IDS_USER_MODE);
  1273. } else {
  1274. if(!m_pAddDlg)
  1275. {
  1276. CAddDlg AddDlg(m_pCore);
  1277. m_pAddDlg=&AddDlg;
  1278. AddDlg.Dlg(IDD_ADD,m_hModule,m_hWnd);
  1279. m_pAddDlg=NULL;
  1280. }
  1281. }
  1282. return 0;
  1283. case IDC_BTN_TSHOOT:
  1284. {
  1285. TCHAR ExeBuff[MAX_PATH];
  1286. if( GetWindowsDirectory(ExeBuff,MAX_PATH) ) {
  1287. TCHAR CmdBuff[256];
  1288. LoadString(m_hModule,IDS_TSHOOT_CMD, CmdBuff, cA(CmdBuff));
  1289. STARTUPINFO Si;
  1290. PROCESS_INFORMATION Pi;
  1291. ZeroMemory(&Si,sizeof(Si));
  1292. ZeroMemory(&Pi,sizeof(Pi));
  1293. Si.cb=sizeof(Si);
  1294. // ISSUE-2000/12/20-MarcAnd Quick Fix to use HSS
  1295. // In other places where HSS is used, STARTF_FORCEONFEEDBACK is not set
  1296. // Changed IDS_TSHOOT_CMD from: "hh.exe joy.chm"
  1297. // to "explorer.exe hcp://help/tshoot/tsInputDev.htm"
  1298. // Need to make this OS specific to allow backprop to Win2k (or further)
  1299. Si.dwFlags=STARTF_USESHOWWINDOW|STARTF_FORCEONFEEDBACK;
  1300. Si.wShowWindow=SW_NORMAL;
  1301. ExeBuff[MAX_PATH-1]=0;
  1302. String Exe=ExeBuff;
  1303. String Cmd=CmdBuff;
  1304. if(Exe[Exe.size()-1]!=_T('\\'))
  1305. {
  1306. Exe+=_T('\\');
  1307. }
  1308. Exe+=_T("explorer.exe");
  1309. Cmd=_T("\"")+Exe+_T("\"")+_T(" ")+Cmd;
  1310. if(CreateProcess(Exe.data(),(LPTSTR)Cmd.data(),0,0,0,0,0,0,&Si,&Pi))
  1311. {
  1312. CloseHandle(Pi.hThread);
  1313. CloseHandle(Pi.hProcess);
  1314. }
  1315. } else {
  1316. // something is wrong when calling GetWindowsDirectory
  1317. ;
  1318. }
  1319. }
  1320. return 0;
  1321. case IDC_BTN_PROPERTIES:
  1322. Prop();
  1323. return 0;
  1324. }
  1325. return CDlg::Command(wNotifyCode,wID,hwndCtl);
  1326. };
  1327. INT_PTR CMainDlg::Notify(int idCtrl,LPNMHDR pnmh)
  1328. {
  1329. switch(pnmh->code )
  1330. {
  1331. /* Keeping this just in case someone changes his/her mind soon.
  1332. case LVN_BEGINLABELEDIT:
  1333. {
  1334. HWND hListCtrl=HDlgItem(IDC_LIST_DEVICE);
  1335. if(!hListCtrl)return TRUE;
  1336. if(!m_pCore->Access())return TRUE;
  1337. PostMessage((HWND)::SendMessage(hListCtrl,LVM_GETEDITCONTROL,0,0),EM_SETLIMITTEXT,MAX_PATH-1,0);
  1338. m_bEditingName=true;
  1339. return(FALSE);
  1340. }
  1341. case LVN_ENDLABELEDIT:
  1342. {
  1343. m_bEditingName=false;
  1344. HWND hListCtrl=HDlgItem(IDC_LIST_DEVICE);
  1345. if(!hListCtrl)
  1346. {
  1347. CoreUpdate();
  1348. return FALSE;
  1349. }
  1350. HWND hCtrl=(HWND)SendMessage(hListCtrl,LVM_GETEDITCONTROL,0,0);
  1351. if(hCtrl)
  1352. {
  1353. if(SendMessage(hCtrl,EM_GETMODIFY,0,0))
  1354. {
  1355. int nLen=lstrlen(((NMLVDISPINFO*)pnmh)->item.pszText);
  1356. if((nLen>(MAX_PATH-1))||(nLen==0))
  1357. MessageBeep(MB_ICONHAND);
  1358. //Make sure the name is usable.
  1359. else if(_tcschr(((NMLVDISPINFO*)pnmh)->item.pszText,TEXT('\\')))
  1360. MessageBox(m_hWnd,m_hModule,IDS_INVALID_NAME_TITLE,IDS_INVALID_NAME);
  1361. else
  1362. {
  1363. int nSelDev=LVGetSel(hListCtrl);
  1364. GUID SelGUID=LVGetItemGUID(hListCtrl,nSelDev);
  1365. CDIDev *pSelDev=m_pCore->FindDIDev(SelGUID);
  1366. if(SUCCEEDED(pSelDev->Rename(((NMLVDISPINFO *)pnmh)->item.pszText)))
  1367. {
  1368. CoreUpdate();
  1369. return TRUE;
  1370. }
  1371. else
  1372. {
  1373. MessageBox(m_hWnd,m_hModule,IDS_NO_RENAME_TITLE,IDS_NO_RENAME);
  1374. }
  1375. }
  1376. }
  1377. }
  1378. CoreUpdate();
  1379. return FALSE;
  1380. }*/
  1381. case LVN_KEYDOWN:
  1382. switch(((LV_KEYDOWN*)pnmh)->wVKey)
  1383. {
  1384. case VK_DELETE:
  1385. Remove();
  1386. return 0;
  1387. case VK_F5:
  1388. CoreUpdate();
  1389. return 0;
  1390. }
  1391. return 0;
  1392. case LVN_ITEMCHANGED:
  1393. if(!(((LPNMLISTVIEW)pnmh)->uOldState&LVIS_SELECTED)&&
  1394. (((LPNMLISTVIEW)pnmh)->uNewState&LVIS_SELECTED)&&
  1395. (((LPNMLISTVIEW)pnmh)->uChanged&LVIF_STATE))
  1396. Update();
  1397. return 0;
  1398. case NM_DBLCLK:
  1399. switch(idCtrl)
  1400. {
  1401. case IDC_LIST_DEVICE:
  1402. Prop();
  1403. return 0;
  1404. }
  1405. return 0;
  1406. }
  1407. return 0;
  1408. }
  1409. void CMainDlg::CoreUpdate()
  1410. {
  1411. m_pCore->Update();
  1412. //KillTimer so if UI is updated for some other reason than WM_TIMER timer will be reset.
  1413. //make sure nothing can fail between KillTimer and SetTimer.
  1414. KillTimer(m_hWnd,1);
  1415. SetTimer(m_hWnd,1,5000,NULL);
  1416. }
  1417. BOOL CMainDlg::InitDialog(HWND hFocus,LPARAM lParam)
  1418. {
  1419. SetTimer(m_hWnd,1,5000,NULL);
  1420. m_pCore->Initialize(m_hWnd);
  1421. //#wi315410. we need to decide...
  1422. // m_pCore->UpdateType();
  1423. HWND hListCtrl=HDlgItem(IDC_LIST_DEVICE);
  1424. if(hListCtrl)
  1425. {
  1426. SendMessage(hListCtrl,LVM_SETEXTENDEDLISTVIEWSTYLE,0,LVS_EX_FULLROWSELECT);
  1427. RECT R;
  1428. GetClientRect(hListCtrl,&R);
  1429. int nWidth=(R.right>>2)*3;
  1430. LVInsertColumn(hListCtrl,DEVICE_COLUMN,IDS_GEN_DEVICE_HEADING,nWidth,m_hModule);
  1431. LVInsertColumn(hListCtrl,STATUS_COLUMN,IDS_GEN_STATUS_HEADING,R.right-nWidth,m_hModule);
  1432. }
  1433. CoreUpdate();
  1434. return TRUE;
  1435. }
  1436. BOOL CMainDlg::Timer(WPARAM wTimerID)
  1437. {
  1438. CoreUpdate();
  1439. return FALSE;
  1440. }
  1441. void CMainDlg::Update()
  1442. {
  1443. if(m_pPrefDlg)m_pPrefDlg->Update();
  1444. if(m_bEditingName)return;//Do not update this dialog when editing name.
  1445. if(m_bBlockUpdate)return;//Some actions may send notify messages which then Update and overflow stack.
  1446. CUpdate U(&m_bBlockUpdate);
  1447. int nSelDev=-1;
  1448. GUID SelGUID=NULLGUID;
  1449. HWND hListCtrl=HDlgItem(IDC_LIST_DEVICE);
  1450. if(hListCtrl)
  1451. {
  1452. nSelDev=LVGetSel(hListCtrl);
  1453. SelGUID=LVGetItemGUID(hListCtrl,nSelDev);
  1454. SendMessage(hListCtrl,WM_SETREDRAW,(WPARAM)FALSE,0);
  1455. SendMessage(hListCtrl,LVM_DELETEALLITEMS,0,0);
  1456. m_ListCtrl.clear();//Must be behind LVM_DELETEALLITEMS
  1457. int nIndex=0;
  1458. for(LISTDIDEV::iterator It=m_pCore->m_ListDIDev.begin();
  1459. It!=m_pCore->m_ListDIDev.end();It++)
  1460. {
  1461. GUID G=It->InstGUID();
  1462. m_ListCtrl.push_back(G);
  1463. LVInsertItem(hListCtrl,nIndex,DEVICE_COLUMN,
  1464. It->InstName(),(LPARAM)&m_ListCtrl.back());
  1465. TCHAR Status[256];
  1466. if(It->Status()==ENotConnected) {
  1467. LoadString(m_hModule,IDS_GEN_STATUS_NOTCONNECTED, Status, cA(Status));
  1468. } else if(It->Status()==EConnected) {
  1469. LoadString(m_hModule,IDS_GEN_STATUS_OK, Status, cA(Status));
  1470. } else {
  1471. LoadString(m_hModule,IDS_GEN_STATUS_UNKNOWN, Status, cA(Status));
  1472. }
  1473. LVSetItem(hListCtrl,nIndex,STATUS_COLUMN,Status);
  1474. nIndex++;
  1475. }
  1476. nSelDev=LVFindGUIDIndex(hListCtrl,SelGUID);
  1477. if(nSelDev>=0)
  1478. {
  1479. LVSetSel(hListCtrl,nSelDev);
  1480. }
  1481. else
  1482. LVSetSel(hListCtrl,0);
  1483. nSelDev=LVGetSel(hListCtrl);
  1484. SendMessage(hListCtrl,WM_SETREDRAW,(WPARAM)TRUE,0);
  1485. InvalidateRect(hListCtrl,NULL,TRUE);
  1486. SelGUID=LVGetItemGUID(hListCtrl,nSelDev);
  1487. }
  1488. CDIDev *pSelDev=m_pCore->FindDIDev(SelGUID);
  1489. //#wi315410. we need to decide...
  1490. // HWND hAddBtn=HDlgItem(IDC_BTN_ADD);
  1491. // if(hAddBtn)
  1492. // {
  1493. // BOOL bE=(m_pCore->m_GprtBus.size()>0)?TRUE:FALSE;
  1494. // EnableWindow(hAddBtn,bE);
  1495. // }
  1496. HWND hRemBtn=HDlgItem(IDC_BTN_REMOVE);
  1497. if(hRemBtn)
  1498. {
  1499. BOOL bE=(nSelDev>=0)?TRUE:FALSE;
  1500. EnableWindow(hRemBtn,bE);
  1501. }
  1502. HWND hPropBtn=HDlgItem(IDC_BTN_PROPERTIES);
  1503. if(hPropBtn)
  1504. {
  1505. BOOL bE=FALSE;
  1506. if((nSelDev>=0)&&pSelDev)
  1507. if(pSelDev->Status()==EConnected)
  1508. bE=TRUE;
  1509. EnableWindow(hPropBtn,bE);
  1510. }
  1511. }
  1512. /******************************************************************************
  1513. Add dialog
  1514. ******************************************************************************/
  1515. int CBGetCurSel(HWND hCtrl)
  1516. {
  1517. int i=ComboBox_GetCurSel(hCtrl);
  1518. if(i==CB_ERR)
  1519. i=-1;
  1520. return i;
  1521. }
  1522. int CBGetCnt(HWND hCtrl)
  1523. {
  1524. int i=ComboBox_GetCount(hCtrl);
  1525. if(i==CB_ERR)
  1526. i=0;
  1527. return i;
  1528. }
  1529. const GUID &CBGetItemGUID(HWND hCtrl,int iIndex)
  1530. {
  1531. LRESULT p=ComboBox_GetItemData(hCtrl,iIndex);
  1532. if(p==CB_ERR)return NULLGUID;
  1533. if(p)
  1534. return *(GUID*)p;
  1535. return NULLGUID;
  1536. }
  1537. int CBFindGUIDIndex(HWND hCtrl,const GUID &G)
  1538. {
  1539. int nCnt=ComboBox_GetCount(hCtrl);
  1540. if(nCnt==CB_ERR)return -1;
  1541. for(int i=0;i<nCnt;i++)
  1542. {
  1543. if(CBGetItemGUID(hCtrl,i)==G)
  1544. return i;
  1545. }
  1546. return -1;
  1547. }
  1548. LPCTSTR CBGetItemTypeName(HWND hCtrl,int iIndex)
  1549. {
  1550. LRESULT p=ComboBox_GetItemData(hCtrl,iIndex);
  1551. if(p==CB_ERR)return NULL;
  1552. if(p)
  1553. return ((String*)p)->data();
  1554. return NULL;
  1555. }
  1556. int CBFindTypeNameIndex(HWND hCtrl,LPCTSTR pTypeName)
  1557. {
  1558. int nCnt=ComboBox_GetCount(hCtrl);
  1559. if(nCnt==CB_ERR)return -1;
  1560. String TN;
  1561. if(pTypeName)
  1562. TN=pTypeName;
  1563. for(int i=0;i<nCnt;i++)
  1564. {
  1565. if(CBGetItemTypeName(hCtrl,i)==TN)
  1566. return i;
  1567. }
  1568. return -1;
  1569. }
  1570. int LBGetCurSel(HWND hCtrl)
  1571. {
  1572. int i=ListBox_GetCurSel(hCtrl);
  1573. if(i==LB_ERR)return -1;
  1574. return i;
  1575. }
  1576. LPCTSTR LBGetItemTypeName(HWND hCtrl,int iIndex)
  1577. {
  1578. LRESULT p=ListBox_GetItemData(hCtrl,iIndex);
  1579. if(p==LB_ERR)return NULL;
  1580. if(p)
  1581. return ((String*)p)->data();
  1582. return NULL;
  1583. }
  1584. int LBFindTypeNameIndex(HWND hCtrl,LPCTSTR pTypeName)
  1585. {
  1586. int nCnt=ListBox_GetCount(hCtrl);
  1587. if(nCnt==LB_ERR)return -1;
  1588. String TN;
  1589. if(pTypeName)
  1590. TN=pTypeName;
  1591. for(int i=0;i<nCnt;i++)
  1592. {
  1593. if(LBGetItemTypeName(hCtrl,i)==TN)
  1594. return i;
  1595. }
  1596. return -1;
  1597. }
  1598. BOOL CAddDlg::InitDialog(HWND hFocus,LPARAM lParam)
  1599. {
  1600. m_pCore->UpdateType();
  1601. Update();
  1602. return TRUE;
  1603. }
  1604. void CAddDlg::Update()
  1605. {
  1606. if(m_bBlockUpdate)return;//Some actions may send notify messages which then Update and overflow stack.
  1607. CUpdate U(&m_bBlockUpdate);
  1608. if(!m_hWnd)return;
  1609. //Update device list.
  1610. int nSelDev=-1;
  1611. String TypeName;
  1612. HWND hListCtrl=HDlgItem(IDC_DEVICE_LIST);
  1613. if(hListCtrl)
  1614. {
  1615. int nTopIndex=ListBox_GetTopIndex(hListCtrl);
  1616. nSelDev=LBGetCurSel(hListCtrl);
  1617. LPCTSTR pTypeName=LBGetItemTypeName(hListCtrl,nSelDev);
  1618. if(pTypeName)TypeName=pTypeName;
  1619. SetWindowRedraw(hListCtrl,FALSE);
  1620. ListBox_ResetContent(hListCtrl);
  1621. m_ListCtrl.clear();//Must be behind ListBox_ResetContent
  1622. for(LISTGPRTDEV::iterator It=m_pCore->m_GprtDev.begin();
  1623. It!=m_pCore->m_GprtDev.end();It++)
  1624. {
  1625. String S=It->TypeName();
  1626. m_ListCtrl.push_back(S);
  1627. int nIndex=ListBox_AddString(hListCtrl,It->Name());
  1628. ListBox_SetItemData(hListCtrl,nIndex,&m_ListCtrl.back());
  1629. }
  1630. nSelDev=LBFindTypeNameIndex(hListCtrl,TypeName.data());
  1631. if(nSelDev>=0)
  1632. ListBox_SetCurSel(hListCtrl,nSelDev);
  1633. else
  1634. ListBox_SetCurSel(hListCtrl,0);
  1635. ListBox_SetTopIndex(hListCtrl,nTopIndex);
  1636. SetWindowRedraw(hListCtrl,TRUE);
  1637. InvalidateRect(hListCtrl,NULL,TRUE);
  1638. nSelDev=LBGetCurSel(hListCtrl);
  1639. }
  1640. HWND hRudder=HDlgItem(IDC_JOY1HASRUDDER);
  1641. if(hRudder)
  1642. {
  1643. BOOL bE=FALSE;
  1644. if(nSelDev>=0)
  1645. {
  1646. LPCTSTR pTypeName=LBGetItemTypeName(hListCtrl,nSelDev);
  1647. if(pTypeName)
  1648. {
  1649. LISTGPRTDEV::iterator It;
  1650. It=find(m_pCore->m_GprtDev.begin(),m_pCore->m_GprtDev.end(),pTypeName);
  1651. if(It!=m_pCore->m_GprtDev.end())
  1652. bE=It->Rudder()?FALSE:TRUE;
  1653. }
  1654. }
  1655. EnableWindow(hRudder,bE);
  1656. }
  1657. //Update gameport list.
  1658. nSelDev=-1;
  1659. TypeName;
  1660. HWND hListCtrlTitle=HDlgItem(IDC_GAMEPORT);
  1661. hListCtrl=HDlgItem(IDC_GAMEPORTLIST);
  1662. if(hListCtrl&&hListCtrlTitle)
  1663. {
  1664. SetWindowRedraw(hListCtrl,FALSE);
  1665. SetWindowPos(hListCtrl,NULL,NULL,NULL,NULL,NULL,
  1666. SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_HIDEWINDOW);
  1667. //How many gameports. Gameport list only if more than 1.
  1668. if(m_pCore->m_GprtBus.size()>1)
  1669. {
  1670. ShowWindow(hListCtrlTitle,SW_SHOWNA);
  1671. nSelDev=CBGetCurSel(hListCtrl);
  1672. LPCTSTR pTypeName=CBGetItemTypeName(hListCtrl,nSelDev);
  1673. if(pTypeName)TypeName=pTypeName;
  1674. ComboBox_ResetContent(hListCtrl);
  1675. m_GprtListCtrl.clear();//Must be behind ComboBox_ResetContent
  1676. for(LISTGPRTDEV::iterator It=m_pCore->m_GprtBus.begin();
  1677. It!=m_pCore->m_GprtBus.end();It++)
  1678. {
  1679. String S=It->TypeName();
  1680. m_GprtListCtrl.push_back(S);
  1681. int nIndex=ComboBox_AddString(hListCtrl,It->Name());
  1682. ComboBox_SetItemData(hListCtrl,nIndex,&m_GprtListCtrl.back());
  1683. }
  1684. nSelDev=CBFindTypeNameIndex(hListCtrl,TypeName.data());
  1685. if(nSelDev>=0)
  1686. ComboBox_SetCurSel(hListCtrl,nSelDev);
  1687. else
  1688. ComboBox_SetCurSel(hListCtrl,0);
  1689. SetWindowPos(hListCtrl,NULL,NULL,NULL,NULL,NULL,
  1690. SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_SHOWWINDOW);
  1691. }
  1692. else
  1693. {
  1694. ShowWindow(hListCtrlTitle,SW_HIDE);
  1695. }
  1696. SetWindowRedraw(hListCtrl,TRUE);
  1697. InvalidateRect(hListCtrl,NULL,TRUE);
  1698. }
  1699. HWND hCustomBtn=HDlgItem(IDC_CUSTOM);
  1700. if(hCustomBtn)
  1701. {
  1702. BOOL bE=(m_pCore->m_GprtDev.size()<MAX_DEVICES)?TRUE:FALSE;
  1703. EnableWindow(hCustomBtn,bE);
  1704. }
  1705. }
  1706. void CAddDlg::AddDev()
  1707. {
  1708. HWND hListCtrl=HDlgItem(IDC_DEVICE_LIST);
  1709. HWND hRudder=HDlgItem(IDC_JOY1HASRUDDER);
  1710. if(hListCtrl&&hRudder)
  1711. {
  1712. int nSelDev=LBGetCurSel(hListCtrl);
  1713. LPCTSTR pTypeName=LBGetItemTypeName(hListCtrl,nSelDev);
  1714. HWND hListCtrlGprt=HDlgItem(IDC_GAMEPORTLIST);
  1715. nSelDev=CBGetCurSel(hListCtrlGprt);
  1716. LPCTSTR pGprtTypeName=CBGetItemTypeName(hListCtrlGprt,nSelDev);
  1717. if(!pGprtTypeName)
  1718. {
  1719. pGprtTypeName=m_pCore->m_GprtBus.front().TypeName();
  1720. }
  1721. if(pTypeName&&pGprtTypeName)
  1722. {
  1723. GUID GOccupied=NULLGUID;
  1724. HRESULT hRes=m_pCore->AddDevice(pTypeName,Button_GetCheck(hRudder)?true:false,pGprtTypeName,GOccupied);
  1725. if(!SUCCEEDED(hRes))
  1726. switch(hRes)
  1727. {
  1728. case E_FAIL:
  1729. break;
  1730. case E_ACCESSDENIED:
  1731. if(GOccupied!=NULLGUID)
  1732. {
  1733. //Find device which occupies the port.
  1734. for(LISTDIDEV::iterator It=m_pCore->m_ListDIDev.begin();It!=m_pCore->m_ListDIDev.end();It++)
  1735. {
  1736. if(It->PortGUID()==GOccupied)
  1737. {
  1738. TCHAR Title[128];
  1739. LoadString(m_hModule,IDS_ADD_PORT_OCCUPIED, Title, cA(Title));
  1740. TCHAR Msg[256];
  1741. LoadString(m_hModule,IDS_ADD_PORT_MSGFORMAT, Msg, cA(Msg));
  1742. //Get gameport name.
  1743. LPCTSTR pBus=_T(" ");
  1744. LISTGPRTDEV::iterator It;
  1745. It=find(m_pCore->m_GprtBus.begin(),m_pCore->m_GprtBus.end(),pGprtTypeName);
  1746. if(It!=m_pCore->m_GprtBus.end())
  1747. pBus=It->Name();
  1748. //Get device name.
  1749. LPCTSTR pDev=_T(" ");
  1750. LISTDIDEV::iterator ItDN;
  1751. for(ItDN=m_pCore->m_ListDIDev.begin();ItDN!=m_pCore->m_ListDIDev.end();ItDN++)
  1752. if(ItDN->PortGUID()==GOccupied)break;
  1753. if(ItDN!=m_pCore->m_ListDIDev.end())
  1754. pDev=ItDN->InstName();
  1755. LPTSTR pT = Insert2Strings(Msg,pDev,pBus);
  1756. lstrcpy(Msg, pT);
  1757. delete[] pT;
  1758. UINT uRTL = (GetWindowLongPtr(m_hWnd,GWL_EXSTYLE) & WS_EX_LAYOUTRTL) ? MB_RTLREADING : 0;
  1759. MessageBox(m_hWnd,Msg,Title,MB_ICONHAND|MB_OK|MB_APPLMODAL|uRTL);
  1760. break;
  1761. }
  1762. }
  1763. }
  1764. break;
  1765. case DIERR_DEVICEFULL:
  1766. MessageBox(m_hWnd,m_hModule,IDS_GAMEPORT_OCCUPIED_TITLE,IDS_GAMEPORT_OCCUPIED);
  1767. break;
  1768. case DIERR_NOTFOUND:
  1769. MessageBox(m_hWnd,m_hModule,IDS_NO_IDS_TITLE,IDS_NO_IDS);
  1770. break;
  1771. case DIERR_DEVICENOTREG:
  1772. MessageBox(m_hWnd,m_hModule,IDS_NO_GAMENUM_TITLE,IDS_NO_GAMENUM);
  1773. break;
  1774. }
  1775. }
  1776. }
  1777. EndDialog(m_hWnd,IDOK);
  1778. }
  1779. INT_PTR CAddDlg::Command(WORD wNotifyCode,WORD wID,HWND hwndCtl)
  1780. {
  1781. switch(wID)
  1782. {
  1783. case IDOK:
  1784. AddDev();
  1785. return 0;
  1786. case IDC_CUSTOM:
  1787. {
  1788. CCustomDlg CustomDlg(m_pCore);
  1789. if(CustomDlg.Dlg(IDD_CUSTOM,m_hModule,m_hWnd)==IDOK)
  1790. {
  1791. Update();
  1792. //Now select new custom device in this dialog box.
  1793. HWND hListCtrl=HDlgItem(IDC_DEVICE_LIST);
  1794. if(hListCtrl)
  1795. {
  1796. int nSelDev=LBFindTypeNameIndex(hListCtrl,CustomDlg.GetVIDPIDName());
  1797. if(nSelDev>=0)
  1798. {
  1799. ListBox_SetCurSel(hListCtrl,nSelDev);
  1800. }
  1801. }
  1802. }
  1803. }
  1804. return 0;
  1805. case IDC_DEVICE_LIST:
  1806. switch(wNotifyCode)
  1807. {
  1808. case LBN_DBLCLK:
  1809. AddDev();
  1810. return 0;
  1811. case LBN_SELCHANGE:
  1812. Update();
  1813. return 0;
  1814. }
  1815. return 0;
  1816. }
  1817. return CDlg::Command(wNotifyCode,wID,hwndCtl);
  1818. }
  1819. INT_PTR CAddDlg::DialogProc(UINT uMsg,WPARAM wParam,LPARAM lParam)
  1820. {
  1821. switch(uMsg)
  1822. {
  1823. case WM_VKEYTOITEM:
  1824. if(LOWORD(wParam)==VK_DELETE)
  1825. {
  1826. HWND hListCtrl=HDlgItem(IDC_DEVICE_LIST);
  1827. if(hListCtrl)
  1828. {
  1829. int nSelDev=LBGetCurSel(hListCtrl);
  1830. LPCTSTR pTypeName=LBGetItemTypeName(hListCtrl,nSelDev);
  1831. if(pTypeName)
  1832. {
  1833. if(m_pCore->IsCustomDevice(pTypeName))
  1834. {
  1835. if(!m_pCore->IsDeviceActive(pTypeName))
  1836. {
  1837. CGprtDev *pDev=m_pCore->FindGprtDev(pTypeName);
  1838. if(!pDev) {
  1839. //This should never happend, but just in case.
  1840. throw JOY_EXCEPTION(E_FAIL);
  1841. }
  1842. TCHAR S[128];
  1843. LoadString(m_hModule,IDS_GEN_AREYOUSURE, S, cA(S));
  1844. LPTSTR pT = Insert1String(S,pDev->Name());
  1845. lstrcpy(S, pT);
  1846. delete[] pT;
  1847. TCHAR Title[128];
  1848. LoadString(m_hModule,IDS_GEN_AREYOUSURE_TITLE, Title, cA(Title));
  1849. UINT uRTL = (GetWindowLongPtr(m_hWnd,GWL_EXSTYLE) & WS_EX_LAYOUTRTL) ? MB_RTLREADING : 0;
  1850. if(MessageBox(m_hWnd,S,Title,
  1851. MB_ICONQUESTION|MB_YESNO|MB_APPLMODAL|uRTL)==IDYES)
  1852. {
  1853. m_pCore->DeleteType(pTypeName);
  1854. }
  1855. }
  1856. else
  1857. {
  1858. MessageBox(m_hWnd,m_hModule,IDS_GEN_AREYOUSURE_TITLE,IDS_NO_REMOVE);
  1859. }
  1860. }
  1861. }
  1862. }
  1863. }
  1864. else return -1;
  1865. return 0;
  1866. }
  1867. return CDlg::DialogProc(uMsg,wParam,lParam);
  1868. }
  1869. /******************************************************************************
  1870. Custom dialog
  1871. ******************************************************************************/
  1872. #define MAX_ANALOG_BUTTONS 4
  1873. #define MIN_ANALOG_AXIS 2
  1874. #define MAX_ANALOG_AXIS 4
  1875. #define MAX_STR_LEN 255
  1876. BOOL CCustomDlg::InitDialog(HWND hFocus,LPARAM lParam)
  1877. {
  1878. if(!m_pCore->IsAvailableVIDPID(m_VIDPIDName))
  1879. {
  1880. MessageBox(m_hWnd,m_hModule,IDS_NO_NAME_TITLE,IDS_NOAVAILABLEVIDPID);
  1881. EndDialog(m_hWnd,IDCANCEL);
  1882. return TRUE;
  1883. }
  1884. HWND hButtons=HDlgItem(IDC_COMBO_BUTTONS);
  1885. if(hButtons)
  1886. {
  1887. for(int i=0;i<=MAX_ANALOG_BUTTONS;i++)
  1888. {
  1889. TCHAR Str[32];
  1890. _sntprintf(Str,32,_T("%d"),i);
  1891. Str[31]=0;
  1892. ComboBox_InsertString(hButtons,i,Str);
  1893. }
  1894. ComboBox_SetCurSel(hButtons,MAX_ANALOG_BUTTONS);
  1895. }
  1896. HWND hAxis=HDlgItem(IDC_COMBO_AXIS);
  1897. if(hAxis)
  1898. {
  1899. for(int i=MIN_ANALOG_AXIS;i<=MAX_ANALOG_AXIS;i++)
  1900. {
  1901. TCHAR Str[32];
  1902. _sntprintf(Str,32,_T("%d"),i);
  1903. Str[31]=0;
  1904. ComboBox_InsertString(hAxis,i-MIN_ANALOG_AXIS,Str);
  1905. }
  1906. ComboBox_SetCurSel(hAxis,0);
  1907. }
  1908. HWND hSpecJoy=HDlgItem(IDC_SPECIAL_JOYSTICK);
  1909. if(hSpecJoy)
  1910. Button_SetCheck(hSpecJoy,BST_CHECKED);
  1911. HWND hEdit=HDlgItem(IDC_EDIT_NAME);
  1912. if(hEdit)
  1913. Edit_LimitText(hEdit,MAX_STR_LEN);
  1914. HWND hHasZAxis=HDlgItem(IDC_HASZAXIS);
  1915. if(hHasZAxis)
  1916. Button_SetCheck(hHasZAxis,BST_CHECKED);
  1917. return TRUE;
  1918. }
  1919. INT_PTR CCustomDlg::Command(WORD wNotifyCode,WORD wID,HWND hwndCtl)
  1920. {
  1921. switch(wID)
  1922. {
  1923. case IDOK:
  1924. {
  1925. HWND hJoy=HDlgItem(IDC_SPECIAL_JOYSTICK);
  1926. HWND hYoke=HDlgItem(IDC_SPECIAL_YOKE);
  1927. HWND hPad=HDlgItem(IDC_SPECIAL_PAD);
  1928. HWND hCar=HDlgItem(IDC_SPECIAL_AUTO);
  1929. HWND hAxis=HDlgItem(IDC_COMBO_AXIS);
  1930. HWND hRudder=HDlgItem(IDC_HASRUDDER);
  1931. HWND hZAxis=HDlgItem(IDC_HASZAXIS);
  1932. HWND hButtons=HDlgItem(IDC_COMBO_BUTTONS);
  1933. HWND hPov=HDlgItem(IDS_CUSTOM_HASPOV);
  1934. HWND hEdit=HDlgItem(IDC_EDIT_NAME);
  1935. if(hJoy&&
  1936. hYoke&&
  1937. hPad&&
  1938. hCar&&
  1939. hAxis&&
  1940. hRudder&&
  1941. hZAxis&&
  1942. hButtons&&
  1943. hPov&&
  1944. hEdit)//Possible internal error.
  1945. {
  1946. TCHAR *pStr=NULL;
  1947. bool bErr=false;
  1948. int nLen=Edit_LineLength(hEdit,0);//Possible internal error.
  1949. if(!nLen)
  1950. {
  1951. bErr=true;
  1952. MessageBox(m_hWnd,m_hModule,IDS_NO_NAME_TITLE,IDS_NO_NAME);
  1953. }
  1954. else
  1955. {
  1956. pStr=new TCHAR[nLen+1];
  1957. if (pStr == NULL)
  1958. return 0; //Internal error
  1959. if(GetDlgItemText(m_hWnd,IDC_EDIT_NAME,pStr,nLen+1)!=nLen)
  1960. return 0;//Internal error.
  1961. if(_tcschr(pStr,_T('\\')))
  1962. {
  1963. bErr=true;
  1964. MessageBox(m_hWnd,m_hModule,IDS_NO_NAME_TITLE,IDS_INVALID_NAME);
  1965. }
  1966. else
  1967. {
  1968. if(m_pCore->DuplicateDeviceName(pStr))
  1969. {
  1970. bErr=true;
  1971. MessageBox(m_hWnd,m_hModule,IDS_NO_NAME_TITLE,IDS_DUPLICATE_TYPE);
  1972. }
  1973. }
  1974. }
  1975. if(bErr)//User entered invalid text for name.
  1976. {
  1977. SetFocus(m_hWnd);
  1978. SetFocus(hEdit);
  1979. Edit_SetSel(hEdit,0,-1);
  1980. return 0;
  1981. }
  1982. m_pCore->AddCustomDevice(
  1983. (Button_GetCheck(hJoy)==BST_CHECKED)?true:false,
  1984. (Button_GetCheck(hPad)==BST_CHECKED)?true:false,
  1985. (Button_GetCheck(hYoke)==BST_CHECKED)?true:false,
  1986. (Button_GetCheck(hCar)==BST_CHECKED)?true:false,
  1987. ComboBox_GetCurSel(hAxis)+MIN_ANALOG_AXIS,
  1988. (Button_GetCheck(hZAxis)==BST_CHECKED)?true:false,
  1989. ComboBox_GetCurSel(hButtons),
  1990. (Button_GetCheck(hPov)==BST_CHECKED)?true:false,
  1991. pStr,
  1992. m_VIDPIDName.data());
  1993. if( pStr ) {
  1994. delete[] pStr;
  1995. }
  1996. }
  1997. }
  1998. EndDialog(m_hWnd,IDOK);
  1999. return 0;
  2000. case IDC_COMBO_AXIS:
  2001. if(wNotifyCode==CBN_SELCHANGE)
  2002. {
  2003. HWND hAxis=HDlgItem(IDC_COMBO_AXIS);
  2004. if(hAxis)
  2005. {
  2006. UINT uShow=SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER;
  2007. if((ComboBox_GetCurSel(hAxis)+MIN_ANALOG_AXIS)==3)//If 3 axis selected.
  2008. uShow|=SWP_SHOWWINDOW;
  2009. else
  2010. uShow|=SWP_HIDEWINDOW;
  2011. HWND hHasZAxis=HDlgItem(IDC_HASZAXIS);
  2012. if(hHasZAxis)
  2013. {
  2014. SetWindowPos(hHasZAxis,NULL,NULL,NULL,NULL,NULL,uShow);
  2015. }
  2016. HWND hHasRudder=HDlgItem(IDC_HASRUDDER);
  2017. if(hHasRudder)
  2018. {
  2019. SetWindowPos(hHasRudder,NULL,NULL,NULL,NULL,NULL,uShow);
  2020. }
  2021. }
  2022. }
  2023. return 0;
  2024. }
  2025. return CDlg::Command(wNotifyCode,wID,hwndCtl);
  2026. }
  2027. /******************************************************************************
  2028. Preferred dialog
  2029. ******************************************************************************/
  2030. void CPreferredDlg::Preferred()
  2031. {
  2032. HWND hListCtrl=HDlgItem(IDC_CHANGE_LIST);
  2033. if(hListCtrl)
  2034. {
  2035. int nSelDev=CBGetCurSel(hListCtrl);
  2036. GUID SelGUID=CBGetItemGUID(hListCtrl,nSelDev);
  2037. if(SelGUID!=NULLGUID)
  2038. m_pCore->Preferred(SelGUID);
  2039. }
  2040. EndDialog(m_hWnd,IDOK);
  2041. }
  2042. INT_PTR CPreferredDlg::Command(WORD wNotifyCode,WORD wID,HWND hwndCtl)
  2043. {
  2044. switch(wID)
  2045. {
  2046. case IDOK:
  2047. Preferred();
  2048. return 0;
  2049. }
  2050. if(wNotifyCode==CBN_CLOSEUP)
  2051. {
  2052. Update();
  2053. return 0;
  2054. }
  2055. return CDlg::Command(wNotifyCode,wID,hwndCtl);
  2056. }
  2057. BOOL CPreferredDlg::InitDialog(HWND hFocus,LPARAM lParam)
  2058. {
  2059. Update();
  2060. HWND hListCtrl=HDlgItem(IDC_CHANGE_LIST);
  2061. if(hListCtrl)
  2062. {
  2063. for(LISTDIDEV::iterator It=m_pCore->m_ListDIDev.begin();
  2064. It!=m_pCore->m_ListDIDev.end();It++)
  2065. {
  2066. if(It->Id()==0)
  2067. {
  2068. int nSelDev=CBFindGUIDIndex(hListCtrl,It->InstGUID());
  2069. if(nSelDev>=0)
  2070. ComboBox_SetCurSel(hListCtrl,nSelDev);
  2071. break;
  2072. }
  2073. }
  2074. }
  2075. return TRUE;
  2076. }
  2077. void CPreferredDlg::Update()
  2078. {
  2079. if(m_bBlockUpdate)return;//Some actions may send notify messages which then Update and overflow stack.
  2080. CUpdate U(&m_bBlockUpdate);
  2081. if(!m_hWnd)return;
  2082. int nSelDev=-1;
  2083. GUID SelGUID=NULLGUID;
  2084. HWND hListCtrl=HDlgItem(IDC_CHANGE_LIST);
  2085. if(hListCtrl)
  2086. {
  2087. if(ComboBox_GetDroppedState(hListCtrl))return;//No update when selecting preferred.
  2088. int nCount=CBGetCnt(hListCtrl);
  2089. nSelDev=CBGetCurSel(hListCtrl);
  2090. SelGUID=CBGetItemGUID(hListCtrl,nSelDev);
  2091. SetWindowRedraw(hListCtrl,FALSE);
  2092. ComboBox_ResetContent(hListCtrl);
  2093. m_ListCtrl.clear();//Must be behind ComboBox_ResetContent.
  2094. int nId0Index=-1;//Index of preferred device.
  2095. for(LISTDIDEV::iterator It=m_pCore->m_ListDIDev.begin();
  2096. It!=m_pCore->m_ListDIDev.end();It++)
  2097. {
  2098. GUID G=It->InstGUID();
  2099. m_ListCtrl.push_back(G);
  2100. int nIndex=ComboBox_AddString(hListCtrl,It->InstName());
  2101. ComboBox_SetItemData(hListCtrl,nIndex,&m_ListCtrl.back());
  2102. if(It->Id()==0)
  2103. nId0Index=nIndex;
  2104. }
  2105. int nNoneIndex=-1;
  2106. if(nId0Index<0)//Only if there is no preferred device.
  2107. {
  2108. TCHAR None[256];
  2109. LoadString(m_hModule,IDS_NONE, None, cA(None));
  2110. nNoneIndex=ComboBox_AddString(hListCtrl,None);
  2111. }
  2112. if((!nCount)||//First update during init.
  2113. (SelGUID==NULLGUID))//Or none is selected.
  2114. {
  2115. if(nId0Index>=0)//Preferred device was added.
  2116. ComboBox_SetCurSel(hListCtrl,nId0Index);
  2117. else//There is no preferred device.
  2118. ComboBox_SetCurSel(hListCtrl,nNoneIndex);
  2119. }
  2120. else//List was not empty before update. Select same thing.
  2121. {
  2122. nSelDev=CBFindGUIDIndex(hListCtrl,SelGUID);
  2123. if(nSelDev>=0)
  2124. ComboBox_SetCurSel(hListCtrl,nSelDev);
  2125. else//Selected device removed.
  2126. {
  2127. if(nId0Index>=0)//Then select original preferred device.
  2128. ComboBox_SetCurSel(hListCtrl,nId0Index);
  2129. else//Select none.
  2130. ComboBox_SetCurSel(hListCtrl,nNoneIndex);
  2131. }
  2132. }
  2133. SetWindowRedraw(hListCtrl,TRUE);
  2134. InvalidateRect(hListCtrl,NULL,TRUE);
  2135. }
  2136. }
  2137. INT_PTR CPreferredDlg::Notify(int idCtrl,LPNMHDR pnmh)
  2138. {
  2139. // switch(pnmh->code)
  2140. // {
  2141. /*case LVN_KEYDOWN:
  2142. switch(((LV_KEYDOWN*)pnmh)->wVKey)
  2143. {
  2144. case VK_F5:
  2145. CoreUpdate();
  2146. return 0;
  2147. }
  2148. return 0;
  2149. case LVN_ITEMCHANGED:
  2150. Update();
  2151. return 0;*/
  2152. /* case NM_DBLCLK:
  2153. switch(pnmh->idFrom)
  2154. {
  2155. case IDC_CHANGE_LIST:
  2156. Preferred();
  2157. return 0;
  2158. }
  2159. return 0;*/
  2160. // }
  2161. return 0;
  2162. }
  2163. /******************************************************************************
  2164. Connect UI and core
  2165. ******************************************************************************/
  2166. class CCP:public CCore,public CMainDlg
  2167. {
  2168. virtual void UIUpdate(){CMainDlg::Update();};
  2169. public:
  2170. CCP(){ConnectUI((CCore*)this);};
  2171. };
  2172. /******************************************************************************
  2173. Entry point.
  2174. ******************************************************************************/
  2175. #define MUTEX_NAME _T("$$$MS_GameControllers_Cpl$$$")
  2176. void Core(HANDLE hModule,HWND hWnd)
  2177. {
  2178. static HWND hPrevHwnd=NULL;
  2179. static HANDLE hMutex=CreateMutex(NULL,TRUE,MUTEX_NAME);
  2180. if(GetLastError()==ERROR_ALREADY_EXISTS)
  2181. {
  2182. SetForegroundWindow(hPrevHwnd);
  2183. }
  2184. else
  2185. {
  2186. hPrevHwnd=hWnd;
  2187. _PNH _old_handler;
  2188. _old_handler = _set_new_handler(my_new_handler);
  2189. if( SHFusionInitializeFromModuleID((HMODULE)hModule,124) )
  2190. {
  2191. // While not initializing would only cause theming to be inactive,
  2192. // a failure to initialize indicates a much worse problem so since
  2193. // PREFIX warns (656863) that the return needs to be tested, abort
  2194. // if the initialization fails.
  2195. try
  2196. {
  2197. CCP CP;
  2198. CP.Dlg(IDD_CPANEL,(HMODULE)hModule,hWnd);
  2199. }
  2200. catch(JoyException E)
  2201. {
  2202. }
  2203. catch(exception)
  2204. {
  2205. }
  2206. SHFusionUninitialize();
  2207. }
  2208. _set_new_handler(_old_handler);
  2209. ReleaseMutex(hMutex);
  2210. CloseHandle(hMutex);
  2211. }
  2212. }
  2213. /******************************************************************************
  2214. Propertiy
  2215. ******************************************************************************/
  2216. class CoInit
  2217. {
  2218. HRESULT m_hRes;
  2219. public:
  2220. ~CoInit()
  2221. {
  2222. if(SUCCEEDED(m_hRes))
  2223. {
  2224. CoFreeUnusedLibraries();//Free gcdef.dll.
  2225. CoUninitialize();
  2226. }
  2227. };
  2228. CoInit(){m_hRes=CoInitialize(NULL);};
  2229. operator HRESULT(){return m_hRes;};
  2230. };
  2231. typedef HPROPSHEETPAGE *LPHPROPSHEETPAGE;
  2232. typedef AutoDeleteArray<LPHPROPSHEETPAGE> LPHPROPSHEETPAGE_ADAR;
  2233. //FUN! FUN! FUN! FUN!
  2234. //This is certain funny code written by some other, quite funny people,
  2235. //so I will put it in the funny code section at the end of the otherwise
  2236. //serious file.
  2237. //tmarkoc cleaned it up. No more memory/interface/freelib leaks, alloc failures handled, no unneccessary allocations.
  2238. /*
  2239. #ifndef PPVOID
  2240. typedef LPVOID* PPVOID;
  2241. #endif
  2242. //WHAT IS THIS FOR????????????????????????????????????????????????????????
  2243. class CDIGameCntrlPropSheet : public IDIGameCntrlPropSheet
  2244. {
  2245. private:
  2246. DWORD m_cProperty_refcount;
  2247. public:
  2248. CDIGameCntrlPropSheet(void);
  2249. ~CDIGameCntrlPropSheet(void);
  2250. // IUnknown methods
  2251. STDMETHODIMP QueryInterface(REFIID, PPVOID);
  2252. STDMETHODIMP_(ULONG) AddRef(void);
  2253. STDMETHODIMP_(ULONG) Release(void);
  2254. // CImpIServerProperty methods
  2255. STDMETHODIMP GetSheetInfo(LPDIGCSHEETINFO *lpSheetInfo);
  2256. STDMETHODIMP GetPageInfo (LPDIGCPAGEINFO *lpPageInfo );
  2257. STDMETHODIMP SetID(USHORT nID);
  2258. STDMETHODIMP_(USHORT) GetID(void);
  2259. };*/
  2260. //typedef CDIGameCntrlPropSheet *LPCDIGAMECNTRLPROPSHEET;
  2261. typedef IDIGameCntrlPropSheet *LPCDIGAMECNTRLPROPSHEET;
  2262. typedef AutoRelease<LPCDIGAMECNTRLPROPSHEET> LPCDIGAMECNTRLPROPSHEET_AR;
  2263. HRESULT Properties(HMODULE hMod,HWND hWnd,CCore *pCore,DWORD dwId)
  2264. {
  2265. // ASSERT(IsWindow(hWnd));
  2266. CLSID clsidPropSheet=CLSID_LegacyServer;
  2267. //Get type name.
  2268. DIJOYCONFIG DIJoyCfg;
  2269. ZeroMemory(&DIJoyCfg,sizeof(DIJoyCfg));
  2270. DIJoyCfg.dwSize=sizeof(DIJoyCfg);
  2271. if(SUCCEEDED(pCore->m_pDIJoyCfg->GetConfig(dwId,&DIJoyCfg,DIJC_REGHWCONFIGTYPE|DIJC_CALLOUT)))
  2272. {
  2273. //Get the clsidConfig.
  2274. DIJOYTYPEINFO DIJoyType;
  2275. ZeroMemory(&DIJoyType,sizeof(DIJoyType));
  2276. DIJoyType.dwSize=sizeof(DIJoyType);
  2277. if(SUCCEEDED(pCore->m_pDIJoyCfg->GetTypeInfo(DIJoyCfg.wszType,&DIJoyType,DITC_CLSIDCONFIG|DITC_REGHWSETTINGS|DITC_FLAGS1)))
  2278. {
  2279. if((DIJoyType.clsidConfig!=GUID_NULL)&&
  2280. !(DIJoyType.dwFlags1&JOYTYPE_DEFAULTPROPSHEET))
  2281. clsidPropSheet=DIJoyType.clsidConfig;
  2282. }
  2283. }
  2284. int nStartPage=(clsidPropSheet==CLSID_LegacyServer)?1:0;
  2285. if(nStartPage>MAX_PAGES)
  2286. return(DIGCERR_STARTPAGETOOLARGE);
  2287. CoInit CI;//CoInitialize(NULL); Auto CoFreeUnusedLibraries();CoUninitialize();.
  2288. LPCDIGAMECNTRLPROPSHEET_AR fnInterface;
  2289. if(SUCCEEDED(CI))
  2290. {
  2291. IClassFactory* pCF;
  2292. if(SUCCEEDED(CoGetClassObject(clsidPropSheet,CLSCTX_INPROC_SERVER,NULL,IID_IClassFactory,(LPVOID*)&pCF)))
  2293. {
  2294. pCF->CreateInstance(NULL,IID_IDIGameCntrlPropSheet,(LPVOID*)&fnInterface);
  2295. pCF->Release();
  2296. }
  2297. else
  2298. {
  2299. //reset to legacy server
  2300. clsidPropSheet=CLSID_LegacyServer;
  2301. nStartPage=1;
  2302. if(SUCCEEDED(CoGetClassObject(clsidPropSheet,CLSCTX_INPROC_SERVER,NULL,IID_IClassFactory,(LPVOID*)&pCF)))
  2303. {
  2304. pCF->CreateInstance(NULL,IID_IDIGameCntrlPropSheet,(LPVOID*)&fnInterface);
  2305. pCF->Release();
  2306. }
  2307. }
  2308. }
  2309. if(*((PVOID *)&fnInterface) == NULL)
  2310. {
  2311. return(E_NOINTERFACE);
  2312. }
  2313. //Send device Id to the property sheet.
  2314. fnInterface->SetID(dwId);
  2315. LPDIGCSHEETINFO pServerSheet=NULL;
  2316. //Get the property sheet info from the server.
  2317. if(FAILED(fnInterface->GetSheetInfo(&pServerSheet)))
  2318. {
  2319. return(E_FAIL);
  2320. }
  2321. //Verify data from server.
  2322. if(pServerSheet->nNumPages==0)
  2323. return(DIGCERR_NUMPAGESZERO);
  2324. else if((pServerSheet->nNumPages>MAX_PAGES)||(pServerSheet->nNumPages<nStartPage))
  2325. return(DIGCERR_NUMPAGESTOOLARGE);
  2326. LPDIGCPAGEINFO pServerPage=NULL;
  2327. //Get the information for all the pages from the server.
  2328. if(FAILED(fnInterface->GetPageInfo(&pServerPage)))
  2329. {
  2330. return(E_FAIL);
  2331. }
  2332. // Allocate memory for the pages.
  2333. LPHPROPSHEETPAGE_ADAR pPages=new HPROPSHEETPAGE[pServerSheet->nNumPages];
  2334. if(*((PVOID *)&pPages) == NULL) return(E_OUTOFMEMORY);
  2335. ZeroMemory((LPHPROPSHEETPAGE)pPages,sizeof(HPROPSHEETPAGE)*pServerSheet->nNumPages);
  2336. // Allocate memory for the header!
  2337. PROPSHEETHEADER SH;
  2338. ZeroMemory(&SH,sizeof(SH));
  2339. SH.dwSize=sizeof(SH);
  2340. SH.hwndParent= hWnd;
  2341. SH.hInstance=pServerPage[0].hInstance;
  2342. if(pServerSheet->fSheetIconFlag)
  2343. {
  2344. if(pServerSheet->lpwszSheetIcon)
  2345. {
  2346. //Check to see if you are an INT or a WSTR.
  2347. if(HIWORD((INT_PTR)pServerSheet->lpwszSheetIcon))
  2348. {
  2349. //You are a string.
  2350. SH.pszIcon=pServerSheet->lpwszSheetIcon;
  2351. }
  2352. else
  2353. SH.pszIcon=(LPCTSTR)(pServerSheet->lpwszSheetIcon);
  2354. SH.dwFlags=PSH_USEICONID;
  2355. }
  2356. else return(DIGCERR_NOICON);
  2357. }
  2358. //Do we have a sheet caption?
  2359. if(pServerSheet->lpwszSheetCaption)
  2360. {
  2361. SH.pszCaption=pServerSheet->lpwszSheetCaption;
  2362. SH.dwFlags|=PSH_PROPTITLE;
  2363. }
  2364. SH.nPages=pServerSheet->nNumPages;
  2365. SH.nStartPage=nStartPage;
  2366. //Set the property pages inofrmation into the header.
  2367. SH.phpage=(LPHPROPSHEETPAGE)pPages;
  2368. //Sheet stuff is done.Now do the pages.
  2369. PROPSHEETPAGE PropPage;
  2370. ZeroMemory(&PropPage,sizeof(PropPage));
  2371. PropPage.dwSize=sizeof(PropPage);
  2372. //Fill up each page.
  2373. int nIndex=0;
  2374. do
  2375. {
  2376. //Assign the things that there are not questionable.
  2377. PropPage.lParam=pServerPage[nIndex].lParam;
  2378. PropPage.hInstance=pServerPage[nIndex].hInstance;
  2379. // Add the title.
  2380. if(pServerPage[nIndex].lpwszPageTitle)
  2381. {
  2382. PropPage.dwFlags=PSP_USETITLE;
  2383. //Check to see if you are a string.
  2384. if(HIWORD((INT_PTR)pServerPage[nIndex].lpwszPageTitle))
  2385. {
  2386. PropPage.pszTitle=pServerPage[nIndex].lpwszPageTitle;
  2387. }
  2388. else
  2389. PropPage.pszTitle=(LPTSTR)pServerPage[nIndex].lpwszPageTitle;
  2390. }
  2391. else PropPage.pszTitle=NULL;
  2392. //If icon is required go ahead and add it.
  2393. if(pServerPage[nIndex].fIconFlag)
  2394. {
  2395. PropPage.dwFlags|=PSP_USEICONID;
  2396. //Check to see if you are an INT or a String.
  2397. if(HIWORD((INT_PTR)pServerPage[nIndex].lpwszPageIcon))
  2398. {
  2399. //You're a string.
  2400. PropPage.pszIcon=pServerPage[nIndex].lpwszPageIcon;
  2401. }
  2402. else
  2403. PropPage.pszIcon=(LPCTSTR)(pServerPage[nIndex].lpwszPageIcon);
  2404. }
  2405. //If a pre - post processing call back proc is required go ahead and add it.
  2406. if(pServerPage[nIndex].fProcFlag)
  2407. {
  2408. if(pServerPage[nIndex].fpPrePostProc)
  2409. {
  2410. PropPage.dwFlags|=PSP_USECALLBACK;
  2411. PropPage.pfnCallback=(LPFNPSPCALLBACK)pServerPage[nIndex].fpPrePostProc;
  2412. }
  2413. else
  2414. return(DIGCERR_NOPREPOSTPROC);
  2415. }
  2416. //And the essential "dialog" proc.
  2417. if(pServerPage[nIndex].fpPageProc)
  2418. PropPage.pfnDlgProc=pServerPage[nIndex].fpPageProc;
  2419. else
  2420. return(DIGCERR_NODLGPROC);
  2421. //Assign the dialog template.
  2422. if(HIWORD((INT_PTR)pServerPage[nIndex].lpwszTemplate))
  2423. {
  2424. PropPage.pszTemplate=pServerPage[nIndex].lpwszTemplate;
  2425. }
  2426. else
  2427. PropPage.pszTemplate=(LPTSTR)pServerPage[nIndex].lpwszTemplate;
  2428. if(clsidPropSheet!=CLSID_LegacyServer)//If third party software do not enforce theme.
  2429. ((LPHPROPSHEETPAGE)pPages)[nIndex++]=SHNoFusionCreatePropertySheetPageW(&PropPage);
  2430. else
  2431. ((LPHPROPSHEETPAGE)pPages)[nIndex++]=CreatePropertySheetPage(&PropPage);
  2432. }
  2433. while(nIndex<pServerSheet->nNumPages);
  2434. //Launch modal property sheet dialog.
  2435. PropertySheet(&SH);
  2436. pCore->Update();
  2437. return(S_OK);
  2438. }
  2439. #undef cA