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.

212 lines
5.5 KiB

  1. // RDSHost.cpp : Implementation of WinMain
  2. // Note: Proxy/Stub Information
  3. // To build a separate proxy/stub DLL,
  4. // run nmake -f RDSHostps.mk in the project directory.
  5. #include "stdafx.h"
  6. #ifdef TRC_FILE
  7. #undef TRC_FILE
  8. #endif
  9. #define TRC_FILE "_rdshost"
  10. #include "resource.h"
  11. #include <initguid.h>
  12. #include "RDSHost.h"
  13. #include "RDSHost_i.c"
  14. #include "RemoteDesktopServerHost.h"
  15. const DWORD dwTimeOut = 5000; // time for EXE to be idle before shutting down
  16. const DWORD dwPause = 1000; // time to wait for threads to finish up
  17. // Passed to CreateThread to monitor the shutdown event
  18. static DWORD WINAPI MonitorProc(void* pv)
  19. {
  20. CExeModule* p = (CExeModule*)pv;
  21. p->MonitorShutdown();
  22. return 0;
  23. }
  24. LONG CExeModule::Lock()
  25. {
  26. DC_BEGIN_FN("CExeModule::Lock");
  27. LONG l = CComModule::Lock();
  28. TRC_NRM((TB, L"Lock count: %ld", l));
  29. DC_END_FN();
  30. return l;
  31. }
  32. LONG CExeModule::Unlock()
  33. {
  34. DC_BEGIN_FN("CExeModule::Unlock");
  35. LONG l = CComModule::Unlock();
  36. if (l == 0)
  37. {
  38. bActivity = true;
  39. SetEvent(hEventShutdown); // tell monitor that we transitioned to zero
  40. }
  41. TRC_NRM((TB, L"Lock count: %ld", l));
  42. DC_END_FN();
  43. return l;
  44. }
  45. //Monitors the shutdown event
  46. void CExeModule::MonitorShutdown()
  47. {
  48. while (1)
  49. {
  50. WaitForSingleObject(hEventShutdown, INFINITE);
  51. DWORD dwWait=0;
  52. do
  53. {
  54. bActivity = false;
  55. dwWait = WaitForSingleObject(hEventShutdown, dwTimeOut);
  56. } while (dwWait == WAIT_OBJECT_0);
  57. // timed out
  58. if (!bActivity && m_nLockCnt == 0) // if no activity let's really bail
  59. {
  60. #if _WIN32_WINNT >= 0x0400 & defined(_ATL_FREE_THREADED)
  61. CoSuspendClassObjects();
  62. if (!bActivity && m_nLockCnt == 0)
  63. #endif
  64. break;
  65. }
  66. }
  67. CloseHandle(hEventShutdown);
  68. PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);
  69. }
  70. bool CExeModule::StartMonitor()
  71. {
  72. hEventShutdown = CreateEvent(NULL, false, false, NULL);
  73. if (hEventShutdown == NULL)
  74. return false;
  75. DWORD dwThreadID;
  76. HANDLE h = CreateThread(NULL, 0, MonitorProc, this, 0, &dwThreadID);
  77. return (h != NULL);
  78. }
  79. CExeModule _Module;
  80. BEGIN_OBJECT_MAP(ObjectMap)
  81. OBJECT_ENTRY(CLSID_SAFRemoteDesktopServerHost, CRemoteDesktopServerHost)
  82. END_OBJECT_MAP()
  83. LPCTSTR FindOneOf(LPCTSTR p1, LPCTSTR p2)
  84. {
  85. while (p1 != NULL && *p1 != NULL)
  86. {
  87. LPCTSTR p = p2;
  88. while (p != NULL && *p != NULL)
  89. {
  90. if (*p1 == *p)
  91. return CharNext(p1);
  92. p = CharNext(p);
  93. }
  94. p1 = CharNext(p1);
  95. }
  96. return NULL;
  97. }
  98. /////////////////////////////////////////////////////////////////////////////
  99. //
  100. extern "C" int WINAPI _tWinMain(HINSTANCE hInstance,
  101. HINSTANCE /*hPrevInstance*/, LPTSTR lpCmdLine, int /*nShowCmd*/)
  102. {
  103. lpCmdLine = GetCommandLine(); //this line necessary for _ATL_MIN_CRT
  104. #if _WIN32_WINNT >= 0x0400 & defined(_ATL_FREE_THREADED)
  105. HRESULT hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  106. #else
  107. HRESULT hRes = CoInitialize(NULL);
  108. #endif
  109. _ASSERTE(SUCCEEDED(hRes));
  110. //
  111. // This makes us accessible by anyone from user-mode. This is required from
  112. // a security perspective because our interfaces are passed from SYSTEM context
  113. // to USER context, by a "trusted" creator.
  114. //
  115. CSecurityDescriptor sd;
  116. sd.InitializeFromThreadToken();
  117. HRESULT testHR = CoInitializeSecurity(sd, -1, NULL, NULL,
  118. RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONATE,
  119. NULL, EOAC_NONE, NULL);
  120. _ASSERTE(SUCCEEDED(testHR));
  121. _Module.Init(ObjectMap, hInstance, &LIBID_RDSSERVERHOSTLib);
  122. _Module.dwThreadID = GetCurrentThreadId();
  123. TCHAR szTokens[] = _T("-/");
  124. int nRet = 0;
  125. BOOL bRun = TRUE;
  126. LPCTSTR lpszToken = FindOneOf(lpCmdLine, szTokens);
  127. while (lpszToken != NULL)
  128. {
  129. if (lstrcmpi(lpszToken, _T("UnregServer"))==0)
  130. {
  131. _Module.UpdateRegistryFromResource(IDR_RDSHost, FALSE);
  132. nRet = _Module.UnregisterServer(TRUE);
  133. bRun = FALSE;
  134. break;
  135. }
  136. if (lstrcmpi(lpszToken, _T("RegServer"))==0)
  137. {
  138. _Module.UpdateRegistryFromResource(IDR_RDSHost, TRUE);
  139. nRet = _Module.RegisterServer(TRUE);
  140. bRun = FALSE;
  141. break;
  142. }
  143. lpszToken = FindOneOf(lpszToken, szTokens);
  144. }
  145. if (bRun)
  146. {
  147. WSADATA wsaData;
  148. //
  149. // ignore WinSock startup error, failure in starting Winsock does not
  150. // damage our function, only thing will failed is gethostbyname()
  151. // which is use in callback, however, connection parameter contain
  152. // all IP address except last one is the machine name.
  153. //
  154. WSAStartup(0x0101, &wsaData);
  155. _Module.StartMonitor();
  156. #if _WIN32_WINNT >= 0x0400 & defined(_ATL_FREE_THREADED)
  157. hRes = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER,
  158. REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED);
  159. _ASSERTE(SUCCEEDED(hRes));
  160. hRes = CoResumeClassObjects();
  161. #else
  162. hRes = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER,
  163. REGCLS_MULTIPLEUSE);
  164. #endif
  165. _ASSERTE(SUCCEEDED(hRes));
  166. MSG msg;
  167. while (GetMessage(&msg, 0, 0, 0))
  168. DispatchMessage(&msg);
  169. _Module.RevokeClassObjects();
  170. Sleep(dwPause); //wait for any threads to finish
  171. WSACleanup();
  172. }
  173. _Module.Term();
  174. CoUninitialize();
  175. return nRet;
  176. }