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.

324 lines
10 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 2000.
  5. //
  6. // File: process.cxx
  7. //
  8. // Contents: CProcess class
  9. // CServiceProcess class
  10. //
  11. // History: 07-Jun-94 DwightKr Created
  12. //
  13. //--------------------------------------------------------------------------
  14. #include <pch.cxx>
  15. #pragma hdrstop
  16. #include <proc32.hxx>
  17. #include <cievtmsg.h>
  18. #include <fwevent.hxx>
  19. //+-------------------------------------------------------------------------
  20. //
  21. // Member: CProcess::CProcess
  22. //
  23. // Purpose: Creates a process on the local machine.
  24. //
  25. // Arguments: [wcsImageName] -- name of EXE to run
  26. // [wcsCommandLine] -- command line passed to EXE
  27. // [fCreateSuspended] -- should the EXE be created suspended?
  28. // [SAProcess] -- Security context to run under
  29. // [fServiceChild] -- Flag set to TRUE if the process is a
  30. // child of a "service" process (ala CiFilter
  31. // service or W3Svc).
  32. // [pAdviseStatus] -- ICiCAdviseStatus interface, optional.
  33. //
  34. // History: 06-Jun-94 DwightKr Created
  35. //
  36. // Notes: If a system process (such as a service) spawning a process
  37. // it will always be created on the SYSTEM desktop, and never
  38. // the user's or DEFAULT desktop. System processes do not have
  39. // sufficient acccess to create windows on the user's desktop.
  40. //
  41. //--------------------------------------------------------------------------
  42. CProcess::CProcess( const WCHAR *wcsImageName,
  43. const WCHAR *wcsCommandLine,
  44. BOOL fCreateSuspended,
  45. const SECURITY_ATTRIBUTES & SAProcess,
  46. BOOL fOFSDaemon,
  47. ICiCAdviseStatus * pAdviseStatus )
  48. {
  49. _pAdviseStatus = pAdviseStatus;
  50. WCHAR wcsEXEName[_MAX_PATH + 1];
  51. if ( ExpandEnvironmentStrings( wcsImageName, wcsEXEName, _MAX_PATH ) == 0 )
  52. {
  53. THROW( CException() );
  54. }
  55. STARTUPINFO siDefault;
  56. RtlZeroMemory( &siDefault, sizeof(siDefault) );
  57. DWORD dwCreateFlags = 0;
  58. siDefault.cb = sizeof(STARTUPINFO); // Size of this struct
  59. if ( fOFSDaemon )
  60. {
  61. siDefault.lpReserved = NULL; // Not used (for now)
  62. siDefault.lpDesktop = L"Default"; // Use default desktop
  63. siDefault.lpTitle = (WCHAR *) wcsImageName; // Default title
  64. siDefault.dwX = 0; // Don't specify where to
  65. siDefault.dwY = 0; // place the window
  66. siDefault.dwXSize = 0; // " " " " "
  67. siDefault.dwYSize = 0; // " " " " "
  68. siDefault.dwFlags = STARTF_USESHOWWINDOW; // Allow for minimizing
  69. siDefault.wShowWindow = SW_MINIMIZE; // Normal display
  70. siDefault.cbReserved2 = 0; // Not used (for now)
  71. siDefault.lpReserved2 = NULL; // " " " " "
  72. dwCreateFlags = CREATE_NEW_CONSOLE;
  73. }
  74. else
  75. {
  76. siDefault.lpTitle = (WCHAR *) wcsImageName; // Default title
  77. dwCreateFlags = DETACHED_PROCESS;
  78. }
  79. if ( fCreateSuspended )
  80. dwCreateFlags |= CREATE_SUSPENDED;
  81. if ( !CreateProcess( fOFSDaemon ? (WCHAR *) wcsEXEName : 0, // EXE name
  82. (WCHAR *) wcsCommandLine, // Command line
  83. (SECURITY_ATTRIBUTES *) &SAProcess, // Proc sec attrib
  84. NULL, // Thread sec attrib
  85. fOFSDaemon, // Inherit handles
  86. dwCreateFlags, // Creation flags
  87. NULL, // Environment
  88. NULL, // Startup directory
  89. &siDefault, // Startup Info
  90. &_piProcessInfo ) ) // Process handles
  91. {
  92. DWORD dwLastError = GetLastError();
  93. if ( ERROR_FILE_NOT_FOUND == dwLastError && _pAdviseStatus )
  94. {
  95. CFwEventItem item( EVENTLOG_AUDIT_FAILURE,
  96. MSG_CI_FILE_NOT_FOUND,
  97. 1 );
  98. item.AddArg( wcsEXEName );
  99. item.ReportEvent(*_pAdviseStatus);
  100. }
  101. THROW( CException( HRESULT_FROM_WIN32( dwLastError) ) );
  102. }
  103. //
  104. // Only AddRef() once we get to a point where the constructor can
  105. // no longer fail (and the destructor is guaranteed to be called)
  106. //
  107. if (_pAdviseStatus)
  108. _pAdviseStatus->AddRef();
  109. } //CProcess
  110. //+-------------------------------------------------------------------------
  111. //
  112. // Member: CProcess::~CProcess
  113. //
  114. // Purpose: destructor
  115. //
  116. // History: 06-Jun-94 DwightKr Created
  117. //
  118. //--------------------------------------------------------------------------
  119. CProcess::~CProcess()
  120. {
  121. if ( 0 != _pAdviseStatus )
  122. _pAdviseStatus->Release();
  123. Terminate();
  124. WaitForDeath();
  125. }
  126. //+-------------------------------------------------------------------------
  127. //
  128. // Member: CProcess::Resume, public
  129. //
  130. // Purpose: Continue a suspended thread
  131. //
  132. // History: 06-Jun-94 DwightKr Created
  133. //
  134. //--------------------------------------------------------------------------
  135. void CProcess::Resume()
  136. {
  137. ResumeThread( _piProcessInfo.hThread );
  138. }
  139. //+-------------------------------------------------------------------------
  140. //
  141. // Member: CProcess::WaitForDeath
  142. //
  143. // Purpose: Blocks until the process has been terminated.
  144. //
  145. // History: 06-Jun-94 DwightKr Created
  146. //
  147. //--------------------------------------------------------------------------
  148. void CProcess::WaitForDeath( DWORD dwTimeout )
  149. {
  150. DWORD res = WaitForSingleObject ( _piProcessInfo.hProcess, dwTimeout );
  151. #if 0
  152. if ( WAIT_FAILED == res )
  153. {
  154. Win4Assert( !"Are we leaking a handle" );
  155. }
  156. #endif // 0
  157. CloseHandle(_piProcessInfo.hThread);
  158. CloseHandle(_piProcessInfo.hProcess);
  159. // if ( WAIT_FAILED == res )
  160. // {
  161. // THROW( CException() );
  162. // }
  163. }
  164. //+-------------------------------------------------------------------------
  165. //
  166. // Member: CProcess::GetProcessToken, private
  167. //
  168. // Purpose: Returns the process token for the process
  169. //
  170. // History: 06-Jun-94 DwightKr Created
  171. //
  172. //--------------------------------------------------------------------------
  173. HANDLE CProcess::GetProcessToken()
  174. {
  175. HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION,
  176. FALSE,
  177. _piProcessInfo.dwProcessId );
  178. if ( NULL == hProcess )
  179. {
  180. THROW( CException() );
  181. }
  182. SWin32Handle process(hProcess); // Save in smart pointer
  183. HANDLE hProcessToken = 0;
  184. if ( !OpenProcessToken( hProcess, TOKEN_ADJUST_DEFAULT | TOKEN_QUERY, &hProcessToken ) )
  185. {
  186. THROW( CException() );
  187. }
  188. return hProcessToken;
  189. }
  190. //+-------------------------------------------------------------------------
  191. //
  192. // Member: CProcess::AddDacl, public
  193. //
  194. // Purpose: Adds the access specified onto the Dacl on the process.
  195. //
  196. // Arguments: [dwAccessMask] -- Any combination of the Win32 ACCESS_MASK bits
  197. //
  198. // History: 06-Jun-94 DwightKr Created
  199. //
  200. //--------------------------------------------------------------------------
  201. void CProcess::AddDacl( DWORD dwAccessMask )
  202. {
  203. HANDLE hProcessToken = GetProcessToken();
  204. SWin32Handle processToken( hProcessToken );
  205. //
  206. // Create a SID that gives everyone access. We want to allow anyone
  207. // to synchronize on the objects created in this process (if they
  208. // can get a handle to the object to synchronize on).
  209. //
  210. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_WORLD_SID_AUTHORITY;
  211. CSid WorldSid( NtAuthority, SECURITY_WORLD_RID );
  212. //
  213. // Read the current Dacl. This requires two steps. The current
  214. // Dacl size is not known, the 1st call determines its current size.
  215. //
  216. DWORD cbRequired;
  217. if ( !GetTokenInformation( hProcessToken,
  218. TokenDefaultDacl,
  219. 0,
  220. 0,
  221. &cbRequired ) )
  222. {
  223. if ( ERROR_INSUFFICIENT_BUFFER != GetLastError() )
  224. THROW( CException() );
  225. }
  226. else
  227. {
  228. ciDebugOut(( DEB_WARN,
  229. "No default dacl(1), invalid CI configuration\n" ));
  230. THROW( CException( STATUS_INVALID_PARAMETER ) );
  231. }
  232. //
  233. // Create a buffer of the size requested to store the Dacl on the next
  234. // call to GetTokenInformation(). Add additional space for the new
  235. // synchronize-all Ace to be appended later.
  236. //
  237. cbRequired += sizeof( ACCESS_ALLOWED_ACE ) + GetLengthSid( WorldSid );
  238. TOKEN_DEFAULT_DACL *pDacl = (TOKEN_DEFAULT_DACL *) new BYTE[cbRequired];
  239. SDacl SDacl(pDacl); // Save in smart pointer
  240. if ( !GetTokenInformation( hProcessToken,
  241. TokenDefaultDacl,
  242. pDacl,
  243. cbRequired,
  244. &cbRequired ) )
  245. {
  246. THROW( CException() );
  247. }
  248. //
  249. // pDacl->DefaultDacl will be 0 if cisvc is started in windbg
  250. // with pipes preconfigured. Don't do that -- we don't support it.
  251. //
  252. if ( 0 == pDacl->DefaultDacl )
  253. {
  254. ciDebugOut(( DEB_WARN,
  255. "No default dacl(2), invalid CI configuration\n" ));
  256. THROW( CException( STATUS_INVALID_PARAMETER ) );
  257. }
  258. pDacl->DefaultDacl->AclSize += (USHORT)(sizeof( ACCESS_ALLOWED_ACE ) + GetLengthSid( WorldSid ) - sizeof(ULONG));
  259. //
  260. // Append synchronize access onto the Dacl.
  261. //
  262. if ( !AddAccessAllowedAce( pDacl->DefaultDacl, // On to this acl,
  263. ACL_REVISION, // built for version X,
  264. dwAccessMask, // allow synchronize,
  265. WorldSid ) ) // for these objects.
  266. {
  267. THROW( CException() );
  268. }
  269. #if CIDBG == 1
  270. if ( !IsValidAcl( pDacl->DefaultDacl ) )
  271. {
  272. Win4Assert(!"Invalid Acl");
  273. }
  274. #endif
  275. //
  276. // Update the process's Dacl.
  277. //
  278. if ( !SetTokenInformation( hProcessToken,
  279. TokenDefaultDacl,
  280. &pDacl->DefaultDacl,
  281. pDacl->DefaultDacl->AclSize ) )
  282. {
  283. THROW( CException() );
  284. }
  285. }