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.

475 lines
12 KiB

  1. //+-------------------------------------------------------------------
  2. //
  3. // File: perfsrv.cxx
  4. //
  5. // Contents: This file contins the DLL entry points
  6. // LibMain
  7. // DllGetClassObject (Bindings key func)
  8. // CPerfCF (class factory)
  9. // CPerf (actual class implementation)
  10. //
  11. // Classes: CPerfCF, CPerf
  12. //
  13. //
  14. // History: 30-Nov-92 SarahJ Created
  15. //
  16. //---------------------------------------------------------------------
  17. // Turn off ole Cairol IUnknown
  18. #define __IUNKNOWN_TMP__
  19. #include <windows.h>
  20. #include <ole2.h>
  21. #include "perfsrv.hxx"
  22. extern "C" {
  23. #include <stdio.h>
  24. #include <stdarg.h>
  25. #include "wterm.h"
  26. }
  27. // These are Cairo symbols. Just define them here so I don't have to rip
  28. // out or conditionally compile all references to them.
  29. #define COINIT_MULTITHREADED 0
  30. #define COINIT_SINGLETHREADED 1
  31. #define IDM_DEBUG 0x100
  32. // Count of objects we have instantiated. When we detect 0, we quit.
  33. ULONG g_cUsage = 0;
  34. const TCHAR *szAppName = L"Performance Server";
  35. HWND g_hMain;
  36. DWORD thread_mode = COINIT_SINGLETHREADED;
  37. DWORD MainThread;
  38. DWORD junk;
  39. void Display(TCHAR *pszFmt, ...)
  40. {
  41. va_list marker;
  42. TCHAR szBuffer[256];
  43. va_start(marker, pszFmt);
  44. int iLen = vswprintf(szBuffer, pszFmt, marker);
  45. va_end(marker);
  46. // Display the message on terminal window
  47. SendMessage(g_hMain, WM_PRINT_LINE, iLen, (LONG) szBuffer);
  48. }
  49. //+-------------------------------------------------------------------------
  50. //
  51. // Function: ProcessMenu
  52. //
  53. // Synopsis: Gets called when a WM_COMMAND message received.
  54. //
  55. // Arguments: [hWindow] - handle for the window
  56. // [uiMessage] - message id
  57. // [wParam] - word parameter
  58. // [lParam] - long parameter
  59. //
  60. // Returns: DefWindowProc result
  61. //
  62. // History: 06-Aug-92 Ricksa Created
  63. //
  64. //--------------------------------------------------------------------------
  65. long ProcessMenu(HWND hWindow, UINT uiMessage, WPARAM wParam, LPARAM lParam,
  66. void *)
  67. {
  68. if ((uiMessage == WM_SYSCOMMAND) && (wParam == IDM_DEBUG))
  69. {
  70. // Request for a debug breakpoint!
  71. DebugBreak();
  72. }
  73. return (DefWindowProc(hWindow, uiMessage, wParam, lParam));
  74. }
  75. //+-------------------------------------------------------------------------
  76. //
  77. // Function: ProcessChar
  78. //
  79. // Synopsis: Gets called when a WM_CHAR message received.
  80. //
  81. // Arguments: [hWindow] - handle for the window
  82. // [uiMessage] - message id
  83. // [wParam] - word parameter
  84. // [lParam] - long parameter
  85. //
  86. // Returns: DefWindowProc result
  87. //
  88. // History: 06-Aug-92 Ricksa Created
  89. //
  90. //--------------------------------------------------------------------------
  91. long ProcessChar(HWND hWindow, UINT uiMessage, WPARAM wParam, LPARAM lParam,
  92. void *)
  93. {
  94. return (DefWindowProc(hWindow, uiMessage, wParam, lParam));
  95. }
  96. //+-------------------------------------------------------------------------
  97. //
  98. // Function: ProcessClose
  99. //
  100. // Synopsis: Gets called when a NC_DESTROY message received.
  101. //
  102. // Arguments: [hWindow] - handle for the window
  103. // [uiMessage] - message id
  104. // [wParam] - word parameter
  105. // [lParam] - long parameter
  106. //
  107. // Returns: DefWindowProc result
  108. //
  109. // History: 06-Aug-92 Ricksa Created
  110. //
  111. //--------------------------------------------------------------------------
  112. long ProcessClose(
  113. HWND hWindow,
  114. UINT uiMessage,
  115. WPARAM wParam,
  116. LPARAM lParam,
  117. void *pvCallBackData)
  118. {
  119. // Take default action with message
  120. return (DefWindowProc(hWindow, uiMessage, wParam, lParam));
  121. }
  122. //+-------------------------------------------------------------------
  123. //
  124. // Function: WinMain
  125. //
  126. // Synopsis: Entry point to DLL - does little else
  127. //
  128. // Arguments:
  129. //
  130. // Returns: TRUE
  131. //
  132. // History: 21-Nov-92 SarahJ Created
  133. //
  134. //--------------------------------------------------------------------
  135. int WINAPI WinMain(
  136. HINSTANCE hInstance,
  137. HINSTANCE hPrevInstance,
  138. char *lpCmdLine,
  139. int nCmdShow)
  140. {
  141. // For windows message
  142. MSG msg;
  143. DWORD dwRegistration;
  144. int len;
  145. TCHAR buffer[80];
  146. MainThread = GetCurrentThreadId();
  147. // Look up the thread mode from the win.ini file.
  148. #if 0
  149. len = GetProfileString( L"My Section", L"ThreadMode", L"MultiThreaded", buffer,
  150. sizeof(buffer) );
  151. if (lstrcmp(buffer, L"SingleThreaded") == 0)
  152. thread_mode = COINIT_SINGLETHREADED;
  153. else if (lstrcmp(buffer, L"MultiThreaded") == 0)
  154. thread_mode = COINIT_MULTITHREADED;
  155. #endif
  156. // Initialize the OLE libraries
  157. OleInitialize(NULL);
  158. // Create our class factory
  159. CPerfCF *perf_cf = new CPerfCF();
  160. // Register our class with OLE
  161. CoRegisterClassObject(CLSID_IPerf, perf_cf, CLSCTX_LOCAL_SERVER,
  162. REGCLS_MULTIPLEUSE, &dwRegistration);
  163. // CoRegister bumps reference count so we don't have to!
  164. perf_cf->Release();
  165. // Register the window class
  166. TermRegisterClass(hInstance, (LPTSTR) szAppName,
  167. (LPTSTR) szAppName, (LPTSTR) (1));
  168. // Create the server window
  169. TermCreateWindow(
  170. (LPTSTR) szAppName,
  171. (LPTSTR) szAppName,
  172. NULL,
  173. ProcessMenu,
  174. ProcessChar,
  175. ProcessClose,
  176. SW_SHOWNORMAL,
  177. &g_hMain,
  178. NULL);
  179. // Add debug option to system menu
  180. HMENU hmenu = GetSystemMenu(g_hMain, FALSE);
  181. AppendMenu(hmenu, MF_SEPARATOR, 0, NULL);
  182. AppendMenu(hmenu, MF_STRING | MF_ENABLED, IDM_DEBUG, L"Debug");
  183. // Print the process id.
  184. Display( L"Hi, I am %x.\n", GetCurrentProcessId() );
  185. // Echo the mode.
  186. if (thread_mode == COINIT_SINGLETHREADED)
  187. Display(L"Server running in single threaded mode.\n");
  188. else
  189. Display(L"Server running in multithreaded mode.\n");
  190. // Message processing loop
  191. while (GetMessage (&msg, NULL, 0, 0))
  192. {
  193. TranslateMessage (&msg);
  194. DispatchMessage (&msg);
  195. }
  196. // Deregister out class - should release object as well
  197. CoRevokeClassObject(dwRegistration);
  198. // Tell OLE we are going away.
  199. OleUninitialize();
  200. return (msg.wParam); /* Returns the value from PostQuitMessage */
  201. }
  202. /***************************************************************************/
  203. void CheckThread( TCHAR *name )
  204. {
  205. if (thread_mode == COINIT_SINGLETHREADED)
  206. {
  207. if (GetCurrentThreadId() != MainThread)
  208. goto complain;
  209. }
  210. else
  211. {
  212. if (GetCurrentThreadId() == MainThread)
  213. goto complain;
  214. }
  215. return;
  216. complain:
  217. Display( L"*********************************************************\n" );
  218. Display( L"* *\n" );
  219. Display( L"* Error *\n" );
  220. Display( L"* *\n" );
  221. Display( L"* Method called on wrong thread. *\n" );
  222. Display( name );
  223. Display( L"* *\n" );
  224. Display( L"*********************************************************\n" );
  225. }
  226. /***************************************************************************/
  227. STDMETHODIMP_(ULONG) CPerf::AddRef( THIS )
  228. {
  229. CheckThread(L"STDMETHODIMP_(ULONG) CPerf::AddRef( THIS )");
  230. InterlockedIncrement( (long *) &ref_count );
  231. return ref_count;
  232. }
  233. /***************************************************************************/
  234. CPerf::CPerf()
  235. {
  236. ref_count = 1;
  237. g_cUsage++;
  238. }
  239. /***************************************************************************/
  240. CPerf::~CPerf()
  241. {
  242. if (--g_cUsage == 0)
  243. {
  244. SendMessage(g_hMain, WM_TERM_WND, 0, 0);
  245. }
  246. }
  247. /***************************************************************************/
  248. STDMETHODIMP CPerf::GetAnotherObject( IPerf **another )
  249. {
  250. CheckThread(L"STDMETHODIMP CPerf::GetAnotherObject( IPerf **another )");
  251. *another = NULL;
  252. CPerf *perf = new FAR CPerf();
  253. if (perf == NULL)
  254. {
  255. return E_OUTOFMEMORY;
  256. }
  257. *another = perf;
  258. return S_OK;
  259. }
  260. /***************************************************************************/
  261. STDMETHODIMP CPerf::HResultCall()
  262. {
  263. CheckThread(L"STDMETHODIMP CPerf::HResultCall()");
  264. return S_OK;
  265. }
  266. /***************************************************************************/
  267. STDMETHODIMP CPerf::NullCall()
  268. {
  269. return S_OK;
  270. }
  271. /***************************************************************************/
  272. STDMETHODIMP CPerf::PassMoniker( IMoniker *moniker )
  273. {
  274. HRESULT result;
  275. IBindCtx *bindctx;
  276. WCHAR *wide_name;
  277. // Get a bind context.
  278. result = CreateBindCtx( NULL, &bindctx );
  279. if (FAILED(result))
  280. {
  281. Display( L"Could not create bind context: 0x%x\n", result );
  282. return E_FAIL;
  283. }
  284. // Display name.
  285. result = moniker->GetDisplayName( bindctx, NULL, &wide_name );
  286. if (FAILED(result))
  287. {
  288. Display( L"Could not get display name: 0x%x\n", result );
  289. return E_FAIL;
  290. }
  291. // Display the name.
  292. Display( L"The moniker is called <%s>\n", wide_name );
  293. // Free string.
  294. CoTaskMemFree( wide_name );
  295. // Release everything.
  296. moniker->Release();
  297. bindctx->Release();
  298. return S_OK;
  299. }
  300. /***************************************************************************/
  301. STDMETHODIMP CPerf::QueryInterface( THIS_ REFIID riid, LPVOID FAR* ppvObj)
  302. {
  303. CheckThread(L"STDMETHODIMP CPerf::QueryInterface( THIS_ REFIID riid, LPVOID FAR* ppvObj)" );
  304. if (IsEqualIID(riid, IID_IUnknown) ||
  305. IsEqualIID(riid, IID_IPerf))
  306. {
  307. *ppvObj = (IUnknown *) this;
  308. AddRef();
  309. return S_OK;
  310. }
  311. else
  312. {
  313. *ppvObj = NULL;
  314. return E_NOINTERFACE;
  315. }
  316. }
  317. /***************************************************************************/
  318. STDMETHODIMP_(ULONG) CPerf::Release( THIS )
  319. {
  320. CheckThread(L"STDMETHODIMP_(ULONG) CPerf::Release( THIS )");
  321. if (InterlockedDecrement( (long*) &ref_count ) == 0)
  322. {
  323. delete this;
  324. return 0;
  325. }
  326. else
  327. return ref_count;
  328. }
  329. /***************************************************************************/
  330. STDMETHODIMP_(ULONG) CPerfCF::AddRef( THIS )
  331. {
  332. CheckThread(L"STDMETHODIMP_(ULONG) CPerfCF::AddRef( THIS )");
  333. InterlockedIncrement( (long *) &ref_count );
  334. return ref_count;
  335. }
  336. /***************************************************************************/
  337. CPerfCF::CPerfCF()
  338. {
  339. ref_count = 1;
  340. }
  341. /***************************************************************************/
  342. CPerfCF::~CPerfCF()
  343. {
  344. }
  345. /***************************************************************************/
  346. STDMETHODIMP CPerfCF::CreateInstance(
  347. IUnknown FAR* pUnkOuter,
  348. REFIID iidInterface,
  349. void FAR* FAR* ppv)
  350. {
  351. CheckThread(L"STDMETHODIMP CPerfCF::CreateInstance(" );
  352. Display(L"CPerfCF::CreateInstance called\n");
  353. *ppv = NULL;
  354. if (pUnkOuter != NULL)
  355. {
  356. return E_FAIL;
  357. }
  358. if (!IsEqualIID( iidInterface, IID_IPerf ))
  359. return E_NOINTERFACE;
  360. CPerf *perf = new FAR CPerf();
  361. if (perf == NULL)
  362. {
  363. return E_OUTOFMEMORY;
  364. }
  365. *ppv = perf;
  366. return S_OK;
  367. }
  368. /***************************************************************************/
  369. STDMETHODIMP CPerfCF::LockServer(BOOL fLock)
  370. {
  371. CheckThread( L"STDMETHODIMP CPerfCF::LockServer(BOOL fLock)" );
  372. return E_FAIL;
  373. }
  374. /***************************************************************************/
  375. STDMETHODIMP CPerfCF::QueryInterface( THIS_ REFIID riid, LPVOID FAR* ppvObj)
  376. {
  377. CheckThread(L"STDMETHODIMP CPerfCF::QueryInterface( THIS_ REFIID riid, LPVOID FAR* ppvObj)");
  378. if (IsEqualIID(riid, IID_IUnknown) ||
  379. IsEqualIID(riid, IID_IClassFactory))
  380. {
  381. *ppvObj = (IUnknown *) this;
  382. AddRef();
  383. return S_OK;
  384. }
  385. *ppvObj = NULL;
  386. return E_NOINTERFACE;
  387. }
  388. /***************************************************************************/
  389. STDMETHODIMP_(ULONG) CPerfCF::Release( THIS )
  390. {
  391. CheckThread(L"STDMETHODIMP_(ULONG) CPerfCF::Release( THIS )");
  392. if (InterlockedDecrement( (long*) &ref_count ) == 0)
  393. {
  394. delete this;
  395. return 0;
  396. }
  397. else
  398. return ref_count;
  399. }
  400.