Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

310 lines
7.5 KiB

  1. //-----------------------------------------------------------------------------
  2. // File: cfrmwrk.cpp
  3. //
  4. // Desc: CDirectInputActionFramework is the outer-most layer of the UI. It
  5. // contains everything else. Its functionality is provided by one
  6. // method: ConfigureDevices.
  7. //
  8. // InternalConfigureDevices is called by the CDirectInputActionFramework
  9. // class. This function actually contains the initialization code and
  10. // the message pump for the UI.
  11. //
  12. // Copyright (C) 1999-2000 Microsoft Corporation. All Rights Reserved.
  13. //-----------------------------------------------------------------------------
  14. #include "common.hpp"
  15. //QueryInterface
  16. STDMETHODIMP CDirectInputActionFramework::QueryInterface(REFIID iid, LPVOID* ppv)
  17. {
  18. //null the out param
  19. *ppv = NULL;
  20. if ((iid == IID_IUnknown) || (iid == IID_IDIActionFramework))
  21. {
  22. *ppv = this;
  23. AddRef();
  24. return S_OK;
  25. }
  26. return E_NOINTERFACE;
  27. }
  28. //AddRef
  29. STDMETHODIMP_(ULONG) CDirectInputActionFramework::AddRef()
  30. {
  31. return InterlockedIncrement(&m_cRef);
  32. }
  33. //Release
  34. STDMETHODIMP_(ULONG) CDirectInputActionFramework::Release()
  35. {
  36. if (InterlockedDecrement(&m_cRef) == 0)
  37. {
  38. delete this;
  39. return 0;
  40. }
  41. return m_cRef;
  42. }
  43. // Manages auto loading/unloading WINMM.DLL
  44. // There will only be one instance of this class: inside InternalConfigureDevicees.
  45. class CWinMmLoader
  46. {
  47. public:
  48. CWinMmLoader()
  49. {
  50. if (!g_hWinMmDLL)
  51. {
  52. g_hWinMmDLL = LoadLibrary(_T("WINMM.DLL"));
  53. if (g_hWinMmDLL)
  54. {
  55. *(FARPROC*)(&g_fptimeSetEvent) = GetProcAddress(g_hWinMmDLL, "timeSetEvent");
  56. }
  57. }
  58. }
  59. ~CWinMmLoader()
  60. {
  61. if (g_hWinMmDLL)
  62. {
  63. /*
  64. * Make sure no new callbacks can get scheduled then sleep to
  65. * allow any pending ones to complete.
  66. //@@BEGIN_MSINTERNAL
  67. * Use 40ms as 20ms is the UI refresh interval
  68. *
  69. * ISSUE-2000/11/21-MarcAnd
  70. * Should either have a more robust way to make sure no
  71. * timers are left running or at least use constants to
  72. * to make sure that if any timer interval is increased,
  73. * that this value is still long enough.
  74. //@@END_MSINTERNAL
  75. */
  76. g_fptimeSetEvent = NULL;
  77. Sleep( 40 );
  78. FreeLibrary(g_hWinMmDLL);
  79. g_hWinMmDLL = NULL;
  80. }
  81. }
  82. };
  83. //@@BEGIN_MSINTERNAL
  84. // Manages auto loading/unloading MSIMG32.DLL
  85. // There will only be one instance of this class: inside InternalConfigureDevicees.
  86. /*
  87. class CMSImgLoader
  88. {
  89. public:
  90. CMSImgLoader()
  91. {
  92. if (!g_MSImg32)
  93. {
  94. g_MSImg32 = LoadLibrary(_T("MSIMG32.DLL"));
  95. if (g_MSImg32)
  96. {
  97. g_AlphaBlend = (ALPHABLEND)GetProcAddress(g_MSImg32, "AlphaBlend");
  98. if (!g_AlphaBlend)
  99. {
  100. FreeLibrary(g_MSImg32);
  101. g_MSImg32 = NULL;
  102. }
  103. }
  104. }
  105. }
  106. ~CMSImgLoader()
  107. {
  108. if (g_MSImg32)
  109. {
  110. FreeLibrary(g_MSImg32);
  111. g_MSImg32 = NULL;
  112. g_AlphaBlend = NULL;
  113. }
  114. }
  115. };
  116. */
  117. //@@END_MSINTERNAL
  118. // internal, which api wraps around
  119. static HRESULT InternalConfigureDevices(LPDICONFIGUREDEVICESCALLBACK lpdiCallback,
  120. LPDICONFIGUREDEVICESPARAMSW lpdiCDParams,
  121. DWORD dwFlags,
  122. LPVOID pvRefData)
  123. {
  124. tracescope(__ts, _T("InternalConfigureDevices()\n"));
  125. //@@BEGIN_MSINTERNAL
  126. // CMSImgLoader g_MSImgLoadingHelper; // Automatically call LoadLibrary and FreeLibrary on MSIMG32.DLL
  127. //@@END_MSINTERNAL
  128. CWinMmLoader g_WinMmLoadingHelper; // Automatically call LoadLibrary and FreeLibrary on WINMM.DLL
  129. // check that we're at least 256 colors
  130. HDC hMemDC = CreateCompatibleDC(NULL);
  131. if (hMemDC == NULL)
  132. {
  133. etrace(_T("Can't get a DC! Exiting.\n"));
  134. return E_FAIL;
  135. }
  136. int bpp = GetDeviceCaps(hMemDC, BITSPIXEL);
  137. DeleteDC(hMemDC);
  138. if (bpp < 8)
  139. {
  140. etrace1(_T("Screen is not at least 8bpp (bpp = %d)\n"), bpp);
  141. return E_FAIL;
  142. }
  143. // do it...
  144. {
  145. // create the globals
  146. CUIGlobals uig(
  147. dwFlags,
  148. lpdiCDParams->lptszUserNames,
  149. lpdiCDParams->dwcFormats,
  150. lpdiCDParams->lprgFormats,
  151. &(lpdiCDParams->dics),
  152. lpdiCDParams->lpUnkDDSTarget,
  153. lpdiCallback,
  154. pvRefData
  155. );
  156. HRESULT hr = uig.GetInitResult();
  157. if (FAILED(hr))
  158. {
  159. etrace(_T("CUIGlobals.Init() failed\n"));
  160. return hr;
  161. }
  162. // make sure the flexwnd window class is registered only during possible use
  163. //@@BEGIN_MSINTERNAL
  164. // TODO: consider doing this wnd class stuff at dll scope, or doing it refcount-ish within flexwnd.cpp
  165. //@@END_MSINTERNAL
  166. {
  167. struct flexwndscope {
  168. flexwndscope(CUIGlobals &uig) : m_uig(uig) {CFlexWnd::RegisterWndClass(m_uig.GetInstance());}
  169. ~flexwndscope() {CFlexWnd::UnregisterWndClass(m_uig.GetInstance());}
  170. CUIGlobals &m_uig;
  171. } scope(uig);
  172. // create the main window
  173. CConfigWnd cfgWnd(uig);
  174. if (!cfgWnd.Create(lpdiCDParams->hwnd))
  175. {
  176. etrace(_T("Failed to create main window\n"));
  177. return E_FAIL;
  178. }
  179. // Initialize the shared tooltip object.
  180. RECT rc = {0, 0, 0, 0};
  181. CFlexWnd::s_ToolTip.Create(cfgWnd.m_hWnd, rc, TRUE);
  182. if (!CFlexWnd::s_ToolTip.m_hWnd)
  183. {
  184. etrace(_T("Failed to create tooltip window\n"));
  185. return E_FAIL;
  186. }
  187. ::ShowWindow(CFlexWnd::s_ToolTip.m_hWnd, SW_HIDE); // Hide window by default
  188. // enter message loop
  189. MSG msg;
  190. while (GetMessage(&msg, NULL, 0, 0))
  191. {
  192. // If this is a message for the parent window (game window), only dispatch if it's WM_PAINT.
  193. if (!cfgWnd.InRenderMode() && msg.hwnd == lpdiCDParams->hwnd && msg.message != WM_PAINT)
  194. continue;
  195. TranslateMessage(&msg);
  196. DispatchMessage(&msg);
  197. }
  198. }
  199. CFlexWnd::s_ToolTip.Destroy();
  200. return uig.GetFinalResult();
  201. }
  202. }
  203. BOOL AreAcForsGood(LPDIACTIONFORMATW lpAcFors, DWORD dwNumAcFors)
  204. {
  205. if (lpAcFors == NULL)
  206. return FALSE;
  207. if (dwNumAcFors < 1)
  208. return FALSE;
  209. if (lpAcFors->dwNumActions == 0)
  210. return FALSE;
  211. return TRUE;
  212. }
  213. //ConfigureDevices
  214. STDMETHODIMP CDirectInputActionFramework::ConfigureDevices(
  215. LPDICONFIGUREDEVICESCALLBACK lpdiCallback,
  216. LPDICONFIGUREDEVICESPARAMSW lpdiCDParams,
  217. DWORD dwFlags,
  218. LPVOID pvRefData)
  219. {
  220. tracescope(__ts,_T("CDirectInputActionFramework::ConfigureDevices()\n"));
  221. trace(_T("\nConfigureDevices() called...\n\n"));
  222. // check parameters
  223. if (lpdiCDParams == NULL)
  224. {
  225. etrace(_T("NULL params structure passed to ConfigureDevices()\n"));
  226. return E_INVALIDARG;
  227. }
  228. // save passed params in case we change 'em
  229. LPDIACTIONFORMATW lpAcFors = lpdiCDParams->lprgFormats;
  230. DWORD dwNumAcFors = lpdiCDParams->dwcFormats;
  231. #ifdef CFGUI__FORCE_GOOD_ACFORS
  232. if (!AreAcForsGood(lpdiCDParams->lprgFormats, lpdiCDParams->dwcFormats))
  233. {
  234. etrace(_T("Passed ActionFormats aren't good... Using GetTestActionFormats() (just 2 of them).\n"));
  235. lpdiCDParams->dwcFormats = 2;
  236. lpdiCDParams->lprgFormats = GetTestActionFormats();
  237. }
  238. #endif
  239. HRESULT hr = InternalConfigureDevices(lpdiCallback, lpdiCDParams, dwFlags, pvRefData);
  240. // restore passed params in case changed
  241. lpdiCDParams->lprgFormats = lpAcFors;
  242. lpdiCDParams->dwcFormats = dwNumAcFors;
  243. trace(_T("\n"));
  244. if (FAILED(hr))
  245. etrace1(_T("ConfigureDevices() failed, returning 0x%08x\n"), hr);
  246. else
  247. trace1(_T("ConfigureDevices() suceeded, returning 0x%08x\n"), hr);
  248. trace(_T("\n"));
  249. return hr;
  250. }
  251. //constructor
  252. CDirectInputActionFramework::CDirectInputActionFramework()
  253. {
  254. //set ref count
  255. m_cRef = 1;
  256. }
  257. //destructor
  258. CDirectInputActionFramework::~CDirectInputActionFramework()
  259. {
  260. // not necessary to cleanup action format here
  261. }