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.

424 lines
12 KiB

  1. #include "precomp.h"
  2. #include <wininet.h>
  3. #include <regstr.h>
  4. // Private forward decalarations
  5. static LPCTSTR mapSingleDw2Psz(PCMAPDW2PSZ pMap, UINT cEntries, DWORD dw, BOOL fFailNotFound = FALSE);
  6. ULONG CoTaskMemSize(LPVOID pv)
  7. {
  8. IMalloc *p;
  9. HRESULT hr;
  10. if (pv == NULL)
  11. return 0;
  12. hr = CoGetMalloc(1, &p);
  13. if (FAILED(hr))
  14. return 0;
  15. return (ULONG)p->GetSize(pv);
  16. }
  17. UINT CoStringFromGUID(REFGUID rguid, LPTSTR pszBuf, UINT cchBuf)
  18. {
  19. WCHAR wszGuid[128];
  20. UINT nSize;
  21. nSize = StringFromGUID2(rguid, wszGuid, countof(wszGuid));
  22. W2Tbuf(wszGuid, pszBuf, cchBuf);
  23. return nSize;
  24. }
  25. LPCTSTR GetHrSz(HRESULT hr)
  26. {
  27. static MAPDW2PSZ mapHr[] = {
  28. // real HRESULTs
  29. DW2PSZ_PAIR(S_OK),
  30. DW2PSZ_PAIR(S_FALSE),
  31. DW2PSZ_PAIR(E_UNEXPECTED),
  32. DW2PSZ_PAIR(E_NOTIMPL),
  33. DW2PSZ_PAIR(E_OUTOFMEMORY),
  34. DW2PSZ_PAIR(E_INVALIDARG),
  35. DW2PSZ_PAIR(E_NOINTERFACE),
  36. DW2PSZ_PAIR(E_POINTER),
  37. DW2PSZ_PAIR(E_HANDLE),
  38. DW2PSZ_PAIR(E_ABORT),
  39. DW2PSZ_PAIR(E_FAIL),
  40. DW2PSZ_PAIR(E_ACCESSDENIED),
  41. DW2PSZ_PAIR(CO_E_NOTINITIALIZED),
  42. DW2PSZ_PAIR(CO_E_ALREADYINITIALIZED),
  43. DW2PSZ_PAIR(CO_E_DLLNOTFOUND),
  44. DW2PSZ_PAIR(CO_E_APPNOTFOUND),
  45. DW2PSZ_PAIR(CO_E_ERRORINDLL),
  46. DW2PSZ_PAIR(CO_E_APPDIDNTREG),
  47. DW2PSZ_PAIR(RPC_E_CHANGED_MODE),
  48. DW2PSZ_PAIR(REGDB_E_CLASSNOTREG),
  49. DW2PSZ_PAIR(REGDB_E_READREGDB),
  50. DW2PSZ_PAIR(REGDB_E_IIDNOTREG),
  51. DW2PSZ_PAIR(CLASS_E_NOAGGREGATION),
  52. DW2PSZ_PAIR(STG_E_FILENOTFOUND),
  53. DW2PSZ_PAIR(STG_E_PATHNOTFOUND),
  54. DW2PSZ_PAIR(TRUST_E_NOSIGNATURE),
  55. DW2PSZ_PAIR(TRUST_E_FAIL),
  56. DW2PSZ_PAIR(TRUST_E_SUBJECT_NOT_TRUSTED),
  57. // win32 errors
  58. DW2PSZ_PAIR(ERROR_FILE_NOT_FOUND),
  59. DW2PSZ_PAIR(ERROR_PATH_NOT_FOUND),
  60. // wininet errors
  61. DW2PSZ_PAIR(ERROR_INTERNET_INTERNAL_ERROR)
  62. };
  63. LPCTSTR pszResult;
  64. pszResult = mapSingleDw2Psz(mapHr, countof(mapHr), hr, TRUE);
  65. if (pszResult != NULL)
  66. return pszResult;
  67. // error from HRESULT_FROM_WIN32
  68. if (hr < 0 && (hr & (FACILITY_WIN32 << 16)) == (FACILITY_WIN32 << 16))
  69. hr &= 0x0000FFFF; // only LOWORD matters
  70. return mapSingleDw2Psz(mapHr, countof(mapHr), hr);
  71. }
  72. DWORD GetStringField(LPTSTR szStr, UINT uField, LPTSTR szBuf, UINT cchBufSize)
  73. {
  74. LPTSTR pszBegin = szStr;
  75. LPTSTR pszEnd;
  76. TCHAR cSeparator;
  77. UINT i = 0;
  78. DWORD dwToCopy;
  79. if(cchBufSize == 0)
  80. return 0;
  81. szBuf[0] = TEXT('\0');
  82. if(szStr == NULL)
  83. return 0;
  84. // figure out whether we're looking for commas or periods
  85. if (StrChr(szStr, TEXT(',')))
  86. cSeparator = TEXT(',');
  87. else
  88. {
  89. if (StrChr(szStr, TEXT('.')))
  90. cSeparator = TEXT('.');
  91. else
  92. return 0;
  93. }
  94. while(pszBegin && *pszBegin != TEXT('\0') && i < uField)
  95. {
  96. pszBegin = StrChr(pszBegin, cSeparator);
  97. if(pszBegin && (*pszBegin != TEXT('\0')))
  98. pszBegin++;
  99. i++;
  100. }
  101. // we reached end of string, no field
  102. if(!pszBegin || *pszBegin == TEXT('\0'))
  103. {
  104. return 0;
  105. }
  106. pszEnd = StrChr(pszBegin, cSeparator);
  107. while(pszBegin <= pszEnd && *pszBegin == TEXT(' '))
  108. pszBegin++;
  109. while(pszEnd > pszBegin && *(pszEnd - 1) == TEXT(' '))
  110. pszEnd--;
  111. if(pszEnd > (pszBegin + 1) && *pszBegin == TEXT('"') && *(pszEnd-1) == TEXT('"'))
  112. {
  113. pszBegin++;
  114. pszEnd--;
  115. }
  116. dwToCopy = (DWORD) (pszEnd - pszBegin + 1);
  117. if(dwToCopy > cchBufSize)
  118. dwToCopy = cchBufSize;
  119. StrCpyN(szBuf, pszBegin, dwToCopy);
  120. return dwToCopy - 1;
  121. }
  122. DWORD GetIntField(LPTSTR szStr, UINT uField, DWORD dwDefault)
  123. {
  124. TCHAR szNumBuf[16];
  125. if (GetStringField(szStr, uField, szNumBuf, countof(szNumBuf)) == 0)
  126. return dwDefault;
  127. else
  128. return StrToInt(szNumBuf);
  129. }
  130. void ConvertVersionStrToDwords(LPTSTR pszVer, LPDWORD pdwVer, LPDWORD pdwBuild)
  131. {
  132. DWORD dwTemp1,dwTemp2;
  133. dwTemp1 = GetIntField(pszVer, 0, 0);
  134. dwTemp2 = GetIntField(pszVer, 1, 0);
  135. *pdwVer = (dwTemp1 << 16) + dwTemp2;
  136. dwTemp1 = GetIntField(pszVer, 2, 0);
  137. dwTemp2 = GetIntField(pszVer, 3, 0);
  138. *pdwBuild = (dwTemp1 << 16) + dwTemp2;
  139. }
  140. void ConvertDwordsToVersionStr(LPTSTR pszVer, DWORD dwVer, DWORD dwBuild)
  141. {
  142. WORD w1, w2, w3, w4;
  143. w1 = HIWORD(dwVer);
  144. w2 = LOWORD(dwVer);
  145. w3 = HIWORD(dwBuild);
  146. w4 = LOWORD(dwBuild);
  147. wnsprintf(pszVer, 32, TEXT("%d,%d,%d,%d"), w1, w2, w3, w4);
  148. }
  149. DWORD GetIEVersion()
  150. {
  151. TCHAR szValue[MAX_PATH];
  152. DWORD dwInstalledVer, dwInstalledBuild, dwSize;
  153. dwInstalledVer = dwInstalledBuild = (DWORD)-1;
  154. szValue[0] = TEXT('\0');
  155. dwSize = sizeof(szValue);
  156. SHGetValue(HKEY_LOCAL_MACHINE, RK_IE, RV_VERSION, NULL, szValue, &dwSize);
  157. if (szValue[0] != TEXT('\0')) {
  158. ConvertVersionStrToDwords(szValue, &dwInstalledVer, &dwInstalledBuild);
  159. return dwInstalledVer;
  160. }
  161. if (dwInstalledVer == (DWORD)-1) {
  162. szValue[0] = TEXT('\0');
  163. dwSize = sizeof(szValue);
  164. SHGetValue(HKEY_LOCAL_MACHINE, REGSTR_PATH_APPPATHS TEXT("\\iexplore.exe"), NULL, NULL, szValue, &dwSize);
  165. if (szValue[0] != TEXT('\0')) {
  166. GetVersionFromFileWrap(szValue, &dwInstalledVer, &dwInstalledBuild, TRUE);
  167. return dwInstalledVer;
  168. }
  169. }
  170. return 0;
  171. }
  172. BOOL SetFlag(LPDWORD pdwFlags, DWORD dwMask, BOOL fSet /*= TRUE*/)
  173. {
  174. if (pdwFlags == NULL)
  175. return FALSE;
  176. if (fSet)
  177. *pdwFlags |= dwMask;
  178. else
  179. *pdwFlags &= ~dwMask;
  180. return TRUE;
  181. }
  182. // taken from IE setup code
  183. BOOL IsNTAdmin()
  184. {
  185. typedef BOOL (WINAPI *LPCHECKTOKENMEMBERSHIP)(HANDLE, PSID, PBOOL);
  186. static int s_fIsAdmin = 2;
  187. HANDLE hAccessToken = NULL;
  188. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  189. PSID AdministratorsGroup;
  190. BOOL bRet = FALSE;
  191. //
  192. // If we have cached a value, return the cached value. Note I never
  193. // set the cached value to false as I want to retry each time in
  194. // case a previous failure was just a temp. problem (ie net access down)
  195. //
  196. bRet = FALSE;
  197. if( s_fIsAdmin != 2 )
  198. return (BOOL)s_fIsAdmin;
  199. if (!IsOS(OS_NT))
  200. {
  201. s_fIsAdmin = TRUE; // If we are not running under NT return TRUE.
  202. return (BOOL)s_fIsAdmin;
  203. }
  204. if(!IsOS(OS_NT5) &&
  205. !OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &hAccessToken ) )
  206. return FALSE;
  207. if(AllocateAndInitializeSid( &NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,
  208. DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &AdministratorsGroup) )
  209. {
  210. // if we're running on W2K use the proper check (b388901 in W2K database) which
  211. // will work for restricted tokens
  212. if (IsOS(OS_NT5))
  213. {
  214. HINSTANCE hAdvapi32 = NULL;
  215. LPCHECKTOKENMEMBERSHIP lpfnCheckTokenMembership = NULL;
  216. hAdvapi32 = LoadLibrary(TEXT("advapi32.dll"));
  217. if (hAdvapi32 != NULL)
  218. {
  219. lpfnCheckTokenMembership =
  220. (LPCHECKTOKENMEMBERSHIP)GetProcAddress(hAdvapi32, "CheckTokenMembership");
  221. if (lpfnCheckTokenMembership != NULL)
  222. {
  223. BOOL fMember = FALSE;
  224. if (lpfnCheckTokenMembership(hAccessToken, AdministratorsGroup,
  225. &fMember) && fMember)
  226. {
  227. s_fIsAdmin = TRUE;
  228. bRet = TRUE;
  229. }
  230. }
  231. FreeLibrary(hAdvapi32);
  232. }
  233. }
  234. else
  235. {
  236. PTOKEN_GROUPS ptgGroups;
  237. DWORD dwReqSize;
  238. UINT i;
  239. ptgGroups = NULL;
  240. // See how big of a buffer we need for the token information
  241. if(!GetTokenInformation( hAccessToken, TokenGroups, NULL, 0, &dwReqSize))
  242. {
  243. // GetTokenInfo should the buffer size we need - Alloc a buffer
  244. if(GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  245. ptgGroups = (PTOKEN_GROUPS) CoTaskMemAlloc(dwReqSize);
  246. }
  247. // ptgGroups could be NULL for a coupla reasons here:
  248. // 1. The alloc above failed
  249. // 2. GetTokenInformation actually managed to succeed the first time (possible?)
  250. // 3. GetTokenInfo failed for a reason other than insufficient buffer
  251. // Any of these seem justification for bailing.
  252. // So, make sure it isn't null, then get the token info
  253. if((ptgGroups != NULL) &&
  254. GetTokenInformation(hAccessToken, TokenGroups, ptgGroups, dwReqSize, &dwReqSize))
  255. {
  256. // Search thru all the groups this process belongs to looking for the
  257. // Administrators Group.
  258. for( i=0; i < ptgGroups->GroupCount; i++ )
  259. {
  260. if (EqualSid(ptgGroups->Groups[i].Sid, AdministratorsGroup))
  261. {
  262. // Yea! This guy looks like an admin
  263. s_fIsAdmin = TRUE;
  264. bRet = TRUE;
  265. break;
  266. }
  267. }
  268. }
  269. if (ptgGroups != NULL)
  270. CoTaskMemFree(ptgGroups);
  271. }
  272. FreeSid(AdministratorsGroup);
  273. }
  274. // BUGBUG: Close handle here? doc's aren't clear whether this is needed.
  275. if (hAccessToken != NULL)
  276. CloseHandle(hAccessToken);
  277. return bRet;
  278. }
  279. HRESULT GetLcid(LCID *pLcid, LPCTSTR pcszLang, LPCTSTR pcszLocaleIni)
  280. {
  281. TCHAR szLookupEntries[1024];
  282. TCHAR szLang[8];
  283. LPTSTR pszIndex;
  284. HRESULT hRetVal = E_FAIL;
  285. if (pLcid == NULL || pcszLang == NULL || *pcszLang == TEXT('\0') || pcszLocaleIni == NULL ||
  286. *pcszLocaleIni == TEXT('\0'))
  287. return hRetVal;
  288. if (GetPrivateProfileString(IS_ACTIVESETUP, NULL, TEXT(""), szLookupEntries, countof(szLookupEntries), pcszLocaleIni))
  289. {
  290. for (pszIndex = szLookupEntries; *pszIndex; pszIndex += StrLen(pszIndex)+1)
  291. {
  292. GetPrivateProfileString(IS_ACTIVESETUP, pszIndex, TEXT(""), szLang, countof(szLang), pcszLocaleIni);
  293. if (StrCmpI(szLang, pcszLang) == 0)
  294. {
  295. TCHAR szHexLCID[16];
  296. StrCpy(szHexLCID, TEXT("0x"));
  297. StrCat(szHexLCID, pszIndex);
  298. if (StrToIntEx(szHexLCID, STIF_SUPPORT_HEX, (int *)pLcid))
  299. hRetVal = S_OK;
  300. break;
  301. }
  302. }
  303. }
  304. return hRetVal;
  305. }
  306. UINT GetUnitsFromCb(UINT cbSrc, UINT cbUnit)
  307. {
  308. ASSERT(0 == cbSrc % cbUnit);
  309. return (cbSrc / cbUnit);
  310. }
  311. /////////////////////////////////////////////////////////////////////////////
  312. // Implementation helpers routines (private)
  313. LPCTSTR mapSingleDw2Psz(PCMAPDW2PSZ pMap, UINT cEntries, DWORD dw, BOOL fFailNotFound /*= FALSE*/)
  314. {
  315. static TCHAR szUnknown[30];
  316. ASSERT(pMap != NULL);
  317. for (UINT i = 0; i < cEntries; i++)
  318. if ((pMap + i)->dw == dw)
  319. return (pMap + i)->psz;
  320. if (fFailNotFound)
  321. return NULL;
  322. wnsprintf(szUnknown, countof(szUnknown), TEXT("(unknown) [0x%08lX]"), dw);
  323. return szUnknown;
  324. }