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.

538 lines
19 KiB

  1. // --------------------------------------------------------------------------
  2. // Module Name: BadApplicationAPIRequest.cpp
  3. //
  4. // Copyright (c) 2000, Microsoft Corporation
  5. //
  6. // This file contains a class to implement bad application manager API
  7. // requests.
  8. //
  9. // History: 2000-08-25 vtan created
  10. // 2000-12-04 vtan moved to separate file
  11. // --------------------------------------------------------------------------
  12. #ifdef _X86_
  13. #include "StandardHeader.h"
  14. #include "BadApplicationAPIRequest.h"
  15. #include "StatusCode.h"
  16. #include "TokenInformation.h"
  17. // --------------------------------------------------------------------------
  18. // CBadApplicationAPIRequest::s_pBadApplicationManager
  19. //
  20. // Purpose: Single instance of the CBadApplicationManager object.
  21. //
  22. // History: 2000-08-26 vtan created
  23. // --------------------------------------------------------------------------
  24. CBadApplicationManager* CBadApplicationAPIRequest::s_pBadApplicationManager = NULL;
  25. // --------------------------------------------------------------------------
  26. // CBadApplicationAPIRequest::CBadApplicationAPIRequest
  27. //
  28. // Arguments: pAPIDispatcher = CAPIDispatcher that calls this object.
  29. //
  30. // Returns: <none>
  31. //
  32. // Purpose: Constructor for the CBadApplicationAPIRequest class. It just passes the
  33. // control to the super class.
  34. //
  35. // History: 2000-08-25 vtan created
  36. // --------------------------------------------------------------------------
  37. CBadApplicationAPIRequest::CBadApplicationAPIRequest (CAPIDispatcher* pAPIDispatcher) :
  38. CAPIRequest(pAPIDispatcher)
  39. {
  40. }
  41. // --------------------------------------------------------------------------
  42. // CBadApplicationAPIRequest::CBadApplicationAPIRequest
  43. //
  44. // Arguments: pAPIDispatcher = CAPIDispatcher that calls this object.
  45. // portMessage = CPortMessage to copy construct.
  46. //
  47. // Returns: <none>
  48. //
  49. // Purpose: Constructor for the CBadApplicationAPIRequest class. It just passes the
  50. // control to the super class.
  51. //
  52. // History: 2000-08-25 vtan created
  53. // --------------------------------------------------------------------------
  54. CBadApplicationAPIRequest::CBadApplicationAPIRequest (CAPIDispatcher* pAPIDispatcher, const CPortMessage& portMessage) :
  55. CAPIRequest(pAPIDispatcher, portMessage)
  56. {
  57. }
  58. // --------------------------------------------------------------------------
  59. // CBadApplicationAPIRequest::~CBadApplicationAPIRequest
  60. //
  61. // Arguments: <none>
  62. //
  63. // Returns: <none>
  64. //
  65. // Purpose: Destructor for the CBadApplicationAPIRequest class.
  66. //
  67. // History: 2000-08-25 vtan created
  68. // --------------------------------------------------------------------------
  69. CBadApplicationAPIRequest::~CBadApplicationAPIRequest (void)
  70. {
  71. }
  72. // --------------------------------------------------------------------------
  73. // CBadApplicationAPIRequest::Execute
  74. //
  75. // Arguments: pAPIDispatchSync - allows request execution access to various
  76. // service notifications and events
  77. //
  78. // Returns: NTSTATUS
  79. //
  80. // Purpose: Execute implementation for bad application API requests. This
  81. // function dispatches requests based on the API request number.
  82. //
  83. // History: 2000-08-25 vtan created
  84. // 2002-03-24 scotthan add DispatchSync arg
  85. // --------------------------------------------------------------------------
  86. NTSTATUS CBadApplicationAPIRequest::Execute (CAPIDispatchSync* pAPIDispatchSync)
  87. {
  88. NTSTATUS status;
  89. UNREFERENCED_PARAMETER(pAPIDispatchSync);
  90. switch (reinterpret_cast<API_BAM*>(&_data)->apiGeneric.ulAPINumber)
  91. {
  92. case API_BAM_QUERYRUNNING:
  93. status = Execute_QueryRunning();
  94. break;
  95. case API_BAM_REGISTERRUNNING:
  96. status = Execute_RegisterRunning();
  97. break;
  98. case API_BAM_QUERYUSERPERMISSION:
  99. status = Execute_QueryUserPermission();
  100. break;
  101. case API_BAM_TERMINATERUNNING:
  102. status = Execute_TerminateRunning();
  103. break;
  104. case API_BAM_REQUESTSWITCHUSER:
  105. status = Execute_RequestSwitchUser();
  106. break;
  107. default:
  108. DISPLAYMSG("Unknown API request in CBadApplicationAPIRequest::Execute");
  109. status = STATUS_NOT_IMPLEMENTED;
  110. break;
  111. }
  112. TSTATUS(status);
  113. return(status);
  114. }
  115. // --------------------------------------------------------------------------
  116. // CBadApplicationAPIRequest::StaticInitialize
  117. //
  118. // Arguments: <none>
  119. //
  120. // Returns: NTSTATUS
  121. //
  122. // Purpose: Static initializer for the class. It creates the static
  123. // instance of the CBadApplicationManager which must be a single
  124. // instance and knows about bad running applications.
  125. //
  126. // History: 2000-08-26 vtan created
  127. // --------------------------------------------------------------------------
  128. NTSTATUS CBadApplicationAPIRequest::StaticInitialize (HINSTANCE hInstance)
  129. {
  130. NTSTATUS status;
  131. if (s_pBadApplicationManager == NULL)
  132. {
  133. s_pBadApplicationManager = new CBadApplicationManager(hInstance);
  134. if (s_pBadApplicationManager != NULL)
  135. {
  136. status = STATUS_SUCCESS;
  137. }
  138. else
  139. {
  140. status = STATUS_NO_MEMORY;
  141. }
  142. }
  143. else
  144. {
  145. status = STATUS_SUCCESS;
  146. }
  147. return(status);
  148. }
  149. // --------------------------------------------------------------------------
  150. // CBadApplicationAPIRequest::StaticTerminate
  151. //
  152. // Arguments: <none>
  153. //
  154. // Returns: NTSTATUS
  155. //
  156. // Purpose: Static destructor for the class. This terminates the bad
  157. // application manager, releases the reference on the object and
  158. // clears out the static variable. When the thread dies it will
  159. // clean itself up.
  160. //
  161. // History: 2000-08-26 vtan created
  162. // --------------------------------------------------------------------------
  163. NTSTATUS CBadApplicationAPIRequest::StaticTerminate (void)
  164. {
  165. if (s_pBadApplicationManager != NULL)
  166. {
  167. s_pBadApplicationManager->Terminate();
  168. s_pBadApplicationManager->Release();
  169. s_pBadApplicationManager = NULL;
  170. }
  171. return(STATUS_SUCCESS);
  172. }
  173. // --------------------------------------------------------------------------
  174. // CBadApplicationAPIRequest::Execute_QueryRunning
  175. //
  176. // Arguments: <none>
  177. //
  178. // Returns: NTSTATUS
  179. //
  180. // Purpose: Handles API_BAM_QUERYRUNNING. Returns whether or not the
  181. // requested image path is currently a known (tracked)
  182. // executable that is running. Let the bad application manager
  183. // do the work. Exclude checking in the same session.
  184. //
  185. // History: 2000-08-26 vtan created
  186. // --------------------------------------------------------------------------
  187. NTSTATUS CBadApplicationAPIRequest::Execute_QueryRunning (void)
  188. {
  189. NTSTATUS status;
  190. HANDLE hProcessClient;
  191. SIZE_T dwNumberOfBytesRead;
  192. API_BAM_QUERYRUNNING_IN *pAPIIn;
  193. API_BAM_QUERYRUNNING_OUT *pAPIOut;
  194. WCHAR szImageName[MAX_PATH];
  195. hProcessClient = _pAPIDispatcher->GetClientProcess();
  196. pAPIIn = &reinterpret_cast<API_BAM*>(&_data)->apiSpecific.apiQueryRunning.in;
  197. pAPIOut = &reinterpret_cast<API_BAM*>(&_data)->apiSpecific.apiQueryRunning.out;
  198. if (ReadProcessMemory(hProcessClient,
  199. pAPIIn->pszImageName,
  200. szImageName,
  201. pAPIIn->cchImageName * sizeof(WCHAR),
  202. &dwNumberOfBytesRead) != FALSE)
  203. {
  204. CBadApplication badApplication(szImageName);
  205. pAPIOut->fResult = s_pBadApplicationManager->QueryRunning(badApplication, _pAPIDispatcher->GetClientSessionID());
  206. status = STATUS_SUCCESS;
  207. }
  208. else
  209. {
  210. status = CStatusCode::StatusCodeOfLastError();
  211. }
  212. SetDataLength(sizeof(API_BAM));
  213. return(status);
  214. }
  215. // --------------------------------------------------------------------------
  216. // CBadApplicationAPIRequest::Execute_RegisterRunning
  217. //
  218. // Arguments: <none>
  219. //
  220. // Returns: NTSTATUS
  221. //
  222. // Purpose: Handles API_BAM_REGISTERRUNNING. Adds the given image
  223. // executable to the list of currently running bad applications
  224. // so that further instances can be excluded.
  225. //
  226. // History: 2000-08-26 vtan created
  227. // --------------------------------------------------------------------------
  228. NTSTATUS CBadApplicationAPIRequest::Execute_RegisterRunning (void)
  229. {
  230. NTSTATUS status;
  231. SIZE_T dwNumberOfBytesRead;
  232. API_BAM_REGISTERRUNNING_IN *pAPIIn;
  233. API_BAM_REGISTERRUNNING_OUT *pAPIOut;
  234. WCHAR szImageName[MAX_PATH];
  235. pAPIIn = &reinterpret_cast<API_BAM*>(&_data)->apiSpecific.apiRegisterRunning.in;
  236. pAPIOut = &reinterpret_cast<API_BAM*>(&_data)->apiSpecific.apiRegisterRunning.out;
  237. if ((pAPIIn->bamType > BAM_TYPE_MINIMUM) && (pAPIIn->bamType < BAM_TYPE_MAXIMUM))
  238. {
  239. if (ReadProcessMemory(_pAPIDispatcher->GetClientProcess(),
  240. pAPIIn->pszImageName,
  241. szImageName,
  242. pAPIIn->cchImageName * sizeof(WCHAR),
  243. &dwNumberOfBytesRead) != FALSE)
  244. {
  245. HANDLE hProcess;
  246. CBadApplication badApplication(szImageName);
  247. hProcess = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION,
  248. FALSE,
  249. pAPIIn->dwProcessID);
  250. if (hProcess != NULL)
  251. {
  252. status = s_pBadApplicationManager->RegisterRunning(badApplication, hProcess, pAPIIn->bamType);
  253. TBOOL(CloseHandle(hProcess));
  254. }
  255. else
  256. {
  257. status = CStatusCode::StatusCodeOfLastError();
  258. }
  259. }
  260. else
  261. {
  262. status = CStatusCode::StatusCodeOfLastError();
  263. }
  264. }
  265. else
  266. {
  267. status = STATUS_INVALID_PARAMETER;
  268. }
  269. SetDataLength(sizeof(API_BAM));
  270. return(status);
  271. }
  272. // --------------------------------------------------------------------------
  273. // CBadApplicationAPIRequest::Execute_QueryUserPermission
  274. //
  275. // Arguments: <none>
  276. //
  277. // Returns: NTSTATUS
  278. //
  279. // Purpose: Handles API_BAM_QUERYUSERPERMISSION. Queries the client
  280. // permission to close down the bad application. Also returns
  281. // the current user of the bad application.
  282. //
  283. // History: 2000-08-31 vtan created
  284. // --------------------------------------------------------------------------
  285. NTSTATUS CBadApplicationAPIRequest::Execute_QueryUserPermission (void)
  286. {
  287. NTSTATUS status;
  288. SIZE_T dwNumberOfBytesRead;
  289. API_BAM_QUERYUSERPERMISSION_IN *pAPIIn;
  290. API_BAM_QUERYUSERPERMISSION_OUT *pAPIOut;
  291. WCHAR szImageName[MAX_PATH];
  292. pAPIIn = &reinterpret_cast<API_BAM*>(&_data)->apiSpecific.apiQueryUserPermission.in;
  293. pAPIOut = &reinterpret_cast<API_BAM*>(&_data)->apiSpecific.apiQueryUserPermission.out;
  294. if (ReadProcessMemory(_pAPIDispatcher->GetClientProcess(),
  295. pAPIIn->pszImageName,
  296. szImageName,
  297. pAPIIn->cchImageName * sizeof(WCHAR),
  298. &dwNumberOfBytesRead) != FALSE)
  299. {
  300. HANDLE hProcess;
  301. CBadApplication badApplication(szImageName);
  302. // Query information on the bad application
  303. // (get back the process handle).
  304. status = s_pBadApplicationManager->QueryInformation(badApplication, hProcess);
  305. if (NT_SUCCESS(status))
  306. {
  307. HANDLE hToken;
  308. // Get the client token and impersonate that user.
  309. status = OpenClientToken(hToken);
  310. if (NT_SUCCESS(status))
  311. {
  312. bool fCanShutdownApplication;
  313. HANDLE hTokenProcess;
  314. CTokenInformation tokenInformationClient(hToken);
  315. fCanShutdownApplication = tokenInformationClient.IsUserAnAdministrator();
  316. // Get the bad application process token to get
  317. // information on the user for the process.
  318. if (OpenProcessToken(hProcess,
  319. TOKEN_QUERY,
  320. &hTokenProcess) != FALSE)
  321. {
  322. const WCHAR *pszUserDisplayName;
  323. CTokenInformation tokenInformationProcess(hTokenProcess);
  324. pszUserDisplayName = tokenInformationProcess.GetUserDisplayName();
  325. if (pszUserDisplayName != NULL)
  326. {
  327. int iCharsToWrite;
  328. SIZE_T dwNumberOfBytesWritten;
  329. // Return the information back to the client.
  330. pAPIOut->fCanShutdownApplication = fCanShutdownApplication;
  331. iCharsToWrite = lstrlen(pszUserDisplayName) + sizeof('\0');
  332. if (iCharsToWrite > pAPIIn->cchUser)
  333. {
  334. iCharsToWrite = pAPIIn->cchUser;
  335. }
  336. if (WriteProcessMemory(_pAPIDispatcher->GetClientProcess(),
  337. pAPIIn->pszUser,
  338. const_cast<WCHAR*>(pszUserDisplayName),
  339. iCharsToWrite * sizeof(WCHAR),
  340. &dwNumberOfBytesWritten) != FALSE)
  341. {
  342. status = STATUS_SUCCESS;
  343. }
  344. else
  345. {
  346. status = CStatusCode::StatusCodeOfLastError();
  347. }
  348. }
  349. else
  350. {
  351. status = CStatusCode::StatusCodeOfLastError();
  352. }
  353. TBOOL(CloseHandle(hTokenProcess));
  354. }
  355. else
  356. {
  357. status = CStatusCode::StatusCodeOfLastError();
  358. }
  359. TBOOL(CloseHandle(hToken));
  360. }
  361. else
  362. {
  363. status = CStatusCode::StatusCodeOfLastError();
  364. }
  365. TBOOL(CloseHandle(hProcess));
  366. }
  367. }
  368. else
  369. {
  370. status = CStatusCode::StatusCodeOfLastError();
  371. }
  372. SetDataLength(sizeof(API_BAM));
  373. return(status);
  374. }
  375. // --------------------------------------------------------------------------
  376. // CBadApplicationAPIRequest::Execute_QueryUserPermission
  377. //
  378. // Arguments: <none>
  379. //
  380. // Returns: NTSTATUS
  381. //
  382. // Purpose: Handles API_BAM_TERMINATERUNNING. Terminates the given running
  383. // bad application so a different instance on a different
  384. // window station can start it.
  385. //
  386. // History: 2000-08-31 vtan created
  387. // --------------------------------------------------------------------------
  388. NTSTATUS CBadApplicationAPIRequest::Execute_TerminateRunning (void)
  389. {
  390. NTSTATUS status;
  391. SIZE_T dwNumberOfBytesRead;
  392. API_BAM_TERMINATERUNNING_IN *pAPIIn;
  393. API_BAM_TERMINATERUNNING_OUT *pAPIOut;
  394. WCHAR szImageName[MAX_PATH];
  395. pAPIIn = &reinterpret_cast<API_BAM*>(&_data)->apiSpecific.apiTerminateRunning.in;
  396. pAPIOut = &reinterpret_cast<API_BAM*>(&_data)->apiSpecific.apiTerminateRunning.out;
  397. if (ReadProcessMemory(_pAPIDispatcher->GetClientProcess(),
  398. pAPIIn->pszImageName,
  399. szImageName,
  400. pAPIIn->cchImageName * sizeof(WCHAR),
  401. &dwNumberOfBytesRead) != FALSE)
  402. {
  403. HANDLE hToken;
  404. // Get the client token and for membership of the local administrators
  405. // group. DO NOT IMPERSONATE THE CLIENT. This will almost certainly
  406. // guarantee that the process cannot be terminated.
  407. status = OpenClientToken(hToken);
  408. if (NT_SUCCESS(status))
  409. {
  410. CTokenInformation tokenInformationClient(hToken);
  411. if (tokenInformationClient.IsUserAnAdministrator())
  412. {
  413. HANDLE hProcess;
  414. CBadApplication badApplication(szImageName);
  415. // Query information on the bad application
  416. // (get back the process handle).
  417. status = s_pBadApplicationManager->QueryInformation(badApplication, hProcess);
  418. if (NT_SUCCESS(status))
  419. {
  420. do
  421. {
  422. status = CBadApplicationManager::PerformTermination(hProcess, true);
  423. TBOOL(CloseHandle(hProcess));
  424. } while (NT_SUCCESS(status) &&
  425. NT_SUCCESS(s_pBadApplicationManager->QueryInformation(badApplication, hProcess)));
  426. }
  427. // If the information could not be found then it's
  428. // probably not running. This indicates success.
  429. else
  430. {
  431. status = STATUS_SUCCESS;
  432. }
  433. }
  434. else
  435. {
  436. status = STATUS_ACCESS_DENIED;
  437. }
  438. TBOOL(CloseHandle(hToken));
  439. }
  440. }
  441. else
  442. {
  443. status = CStatusCode::StatusCodeOfLastError();
  444. }
  445. pAPIOut->fResult = NT_SUCCESS(status);
  446. SetDataLength(sizeof(API_BAM));
  447. return(status);
  448. }
  449. // --------------------------------------------------------------------------
  450. // CBadApplicationAPIRequest::Execute_RequestSwitchUser
  451. //
  452. // Arguments: <none>
  453. //
  454. // Returns: NTSTATUS
  455. //
  456. // Purpose: Handles API_BAM_REQUESTSWITCHUSER. Request from
  457. // winlogon/msgina to switch a user. Terminate all bad
  458. // applications related to disconnect. Reject the disconnect if
  459. // it fails.
  460. //
  461. // History: 2000-11-02 vtan created
  462. // --------------------------------------------------------------------------
  463. NTSTATUS CBadApplicationAPIRequest::Execute_RequestSwitchUser (void)
  464. {
  465. API_BAM_REQUESTSWITCHUSER_OUT *pAPIOut;
  466. pAPIOut = &reinterpret_cast<API_BAM*>(&_data)->apiSpecific.apiRequestSwitchUser.out;
  467. pAPIOut->fAllowSwitch = NT_SUCCESS(s_pBadApplicationManager->RequestSwitchUser());
  468. SetDataLength(sizeof(API_BAM));
  469. return(STATUS_SUCCESS);
  470. }
  471. #endif /* _X86_ */