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.

420 lines
10 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1997 - 1999
  3. Module Name:
  4. reghkcu.c
  5. Abstract:
  6. This module implements functionality to correctly access the pre-defined
  7. registry key HKEY_CURRENT_USER.
  8. Author:
  9. Scott Field (sfield) 03-Jul-97
  10. --*/
  11. #include <windows.h>
  12. #include "crtem.h"
  13. #include "unicode.h"
  14. #define TEXTUAL_SID_LOCAL_SYSTEM L"S-1-5-18"
  15. BOOL
  16. GetTextualSidHKCU(
  17. IN PSID pSid, // binary Sid
  18. IN LPWSTR TextualSid, // buffer for Textual representaion of Sid
  19. IN OUT LPDWORD pcchTextualSid // required/provided TextualSid buffersize
  20. );
  21. BOOL
  22. GetTokenUserSidHKCU(
  23. IN HANDLE hToken, // token to query
  24. IN OUT PSID *ppUserSid // resultant user sid
  25. );
  26. static LONG GetStatus()
  27. {
  28. DWORD dwErr = GetLastError();
  29. if (ERROR_SUCCESS == dwErr)
  30. return ERROR_INVALID_DATA;
  31. else
  32. return (LONG) dwErr;
  33. }
  34. LONG
  35. WINAPI
  36. RegOpenHKCU(
  37. HKEY *phKeyCurrentUser
  38. )
  39. {
  40. return RegOpenHKCUEx(phKeyCurrentUser, 0);
  41. }
  42. LONG
  43. WINAPI
  44. RegOpenHKCUEx(
  45. HKEY *phKeyCurrentUser,
  46. DWORD dwFlags
  47. )
  48. {
  49. WCHAR wszFastBuffer[256];
  50. LPWSTR wszSlowBuffer = NULL;
  51. LPWSTR wszTextualSid;
  52. DWORD cchTextualSid;
  53. LONG lRet = ERROR_SUCCESS;
  54. *phKeyCurrentUser = NULL;
  55. //
  56. // Win95: just return HKEY_CURRENT_USER, as we don't have
  57. // multiple security contexts on that platform.
  58. //
  59. if(!FIsWinNT()) {
  60. *phKeyCurrentUser = HKEY_CURRENT_USER;
  61. return ERROR_SUCCESS;
  62. }
  63. //
  64. // WinNT: first, map the binary Sid associated with the
  65. // current security context to an textual Sid.
  66. //
  67. wszTextualSid = wszFastBuffer;
  68. cchTextualSid = sizeof(wszFastBuffer) / sizeof(WCHAR);
  69. if(!GetUserTextualSidHKCU(wszTextualSid, &cchTextualSid)) {
  70. if(GetLastError() != ERROR_INSUFFICIENT_BUFFER)
  71. return GetStatus();
  72. //
  73. // try again with larger buffer.
  74. //
  75. wszSlowBuffer = (LPWSTR)malloc(cchTextualSid * sizeof(WCHAR));
  76. if(wszSlowBuffer == NULL)
  77. return GetStatus();
  78. wszTextualSid = wszSlowBuffer;
  79. if(!GetUserTextualSidHKCU(wszTextualSid, &cchTextualSid)) {
  80. free(wszSlowBuffer);
  81. return GetStatus();
  82. }
  83. }
  84. //
  85. // next, try to open the registry key below HKEY_USERS
  86. // that corresponds to the textual Sid.
  87. //
  88. lRet = RegOpenKeyExW(
  89. HKEY_USERS,
  90. wszTextualSid,
  91. 0, // dwOptions
  92. MAXIMUM_ALLOWED,
  93. phKeyCurrentUser
  94. );
  95. if(lRet != ERROR_SUCCESS) {
  96. if (dwFlags & REG_HKCU_DISABLE_DEFAULT_FLAG)
  97. lRet = ERROR_FILE_NOT_FOUND;
  98. else if (0 == (dwFlags & REG_HKCU_LOCAL_SYSTEM_ONLY_DEFAULT_FLAG) ||
  99. 0 == wcscmp(TEXTUAL_SID_LOCAL_SYSTEM, wszTextualSid)) {
  100. //
  101. // If that failed, fall back to HKEY_USERS\.Default.
  102. // Note: this is correct behavior with respect to the
  103. // rest of the system, eg, Local System security context
  104. // has no registry hive loaded by default
  105. //
  106. lRet = RegOpenKeyExW(
  107. HKEY_USERS,
  108. L".Default",
  109. 0, // dwOptions
  110. MAXIMUM_ALLOWED,
  111. phKeyCurrentUser
  112. );
  113. }
  114. }
  115. if(wszSlowBuffer)
  116. free(wszSlowBuffer);
  117. return lRet;
  118. }
  119. LONG
  120. WINAPI
  121. RegCloseHKCU(
  122. HKEY hKeyCurrentUser
  123. )
  124. {
  125. LONG lRet = ERROR_SUCCESS;
  126. if( hKeyCurrentUser != NULL && hKeyCurrentUser != HKEY_CURRENT_USER )
  127. lRet = RegCloseKey( hKeyCurrentUser );
  128. return lRet;
  129. }
  130. BOOL
  131. WINAPI
  132. GetUserTextualSidHKCU(
  133. IN LPWSTR wszTextualSid,
  134. IN OUT LPDWORD pcchTextualSid
  135. )
  136. {
  137. HANDLE hToken;
  138. PSID pSidUser = NULL;
  139. BOOL fSuccess = FALSE;
  140. //
  141. // first, attempt to look at the thread token. If none exists,
  142. // which is true if the thread is not impersonating, try the
  143. // process token.
  144. //
  145. if(!OpenThreadToken(
  146. GetCurrentThread(),
  147. TOKEN_QUERY,
  148. TRUE,
  149. &hToken
  150. ))
  151. {
  152. if(GetLastError() != ERROR_NO_TOKEN)
  153. return FALSE;
  154. if(!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
  155. return FALSE;
  156. }
  157. fSuccess = GetTokenUserSidHKCU(hToken, &pSidUser);
  158. CloseHandle(hToken);
  159. if(fSuccess) {
  160. //
  161. // obtain the textual representaion of the Sid
  162. //
  163. fSuccess = GetTextualSidHKCU(
  164. pSidUser, // user binary Sid
  165. wszTextualSid, // buffer for TextualSid
  166. pcchTextualSid // required/result buffer size in chars (including NULL)
  167. );
  168. }
  169. if(pSidUser)
  170. free(pSidUser);
  171. return fSuccess;
  172. }
  173. BOOL
  174. GetTextualSidHKCU(
  175. IN PSID pSid, // binary Sid
  176. IN LPWSTR TextualSid, // buffer for Textual representaion of Sid
  177. IN OUT LPDWORD pcchTextualSid // required/provided TextualSid buffersize
  178. )
  179. {
  180. PSID_IDENTIFIER_AUTHORITY psia;
  181. DWORD dwSubAuthorities;
  182. DWORD dwCounter;
  183. DWORD cchSidSize;
  184. //
  185. // validate Sid validity
  186. //
  187. if(!IsValidSid(pSid))
  188. return FALSE;
  189. //
  190. // obtain SidIdentifierAuthority
  191. //
  192. psia = GetSidIdentifierAuthority(pSid);
  193. //
  194. // obtain sidsubauthority count
  195. //
  196. dwSubAuthorities = *GetSidSubAuthorityCount(pSid);
  197. //
  198. // compute buffer length in chars (conservative guess)
  199. // S-SID_REVISION- + identifierauthority- + subauthorities- + NULL
  200. //
  201. cchSidSize = (15 + 12 + (12 * dwSubAuthorities) + 1) ;
  202. //
  203. // check provided buffer length.
  204. // If not large enough, indicate proper size and setlasterror
  205. //
  206. if(*pcchTextualSid < cchSidSize) {
  207. *pcchTextualSid = cchSidSize;
  208. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  209. return FALSE;
  210. }
  211. //
  212. // prepare S-SID_REVISION-
  213. //
  214. cchSidSize = wsprintfW(TextualSid, L"S-%lu-", SID_REVISION );
  215. //
  216. // prepare SidIdentifierAuthority
  217. //
  218. if ( (psia->Value[0] != 0) || (psia->Value[1] != 0) ) {
  219. cchSidSize += wsprintfW(TextualSid + cchSidSize,
  220. L"0x%02hx%02hx%02hx%02hx%02hx%02hx",
  221. (USHORT)psia->Value[0],
  222. (USHORT)psia->Value[1],
  223. (USHORT)psia->Value[2],
  224. (USHORT)psia->Value[3],
  225. (USHORT)psia->Value[4],
  226. (USHORT)psia->Value[5]);
  227. } else {
  228. cchSidSize += wsprintfW(TextualSid + cchSidSize,
  229. L"%lu",
  230. (ULONG)(psia->Value[5] ) +
  231. (ULONG)(psia->Value[4] << 8) +
  232. (ULONG)(psia->Value[3] << 16) +
  233. (ULONG)(psia->Value[2] << 24) );
  234. }
  235. //
  236. // loop through SidSubAuthorities
  237. //
  238. for (dwCounter = 0 ; dwCounter < dwSubAuthorities ; dwCounter++) {
  239. cchSidSize += wsprintfW(TextualSid + cchSidSize,
  240. L"-%lu", *GetSidSubAuthority(pSid, dwCounter) );
  241. }
  242. //
  243. // tell caller how many chars copied, including terminal NULL
  244. //
  245. *pcchTextualSid = cchSidSize + 1;
  246. return TRUE;
  247. }
  248. BOOL
  249. GetTokenUserSidHKCU(
  250. IN HANDLE hToken, // token to query
  251. IN OUT PSID *ppUserSid // resultant user sid
  252. )
  253. /*++
  254. This function queries the access token specified by the
  255. hToken parameter, and returns an allocated copy of the
  256. TokenUser information on success.
  257. The access token specified by hToken must be opened for
  258. TOKEN_QUERY access.
  259. On success, the return value is TRUE. The caller is
  260. responsible for freeing the resultant UserSid via a call
  261. to free().
  262. On failure, the return value is FALSE. The caller does
  263. not need to free any buffer.
  264. --*/
  265. {
  266. BYTE FastBuffer[256];
  267. LPBYTE SlowBuffer = NULL;
  268. PTOKEN_USER ptgUser;
  269. DWORD cbBuffer;
  270. BOOL fSuccess = FALSE;
  271. *ppUserSid = NULL;
  272. //
  273. // try querying based on a fast stack based buffer first.
  274. //
  275. ptgUser = (PTOKEN_USER)FastBuffer;
  276. cbBuffer = sizeof(FastBuffer);
  277. fSuccess = GetTokenInformation(
  278. hToken, // identifies access token
  279. TokenUser, // TokenUser info type
  280. ptgUser, // retrieved info buffer
  281. cbBuffer, // size of buffer passed-in
  282. &cbBuffer // required buffer size
  283. );
  284. if(!fSuccess) {
  285. if(GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
  286. //
  287. // try again with the specified buffer size
  288. //
  289. SlowBuffer = (LPBYTE)malloc(cbBuffer);
  290. if(SlowBuffer != NULL) {
  291. ptgUser = (PTOKEN_USER)SlowBuffer;
  292. fSuccess = GetTokenInformation(
  293. hToken, // identifies access token
  294. TokenUser, // TokenUser info type
  295. ptgUser, // retrieved info buffer
  296. cbBuffer, // size of buffer passed-in
  297. &cbBuffer // required buffer size
  298. );
  299. }
  300. }
  301. }
  302. //
  303. // if we got the token info successfully, copy the
  304. // relevant element for the caller.
  305. //
  306. if(fSuccess) {
  307. DWORD cbSid;
  308. // reset to assume failure
  309. fSuccess = FALSE;
  310. cbSid = GetLengthSid(ptgUser->User.Sid);
  311. *ppUserSid = malloc( cbSid );
  312. if(*ppUserSid != NULL) {
  313. fSuccess = CopySid(cbSid, *ppUserSid, ptgUser->User.Sid);
  314. }
  315. }
  316. if(!fSuccess) {
  317. if(*ppUserSid) {
  318. free(*ppUserSid);
  319. *ppUserSid = NULL;
  320. }
  321. }
  322. if(SlowBuffer)
  323. free(SlowBuffer);
  324. return fSuccess;
  325. }