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.

377 lines
9.0 KiB

  1. /*
  2. IisRsta.cpp
  3. Implementation of WinMain for COM IIisServiceControl handler
  4. FILE HISTORY:
  5. Phillich 06-Oct-1998 Created
  6. */
  7. #include "stdafx.h"
  8. #include "resource.h"
  9. #include <initguid.h>
  10. #include "iisrsta.h"
  11. #include <secfcns.h>
  12. #include <Aclapi.h>
  13. #include "IisRestart.h"
  14. const DWORD dwTimeOut = 5000; // time for EXE to be idle before shutting down
  15. const DWORD dwPause = 1000; // time to wait for threads to finish up
  16. HRESULT
  17. AddLaunchPermissionsAcl(
  18. PSECURITY_DESCRIPTOR pSD
  19. );
  20. // Passed to CreateThread to monitor the shutdown event
  21. static DWORD WINAPI MonitorProc(void* pv)
  22. {
  23. CExeModule* p = (CExeModule*)pv;
  24. p->MonitorShutdown();
  25. return 0;
  26. }
  27. LONG CExeModule::Unlock()
  28. {
  29. LONG l = CComModule::Unlock();
  30. if (l == 0)
  31. {
  32. bActivity = true;
  33. SetEvent(hEventShutdown); // tell monitor that we transitioned to zero
  34. }
  35. return l;
  36. }
  37. //Monitors the shutdown event
  38. void CExeModule::MonitorShutdown()
  39. {
  40. while (1)
  41. {
  42. WaitForSingleObject(hEventShutdown, INFINITE);
  43. DWORD dwWait=0;
  44. do
  45. {
  46. bActivity = false;
  47. dwWait = WaitForSingleObject(hEventShutdown, dwTimeOut);
  48. } while (dwWait == WAIT_OBJECT_0);
  49. // timed out
  50. if (!bActivity && m_nLockCnt == 0) // if no activity let's really bail
  51. {
  52. break;
  53. }
  54. }
  55. CloseHandle(hEventShutdown);
  56. PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);
  57. }
  58. bool CExeModule::StartMonitor()
  59. {
  60. hEventShutdown = CreateEvent(NULL, false, false, NULL);
  61. if (hEventShutdown == NULL)
  62. return false;
  63. DWORD dwThreadID;
  64. HANDLE h = CreateThread(NULL, 0, MonitorProc, this, 0, &dwThreadID);
  65. return (h != NULL);
  66. }
  67. CExeModule _Module;
  68. BEGIN_OBJECT_MAP(ObjectMap)
  69. OBJECT_ENTRY(CLSID_IisServiceControl, CIisRestart)
  70. END_OBJECT_MAP()
  71. LPCTSTR FindOneOf(LPCTSTR p1, LPCTSTR p2)
  72. {
  73. while (p1 != NULL && *p1 != NULL)
  74. {
  75. LPCTSTR p = p2;
  76. while (p != NULL && *p != NULL)
  77. {
  78. if (*p1 == *p)
  79. return CharNext(p1);
  80. p = CharNext(p);
  81. }
  82. p1 = CharNext(p1);
  83. }
  84. return NULL;
  85. }
  86. /////////////////////////////////////////////////////////////////////////////
  87. //
  88. int _cdecl
  89. main(
  90. int,
  91. char
  92. )
  93. {
  94. LPTSTR lpCmdLine = GetCommandLine(); // necessary for minimal CRT
  95. HRESULT hRes = S_OK;
  96. DWORD dwErr = ERROR_SUCCESS;
  97. PSID psidAdmin = NULL;
  98. PACL pACL = NULL;
  99. EXPLICIT_ACCESS ea;
  100. SECURITY_DESCRIPTOR sd = {0};
  101. BOOL fCoInitialized = FALSE;
  102. hRes = CoInitializeEx(NULL,COINIT_MULTITHREADED);
  103. if (FAILED(hRes)) {
  104. goto exit;
  105. }
  106. fCoInitialized = TRUE;
  107. //
  108. // Get a sid that represents the Administrators group.
  109. //
  110. dwErr = AllocateAndCreateWellKnownSid( WinBuiltinAdministratorsSid,
  111. &psidAdmin );
  112. if ( dwErr != ERROR_SUCCESS )
  113. {
  114. hRes = HRESULT_FROM_WIN32(dwErr);
  115. goto exit;
  116. }
  117. // Initialize an EXPLICIT_ACCESS structure for an ACE.
  118. SecureZeroMemory(&ea, sizeof(ea));
  119. //
  120. // Setup Administrators for read access.
  121. //
  122. SetExplicitAccessSettings( &ea,
  123. COM_RIGHTS_EXECUTE,
  124. SET_ACCESS,
  125. psidAdmin );
  126. //
  127. // Create a new ACL that contains the new ACEs.
  128. //
  129. dwErr = SetEntriesInAcl(sizeof(ea)/sizeof(EXPLICIT_ACCESS), &ea, NULL, &pACL);
  130. if ( dwErr != ERROR_SUCCESS )
  131. {
  132. hRes = HRESULT_FROM_WIN32(dwErr);
  133. goto exit;
  134. }
  135. if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
  136. {
  137. hRes = HRESULT_FROM_WIN32(GetLastError());
  138. goto exit;
  139. }
  140. if (!SetSecurityDescriptorDacl(&sd,
  141. TRUE, // fDaclPresent flag
  142. pACL,
  143. FALSE)) // not a default DACL
  144. {
  145. hRes = HRESULT_FROM_WIN32(GetLastError());
  146. goto exit;
  147. }
  148. if (!SetSecurityDescriptorOwner(&sd,
  149. psidAdmin, // fDaclPresent flag
  150. FALSE)) // not a default DACL
  151. {
  152. hRes = HRESULT_FROM_WIN32(GetLastError());
  153. goto exit;
  154. }
  155. if (!SetSecurityDescriptorGroup(&sd,
  156. psidAdmin, // fDaclPresent flag
  157. FALSE)) // not a default DACL
  158. {
  159. hRes = HRESULT_FROM_WIN32(GetLastError());
  160. goto exit;
  161. }
  162. hRes = CoInitializeSecurity(
  163. &sd,
  164. -1,
  165. NULL,
  166. NULL,
  167. RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
  168. RPC_C_IMP_LEVEL_ANONYMOUS,
  169. NULL,
  170. EOAC_DYNAMIC_CLOAKING |
  171. EOAC_DISABLE_AAA |
  172. EOAC_NO_CUSTOM_MARSHAL,
  173. NULL );
  174. if (FAILED(hRes))
  175. {
  176. goto exit;
  177. }
  178. _ASSERTE(SUCCEEDED(hRes));
  179. _Module.Init(ObjectMap,GetModuleHandle(NULL));
  180. _Module.dwThreadID = GetCurrentThreadId();
  181. TCHAR szTokens[] = _T("-/");
  182. BOOL bRun = TRUE;
  183. LPCTSTR lpszToken = FindOneOf(lpCmdLine,szTokens);
  184. while (lpszToken != NULL)
  185. {
  186. #pragma prefast(push)
  187. #pragma prefast(disable:400, "Don't complain about case insensitive compares")
  188. if (lstrcmpi(lpszToken, _T("UnregServer"))==0)
  189. {
  190. _Module.UpdateRegistryFromResource(IDR_IISRESTART, FALSE);
  191. bRun = FALSE;
  192. break;
  193. }
  194. if (lstrcmpi(lpszToken, _T("RegServer"))==0)
  195. {
  196. _Module.UpdateRegistryFromResource(IDR_IISRESTART, TRUE);
  197. // we need to do the Module.Terminate so we
  198. // will just flow on with a bad hresult, however
  199. // it will end up getting returned to the user
  200. // so it is ok.
  201. hRes = AddLaunchPermissionsAcl(&sd);
  202. bRun = FALSE;
  203. break;
  204. }
  205. lpszToken = FindOneOf(lpszToken, szTokens);
  206. #pragma prefast(pop)
  207. }
  208. if (bRun) {
  209. _Module.StartMonitor();
  210. hRes = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER,
  211. REGCLS_MULTIPLEUSE);
  212. _ASSERTE(SUCCEEDED(hRes));
  213. MSG msg;
  214. while (GetMessage(&msg, 0, 0, 0))
  215. {
  216. DispatchMessage(&msg);
  217. }
  218. _Module.RevokeClassObjects();
  219. Sleep(dwPause); //wait for any threads to finish
  220. }
  221. _Module.Term();
  222. exit:
  223. FreeWellKnownSid(&psidAdmin);
  224. if (pACL)
  225. {
  226. LocalFree(pACL);
  227. pACL = NULL;
  228. }
  229. if ( fCoInitialized )
  230. {
  231. CoUninitialize();
  232. }
  233. return (hRes);
  234. }
  235. HRESULT
  236. AddLaunchPermissionsAcl(
  237. PSECURITY_DESCRIPTOR pSD
  238. )
  239. {
  240. DWORD Win32Error = NO_ERROR;
  241. HRESULT hr = S_OK;
  242. HKEY KeyHandle = NULL;
  243. PSECURITY_DESCRIPTOR pSDRelative = NULL;
  244. DWORD dwBytesNeeded = 0;
  245. if ( MakeSelfRelativeSD( pSD,
  246. pSDRelative,
  247. &dwBytesNeeded ) )
  248. {
  249. // If this passes, then there is a real problem because
  250. // we didn't give it anywhere to copy to. So
  251. // we fail here.
  252. return E_FAIL;
  253. }
  254. Win32Error = GetLastError();
  255. if ( Win32Error != ERROR_INSUFFICIENT_BUFFER )
  256. {
  257. return HRESULT_FROM_WIN32(Win32Error);
  258. }
  259. // At this point we know the size of the data
  260. // that we are going to receive, so we can allocated
  261. // enough space.
  262. pSDRelative = ( PSECURITY_DESCRIPTOR ) new BYTE[ dwBytesNeeded ];
  263. if ( pSDRelative == NULL )
  264. {
  265. return E_OUTOFMEMORY;
  266. }
  267. if ( !MakeSelfRelativeSD( pSD,
  268. pSDRelative,
  269. &dwBytesNeeded ) )
  270. {
  271. hr = HRESULT_FROM_WIN32(GetLastError());
  272. goto exit;
  273. }
  274. Win32Error = RegOpenKeyEx(
  275. HKEY_CLASSES_ROOT,
  276. L"AppID\\{E8FB8615-588F-11D2-9D61-00C04F79C5FE}",
  277. NULL,
  278. KEY_WRITE,
  279. &KeyHandle
  280. );
  281. if ( Win32Error != NO_ERROR )
  282. {
  283. hr = HRESULT_FROM_WIN32( Win32Error );
  284. goto exit;
  285. }
  286. Win32Error = RegSetValueEx(
  287. KeyHandle,
  288. L"LaunchPermission",
  289. NULL,
  290. REG_BINARY,
  291. reinterpret_cast<BYTE *>( pSDRelative ),
  292. dwBytesNeeded
  293. );
  294. if ( Win32Error != NO_ERROR )
  295. {
  296. hr = HRESULT_FROM_WIN32( Win32Error );
  297. goto exit;
  298. }
  299. exit:
  300. if ( KeyHandle != NULL )
  301. {
  302. RegCloseKey( KeyHandle );
  303. }
  304. if ( pSDRelative != NULL )
  305. {
  306. delete [] pSDRelative;
  307. }
  308. return hr;
  309. }