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.

313 lines
8.9 KiB

  1. //+-----------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (c) Microsoft Corporation 1991 - 1992
  6. //
  7. // File: scmsvc.cxx
  8. //
  9. // Contents: Initialization for win32 service controller.
  10. //
  11. // History: 14-Jul-92 CarlH Created.
  12. // 31-Dec-93 ErikGav Chicago port
  13. // 25-Aug-99 a-sergiv Fixed ScmCreatedEvent vulnerability
  14. //
  15. //------------------------------------------------------------------------
  16. #include "act.hxx"
  17. #ifdef DFSACTIVATION
  18. HANDLE ghDfs = 0;
  19. #endif
  20. #define SCM_CREATED_EVENT TEXT("ScmCreatedEvent")
  21. DECLARE_INFOLEVEL(Cairole);
  22. extern CRITICAL_SECTION ShellQueryCS;
  23. SC_HANDLE g_hServiceController = 0;
  24. PSID psidMySid = NULL;
  25. #if DBG
  26. //+-------------------------------------------------------------------------
  27. //
  28. // Function: SetScmDefaultInfoLevel
  29. //
  30. // Synopsis: Sets the default infolevel for the SCM
  31. //
  32. // History: 07-Jan-94 Ricksa Created
  33. //
  34. // Notes: Uses standard place in win.ini defined by KevinRo but
  35. // does not use the same value as compob32.dll so you don't
  36. // have to get all the debugging in the universe just to
  37. // get the SCM's debug output.
  38. //
  39. // A second point is that we don't use unicode here because
  40. // it is just easier to avoid the unicode headache with
  41. // mulitple builds between chicago and nt
  42. //
  43. //--------------------------------------------------------------------------
  44. char *pszInfoLevelSectionName = "Cairo InfoLevels";
  45. char *pszInfoLevelName = "scm";
  46. char *pszInfoLevelDefault = "$";
  47. #define INIT_VALUE_SIZE 16
  48. void SetScmDefaultInfoLevel(void)
  49. {
  50. char aszInitValue[INIT_VALUE_SIZE];
  51. ULONG ulRet;
  52. ulRet = GetProfileStringA(pszInfoLevelSectionName,
  53. pszInfoLevelName,
  54. pszInfoLevelDefault,
  55. aszInitValue,
  56. INIT_VALUE_SIZE);
  57. if ((ulRet != INIT_VALUE_SIZE - 1) && (aszInitValue[0] != L'$'))
  58. {
  59. if((ulRet = strtoul(aszInitValue, NULL, 16)) == 1)
  60. {
  61. CairoleInfoLevel = ulRet;
  62. }
  63. }
  64. }
  65. #endif // DBG
  66. //+-------------------------------------------------------------------------
  67. //
  68. // Function: InitializeSCMBeforeListen
  69. //
  70. // Synopsis: Initializes OLE side of rpcss. Put things in here that do
  71. // not depend on RPC being initialized, etc.
  72. //
  73. // Arguments: None.
  74. //
  75. // Returns: Status of initialization. Note that this function is a bit
  76. // weak on cleanup in the face of errors, but this is okay since if this
  77. // function fails, RPCSS will not start.
  78. //
  79. //--------------------------------------------------------------------------
  80. DWORD
  81. InitializeSCMBeforeListen( void )
  82. {
  83. LONG Status;
  84. SCODE sc;
  85. RPC_STATUS rs;
  86. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  87. UpdateState(SERVICE_START_PENDING);
  88. Status = RtlInitializeCriticalSection(&gTokenCS);
  89. if (!NT_SUCCESS(Status))
  90. return Status;
  91. Status = RtlInitializeCriticalSection(&ShellQueryCS);
  92. if (!NT_SUCCESS(Status))
  93. return Status;
  94. // Allocate locks
  95. Status = OR_NOMEM;
  96. gpClientLock = new CSharedLock(Status);
  97. if (OR_OK != Status)
  98. return(Status);
  99. Status = OR_NOMEM;
  100. gpServerLock = new CSharedLock(Status);
  101. if (OR_OK != Status)
  102. return(Status);
  103. Status = OR_NOMEM;
  104. gpIPCheckLock = new CSharedLock(Status);
  105. if (OR_OK != Status)
  106. return(Status);
  107. g_hServiceController = OpenSCManager(NULL, NULL, GENERIC_EXECUTE);
  108. if (!g_hServiceController)
  109. return GetLastError();
  110. //
  111. // Get my sid
  112. // This is simplified under the assumption that SCM runs as LocalSystem.
  113. // We should remove this code when we incorporate OLE service into the
  114. // Service Control Manager since this becomes duplicated code then.
  115. //
  116. Status = RtlAllocateAndInitializeSid (
  117. &NtAuthority,
  118. 1,
  119. SECURITY_LOCAL_SYSTEM_RID,
  120. 0, 0, 0, 0, 0, 0, 0,
  121. &psidMySid
  122. );
  123. if (!NT_SUCCESS(Status))
  124. return Status;
  125. UpdateState(SERVICE_START_PENDING);
  126. HRESULT hr = S_OK;
  127. hr = InitSCMRegistry();
  128. if (FAILED(hr))
  129. return ERROR_NOT_ENOUGH_MEMORY;
  130. //Initialize runas cache
  131. InitRunAsCache(); // returns void
  132. gpClassLock = new CSharedLock(Status);
  133. if (!gpClassLock)
  134. return ERROR_NOT_ENOUGH_MEMORY;
  135. gpProcessLock = new CSharedLock(Status);
  136. if (!gpProcessLock)
  137. return ERROR_NOT_ENOUGH_MEMORY;
  138. gpProcessListLock = new CSharedLock(Status);
  139. if (!gpProcessListLock)
  140. return ERROR_NOT_ENOUGH_MEMORY;
  141. gpClassTable = new CServerTable(Status, ENTRY_TYPE_CLASS);
  142. if (!gpClassTable)
  143. return ERROR_NOT_ENOUGH_MEMORY;
  144. gpProcessTable = new CServerTable(Status, ENTRY_TYPE_PROCESS);
  145. if (!gpProcessTable)
  146. return ERROR_NOT_ENOUGH_MEMORY;
  147. gpSurrogateList = new CSurrogateList();
  148. if (!gpSurrogateList)
  149. return ERROR_NOT_ENOUGH_MEMORY;
  150. gpRemoteMachineLock = new CSharedLock(Status);
  151. if (!gpRemoteMachineLock)
  152. return ERROR_NOT_ENOUGH_MEMORY;
  153. gpRemoteMachineList = new CRemoteMachineList();
  154. if (!gpRemoteMachineList)
  155. return ERROR_NOT_ENOUGH_MEMORY;
  156. UpdateState(SERVICE_START_PENDING);
  157. #ifdef DFSACTIVATION
  158. DfsOpen( &ghDfs );
  159. #endif
  160. return 0;
  161. }
  162. //+-------------------------------------------------------------------------
  163. //
  164. // Function: InitializeSCM
  165. //
  166. // Synopsis: Initializes OLE side of rpcss.
  167. //
  168. // Arguments: None.
  169. //
  170. // Returns: ERROR_SUCCESS
  171. //
  172. // (REVIEW: should we be returning an error whenever any of
  173. // the stuff in this function fails?)
  174. //
  175. //--------------------------------------------------------------------------
  176. DWORD
  177. InitializeSCM( void )
  178. {
  179. LONG Status;
  180. SCODE sc;
  181. RPC_STATUS rs;
  182. HRESULT hr;
  183. // start the RPC service
  184. hr = InitScmRot();
  185. if (FAILED(hr))
  186. return ERROR_NOT_ENOUGH_MEMORY;
  187. sc = RpcServerRegisterIf(ISCM_ServerIfHandle, 0, 0);
  188. Win4Assert((sc == 0) && "RpcServerRegisterIf failed!");
  189. sc = RpcServerRegisterIf(ISCMActivator_ServerIfHandle, 0, 0);
  190. Win4Assert((sc == 0) && "RpcServerRegisterIf failed!");
  191. sc = RpcServerRegisterIf(IMachineActivatorControl_ServerIfHandle, 0, 0);
  192. Win4Assert((sc == 0) && "RpcServerRegisterIf failed!");
  193. sc = RpcServerRegisterIf(_IActivation_ServerIfHandle, 0, 0);
  194. Win4Assert((sc == 0) && "RpcServerRegisterIf failed!");
  195. sc = RpcServerRegisterIf(_IRemoteSCMActivator_ServerIfHandle, 0, 0);
  196. Win4Assert((sc == 0) && "RpcServerRegisterIf failed!");
  197. UpdateState(SERVICE_START_PENDING);
  198. return ERROR_SUCCESS;
  199. }
  200. void
  201. InitializeSCMAfterListen()
  202. {
  203. //
  204. // This is for the OLE apps which start during boot. They must wait for
  205. // rpcss to start before completing OLE calls that talk to rpcss.
  206. //
  207. // Need to do this work to make sure the DACL for the event doesn't have
  208. // WRITE_DAC and WRITE_OWNER on it.
  209. //
  210. SID_IDENTIFIER_AUTHORITY SidAuthority = SECURITY_WORLD_SID_AUTHORITY;
  211. PSID pSidEveryone = NULL;
  212. PACL pAcl = NULL;
  213. DWORD cbAcl = 0;
  214. AllocateAndInitializeSid(&SidAuthority, 1, SECURITY_WORLD_RID,
  215. 0, 0, 0, 0, 0, 0, 0, &pSidEveryone);
  216. if(pSidEveryone)
  217. {
  218. cbAcl = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(pSidEveryone);
  219. pAcl = (PACL) LocalAlloc(LMEM_FIXED, cbAcl);
  220. if(pAcl)
  221. {
  222. InitializeAcl(pAcl, cbAcl, ACL_REVISION);
  223. AddAccessAllowedAce(pAcl, ACL_REVISION, EVENT_QUERY_STATE|EVENT_MODIFY_STATE|SYNCHRONIZE|READ_CONTROL, pSidEveryone);
  224. }
  225. }
  226. // Create security descriptor and attach the DACL to it
  227. SECURITY_DESCRIPTOR sd;
  228. InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
  229. SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE);
  230. SECURITY_ATTRIBUTES sa;
  231. sa.nLength = sizeof(sa);
  232. sa.bInheritHandle = FALSE;
  233. sa.lpSecurityDescriptor = &sd;
  234. HANDLE EventHandle;
  235. RPC_STATUS rpcstatus;
  236. EventHandle = CreateEventT( &sa, TRUE, FALSE, SCM_CREATED_EVENT );
  237. if ( !EventHandle && GetLastError() == ERROR_ACCESS_DENIED )
  238. EventHandle = OpenEvent(EVENT_MODIFY_STATE | SYNCHRONIZE, FALSE, SCM_CREATED_EVENT);
  239. if ( EventHandle )
  240. SetEvent( EventHandle );
  241. else
  242. ASSERT(0 && "Unable to get ScmCreatedEvent");
  243. if (pSidEveryone)
  244. FreeSid(pSidEveryone);
  245. if (pAcl)
  246. LocalFree(pAcl);
  247. // Tell RPC to enable cleanup of idle connections. This function only needs to be
  248. // called one time.
  249. rpcstatus = RpcMgmtEnableIdleCleanup();
  250. ASSERT(rpcstatus == RPC_S_OK && "unexpected failure from RpcMgmtEnableIdleCleanup");
  251. // don't fail in free builds, this is an non-essential optimization
  252. return;
  253. }