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.

420 lines
12 KiB

  1. // --------------------------------------------------------------------------
  2. // Module Name: UIHost.cpp
  3. //
  4. // Copyright (c) 1999-2000, Microsoft Corporation
  5. //
  6. // Class to handle the UI host for the logon process. This handles the IPC
  7. // as well as the creation and monitoring of process death. The process is
  8. // a restricted SYSTEM context process.
  9. //
  10. // History: 1999-09-14 vtan created
  11. // 2000-02-01 vtan moved from Neptune to Whistler
  12. // --------------------------------------------------------------------------
  13. #include "StandardHeader.h"
  14. #include "UIHost.h"
  15. #include "RegistryResources.h"
  16. #include "StatusCode.h"
  17. #include "SystemSettings.h"
  18. // --------------------------------------------------------------------------
  19. // CUIHost::CUIHost
  20. //
  21. // Arguments: <none>
  22. //
  23. // Returns: <none>
  24. //
  25. // Purpose: Constructor for CUIHost. Determine UI host process. If none
  26. // exists then indicate it.
  27. //
  28. // History: 1999-09-14 vtan created
  29. // --------------------------------------------------------------------------
  30. CUIHost::CUIHost (const TCHAR *pszCommandLine) :
  31. CExternalProcess(),
  32. _hwndArray(sizeof(HWND)),
  33. _pBufferAddress(NULL)
  34. {
  35. ExpandCommandLine(pszCommandLine);
  36. AdjustForDebugging();
  37. }
  38. // --------------------------------------------------------------------------
  39. // CUIHost::~CUIHost
  40. //
  41. // Arguments: <none>
  42. //
  43. // Returns: <none>
  44. //
  45. // Purpose: Destructor for CUIHost.
  46. //
  47. // History: 1999-09-14 vtan created
  48. // --------------------------------------------------------------------------
  49. CUIHost::~CUIHost (void)
  50. {
  51. if (_pBufferAddress != NULL)
  52. {
  53. (BOOL)VirtualFreeEx(_hProcess, _pBufferAddress, 0, MEM_DECOMMIT);
  54. _pBufferAddress = NULL;
  55. }
  56. }
  57. // --------------------------------------------------------------------------
  58. // CUIHost::WaitRequired
  59. //
  60. // Arguments: <none>
  61. //
  62. // Returns: bool
  63. //
  64. // Purpose: Returns whether a wait is required for the UI host. This is
  65. // important when communication with the UI host is required or
  66. // if the UI host is being debugged.
  67. //
  68. // History: 2000-10-05 vtan created
  69. // --------------------------------------------------------------------------
  70. bool CUIHost::WaitRequired (void) const
  71. {
  72. #ifdef DBG
  73. return(IsBeingDebugged());
  74. #else /* DBG */
  75. return(false);
  76. #endif /* DBG */
  77. }
  78. // --------------------------------------------------------------------------
  79. // CUIHost::GetData
  80. //
  81. // Arguments: pUIHostProcessAddress = Address in the UI host.
  82. // pLogonProcessAddress = Address in the logon process.
  83. // iDataSize = Size of the data.
  84. //
  85. // Returns: NTSTATUS
  86. //
  87. // Purpose: Extracts the data from the UI host. This could be another
  88. // process that we started or it could be in process if we
  89. // failed to start the UI host. This function deals with it
  90. // either way.
  91. //
  92. // History: 1999-08-24 vtan created
  93. // 1999-09-14 vtan factored
  94. // --------------------------------------------------------------------------
  95. NTSTATUS CUIHost::GetData (const void *pUIHostProcessAddress, void *pLogonProcessAddress, int iDataSize) const
  96. {
  97. NTSTATUS status;
  98. status = STATUS_SUCCESS;
  99. if (_hProcess == NULL)
  100. {
  101. CopyMemory(pLogonProcessAddress, pUIHostProcessAddress, iDataSize);
  102. }
  103. else
  104. {
  105. if (ReadProcessMemory(_hProcess, pUIHostProcessAddress, pLogonProcessAddress, iDataSize, NULL) == FALSE)
  106. {
  107. status = CStatusCode::StatusCodeOfLastError();
  108. }
  109. }
  110. return(status);
  111. }
  112. // --------------------------------------------------------------------------
  113. // CUIHost::PutData
  114. //
  115. // Arguments: pUIHostProcessAddress = Address in the UI host.
  116. // pLogonProcessAddress = Address in the logon process.
  117. // iDataSize = Size of the data.
  118. //
  119. // Returns: NTSTATUS
  120. //
  121. // Purpose: Puts data into the UI host. This could be another process that
  122. // we started or it could be in process if we failed to start the
  123. // UI host. This function deals with it either way.
  124. //
  125. // History: 1999-08-24 vtan created
  126. // 1999-09-14 vtan factored
  127. // --------------------------------------------------------------------------
  128. NTSTATUS CUIHost::PutData (void *pUIHostProcessAddress, const void *pLogonProcessAddress, int iDataSize) const
  129. {
  130. NTSTATUS status;
  131. status = STATUS_SUCCESS;
  132. if (_hProcess == NULL)
  133. {
  134. CopyMemory(pUIHostProcessAddress, pLogonProcessAddress, iDataSize);
  135. }
  136. else
  137. {
  138. if (WriteProcessMemory(_hProcess, pUIHostProcessAddress, const_cast<void*>(pLogonProcessAddress), iDataSize, NULL) == FALSE)
  139. {
  140. status = CStatusCode::StatusCodeOfLastError();
  141. }
  142. }
  143. return(status);
  144. }
  145. // --------------------------------------------------------------------------
  146. // CUIHost::Show
  147. //
  148. // Arguments: <none>
  149. //
  150. // Returns: NTSTATUS
  151. //
  152. // Purpose: Iterate the top level windows on this desktop and for any that
  153. // correspond to the UI host - show them!
  154. //
  155. // History: 2000-03-08 vtan created
  156. // --------------------------------------------------------------------------
  157. NTSTATUS CUIHost::Show (void)
  158. {
  159. int i;
  160. i = _hwndArray.GetCount();
  161. if (i > 0)
  162. {
  163. for (--i; i >= 0; --i)
  164. {
  165. HWND hwnd;
  166. if (NT_SUCCESS(_hwndArray.Get(&hwnd, i)) && (hwnd != NULL))
  167. {
  168. (BOOL)ShowWindow(hwnd, SW_SHOW);
  169. }
  170. TSTATUS(_hwndArray.Remove(i));
  171. }
  172. }
  173. return(STATUS_SUCCESS);
  174. }
  175. // --------------------------------------------------------------------------
  176. // CUIHost::Hide
  177. //
  178. // Arguments: <none>
  179. //
  180. // Returns: NTSTATUS
  181. //
  182. // Purpose: Iterate the top level windows on this desktop and for any that
  183. // correspond to the UI host - hide them!
  184. //
  185. // History: 2000-03-08 vtan created
  186. // --------------------------------------------------------------------------
  187. NTSTATUS CUIHost::Hide (void)
  188. {
  189. NTSTATUS status;
  190. status = STATUS_SUCCESS;
  191. if (_hwndArray.GetCount() == 0)
  192. {
  193. if (EnumWindows(EnumWindowsProc, reinterpret_cast<LPARAM>(this)) == FALSE)
  194. {
  195. status = CStatusCode::StatusCodeOfLastError();
  196. }
  197. }
  198. return(status);
  199. }
  200. // --------------------------------------------------------------------------
  201. // CUIHost::IsHidden
  202. //
  203. // Arguments: <none>
  204. //
  205. // Returns: bool
  206. //
  207. // Purpose: Returns whether the UI host is currently hidden or not.
  208. //
  209. // History: 2000-07-05 vtan created
  210. // --------------------------------------------------------------------------
  211. bool CUIHost::IsHidden (void) const
  212. {
  213. return(_hwndArray.GetCount() != 0);
  214. }
  215. // --------------------------------------------------------------------------
  216. // CUIHost::GetDataAddress
  217. //
  218. // Arguments: <none>
  219. //
  220. // Returns: void*
  221. //
  222. // Purpose: Returns the address of the buffer valid in the UI host process
  223. // context.
  224. //
  225. // History: 2000-05-05 vtan created
  226. // --------------------------------------------------------------------------
  227. void* CUIHost::GetDataAddress (void) const
  228. {
  229. return(_pBufferAddress);
  230. }
  231. // --------------------------------------------------------------------------
  232. // CUIHost::PutData
  233. //
  234. // Arguments: pvData = Pointer to data.
  235. // dwDataSize = Size of data (in bytes).
  236. //
  237. // Returns: NTSTATUS
  238. //
  239. // Purpose: Writes the data to the UI host process at an allocated
  240. // address. If the address has not been allocated then it's
  241. // allocated and cached. It's released when this object goes
  242. // out of scope.
  243. //
  244. // History: 2000-05-05 vtan created
  245. // 2001-01-10 vtan changed to generic data placement
  246. // --------------------------------------------------------------------------
  247. NTSTATUS CUIHost::PutData (const void *pvData, DWORD dwDataSize)
  248. {
  249. NTSTATUS status;
  250. if (_pBufferAddress == NULL)
  251. {
  252. _pBufferAddress = VirtualAllocEx(_hProcess,
  253. 0,
  254. 2048,
  255. MEM_COMMIT,
  256. PAGE_READWRITE);
  257. }
  258. if (_pBufferAddress != NULL)
  259. {
  260. ASSERTMSG(dwDataSize < 2048, "Impending kernel32!WriteProcessMemory failure in CUIHost::PutData");
  261. if (WriteProcessMemory(_hProcess,
  262. _pBufferAddress,
  263. const_cast<void*>(pvData),
  264. dwDataSize,
  265. NULL) != FALSE)
  266. {
  267. status = STATUS_SUCCESS;
  268. }
  269. else
  270. {
  271. status = CStatusCode::StatusCodeOfLastError();
  272. }
  273. }
  274. else
  275. {
  276. status = STATUS_NO_MEMORY;
  277. }
  278. return(status);
  279. }
  280. // --------------------------------------------------------------------------
  281. // CUIHost::PutString
  282. //
  283. // Arguments: pszString = String to put into UI host process.
  284. //
  285. // Returns: NTSTATUS
  286. //
  287. // Purpose: Writes the string to the UI host process at an allocated
  288. // address. If the address has not been allocated then it's
  289. // allocated and cached. It's released when this object goes
  290. // out of scope.
  291. //
  292. // History: 2000-05-05 vtan created
  293. // --------------------------------------------------------------------------
  294. NTSTATUS CUIHost::PutString (const WCHAR *pszString)
  295. {
  296. ASSERTMSG(lstrlenW(pszString) < 256, "Too many characters in string passed to CUIHost::PutString");
  297. return(PutData(pszString, (lstrlenW(pszString) + sizeof('\0')) * sizeof(WCHAR)));
  298. }
  299. // --------------------------------------------------------------------------
  300. // CUIHost::NotifyNoProcess
  301. //
  302. // Arguments: <none>
  303. //
  304. // Returns: NTSTATUS
  305. //
  306. // Purpose: Clears the string address associated with the process that
  307. // has now died.
  308. //
  309. // History: 2001-01-09 vtan created
  310. // --------------------------------------------------------------------------
  311. void CUIHost::NotifyNoProcess (void)
  312. {
  313. _pBufferAddress = NULL;
  314. }
  315. // --------------------------------------------------------------------------
  316. // CUIHost::ExpandCommandLine
  317. //
  318. // Arguments: pszCommandLine = Command line of UI host
  319. //
  320. // Returns: <none>
  321. //
  322. // Purpose: Find out which UI host we should use for the logon UI. This
  323. // is specified in registry at the moment but should be a less
  324. // accessible place to prevent tampering. An error is returned
  325. // if no host is specified.
  326. //
  327. // History: 1999-08-24 vtan created
  328. // 1999-09-14 vtan factored
  329. // --------------------------------------------------------------------------
  330. void CUIHost::ExpandCommandLine (const TCHAR *pszCommandLine)
  331. {
  332. if (ExpandEnvironmentStrings(pszCommandLine, _szCommandLine, ARRAYSIZE(_szCommandLine)) == 0)
  333. {
  334. lstrcpy(_szCommandLine, pszCommandLine);
  335. }
  336. }
  337. // --------------------------------------------------------------------------
  338. // CUIHost::EnumWindowsProc
  339. //
  340. // Arguments: hwnd = HWND from user32
  341. // lParam = this object.
  342. //
  343. // Returns: BOOL
  344. //
  345. // Purpose: Determines if the given HWND in the iteration belongs to the
  346. // UI host process.
  347. //
  348. // History: 2000-03-08 vtan created
  349. // --------------------------------------------------------------------------
  350. BOOL CALLBACK CUIHost::EnumWindowsProc (HWND hwnd, LPARAM lParam)
  351. {
  352. DWORD dwThreadID, dwProcessID;
  353. CUIHost *pUIHost;
  354. pUIHost = reinterpret_cast<CUIHost*>(lParam);
  355. dwThreadID = GetWindowThreadProcessId(hwnd, &dwProcessID);
  356. if ((dwProcessID == pUIHost->_dwProcessID) && IsWindowVisible(hwnd))
  357. {
  358. (NTSTATUS)pUIHost->_hwndArray.Add(&hwnd);
  359. (BOOL)ShowWindow(hwnd, SW_HIDE);
  360. }
  361. return(TRUE);
  362. }