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.

352 lines
8.5 KiB

  1. //+-------------------------------------------------------------------
  2. //
  3. // File: srvmain.cxx
  4. //
  5. // Contents: Server entry points.
  6. //
  7. // Classes: none
  8. //
  9. // History: 23-Nov-92 Rickhi Created
  10. //
  11. //--------------------------------------------------------------------
  12. #include <pch.cxx>
  13. #pragma hdrstop
  14. extern "C"
  15. {
  16. #include "wterm.h"
  17. #include <memory.h>
  18. #include <stdio.h>
  19. }
  20. // globals
  21. LONG g_Usage = 0;
  22. DWORD gTlsIndex = TlsAlloc();
  23. //+-------------------------------------------------------------------
  24. //
  25. // typedef: SCLASSDATA - class data stored in TLS.
  26. //
  27. //+-------------------------------------------------------------------
  28. typedef struct tagSCLASSDATA
  29. {
  30. ULONG cClasses;
  31. SCLASSINFO *pClsInfo;
  32. } SCLASSDATA;
  33. //+-------------------------------------------------------------------
  34. //
  35. // Function: RememberClasses
  36. //
  37. // Synopsis: Stores the class info for this thread in TLS.
  38. //
  39. // History: 21-Nov-92 SarahJ Created
  40. //
  41. //--------------------------------------------------------------------
  42. HRESULT RememberClasses(SCLASSINFO *pClsInfo, ULONG cClasses)
  43. {
  44. SCLASSDATA *pClsData = (SCLASSDATA *) new BYTE[sizeof(SCLASSDATA)];
  45. if (pClsData)
  46. {
  47. pClsData->cClasses = cClasses;
  48. pClsData->pClsInfo = pClsInfo;
  49. TlsSetValue(gTlsIndex, pClsData);
  50. return S_OK;
  51. }
  52. return E_OUTOFMEMORY;
  53. }
  54. //+-------------------------------------------------------------------
  55. //
  56. // Function: RecallClasses
  57. //
  58. // Synopsis: retrieves the class info for this thread from TLS.
  59. //
  60. // History: 21-Nov-92 SarahJ Created
  61. //
  62. //--------------------------------------------------------------------
  63. void RecallClasses(SCLASSINFO **ppClsInfo, ULONG *pcClasses)
  64. {
  65. SCLASSDATA *pClsData = (SCLASSDATA *) TlsGetValue(gTlsIndex);
  66. if (pClsData)
  67. {
  68. *pcClasses = pClsData->cClasses;
  69. *ppClsInfo = pClsData->pClsInfo;
  70. }
  71. else
  72. {
  73. *pcClasses = 0;
  74. *ppClsInfo = NULL;
  75. }
  76. }
  77. //+-------------------------------------------------------------------
  78. //
  79. // Function: ForgetClasses
  80. //
  81. // Synopsis: removes the class info for this thread from TLS.
  82. //
  83. // History: 21-Nov-92 SarahJ Created
  84. //
  85. //--------------------------------------------------------------------
  86. void ForgetClasses()
  87. {
  88. SCLASSDATA *pClsData = (SCLASSDATA *) TlsGetValue(gTlsIndex);
  89. if (pClsData)
  90. {
  91. delete pClsData;
  92. TlsSetValue(gTlsIndex, NULL);
  93. }
  94. }
  95. //+-------------------------------------------------------------------
  96. //
  97. // Function: RegisterAllClasses
  98. //
  99. // Synopsis: loops, registering each class specified by the server.
  100. //
  101. // History: 21-Nov-92 SarahJ Created
  102. //
  103. //--------------------------------------------------------------------
  104. void RegisterAllClasses(SCLASSINFO *pClsInfo, ULONG cClasses)
  105. {
  106. // store the class info in TLS so we can get it back later
  107. // in GlobalRefs.
  108. if (FAILED(RememberClasses(pClsInfo, cClasses)))
  109. return;
  110. HRESULT hr;
  111. for (ULONG i=0; i<cClasses; i++, pClsInfo++)
  112. {
  113. // register the CF. Note that we do this AFTER creating the
  114. // window, so that if we get a Release very quickly we have
  115. // a valid window handle to send a message to.
  116. hr = CoRegisterClassObject(pClsInfo->clsid,
  117. pClsInfo->pCF,
  118. pClsInfo->dwCtx,
  119. pClsInfo->dwClsReg,
  120. &pClsInfo->dwReg);
  121. if (FAILED(hr))
  122. {
  123. Display(TEXT("ERROR: failed CoRegisterClassObject %x\n"), hr);
  124. }
  125. }
  126. if (FAILED(hr))
  127. {
  128. Display(TEXT("ERROR: failed CoResumeClassObjects %x\n"), hr);
  129. }
  130. }
  131. //+-------------------------------------------------------------------
  132. //
  133. // Function: RevokeAllClasses
  134. //
  135. // Synopsis: loops, revoking each class specified by the server.
  136. //
  137. // History: 21-Nov-92 SarahJ Created
  138. //
  139. //--------------------------------------------------------------------
  140. void RevokeAllClasses()
  141. {
  142. // first, get the class information from TLS
  143. SCLASSINFO *pClsInfo;
  144. ULONG cClasses;
  145. RecallClasses(&pClsInfo, &cClasses);
  146. // now revoke each of the registered classes
  147. for (ULONG i=0; i<cClasses; i++, pClsInfo++)
  148. {
  149. if (pClsInfo->dwReg != 0)
  150. {
  151. ULONG ulRef = CoRevokeClassObject(pClsInfo->dwReg);
  152. Display(TEXT("Revoked ClassObject\n"));
  153. pClsInfo->dwReg = 0;
  154. }
  155. }
  156. }
  157. //+-------------------------------------------------------------------
  158. //
  159. // Function: ReleaseAllClasses
  160. //
  161. // Synopsis: loops, releasing each class factory object.
  162. //
  163. // History: 21-Nov-92 SarahJ Created
  164. //
  165. //--------------------------------------------------------------------
  166. void ReleaseAllClasses()
  167. {
  168. // first, get the class information from TLS
  169. SCLASSINFO *pClsInfo;
  170. ULONG cClasses;
  171. RecallClasses(&pClsInfo, &cClasses);
  172. // now release each of the class factories
  173. for (ULONG i=0; i<cClasses; i++, pClsInfo++)
  174. {
  175. ULONG ulRef = pClsInfo->pCF->Release();
  176. Display(TEXT("CF RefCnt = %x\n"), ulRef);
  177. }
  178. // now remove the class information from TLS
  179. ForgetClasses();
  180. }
  181. //+-------------------------------------------------------------------------
  182. //
  183. // Function: GlobalRefs
  184. //
  185. // Synopsis: keeps track of global reference couting. Revokes all the
  186. // classes when the global count reaches 0.
  187. //
  188. // History: 06-Aug-92 Ricksa Created
  189. //
  190. //--------------------------------------------------------------------------
  191. void GlobalRefs(BOOL fAddRef)
  192. {
  193. if (fAddRef)
  194. {
  195. g_Usage = CoAddRefServerProcess();
  196. Display(TEXT("Object Count: %ld\n"), g_Usage);
  197. }
  198. else
  199. {
  200. if (0 == (g_Usage = CoReleaseServerProcess()))
  201. {
  202. // No more objects so we can quit
  203. Display(TEXT("Object Server Exiting\n"));
  204. PostMessage((HWND)g_hMain, WM_TERM_WND, 0, 0);
  205. }
  206. }
  207. }
  208. //+-------------------------------------------------------------------
  209. //
  210. // Function: SrvMain
  211. //
  212. // Synopsis: Special entry point for registing just 1 class.
  213. //
  214. // History: 21-Nov-92 SarahJ Created
  215. //
  216. //--------------------------------------------------------------------
  217. int SrvMain(
  218. HANDLE hInstance,
  219. REFCLSID rclsid,
  220. DWORD dwClsReg,
  221. TCHAR *pszAppName,
  222. IClassFactory *pCF)
  223. {
  224. SCLASSINFO clsinfo;
  225. clsinfo.clsid = rclsid;
  226. clsinfo.dwCtx = CLSCTX_LOCAL_SERVER,
  227. clsinfo.dwClsReg = dwClsReg;
  228. clsinfo.pCF = pCF;
  229. clsinfo.dwReg = 0;
  230. STHREADINFO ThrdInfo;
  231. ThrdInfo.hEventRun = CreateEvent(NULL, FALSE, FALSE, NULL);
  232. ThrdInfo.hEventDone = CreateEvent(NULL, FALSE, FALSE, NULL);
  233. ThrdInfo.hInstance = (HINSTANCE)hInstance;
  234. ThrdInfo.dwTid = GetCurrentThreadId();
  235. ThrdInfo.pszWindow = pszAppName;
  236. ThrdInfo.dwFlags = SRVF_THREADMODEL_UNKNOWN;
  237. ThrdInfo.cClasses = 1;
  238. ThrdInfo.pClsInfo = &clsinfo;
  239. return SrvMain2(&ThrdInfo);
  240. }
  241. //+-------------------------------------------------------------------
  242. //
  243. // Function: SrvMain2
  244. //
  245. // Synopsis: Main entry point for registering classes, entering modal
  246. // loop, and cleaning up on exit.
  247. //
  248. // History: 21-Nov-92 SarahJ Created
  249. //
  250. //--------------------------------------------------------------------
  251. int SrvMain2(STHREADINFO *pThrdInfo)
  252. {
  253. MakeTheWindow(pThrdInfo->hInstance, pThrdInfo->pszWindow);
  254. // Initialize the OLE libraries
  255. DWORD dwThreadMode = COINIT_APARTMENTTHREADED;
  256. if (pThrdInfo->dwFlags & SRVF_THREADMODEL_UNKNOWN)
  257. {
  258. // Look up the thread mode from the win.ini file.
  259. TCHAR buffer[80];
  260. int len;
  261. len = GetProfileString( TEXT("OleSrv"),
  262. TEXT("ThreadMode"),
  263. TEXT("MultiThreaded"),
  264. buffer,
  265. sizeof(buffer) );
  266. if (lstrcmp(buffer, TEXT("ApartmentThreaded")) != 0)
  267. dwThreadMode = COINIT_MULTITHREADED;
  268. }
  269. else if (pThrdInfo->dwFlags & SRVF_THREADMODEL_MULTI)
  270. {
  271. dwThreadMode = COINIT_MULTITHREADED;
  272. }
  273. HRESULT hr = CoInitializeEx(NULL, dwThreadMode);
  274. if (SUCCEEDED(hr))
  275. {
  276. // registe all the classes
  277. RegisterAllClasses(pThrdInfo->pClsInfo, pThrdInfo->cClasses);
  278. }
  279. else
  280. {
  281. Display(TEXT("ERROR: failed OleInitialize %x\n"), hr);
  282. }
  283. if (pThrdInfo->dwFlags & SRVF_REGISTER_RESUME)
  284. {
  285. hr = CoResumeClassObjects();
  286. }
  287. // notify the main thread we are running now
  288. SetEvent(pThrdInfo->hEventRun);
  289. // Message processing loop
  290. MSG msg;
  291. while (GetMessage (&msg, NULL, 0, 0))
  292. {
  293. TranslateMessage (&msg);
  294. DispatchMessage (&msg);
  295. }
  296. // revoke the classes again incase we missed any (eg. no instances
  297. // were created, the user just closed the app).
  298. RevokeAllClasses();
  299. // release the classes
  300. ReleaseAllClasses();
  301. // Tell OLE we are going away.
  302. CoUninitialize();
  303. // notify the main thread that we are done
  304. SetEvent(pThrdInfo->hEventDone);
  305. return (msg.wParam); /* Returns the value from PostQuitMessage */
  306. }