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.

584 lines
19 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. psz = static_cast<WCHAR*>(LocalAlloc(LMEM_FIXED, string.Length + (sizeof('\0') * sizeof(WCHAR))));
  296. if (psz != NULL)
  297. {
  298. SIZE_T dwNumberOfBytesRead;
  299. if (ReadProcessMemory(hProcess,
  300. string.Buffer,
  301. psz,
  302. string.Length,
  303. &dwNumberOfBytesRead) != FALSE)
  304. {
  305. psz[string.Length / sizeof(WCHAR)] = L'\0';
  306. status = STATUS_SUCCESS;
  307. }
  308. else
  309. {
  310. ReleaseMemory(psz);
  311. status = CStatusCode::StatusCodeOfLastError();
  312. }
  313. }
  314. else
  315. {
  316. status = STATUS_NO_MEMORY;
  317. }
  318. *ppsz = psz;
  319. return(status);
  320. }
  321. // --------------------------------------------------------------------------
  322. // CRestoreApplication::GetToken
  323. //
  324. // Arguments: hProcess = Handle to process to get token of.
  325. //
  326. // Returns: NTSTATUS
  327. //
  328. // Purpose: Stores internally the token of the give process.
  329. //
  330. // History: 2000-10-26 vtan created
  331. // --------------------------------------------------------------------------
  332. NTSTATUS CRestoreApplication::GetToken (HANDLE hProcess)
  333. {
  334. NTSTATUS status;
  335. if ((OpenProcessToken(hProcess,
  336. TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_QUERY,
  337. &_hToken) != FALSE))
  338. {
  339. status = STATUS_SUCCESS;
  340. }
  341. else
  342. {
  343. status = CStatusCode::StatusCodeOfLastError();
  344. }
  345. return(status);
  346. }
  347. // --------------------------------------------------------------------------
  348. // CRestoreApplication::GetSessionID
  349. //
  350. // Arguments: hProcess = Handle to the process.
  351. //
  352. // Returns: NTSTATUS
  353. //
  354. // Purpose: Stores the session ID associated with the process.
  355. //
  356. // History: 2000-10-26 vtan created
  357. // --------------------------------------------------------------------------
  358. NTSTATUS CRestoreApplication::GetSessionID (HANDLE hProcess)
  359. {
  360. NTSTATUS status;
  361. ULONG ulReturnLength;
  362. PROCESS_SESSION_INFORMATION processSessionInformation;
  363. status = NtQueryInformationProcess(hProcess,
  364. ProcessSessionInformation,
  365. &processSessionInformation,
  366. sizeof(processSessionInformation),
  367. &ulReturnLength);
  368. if (NT_SUCCESS(status))
  369. {
  370. _dwSessionID = processSessionInformation.SessionId;
  371. }
  372. return(status);
  373. }
  374. // --------------------------------------------------------------------------
  375. // CRestoreApplication::GetCommandLine
  376. //
  377. // Arguments: hProcess = Handle to the process.
  378. // processParameters = Process parameters returned.
  379. //
  380. // Returns: NTSTATUS
  381. //
  382. // Purpose: Stores the command line (that started the process) from the
  383. // given process.
  384. //
  385. // History: 2000-10-26 vtan created
  386. // --------------------------------------------------------------------------
  387. NTSTATUS CRestoreApplication::GetCommandLine (HANDLE hProcess, const RTL_USER_PROCESS_PARAMETERS& processParameters)
  388. {
  389. return(GetUnicodeString(hProcess, processParameters.CommandLine, &_pszCommandLine));
  390. }
  391. // --------------------------------------------------------------------------
  392. // CRestoreApplication::GetEnvironment
  393. //
  394. // Arguments: hProcess = Handle to the process.
  395. // processParameters = Process parameters returned.
  396. //
  397. // Returns: NTSTATUS
  398. //
  399. // Purpose: Stores the environment block for the given process. Currently
  400. // this is NOT implemented.
  401. //
  402. // History: 2000-10-26 vtan created
  403. // --------------------------------------------------------------------------
  404. NTSTATUS CRestoreApplication::GetEnvironment (HANDLE hProcess, const RTL_USER_PROCESS_PARAMETERS& processParameters)
  405. {
  406. UNREFERENCED_PARAMETER(hProcess);
  407. UNREFERENCED_PARAMETER(processParameters);
  408. return(STATUS_SUCCESS);
  409. }
  410. // --------------------------------------------------------------------------
  411. // CRestoreApplication::GetCurrentDirectory
  412. //
  413. // Arguments: hProcess = Handle to the process.
  414. // processParameters = Process parameters returned.
  415. //
  416. // Returns: NTSTATUS
  417. //
  418. // Purpose: Stores the current directory of the given process.
  419. //
  420. // History: 2000-10-26 vtan created
  421. // --------------------------------------------------------------------------
  422. NTSTATUS CRestoreApplication::GetCurrentDirectory (HANDLE hProcess, const RTL_USER_PROCESS_PARAMETERS& processParameters)
  423. {
  424. return(GetUnicodeString(hProcess, processParameters.CurrentDirectory.DosPath, &_pszCurrentDirectory));
  425. }
  426. // --------------------------------------------------------------------------
  427. // CRestoreApplication::GetDesktop
  428. //
  429. // Arguments: hProcess = Handle to the process.
  430. // processParameters = Process parameters returned.
  431. //
  432. // Returns: NTSTATUS
  433. //
  434. // Purpose: Stores the window station and desktop that the given process
  435. // was started on.
  436. //
  437. // History: 2000-10-26 vtan created
  438. // --------------------------------------------------------------------------
  439. NTSTATUS CRestoreApplication::GetDesktop (HANDLE hProcess, const RTL_USER_PROCESS_PARAMETERS& processParameters)
  440. {
  441. NTSTATUS status;
  442. status = GetUnicodeString(hProcess, processParameters.DesktopInfo, &_pszDesktop);
  443. if (!NT_SUCCESS(status))
  444. {
  445. _pszDesktop = static_cast<WCHAR*>(LocalAlloc(LMEM_FIXED, sizeof(s_szDefaultDesktop)));
  446. if (_pszDesktop != NULL)
  447. {
  448. CopyMemory(_pszDesktop, s_szDefaultDesktop, sizeof(s_szDefaultDesktop));
  449. status = STATUS_SUCCESS;
  450. }
  451. else
  452. {
  453. status = STATUS_NO_MEMORY;
  454. }
  455. }
  456. return(status);
  457. }
  458. // --------------------------------------------------------------------------
  459. // CRestoreApplication::GetTitle
  460. //
  461. // Arguments: hProcess = Handle to the process.
  462. // processParameters = Process parameters returned.
  463. //
  464. // Returns: NTSTATUS
  465. //
  466. // Purpose: Stores the window title used to start the given process.
  467. //
  468. // History: 2000-10-26 vtan created
  469. // --------------------------------------------------------------------------
  470. NTSTATUS CRestoreApplication::GetTitle (HANDLE hProcess, const RTL_USER_PROCESS_PARAMETERS& processParameters)
  471. {
  472. return(GetUnicodeString(hProcess, processParameters.WindowTitle, &_pszTitle));
  473. }
  474. // --------------------------------------------------------------------------
  475. // CRestoreApplication::GetFlags
  476. //
  477. // Arguments: hProcess = Handle to the process.
  478. // processParameters = Process parameters returned.
  479. //
  480. // Returns: NTSTATUS
  481. //
  482. // Purpose: Stores the flags and wShowWindow used to start the given
  483. // process.
  484. //
  485. // History: 2000-10-26 vtan created
  486. // --------------------------------------------------------------------------
  487. NTSTATUS CRestoreApplication::GetFlags (HANDLE hProcess, const RTL_USER_PROCESS_PARAMETERS& processParameters)
  488. {
  489. UNREFERENCED_PARAMETER(hProcess);
  490. _dwFlags = processParameters.WindowFlags;
  491. _wShowWindow = static_cast<WORD>(processParameters.ShowWindowFlags);
  492. return(STATUS_SUCCESS);
  493. }
  494. // --------------------------------------------------------------------------
  495. // CRestoreApplication::GetStdHandles
  496. //
  497. // Arguments: hProcess = Handle to the process.
  498. // processParameters = Process parameters returned.
  499. //
  500. // Returns: NTSTATUS
  501. //
  502. // Purpose: Stores the standard handles that may have been used to start
  503. // the given process. Currently NOT implemented.
  504. //
  505. // History: 2000-10-26 vtan created
  506. // --------------------------------------------------------------------------
  507. NTSTATUS CRestoreApplication::GetStdHandles (HANDLE hProcess, const RTL_USER_PROCESS_PARAMETERS& processParameters)
  508. {
  509. UNREFERENCED_PARAMETER(hProcess);
  510. UNREFERENCED_PARAMETER(processParameters);
  511. return(STATUS_SUCCESS);
  512. }
  513. #endif /* _X86_ */