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.

585 lines
20 KiB

  1. // --------------------------------------------------------------------------
  2. // Module Name: RestoreApplication.cpp
  3. //
  4. // Copyright (c) 2000, Microsoft Corporation
  5. //
  6. // Class to implement holding information required to restore an application
  7. // and to actually restore it.
  8. //
  9. // History: 2000-10-26 vtan created
  10. // 2000-11-04 vtan split into separate file
  11. // --------------------------------------------------------------------------
  12. #ifdef _X86_
  13. #include "StandardHeader.h"
  14. #include "RestoreApplication.h"
  15. #include "StatusCode.h"
  16. // --------------------------------------------------------------------------
  17. // CRestoreApplication::CRestoreApplication
  18. //
  19. // Purpose: Static const string to the user desktop..
  20. //
  21. // History: 2000-11-04 vtan created
  22. // --------------------------------------------------------------------------
  23. const WCHAR CRestoreApplication::s_szDefaultDesktop[] = L"WinSta0\\Default";
  24. // --------------------------------------------------------------------------
  25. // CRestoreApplication::CRestoreApplication
  26. //
  27. // Arguments: <none>
  28. //
  29. // Returns: <none>
  30. //
  31. // Purpose: Constructor for CRestoreApplication.
  32. //
  33. // History: 2000-10-26 vtan created
  34. // --------------------------------------------------------------------------
  35. CRestoreApplication::CRestoreApplication (void) :
  36. _hToken(NULL),
  37. _dwSessionID(static_cast<DWORD>(-1)),
  38. _pszCommandLine(NULL),
  39. _pEnvironment(NULL),
  40. _pszCurrentDirectory(NULL),
  41. _pszDesktop(NULL),
  42. _pszTitle(NULL),
  43. _dwFlags(0),
  44. _wShowWindow(0),
  45. _hStdInput(NULL),
  46. _hStdOutput(NULL),
  47. _hStdError(NULL)
  48. {
  49. }
  50. // --------------------------------------------------------------------------
  51. // CRestoreApplication::~CRestoreApplication
  52. //
  53. // Arguments: <none>
  54. //
  55. // Returns: <none>
  56. //
  57. // Purpose: Destructor for CRestoreApplication. Release any resources.
  58. //
  59. // History: 2000-10-26 vtan created
  60. // --------------------------------------------------------------------------
  61. CRestoreApplication::~CRestoreApplication (void)
  62. {
  63. ReleaseMemory(_pszTitle);
  64. ReleaseMemory(_pszDesktop);
  65. ReleaseMemory(_pszCurrentDirectory);
  66. ReleaseMemory(_pEnvironment);
  67. ReleaseMemory(_pszCommandLine);
  68. ReleaseHandle(_hToken);
  69. }
  70. // --------------------------------------------------------------------------
  71. // CRestoreApplication::GetInformation
  72. //
  73. // Arguments: hProcessIn = Handle to the process to get information.
  74. //
  75. // Returns: NTSTATUS
  76. //
  77. // Purpose: Gets information about the currently running process to
  78. // allow it to be re-run in the case when the user re-connects.
  79. // This effectively restores the process but it's not identical
  80. // to how it was originally run.
  81. //
  82. // History: 2000-10-26 vtan created
  83. // --------------------------------------------------------------------------
  84. NTSTATUS CRestoreApplication::GetInformation (HANDLE hProcessIn)
  85. {
  86. NTSTATUS status;
  87. HANDLE hProcess;
  88. if (DuplicateHandle(GetCurrentProcess(),
  89. hProcessIn,
  90. GetCurrentProcess(),
  91. &hProcess,
  92. PROCESS_VM_READ | PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION,
  93. FALSE,
  94. 0) != FALSE)
  95. {
  96. status = GetToken(hProcess);
  97. if (NT_SUCCESS(status))
  98. {
  99. status = GetSessionID(hProcess);
  100. if (NT_SUCCESS(status))
  101. {
  102. RTL_USER_PROCESS_PARAMETERS processParameters;
  103. status = GetProcessParameters(hProcess, &processParameters);
  104. if (NT_SUCCESS(status))
  105. {
  106. status = GetCommandLine(hProcess, processParameters);
  107. if (NT_SUCCESS(status))
  108. {
  109. TSTATUS(GetEnvironment(hProcess, processParameters));
  110. TSTATUS(GetCurrentDirectory(hProcess, processParameters));
  111. TSTATUS(GetDesktop(hProcess, processParameters));
  112. TSTATUS(GetTitle(hProcess, processParameters));
  113. TSTATUS(GetFlags(hProcess, processParameters));
  114. TSTATUS(GetStdHandles(hProcess, processParameters));
  115. }
  116. }
  117. }
  118. }
  119. TBOOL(CloseHandle(hProcess));
  120. }
  121. else
  122. {
  123. status = CStatusCode::StatusCodeOfLastError();
  124. }
  125. return(status);
  126. }
  127. // --------------------------------------------------------------------------
  128. // CRestoreApplication::IsEqualSessionID
  129. //
  130. // Arguments: dwSessionID = Session ID to check.
  131. //
  132. // Returns: bool
  133. //
  134. // Purpose: Returns whether the given session ID is the same as the
  135. // process that needs restoration. This assists in determining
  136. // whether restoration is required.
  137. //
  138. // History: 2000-10-26 vtan created
  139. // --------------------------------------------------------------------------
  140. bool CRestoreApplication::IsEqualSessionID (DWORD dwSessionID) const
  141. {
  142. return(_dwSessionID == dwSessionID);
  143. }
  144. // --------------------------------------------------------------------------
  145. // CRestoreApplication::GetCommandLine
  146. //
  147. // Arguments: <none>
  148. //
  149. // Returns: const WCHAR*
  150. //
  151. // Purpose: Returns the pointer to the internal storage for the command
  152. // line of the process.
  153. //
  154. // History: 2000-10-26 vtan created
  155. // --------------------------------------------------------------------------
  156. const WCHAR* CRestoreApplication::GetCommandLine (void) const
  157. {
  158. return(_pszCommandLine);
  159. }
  160. // --------------------------------------------------------------------------
  161. // CRestoreApplication::Restore
  162. //
  163. // Arguments: phProcess = Receives the handle to the restored process.
  164. //
  165. // Returns: NTSTATUS
  166. //
  167. // Purpose: Restores the process whose information was gathered with
  168. // GetInformation to as close as possibly to the original start
  169. // state. Relevant information was saved off to allow an
  170. // effective restore.
  171. //
  172. // The handle returned is optional. If requested a non-NULL
  173. // phProcess must be passed in and it is the caller's
  174. // responsibility to close that handle. If not required then
  175. // NULL is passed in and the handle is closed.
  176. //
  177. // History: 2000-10-26 vtan created
  178. // --------------------------------------------------------------------------
  179. NTSTATUS CRestoreApplication::Restore (HANDLE *phProcess) const
  180. {
  181. NTSTATUS status;
  182. STARTUPINFO startupInfo;
  183. PROCESS_INFORMATION processInformation;
  184. ZeroMemory(&startupInfo, sizeof(startupInfo));
  185. ZeroMemory(&processInformation, sizeof(processInformation));
  186. startupInfo.cb = sizeof(startupInfo);
  187. startupInfo.lpDesktop = _pszDesktop;
  188. startupInfo.lpTitle = _pszTitle;
  189. startupInfo.dwFlags = _dwFlags;
  190. startupInfo.wShowWindow = _wShowWindow;
  191. if (ImpersonateLoggedOnUser(_hToken) != FALSE)
  192. {
  193. if (CreateProcessAsUser(_hToken,
  194. NULL,
  195. _pszCommandLine,
  196. NULL,
  197. NULL,
  198. FALSE,
  199. 0,
  200. NULL,
  201. _pszCurrentDirectory,
  202. &startupInfo,
  203. &processInformation) != FALSE)
  204. {
  205. if (phProcess != NULL)
  206. {
  207. *phProcess = processInformation.hProcess;
  208. }
  209. else
  210. {
  211. TBOOL(CloseHandle(processInformation.hProcess));
  212. }
  213. TBOOL(CloseHandle(processInformation.hThread));
  214. status = STATUS_SUCCESS;
  215. }
  216. else
  217. {
  218. status = CStatusCode::StatusCodeOfLastError();
  219. }
  220. TBOOL(RevertToSelf());
  221. }
  222. else
  223. {
  224. status = CStatusCode::StatusCodeOfLastError();
  225. }
  226. return(status);
  227. }
  228. // --------------------------------------------------------------------------
  229. // CRestoreApplication::GetProcessParameters
  230. //
  231. // Arguments: hProcess = Handle to the process.
  232. // processParameters = Process parameters returned.
  233. //
  234. // Returns: NTSTATUS
  235. //
  236. // Purpose: Reads the RTL_USER_PROCESS_PARAMETERS information from the
  237. // given process. Addresses in this struct belong to the given
  238. // process address space.
  239. //
  240. // History: 2000-10-26 vtan created
  241. // --------------------------------------------------------------------------
  242. NTSTATUS CRestoreApplication::GetProcessParameters (HANDLE hProcess, RTL_USER_PROCESS_PARAMETERS* pProcessParameters)
  243. {
  244. NTSTATUS status;
  245. ULONG ulReturnLength;
  246. PROCESS_BASIC_INFORMATION processBasicInformation;
  247. status = NtQueryInformationProcess(hProcess,
  248. ProcessBasicInformation,
  249. &processBasicInformation,
  250. sizeof(processBasicInformation),
  251. &ulReturnLength);
  252. if (NT_SUCCESS(status))
  253. {
  254. SIZE_T dwNumberOfBytesRead;
  255. PEB peb;
  256. if ((ReadProcessMemory(hProcess,
  257. processBasicInformation.PebBaseAddress,
  258. &peb,
  259. sizeof(peb),
  260. &dwNumberOfBytesRead) != FALSE) &&
  261. (ReadProcessMemory(hProcess,
  262. peb.ProcessParameters,
  263. pProcessParameters,
  264. sizeof(*pProcessParameters),
  265. &dwNumberOfBytesRead) != FALSE))
  266. {
  267. status = STATUS_SUCCESS;
  268. }
  269. else
  270. {
  271. status = CStatusCode::StatusCodeOfLastError();
  272. }
  273. }
  274. return(status);
  275. }
  276. // --------------------------------------------------------------------------
  277. // CRestoreApplication::GetUnicodeString
  278. //
  279. // Arguments: hProcess = Handle to the process.
  280. // string = UNICODE_STRING to read from process.
  281. // psz = Received newly allocated memory for string.
  282. //
  283. // Returns: NTSTATUS
  284. //
  285. // Purpose: Reads the given UNICODE_STRING from the process and allocates
  286. // memory to hold this string and copies it. The string is
  287. // NULL terminated.
  288. //
  289. // History: 2000-10-26 vtan created
  290. // --------------------------------------------------------------------------
  291. NTSTATUS CRestoreApplication::GetUnicodeString (HANDLE hProcess, const UNICODE_STRING& string, WCHAR** ppsz)
  292. {
  293. NTSTATUS status;
  294. WCHAR *psz;
  295. // sizeof(WCHAR) is for the '\0' terminator
  296. psz = static_cast<WCHAR*>(LocalAlloc(LMEM_FIXED, string.Length + sizeof(WCHAR)));
  297. if (psz != NULL)
  298. {
  299. SIZE_T dwNumberOfBytesRead;
  300. if (ReadProcessMemory(hProcess,
  301. string.Buffer,
  302. psz,
  303. string.Length,
  304. &dwNumberOfBytesRead) != FALSE)
  305. {
  306. psz[string.Length / sizeof(WCHAR)] = L'\0';
  307. status = STATUS_SUCCESS;
  308. }
  309. else
  310. {
  311. ReleaseMemory(psz);
  312. status = CStatusCode::StatusCodeOfLastError();
  313. }
  314. }
  315. else
  316. {
  317. status = STATUS_NO_MEMORY;
  318. }
  319. *ppsz = psz;
  320. return(status);
  321. }
  322. // --------------------------------------------------------------------------
  323. // CRestoreApplication::GetToken
  324. //
  325. // Arguments: hProcess = Handle to process to get token of.
  326. //
  327. // Returns: NTSTATUS
  328. //
  329. // Purpose: Stores internally the token of the give process.
  330. //
  331. // History: 2000-10-26 vtan created
  332. // --------------------------------------------------------------------------
  333. NTSTATUS CRestoreApplication::GetToken (HANDLE hProcess)
  334. {
  335. NTSTATUS status;
  336. if ((OpenProcessToken(hProcess,
  337. TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_QUERY,
  338. &_hToken) != FALSE))
  339. {
  340. status = STATUS_SUCCESS;
  341. }
  342. else
  343. {
  344. status = CStatusCode::StatusCodeOfLastError();
  345. }
  346. return(status);
  347. }
  348. // --------------------------------------------------------------------------
  349. // CRestoreApplication::GetSessionID
  350. //
  351. // Arguments: hProcess = Handle to the process.
  352. //
  353. // Returns: NTSTATUS
  354. //
  355. // Purpose: Stores the session ID associated with the process.
  356. //
  357. // History: 2000-10-26 vtan created
  358. // --------------------------------------------------------------------------
  359. NTSTATUS CRestoreApplication::GetSessionID (HANDLE hProcess)
  360. {
  361. NTSTATUS status;
  362. ULONG ulReturnLength;
  363. PROCESS_SESSION_INFORMATION processSessionInformation;
  364. status = NtQueryInformationProcess(hProcess,
  365. ProcessSessionInformation,
  366. &processSessionInformation,
  367. sizeof(processSessionInformation),
  368. &ulReturnLength);
  369. if (NT_SUCCESS(status))
  370. {
  371. _dwSessionID = processSessionInformation.SessionId;
  372. }
  373. return(status);
  374. }
  375. // --------------------------------------------------------------------------
  376. // CRestoreApplication::GetCommandLine
  377. //
  378. // Arguments: hProcess = Handle to the process.
  379. // processParameters = Process parameters returned.
  380. //
  381. // Returns: NTSTATUS
  382. //
  383. // Purpose: Stores the command line (that started the process) from the
  384. // given process.
  385. //
  386. // History: 2000-10-26 vtan created
  387. // --------------------------------------------------------------------------
  388. NTSTATUS CRestoreApplication::GetCommandLine (HANDLE hProcess, const RTL_USER_PROCESS_PARAMETERS& processParameters)
  389. {
  390. return(GetUnicodeString(hProcess, processParameters.CommandLine, &_pszCommandLine));
  391. }
  392. // --------------------------------------------------------------------------
  393. // CRestoreApplication::GetEnvironment
  394. //
  395. // Arguments: hProcess = Handle to the process.
  396. // processParameters = Process parameters returned.
  397. //
  398. // Returns: NTSTATUS
  399. //
  400. // Purpose: Stores the environment block for the given process. Currently
  401. // this is NOT implemented.
  402. //
  403. // History: 2000-10-26 vtan created
  404. // --------------------------------------------------------------------------
  405. NTSTATUS CRestoreApplication::GetEnvironment (HANDLE hProcess, const RTL_USER_PROCESS_PARAMETERS& processParameters)
  406. {
  407. UNREFERENCED_PARAMETER(hProcess);
  408. UNREFERENCED_PARAMETER(processParameters);
  409. return(STATUS_SUCCESS);
  410. }
  411. // --------------------------------------------------------------------------
  412. // CRestoreApplication::GetCurrentDirectory
  413. //
  414. // Arguments: hProcess = Handle to the process.
  415. // processParameters = Process parameters returned.
  416. //
  417. // Returns: NTSTATUS
  418. //
  419. // Purpose: Stores the current directory of the given process.
  420. //
  421. // History: 2000-10-26 vtan created
  422. // --------------------------------------------------------------------------
  423. NTSTATUS CRestoreApplication::GetCurrentDirectory (HANDLE hProcess, const RTL_USER_PROCESS_PARAMETERS& processParameters)
  424. {
  425. return(GetUnicodeString(hProcess, processParameters.CurrentDirectory.DosPath, &_pszCurrentDirectory));
  426. }
  427. // --------------------------------------------------------------------------
  428. // CRestoreApplication::GetDesktop
  429. //
  430. // Arguments: hProcess = Handle to the process.
  431. // processParameters = Process parameters returned.
  432. //
  433. // Returns: NTSTATUS
  434. //
  435. // Purpose: Stores the window station and desktop that the given process
  436. // was started on.
  437. //
  438. // History: 2000-10-26 vtan created
  439. // --------------------------------------------------------------------------
  440. NTSTATUS CRestoreApplication::GetDesktop (HANDLE hProcess, const RTL_USER_PROCESS_PARAMETERS& processParameters)
  441. {
  442. NTSTATUS status;
  443. status = GetUnicodeString(hProcess, processParameters.DesktopInfo, &_pszDesktop);
  444. if (!NT_SUCCESS(status))
  445. {
  446. _pszDesktop = static_cast<WCHAR*>(LocalAlloc(LMEM_FIXED, sizeof(s_szDefaultDesktop)));
  447. if (_pszDesktop != NULL)
  448. {
  449. CopyMemory(_pszDesktop, s_szDefaultDesktop, sizeof(s_szDefaultDesktop));
  450. status = STATUS_SUCCESS;
  451. }
  452. else
  453. {
  454. status = STATUS_NO_MEMORY;
  455. }
  456. }
  457. return(status);
  458. }
  459. // --------------------------------------------------------------------------
  460. // CRestoreApplication::GetTitle
  461. //
  462. // Arguments: hProcess = Handle to the process.
  463. // processParameters = Process parameters returned.
  464. //
  465. // Returns: NTSTATUS
  466. //
  467. // Purpose: Stores the window title used to start the given process.
  468. //
  469. // History: 2000-10-26 vtan created
  470. // --------------------------------------------------------------------------
  471. NTSTATUS CRestoreApplication::GetTitle (HANDLE hProcess, const RTL_USER_PROCESS_PARAMETERS& processParameters)
  472. {
  473. return(GetUnicodeString(hProcess, processParameters.WindowTitle, &_pszTitle));
  474. }
  475. // --------------------------------------------------------------------------
  476. // CRestoreApplication::GetFlags
  477. //
  478. // Arguments: hProcess = Handle to the process.
  479. // processParameters = Process parameters returned.
  480. //
  481. // Returns: NTSTATUS
  482. //
  483. // Purpose: Stores the flags and wShowWindow used to start the given
  484. // process.
  485. //
  486. // History: 2000-10-26 vtan created
  487. // --------------------------------------------------------------------------
  488. NTSTATUS CRestoreApplication::GetFlags (HANDLE hProcess, const RTL_USER_PROCESS_PARAMETERS& processParameters)
  489. {
  490. UNREFERENCED_PARAMETER(hProcess);
  491. _dwFlags = processParameters.WindowFlags;
  492. _wShowWindow = static_cast<WORD>(processParameters.ShowWindowFlags);
  493. return(STATUS_SUCCESS);
  494. }
  495. // --------------------------------------------------------------------------
  496. // CRestoreApplication::GetStdHandles
  497. //
  498. // Arguments: hProcess = Handle to the process.
  499. // processParameters = Process parameters returned.
  500. //
  501. // Returns: NTSTATUS
  502. //
  503. // Purpose: Stores the standard handles that may have been used to start
  504. // the given process. Currently NOT implemented.
  505. //
  506. // History: 2000-10-26 vtan created
  507. // --------------------------------------------------------------------------
  508. NTSTATUS CRestoreApplication::GetStdHandles (HANDLE hProcess, const RTL_USER_PROCESS_PARAMETERS& processParameters)
  509. {
  510. UNREFERENCED_PARAMETER(hProcess);
  511. UNREFERENCED_PARAMETER(processParameters);
  512. return(STATUS_SUCCESS);
  513. }
  514. #endif /* _X86_ */