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.

512 lines
12 KiB

  1. #include <nt.h>
  2. #include <ntrtl.h>
  3. #include <nturtl.h>
  4. #include <windows.h>
  5. #include <lmaccess.h>
  6. #include <lmapibuf.h>
  7. #include <winsta.h>
  8. #include <dsgetdc.h>
  9. #include <userenv.h>
  10. #include <userenvp.h>
  11. extern "C"
  12. {
  13. #include <syslib.h>
  14. }
  15. #ifdef ASSERT
  16. #undef ASSERT
  17. #endif
  18. #include "users.h"
  19. #include "sfstr.h"
  20. #include "str.h"
  21. #include "mischlpr.h"
  22. #include "dbg.h"
  23. #include "tfids.h"
  24. #define ARRAYSIZE(a) (sizeof((a))/sizeof((a)[0]))
  25. HRESULT _GetUserHKCU(HANDLE hThreadToken, LPCWSTR pszUserName, HKEY* phkey)
  26. {
  27. HRESULT hr;
  28. PROFILEINFO profileinfo = {0};
  29. *phkey = NULL;
  30. profileinfo.dwSize = sizeof(profileinfo);
  31. profileinfo.dwFlags = PI_NOUI | PI_LITELOAD;
  32. profileinfo.lpUserName = (LPWSTR)pszUserName;
  33. if (LoadUserProfile(hThreadToken, &profileinfo))
  34. {
  35. *phkey = (HKEY)(profileinfo.hProfile);
  36. hr = S_OK;
  37. TRACE(TF_USERS, TEXT("Loaded user profile"));
  38. }
  39. else
  40. {
  41. hr = S_FALSE;
  42. TRACE(TF_USERS,
  43. TEXT("FAILED to load user profile: GLE = 0x%08X"),
  44. GetLastError());
  45. }
  46. return hr;
  47. }
  48. HRESULT _GetThreadTokenAndUserName(HANDLE* phThreadToken,
  49. LPWSTR pszUserName, DWORD cchUserName)
  50. {
  51. HRESULT hr = E_FAIL;
  52. if (OpenThreadToken(GetCurrentThread(),
  53. TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE,
  54. TRUE, phThreadToken))
  55. {
  56. #ifdef DEBUG
  57. // For information only
  58. DWORD dwImp = 0;
  59. DWORD dwBytesReturned;
  60. if (GetTokenInformation(*phThreadToken, TokenImpersonationLevel,
  61. &dwImp, sizeof(DWORD), &dwBytesReturned))
  62. {
  63. switch (dwImp)
  64. {
  65. case SecurityAnonymous:
  66. TRACE(TF_USERS, TEXT("SecurityAnonymous"));
  67. break;
  68. case SecurityIdentification:
  69. TRACE(TF_USERS, TEXT("SecurityIdentification"));
  70. break;
  71. case SecurityImpersonation:
  72. TRACE(TF_USERS, TEXT("SecurityImpersonation"));
  73. break;
  74. case SecurityDelegation:
  75. TRACE(TF_USERS, TEXT("SecurityDelegation"));
  76. break;
  77. default:
  78. TRACE(TF_USERS, TEXT("Error. Unable to determine impersonation level"));
  79. break;
  80. }
  81. }
  82. else
  83. {
  84. TRACE(TF_USERS, TEXT("Unable to read impersonation level"));
  85. }
  86. #endif
  87. if (GetUserName(pszUserName, &cchUserName))
  88. {
  89. TRACE(TF_USERS, TEXT("UserName: %s"), pszUserName);
  90. hr = S_OK;
  91. }
  92. else
  93. {
  94. TRACE(TF_USERS, TEXT("Failed to get username"));
  95. }
  96. }
  97. else
  98. {
  99. TRACE(TF_USERS, TEXT("Unable to read thread token (%d)"),
  100. GetLastError());
  101. }
  102. return hr;
  103. }
  104. HRESULT _GetCurrentUserHKCU(HANDLE* phThreadToken, HKEY* phkey)
  105. {
  106. HRESULT hr = E_INVALIDARG;
  107. if (phkey && phThreadToken)
  108. {
  109. CImpersonateConsoleSessionUser icsu;
  110. hr = icsu.Impersonate();
  111. if (SUCCEEDED(hr) && (S_FALSE != hr))
  112. {
  113. WCHAR szUserName[UNLEN + 1];
  114. hr = _GetThreadTokenAndUserName(phThreadToken,
  115. szUserName, ARRAYSIZE(szUserName));
  116. icsu.RevertToSelf();
  117. if (SUCCEEDED(hr) && (S_FALSE != hr))
  118. {
  119. hr = _GetUserHKCU(*phThreadToken, szUserName, phkey);
  120. }
  121. }
  122. else
  123. {
  124. TRACE(TF_USERS, TEXT("WinStationQueryInformation FAILED"));
  125. }
  126. }
  127. if (FAILED(hr) || (S_FALSE == hr))
  128. {
  129. TRACE(TF_USERS, TEXT("_GetCurrentUserHKCU FAILED or S_FALSE'D: 0x%08X"), hr);
  130. }
  131. else
  132. {
  133. TRACE(TF_USERS, TEXT("_GetCurrentUserHKCU SUCCEEDED"));
  134. }
  135. return hr;
  136. }
  137. HRESULT _CloseCurrentUserHKCU(HANDLE hThreadToken, HKEY hkey)
  138. {
  139. UnloadUserProfile(hThreadToken, hkey);
  140. CloseHandle(hThreadToken);
  141. return S_OK;
  142. }
  143. HRESULT _CoGetCallingUserHKCU(HANDLE* phThreadToken, HKEY* phkey)
  144. {
  145. HRESULT hr = E_INVALIDARG;
  146. if (phkey && phThreadToken)
  147. {
  148. CImpersonateCOMCaller icc;
  149. // You must call this before trying to open a thread token!
  150. hr = icc.Impersonate();
  151. if (SUCCEEDED(hr) && (S_FALSE != hr))
  152. {
  153. WCHAR szUserName[UNLEN + 1];
  154. hr = _GetThreadTokenAndUserName(phThreadToken,
  155. szUserName, ARRAYSIZE(szUserName));
  156. icc.RevertToSelf();
  157. if (SUCCEEDED(hr) && (S_FALSE != hr))
  158. {
  159. hr = _GetUserHKCU(*phThreadToken, szUserName, phkey);
  160. }
  161. }
  162. else
  163. {
  164. TRACE(TF_USERS, TEXT("CoImpersonateClient failed: 0x%08X"), hr);
  165. }
  166. }
  167. if (FAILED(hr) || (S_FALSE == hr))
  168. {
  169. TRACE(TF_USERS, TEXT("_CoGetCallingUserHKCU FAILED or S_FALSE'D: 0x%08X"), hr);
  170. }
  171. else
  172. {
  173. TRACE(TF_USERS, TEXT("_CoGetCallingUserHKCU SUCCEEDED"));
  174. }
  175. return hr;
  176. }
  177. HRESULT _CoCloseCallingUserHKCU(HANDLE hThreadToken, HKEY hkey)
  178. {
  179. UnloadUserProfile(hThreadToken, hkey);
  180. CloseHandle(hThreadToken);
  181. return S_OK;
  182. }
  183. #define SESSION_MONIKER TEXT("Session:Console!clsid:")
  184. HRESULT _CoCreateInstanceInConsoleSession(REFCLSID rclsid, IUnknown* punkOuter,
  185. DWORD /*dwClsContext*/, REFIID riid, void** ppv)
  186. {
  187. IBindCtx* pbc;
  188. HRESULT hr = CreateBindCtx(0, &pbc);
  189. *ppv = NULL;
  190. if (SUCCEEDED(hr))
  191. {
  192. WCHAR szCLSID[39];
  193. hr = _StringFromGUID(&rclsid, szCLSID, ARRAYSIZE(szCLSID));
  194. if (SUCCEEDED(hr))
  195. {
  196. ULONG ulEaten;
  197. IMoniker* pmoniker;
  198. WCHAR szDisplayName[ARRAYSIZE(SESSION_MONIKER) + ARRAYSIZE(szCLSID)] =
  199. SESSION_MONIKER;
  200. // We want something like: "Session:Console!clsid:760befd0-5b0b-44d7-957e-969af35ce954"
  201. szCLSID[ARRAYSIZE(szCLSID) - 2] = 0;
  202. // Form display name string
  203. hr = SafeStrCatN(szDisplayName, szCLSID + 1, ARRAYSIZE(szDisplayName));
  204. if (SUCCEEDED(hr))
  205. {
  206. // Parse the name and get a moniker:
  207. hr = MkParseDisplayName(pbc, szDisplayName, &ulEaten, &pmoniker);
  208. if (SUCCEEDED(hr))
  209. {
  210. IClassFactory* pcf;
  211. hr = pmoniker->BindToObject(pbc, NULL, IID_IClassFactory, (void**)&pcf);
  212. if (SUCCEEDED(hr))
  213. {
  214. hr = pcf->CreateInstance(punkOuter, riid, ppv);
  215. TRACE(TF_USERS,
  216. TEXT("pcf->CreateInstance returned: hr = 0x%08X"), hr);
  217. pcf->Release();
  218. }
  219. else
  220. {
  221. TRACE(TF_USERS, TEXT("pmoniker->BindToObject returned: hr = 0x%08X"), hr);
  222. }
  223. pmoniker->Release();
  224. }
  225. }
  226. }
  227. else
  228. {
  229. TRACE(TF_USERS, TEXT("MkParseDisplayName returned: hr = 0x%08X"), hr);
  230. }
  231. pbc->Release();
  232. }
  233. else
  234. {
  235. TRACE(TF_USERS, TEXT("CreateBindCtxt returned: hr = 0x%08X"), hr);
  236. }
  237. return hr;
  238. }
  239. HRESULT CImpersonateTokenBased::Impersonate()
  240. {
  241. HRESULT hr = S_FALSE;
  242. if (!_hToken)
  243. {
  244. hr = _GetToken(&_hToken);
  245. }
  246. if (SUCCEEDED(hr) && (S_FALSE != hr))
  247. {
  248. if (ImpersonateLoggedOnUser(_hToken))
  249. {
  250. hr = S_OK;
  251. }
  252. else
  253. {
  254. TRACE(TF_USERS, TEXT("Impersonate FAILED"));
  255. }
  256. }
  257. return hr;
  258. }
  259. HRESULT CImpersonateTokenBased::RevertToSelf()
  260. {
  261. return _RevertToSelf();
  262. }
  263. HRESULT CImpersonateTokenBased::_RevertToSelf()
  264. {
  265. if (_hToken)
  266. {
  267. ::RevertToSelf();
  268. CloseHandle(_hToken);
  269. _hToken = NULL;
  270. }
  271. return S_OK;
  272. }
  273. CImpersonateTokenBased::CImpersonateTokenBased()
  274. {
  275. _hToken = NULL;
  276. }
  277. CImpersonateTokenBased::~CImpersonateTokenBased()
  278. {
  279. _RevertToSelf();
  280. }
  281. HRESULT CImpersonateConsoleSessionUser::_GetToken(HANDLE* phToken)
  282. {
  283. HRESULT hr;
  284. ULONG ulReturnLength;
  285. WINSTATIONUSERTOKEN wsUserToken = {0};
  286. // Yep, the next casts are intentional...
  287. wsUserToken.ProcessId = (HANDLE)(DWORD_PTR)GetCurrentProcessId();
  288. wsUserToken.ThreadId = (HANDLE)(DWORD_PTR)GetCurrentThreadId();
  289. wsUserToken.UserToken = NULL;
  290. BOOL fActiveConsole = WinStationQueryInformation(SERVERNAME_CURRENT,
  291. USER_SHARED_DATA->ActiveConsoleId, WinStationUserToken,
  292. &wsUserToken, sizeof(wsUserToken), &ulReturnLength);
  293. if (fActiveConsole)
  294. {
  295. *phToken = wsUserToken.UserToken;
  296. hr = S_OK;
  297. }
  298. else
  299. {
  300. hr = S_FALSE;
  301. }
  302. return hr;
  303. }
  304. HRESULT CImpersonateEveryone::_GetToken(HANDLE* phToken)
  305. {
  306. HRESULT hr = S_FALSE;
  307. PSID gAdminSid;
  308. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  309. NTSTATUS ntstatus = RtlAllocateAndInitializeSid(
  310. &NtAuthority,
  311. 2,
  312. SECURITY_BUILTIN_DOMAIN_RID,
  313. DOMAIN_ALIAS_RID_ADMINS,
  314. 0, 0, 0, 0, 0, 0,
  315. &gAdminSid);
  316. if (NT_SUCCESS(ntstatus))
  317. {
  318. HANDLE hTokenProcess;
  319. ntstatus = NtOpenProcessToken(
  320. NtCurrentProcess(),
  321. TOKEN_ALL_ACCESS,
  322. &hTokenProcess);
  323. if (NT_SUCCESS(ntstatus))
  324. {
  325. TOKEN_GROUPS TokenGroups = {0};
  326. TokenGroups.GroupCount = 1 ;
  327. TokenGroups.Groups[0].Attributes = 0 ;
  328. TokenGroups.Groups[0].Sid = gAdminSid ;
  329. ntstatus = NtFilterToken(
  330. hTokenProcess,
  331. DISABLE_MAX_PRIVILEGE,
  332. &TokenGroups,
  333. NULL,
  334. NULL,
  335. phToken);
  336. NtClose(hTokenProcess);
  337. hr = S_OK;
  338. }
  339. RtlFreeSid(gAdminSid);
  340. }
  341. return hr;
  342. }
  343. ///////////////////////////////////////////////////////////////////////////////
  344. ///////////////////////////////////////////////////////////////////////////////
  345. HRESULT CImpersonateCOMCaller::Impersonate()
  346. {
  347. HRESULT hr = CoImpersonateClient();
  348. if (SUCCEEDED(hr))
  349. {
  350. _fImpersonating = TRUE;
  351. }
  352. else
  353. {
  354. hr = S_FALSE;
  355. }
  356. return hr;
  357. }
  358. HRESULT CImpersonateCOMCaller::RevertToSelf()
  359. {
  360. return _RevertToSelf();
  361. }
  362. HRESULT CImpersonateCOMCaller::_RevertToSelf()
  363. {
  364. if (_fImpersonating)
  365. {
  366. CoRevertToSelf();
  367. _fImpersonating = FALSE;
  368. }
  369. return S_OK;
  370. }
  371. CImpersonateCOMCaller::CImpersonateCOMCaller() : _fImpersonating(FALSE)
  372. {}
  373. CImpersonateCOMCaller::~CImpersonateCOMCaller()
  374. {
  375. _RevertToSelf();
  376. }
  377. HRESULT _GiveAllowForegroundToConsoleShell()
  378. {
  379. HANDLE hImpersonationToken;
  380. DWORD dwSessionID = USER_SHARED_DATA->ActiveConsoleId;
  381. if (GetWinStationUserToken(dwSessionID, &hImpersonationToken))
  382. {
  383. HANDLE hUserToken;
  384. if (DuplicateTokenEx(hImpersonationToken, 0, NULL,
  385. SecurityImpersonation, TokenPrimary, &hUserToken))
  386. {
  387. STARTUPINFO StartupInfo = {0};
  388. PROCESS_INFORMATION ProcessInfo = {0};
  389. WCHAR szCommand[] = TEXT("rundll32.exe shell32.dll,Activate_RunDLL");
  390. StartupInfo.cb = sizeof(StartupInfo);
  391. StartupInfo.wShowWindow = SW_SHOW;
  392. StartupInfo.lpDesktop = L"WinSta0\\Default";
  393. if (CreateProcessAsUser(hUserToken, NULL, szCommand,
  394. NULL, NULL, FALSE, DETACHED_PROCESS, NULL, NULL,
  395. &StartupInfo, &ProcessInfo))
  396. {
  397. CloseHandle(ProcessInfo.hProcess);
  398. CloseHandle(ProcessInfo.hThread);
  399. }
  400. CloseHandle(hUserToken);
  401. }
  402. CloseHandle(hImpersonationToken);
  403. }
  404. return S_OK;
  405. }