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.

403 lines
11 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. DirectPlayEnumOrder.cpp
  5. Abstract:
  6. Certain applications (Midtown Madness) expects the DPLAY providers to enumerate in a specific order.
  7. History:
  8. 04/25/2000 robkenny
  9. --*/
  10. #include "precomp.h"
  11. #include "CharVector.h"
  12. #include <Dplay.h>
  13. IMPLEMENT_SHIM_BEGIN(DirectPlayEnumOrder)
  14. #include "ShimHookMacro.h"
  15. APIHOOK_ENUM_BEGIN
  16. APIHOOK_ENUM_ENTRY_DIRECTX_COMSERVER()
  17. APIHOOK_ENUM_END
  18. IMPLEMENT_DIRECTX_COMSERVER_HOOKS()
  19. // A class that makes it easy to store DPlay::EnumConnections information.
  20. class DPlayConnectionsInfo
  21. {
  22. public:
  23. BOOL m_beenUsed;
  24. GUID m_lpguidSP;
  25. LPVOID m_lpConnection;
  26. DWORD m_dwConnectionSize;
  27. DPNAME m_lpName;
  28. DWORD m_dwFlags;
  29. LPVOID m_lpContext;
  30. // Construct our object, saveing all these values.
  31. DPlayConnectionsInfo(
  32. LPCGUID lpguidSP,
  33. LPVOID lpConnection,
  34. DWORD dwConnectionSize,
  35. LPCDPNAME lpName,
  36. DWORD dwFlags,
  37. LPVOID lpContext
  38. )
  39. {
  40. m_beenUsed = FALSE;
  41. m_lpguidSP = *lpguidSP;
  42. m_lpConnection = malloc(dwConnectionSize);
  43. if (m_lpConnection)
  44. {
  45. memcpy(m_lpConnection, lpConnection, dwConnectionSize);
  46. }
  47. m_dwConnectionSize = dwConnectionSize;
  48. m_lpName = *lpName;
  49. m_lpName.lpszShortNameA = StringDuplicateA(lpName->lpszShortNameA);
  50. m_dwFlags = dwFlags;
  51. m_lpContext = lpContext;
  52. }
  53. // Free our allocated space, and erase values.
  54. void Erase()
  55. {
  56. free(m_lpConnection);
  57. free(m_lpName.lpszShortNameA);
  58. m_lpConnection = NULL;
  59. m_dwConnectionSize = 0;
  60. m_lpName.lpszShortNameA = NULL;
  61. m_dwFlags = 0;
  62. m_lpContext = 0;
  63. }
  64. // Do we match this GUID?
  65. BOOL operator == (const GUID & guidSP)
  66. {
  67. return IsEqualGUID(guidSP, m_lpguidSP);
  68. }
  69. // Call the callback routine with this saved information
  70. void CallEnumRoutine(LPDPENUMCONNECTIONSCALLBACK lpEnumCallback)
  71. {
  72. lpEnumCallback(
  73. &m_lpguidSP,
  74. m_lpConnection,
  75. m_dwConnectionSize,
  76. &m_lpName,
  77. m_dwFlags,
  78. m_lpContext
  79. );
  80. m_beenUsed = TRUE;
  81. }
  82. };
  83. // A list of DPlay connections
  84. class DPlayConnectionsInfoVector : public VectorT<DPlayConnectionsInfo>
  85. {
  86. public:
  87. // Deconstruct the elements
  88. ~DPlayConnectionsInfoVector()
  89. {
  90. for (int i = 0; i < Size(); ++i)
  91. {
  92. DPlayConnectionsInfo & deleteMe = Get(i);
  93. deleteMe.Erase();
  94. }
  95. }
  96. // Find an entry that matches this GUID
  97. DPlayConnectionsInfo * Find(const GUID & guidSP)
  98. {
  99. const int size = Size();
  100. DPFN(
  101. eDbgLevelSpew,
  102. "Find GUID(%08x-%08x-%08x-%08x) Size(%d).",
  103. guidSP.Data1,
  104. guidSP.Data2,
  105. guidSP.Data3,
  106. guidSP.Data4,
  107. size);
  108. for (int i = 0; i < size; ++i)
  109. {
  110. DPlayConnectionsInfo & dpci = Get(i);
  111. DPFN(
  112. eDbgLevelSpew,
  113. " Compare[%02d] = GUID(%08x-%08x-%08x-%08x) (%s).",
  114. i,
  115. dpci.m_lpguidSP.Data1,
  116. dpci.m_lpguidSP.Data2,
  117. dpci.m_lpguidSP.Data3,
  118. dpci.m_lpguidSP.Data4,
  119. dpci.m_lpName.lpszShortNameA);
  120. if (dpci == guidSP)
  121. {
  122. DPFN(
  123. eDbgLevelSpew,
  124. "FOUND(%s).",
  125. dpci.m_lpName.lpszShortNameA);
  126. return &dpci;
  127. }
  128. }
  129. DPFN(eDbgLevelSpew, "NOT FOUND.");
  130. return NULL;
  131. }
  132. // Lookup the GUID and if found, call the callback routine.
  133. void CallEnumRoutine(const GUID & guidSP, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback)
  134. {
  135. DPFN(
  136. eDbgLevelSpew,
  137. "CallEnumRoutine(%08x) Find GUID(%08x-%08x-%08x-%08x).",
  138. lpEnumCallback,
  139. guidSP.Data1,
  140. guidSP.Data2,
  141. guidSP.Data3,
  142. guidSP.Data4);
  143. DPlayConnectionsInfo * dpci = Find(guidSP);
  144. if (dpci)
  145. {
  146. dpci->CallEnumRoutine(lpEnumCallback);
  147. }
  148. }
  149. };
  150. class DPlayEnumInfo
  151. {
  152. public:
  153. DPlayEnumInfo(LPVOID context, DPlayConnectionsInfoVector * conn)
  154. {
  155. lpContext = context;
  156. dPlayConnection = conn;
  157. }
  158. LPVOID lpContext;
  159. DPlayConnectionsInfoVector * dPlayConnection;
  160. };
  161. /*++
  162. Our private callback for IDirectPlay4::EnumConnections. We simply save all
  163. the connections in our private list for later use.
  164. --*/
  165. BOOL FAR PASCAL EnumConnectionsCallback(
  166. LPCGUID lpguidSP,
  167. LPVOID lpConnection,
  168. DWORD dwConnectionSize,
  169. LPCDPNAME lpName,
  170. DWORD dwFlags,
  171. LPVOID lpContext
  172. )
  173. {
  174. DPlayEnumInfo * enumInfo = (DPlayEnumInfo*)lpContext;
  175. // Only add it to the list if it is not already there
  176. // App calls EnumConnections from inside Enum callback routine.
  177. if (!enumInfo->dPlayConnection->Find(*lpguidSP))
  178. {
  179. DPFN(
  180. eDbgLevelSpew,
  181. "EnumConnectionsCallback Add(%d) (%s).",
  182. enumInfo->dPlayConnection->Size(),
  183. lpName->lpszShortName );
  184. // Store the info for later
  185. DPlayConnectionsInfo dpci(lpguidSP, lpConnection, dwConnectionSize, lpName, dwFlags, enumInfo->lpContext);
  186. enumInfo->dPlayConnection->Append(dpci);
  187. }
  188. else
  189. {
  190. DPFN(
  191. eDbgLevelSpew,
  192. "EnumConnectionsCallback Already in the list(%s).",
  193. lpName->lpszShortName );
  194. }
  195. return TRUE;
  196. }
  197. /*++
  198. Win9x Direct play enumerates hosts in this order:
  199. DPSPGUID_IPX,
  200. DPSPGUID_TCPIP,
  201. DPSPGUID_MODEM,
  202. DPSPGUID_SERIAL,
  203. IXP, TCP, Modem, Serial. Have EnumConnections call our callback
  204. routine to gather the host list, sort it, then call the app's callback routine.
  205. --*/
  206. HRESULT
  207. COMHOOK(IDirectPlay4A, EnumConnections)(
  208. PVOID pThis,
  209. LPCGUID lpguidApplication,
  210. LPDPENUMCONNECTIONSCALLBACK lpEnumCallback,
  211. LPVOID lpContext,
  212. DWORD dwFlags
  213. )
  214. {
  215. DPFN( eDbgLevelSpew, "======================================");
  216. DPFN( eDbgLevelSpew, "COMHOOK IDirectPlay4A EnumConnections" );
  217. // Don't let a bad callback routine spoil our day
  218. if (IsBadCodePtr( (FARPROC) lpEnumCallback))
  219. {
  220. return DPERR_INVALIDPARAMS;
  221. }
  222. HRESULT hResult = DPERR_CONNECTIONLOST;
  223. typedef HRESULT (*_pfn_IDirectPlay4_EnumConnections)( PVOID pThis, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags);
  224. _pfn_IDirectPlay4A_EnumConnections EnumConnections = ORIGINAL_COM(
  225. IDirectPlay4A,
  226. EnumConnections,
  227. pThis);
  228. if (EnumConnections)
  229. {
  230. DPFN( eDbgLevelSpew, "EnumConnections(%08x)\n", EnumConnections );
  231. DPlayConnectionsInfoVector dPlayConnection;
  232. DPlayEnumInfo enumInfo(lpContext, &dPlayConnection);
  233. // Enumerate connections to our own routine.
  234. hResult = EnumConnections(pThis, lpguidApplication, EnumConnectionsCallback, (LPVOID)&enumInfo, dwFlags);
  235. LOGN( eDbgLevelError,
  236. "EnumConnections calling app with ordered connection list of Size(%d).",
  237. dPlayConnection.Size());
  238. // Call the application's callback routine with the GUID in the order it expects
  239. if (hResult == DP_OK)
  240. {
  241. dPlayConnection.CallEnumRoutine(DPSPGUID_IPX, lpEnumCallback);
  242. dPlayConnection.CallEnumRoutine(DPSPGUID_TCPIP, lpEnumCallback);
  243. dPlayConnection.CallEnumRoutine(DPSPGUID_MODEM, lpEnumCallback);
  244. dPlayConnection.CallEnumRoutine(DPSPGUID_SERIAL, lpEnumCallback);
  245. // Now loop over the list and enum any remaining providers
  246. for (int i = 0; i < dPlayConnection.Size(); ++i)
  247. {
  248. DPlayConnectionsInfo & dpci = dPlayConnection.Get(i);
  249. if (!dpci.m_beenUsed)
  250. {
  251. dpci.CallEnumRoutine(lpEnumCallback);
  252. dpci.m_beenUsed = TRUE;
  253. }
  254. }
  255. }
  256. }
  257. return hResult;
  258. }
  259. /*++
  260. Do the same thing for DirectPlay3
  261. --*/
  262. HRESULT
  263. COMHOOK(IDirectPlay3A, EnumConnections)(
  264. PVOID pThis,
  265. LPCGUID lpguidApplication,
  266. LPDPENUMCONNECTIONSCALLBACK lpEnumCallback,
  267. LPVOID lpContext,
  268. DWORD dwFlags
  269. )
  270. {
  271. DPFN( eDbgLevelSpew, "======================================");
  272. DPFN( eDbgLevelSpew, "COMHOOK IDirectPlay3A EnumConnections" );
  273. // Don't let a bad callback routine spoil our day
  274. if (IsBadCodePtr( (FARPROC) lpEnumCallback))
  275. {
  276. return DPERR_INVALIDPARAMS;
  277. }
  278. HRESULT hResult = DPERR_CONNECTIONLOST;
  279. typedef HRESULT (*_pfn_IDirectPlay3A_EnumConnections)( PVOID pThis, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags);
  280. _pfn_IDirectPlay3A_EnumConnections EnumConnections = ORIGINAL_COM(
  281. IDirectPlay3A,
  282. EnumConnections,
  283. pThis);
  284. if (EnumConnections)
  285. {
  286. DPFN( eDbgLevelSpew, "EnumConnections(%08x)\n", EnumConnections );
  287. DPlayConnectionsInfoVector dPlayConnection;
  288. DPlayEnumInfo enumInfo(lpContext, &dPlayConnection);
  289. // Enumerate connections to our own routine.
  290. hResult = EnumConnections(pThis, lpguidApplication, EnumConnectionsCallback, (LPVOID)&enumInfo, dwFlags);
  291. LOGN( eDbgLevelError,
  292. "EnumConnections calling app with ordered connection list of Size(%d).",
  293. dPlayConnection.Size());
  294. // Call the application's callback routine with the GUID in the order it expects
  295. if (hResult == DP_OK)
  296. {
  297. dPlayConnection.CallEnumRoutine(DPSPGUID_IPX, lpEnumCallback);
  298. dPlayConnection.CallEnumRoutine(DPSPGUID_TCPIP, lpEnumCallback);
  299. dPlayConnection.CallEnumRoutine(DPSPGUID_MODEM, lpEnumCallback);
  300. dPlayConnection.CallEnumRoutine(DPSPGUID_SERIAL, lpEnumCallback);
  301. // Now loop over the list and enum any remaining providers
  302. for (int i = 0; i < dPlayConnection.Size(); ++i)
  303. {
  304. DPlayConnectionsInfo & dpci = dPlayConnection.Get(i);
  305. if (!dpci.m_beenUsed)
  306. {
  307. dpci.CallEnumRoutine(lpEnumCallback);
  308. dpci.m_beenUsed = TRUE;
  309. }
  310. }
  311. }
  312. }
  313. return hResult;
  314. }
  315. /*++
  316. Register hooked functions
  317. --*/
  318. HOOK_BEGIN
  319. APIHOOK_ENTRY_DIRECTX_COMSERVER()
  320. COMHOOK_ENTRY(DirectPlay, IDirectPlay4A, EnumConnections, 35)
  321. COMHOOK_ENTRY(DirectPlay, IDirectPlay3A, EnumConnections, 35)
  322. HOOK_END
  323. IMPLEMENT_SHIM_END