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.

305 lines
7.8 KiB

  1. //+-------------------------------------------------------------------
  2. //
  3. // File: srvmain.cxx
  4. //
  5. // Contents: This file contins the EXE entry points
  6. //
  7. // History: 28-Feb-96 Rickhi Created
  8. //
  9. //---------------------------------------------------------------------
  10. #include <common.h>
  11. #include <mixedcf.hxx>
  12. extern "C" const GUID CLSID_QI;
  13. extern "C" const GUID CLSID_Balls;
  14. extern "C" const GUID CLSID_Loop;
  15. extern "C" const GUID CLSID_Cubes;
  16. int WINAPI RegisterSameThread(
  17. HINSTANCE hInstance,
  18. HINSTANCE hPrevInstance,
  19. LPSTR lpCmdLine,
  20. int nCmdShow,
  21. DWORD dwThreadModel);
  22. int WINAPI RegisterDifferentThreads(
  23. HINSTANCE hInstance,
  24. HINSTANCE hPrevInstance,
  25. LPSTR lpCmdLine,
  26. int nCmdShow,
  27. DWORD dwThreadModel);
  28. void RunServerThread(STHREADINFO *pThrdInfo);
  29. DWORD _stdcall ServerThread(void *param);
  30. void WakeupAllThreads();
  31. TCHAR *pszWindow[] = { TEXT("QI Server"),
  32. TEXT("Balls Server"),
  33. TEXT("Cubes Server"),
  34. TEXT("Loops Server")};
  35. STHREADINFO *gpThrdInfo = NULL;
  36. ULONG gcThrds = 0;
  37. BOOL gfWokenUpAllThreads = FALSE;
  38. //+-------------------------------------------------------------------
  39. //
  40. // Function: MakeClassInfo
  41. //
  42. // Synopsis: fills in a SCLASSINFO structure
  43. //
  44. // History: 28-Feb-96 Rickhi Created
  45. //
  46. //--------------------------------------------------------------------
  47. HRESULT MakeClassInfo(REFCLSID rclsid, SCLASSINFO *pClsInfo)
  48. {
  49. pClsInfo->clsid = rclsid;
  50. pClsInfo->pCF = (IClassFactory *) new CMixedClassFactory(rclsid);
  51. pClsInfo->dwCtx = CLSCTX_LOCAL_SERVER;
  52. pClsInfo->dwClsReg = REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED;
  53. pClsInfo->dwReg = 0;
  54. return (pClsInfo->pCF != NULL) ? S_OK : E_OUTOFMEMORY;
  55. }
  56. //+-------------------------------------------------------------------
  57. //
  58. // Function: WinMain
  59. //
  60. // Synopsis: Entry point. Creates the classinfo and enters the main
  61. // server loop.
  62. //
  63. // History: 28-Feb-96 Rickhi Created
  64. //
  65. //--------------------------------------------------------------------
  66. int WINAPI WinMain(
  67. HINSTANCE hInstance,
  68. HINSTANCE hPrevInstance,
  69. LPSTR lpCmdLine,
  70. int nCmdShow)
  71. {
  72. if (lpCmdLine == NULL)
  73. {
  74. // ShowHelp();
  75. return -1;
  76. }
  77. if (!(strncmp(lpCmdLine, "ApartmentSameThread", 19)))
  78. {
  79. return RegisterSameThread(hInstance, hPrevInstance, lpCmdLine, nCmdShow,
  80. SRVF_THREADMODEL_APARTMENT);
  81. }
  82. else if (!(strncmp(lpCmdLine, "FreeSameThread", 14)))
  83. {
  84. return RegisterSameThread(hInstance, hPrevInstance, lpCmdLine, nCmdShow,
  85. SRVF_THREADMODEL_MULTI);
  86. }
  87. else if (!(strncmp(lpCmdLine, "ApartmentDifferentThread", 24)))
  88. {
  89. return RegisterDifferentThreads(hInstance, hPrevInstance, lpCmdLine, nCmdShow,
  90. SRVF_THREADMODEL_APARTMENT);
  91. }
  92. else if (!(strncmp(lpCmdLine, "FreeDifferentThread", 24)))
  93. {
  94. return RegisterDifferentThreads(hInstance, hPrevInstance, lpCmdLine, nCmdShow,
  95. SRVF_THREADMODEL_MULTI);
  96. }
  97. return -1;
  98. }
  99. //+-------------------------------------------------------------------
  100. //
  101. // Function: RegisterSameThread
  102. //
  103. // Synopsis: Entry point. Creates the classinfo and enters the main
  104. // server loop.
  105. //
  106. // History: 28-Feb-96 Rickhi Created
  107. //
  108. //--------------------------------------------------------------------
  109. int WINAPI RegisterSameThread(
  110. HINSTANCE hInstance,
  111. HINSTANCE hPrevInstance,
  112. LPSTR lpCmdLine,
  113. int nCmdShow,
  114. DWORD dwThreadModel)
  115. {
  116. SCLASSINFO ClsInfo[4];
  117. STHREADINFO ThrdInfo;
  118. HRESULT hr[4];
  119. hr[0] = MakeClassInfo(CLSID_QI, &ClsInfo[0]);
  120. hr[1] = MakeClassInfo(CLSID_Balls, &ClsInfo[1]);
  121. hr[2] = MakeClassInfo(CLSID_Cubes, &ClsInfo[2]);
  122. hr[3] = MakeClassInfo(CLSID_Loop, &ClsInfo[3]);
  123. ThrdInfo.hEventRun = CreateEvent(NULL, FALSE, FALSE, NULL);
  124. ThrdInfo.hEventDone = CreateEvent(NULL, FALSE, FALSE, NULL);
  125. ThrdInfo.hInstance = hInstance;
  126. ThrdInfo.pszWindow = pszWindow[0];
  127. ThrdInfo.dwFlags = dwThreadModel;
  128. ThrdInfo.cClasses = 4;
  129. ThrdInfo.pClsInfo = &ClsInfo[0];
  130. // this thread is the one that should call resume.
  131. ThrdInfo.dwFlags |= SRVF_REGISTER_RESUME;
  132. ThrdInfo.dwTid = GetCurrentThreadId();
  133. // stuff the thrd pointers and count into globals so we can
  134. // wake the threads up whenever 1 single thread exits.
  135. gpThrdInfo = &ThrdInfo;
  136. gcThrds = 1;
  137. hr[0] = SrvMain2(&ThrdInfo);
  138. return hr[0];
  139. }
  140. //+-------------------------------------------------------------------
  141. //
  142. // Function: RegisterDifferentThreads
  143. //
  144. // Synopsis: Entry point. Creates the classinfo and enters the main
  145. // server loop.
  146. //
  147. // History: 28-Feb-96 Rickhi Created
  148. //
  149. //--------------------------------------------------------------------
  150. int WINAPI RegisterDifferentThreads(
  151. HINSTANCE hInstance,
  152. HINSTANCE hPrevInstance,
  153. LPSTR lpCmdLine,
  154. int nCmdShow,
  155. DWORD dwThreadModel)
  156. {
  157. SCLASSINFO ClsInfo[4];
  158. STHREADINFO ThrdInfo[4];
  159. HRESULT hr[4];
  160. hr[0] = MakeClassInfo(CLSID_QI, &ClsInfo[0]);
  161. hr[1] = MakeClassInfo(CLSID_Balls, &ClsInfo[1]);
  162. hr[2] = MakeClassInfo(CLSID_Cubes, &ClsInfo[2]);
  163. hr[3] = MakeClassInfo(CLSID_Loop, &ClsInfo[3]);
  164. for (int i=0; i<4; i++)
  165. {
  166. if (SUCCEEDED(hr[i]))
  167. {
  168. ThrdInfo[i].hEventRun = CreateEvent(NULL, FALSE, FALSE, NULL);
  169. ThrdInfo[i].hEventDone = CreateEvent(NULL, FALSE, FALSE, NULL);
  170. ThrdInfo[i].hInstance = hInstance;
  171. ThrdInfo[i].pszWindow = pszWindow[i];
  172. ThrdInfo[i].dwFlags = dwThreadModel;
  173. ThrdInfo[i].cClasses = 1;
  174. ThrdInfo[i].pClsInfo = &ClsInfo[i];
  175. if (i > 0)
  176. {
  177. // run the thread and wait for it signal it's ready
  178. RunServerThread(&ThrdInfo[i]);
  179. WaitForSingleObject(ThrdInfo[i].hEventRun, 0xffffffff);
  180. CloseHandle(ThrdInfo[i].hEventRun);
  181. }
  182. }
  183. }
  184. // this thread is the one that should call resume.
  185. ThrdInfo[0].dwFlags |= SRVF_REGISTER_RESUME;
  186. ThrdInfo[0].dwTid = GetCurrentThreadId();
  187. // stuff the thrd pointers and count into globals so we can
  188. // wake the threads up whenever 1 single thread exits.
  189. gpThrdInfo = &ThrdInfo[0];
  190. gcThrds = 4;
  191. hr[0] = SrvMain2(&ThrdInfo[0]);
  192. WakeupAllThreads();
  193. for (i=0; i<4; i++)
  194. {
  195. if (SUCCEEDED(hr[i]))
  196. {
  197. // wait for other thread to complete before exiting.
  198. WaitForSingleObject(ThrdInfo[i].hEventDone, 0xffffffff);
  199. CloseHandle(ThrdInfo[i].hEventDone);
  200. }
  201. }
  202. return hr[0];
  203. }
  204. //+-------------------------------------------------------------------
  205. //
  206. // Function: WakeupAllThreads
  207. //
  208. // Synopsis: Wakes up all the other threads in the process when
  209. // one thread decides to exit.
  210. //
  211. // History: 28-Feb-96 Rickhi Created
  212. //
  213. //--------------------------------------------------------------------
  214. void WakeupAllThreads()
  215. {
  216. if (gfWokenUpAllThreads)
  217. return;
  218. gfWokenUpAllThreads = TRUE;
  219. STHREADINFO *pThrdInfo = gpThrdInfo;
  220. for (ULONG i=0; i<gcThrds; i++, pThrdInfo++)
  221. {
  222. PostThreadMessage(pThrdInfo->dwTid, WM_QUIT, 0, 0);
  223. }
  224. }
  225. //+-------------------------------------------------------------------
  226. //
  227. // Function: ServerThread
  228. //
  229. // Synopsis: Thread Entry point. Registers a class and waits for calls
  230. // on it.
  231. //
  232. // History: 28-Feb-96 Rickhi Created
  233. //
  234. //--------------------------------------------------------------------
  235. DWORD _stdcall ServerThread(void *param)
  236. {
  237. STHREADINFO *pThrdInfo = (STHREADINFO *)param;
  238. HRESULT hr = SrvMain2(pThrdInfo);
  239. // wake up the other threads.
  240. WakeupAllThreads();
  241. return hr;
  242. }
  243. //+-------------------------------------------------------------------
  244. //
  245. // Function: RunServerThread
  246. //
  247. // Synopsis: Spins up a thread to act as a class server.
  248. //
  249. // History: 28-Feb-96 Rickhi Created
  250. //
  251. //--------------------------------------------------------------------
  252. void RunServerThread(STHREADINFO *pThrdInfo)
  253. {
  254. HANDLE hThrd = CreateThread(NULL, 0, ServerThread, pThrdInfo,
  255. 0, &(pThrdInfo->dwTid));
  256. if (hThrd)
  257. {
  258. CloseHandle(hThrd);
  259. }
  260. return;
  261. }