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.

516 lines
13 KiB

  1. //=======================================================================
  2. //
  3. // Copyright (c) 1998-2000 Microsoft Corporation. All Rights Reserved.
  4. //
  5. // File: osdetutl.cpp
  6. //
  7. // Description:
  8. //
  9. // Additional OS detection utility routines for:
  10. // * Returning free drive space
  11. // * Returning "Administrator" flag
  12. //
  13. //=======================================================================
  14. #include <windows.h>
  15. #include <oleauto.h>
  16. #include <wuiutest.h>
  17. #include <tchar.h>
  18. #include <osdet.h>
  19. #include <logging.h>
  20. #include <iucommon.h>
  21. #include <stdio.h> // for _i64tot
  22. // #define __IUENGINE_USES_ATL_
  23. #if defined(__IUENGINE_USES_ATL_)
  24. #include <atlbase.h>
  25. #define USES_IU_CONVERSION USES_CONVERSION
  26. #else
  27. #include <MemUtil.h>
  28. #endif
  29. typedef BOOL (WINAPI * PFN_GetDiskFreeSpaceEx) (LPTSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER);
  30. const TCHAR REGPATH_AU[] = _T("Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU");
  31. const TCHAR REGKEY_AU_OPTIONS[] = _T("NoAutoUpdate");
  32. const TCHAR REGPATH_EXPLORER[] = _T("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer");
  33. const TCHAR REGKEY_WINUPD_DISABLED[] = _T("NoWindowsUpdate");
  34. const TCHAR REGPATH_POLICY_USERACCESS_DISABLED[] = _T("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\WindowsUpdate");
  35. const TCHAR REGKEY_WU_USERACCESS_DISABLED[] = _T("DisableWindowsUpdateAccess");
  36. HRESULT GetLocalFixedDriveInfo(DWORD* pdwNumDrives, PPIU_DRIVEINFO ppDriveInfo)
  37. {
  38. USES_IU_CONVERSION;
  39. LOG_Block("GetLocalFixedDriveInfo");
  40. DWORD dwNumCharacters = 0;
  41. LPTSTR pszDriveStrBuffer = NULL;
  42. HRESULT hr = E_FAIL;
  43. LPTSTR pszRootPathName;
  44. if (NULL == pdwNumDrives || ppDriveInfo == NULL)
  45. {
  46. LOG_Error(_T("E_INVALIDARG"));
  47. return E_INVALIDARG;
  48. }
  49. *ppDriveInfo = NULL;
  50. *pdwNumDrives = 0;
  51. //
  52. // kernel32.dll is loaded into all processes, so we don't need to LoadLibrary, but need to look for W or A versions
  53. //
  54. PFN_GetDiskFreeSpaceEx pfnGetDiskFreeSpaceEx;
  55. #if defined(UNICODE) || defined (_UNICODE)
  56. pfnGetDiskFreeSpaceEx = (PFN_GetDiskFreeSpaceEx) GetProcAddress( GetModuleHandle(L"kernel32.dll"), "GetDiskFreeSpaceExW");
  57. #else
  58. pfnGetDiskFreeSpaceEx = (PFN_GetDiskFreeSpaceEx) GetProcAddress( GetModuleHandle("kernel32.dll"), "GetDiskFreeSpaceExA");
  59. #endif
  60. if (NULL == pfnGetDiskFreeSpaceEx)
  61. {
  62. //
  63. // This could fail on Win95 Gold, but we don't support that anyway
  64. //
  65. Win32MsgSetHrGotoCleanup(GetLastError());
  66. }
  67. //
  68. // Handle corner case of race issue when new drives are hot-plugged between the first
  69. // and second calls to GetLogicalDriveStrings and the buffer requirements increase
  70. //
  71. for (;;)
  72. {
  73. if (0 == (dwNumCharacters = GetLogicalDriveStrings(0, NULL)))
  74. {
  75. Win32MsgSetHrGotoCleanup(GetLastError());
  76. }
  77. //
  78. // Add space for terminating NULL
  79. //
  80. dwNumCharacters += 1;
  81. CleanUpFailedAllocSetHrMsg(pszDriveStrBuffer = (LPTSTR) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwNumCharacters * sizeof(TCHAR)));
  82. DWORD dwRet = GetLogicalDriveStrings(dwNumCharacters, pszDriveStrBuffer);
  83. if (0 == dwRet)
  84. {
  85. //
  86. // Unknown error - we gotta bail
  87. //
  88. Win32MsgSetHrGotoCleanup(GetLastError());
  89. }
  90. else if (dwRet > dwNumCharacters)
  91. {
  92. //
  93. // Someone plugged in a new drive, get the new buffer space requirements and try again
  94. //
  95. SafeHeapFree(pszDriveStrBuffer);
  96. continue;
  97. }
  98. //
  99. // GetLogicalDriveStrings succeeded, break and continue
  100. //
  101. break;
  102. }
  103. //
  104. // Count the number of fixed drives while building the return array of IU_DRIVEINFO
  105. //
  106. for (pszRootPathName = pszDriveStrBuffer; NULL != *pszRootPathName; pszRootPathName += lstrlen(pszRootPathName) + 1)
  107. {
  108. //
  109. // Only return sizes for fixed drives
  110. //
  111. if (DRIVE_FIXED == GetDriveType(pszRootPathName))
  112. {
  113. //
  114. // Make sure pszRootPathName is of the form "<drive letter>:\" by checking for ':' in second position
  115. //
  116. if (_T(':') != pszRootPathName[1])
  117. {
  118. LOG_Error(_T("Root paths must be of form \"<drive letter>:\\\""));
  119. SetHrAndGotoCleanUp(E_FAIL);
  120. }
  121. ULARGE_INTEGER i64FreeBytesAvailable;
  122. ULARGE_INTEGER i64TotalBytes;
  123. ULARGE_INTEGER i64TotalFreeBytes;
  124. BOOL fResult;
  125. //
  126. // Get the free space
  127. //
  128. fResult = pfnGetDiskFreeSpaceEx(pszRootPathName,
  129. &i64FreeBytesAvailable,
  130. &i64TotalBytes,
  131. &i64TotalFreeBytes);
  132. // Process GetDiskFreeSpaceEx results.
  133. if (!fResult)
  134. {
  135. LOG_Driver(_T("GetDiskFreeSpaceEx(%s, ...) returned an error. We will not report space for this drive"), \
  136. pszRootPathName);
  137. LOG_ErrorMsg(GetLastError());
  138. }
  139. else
  140. {
  141. //
  142. // We return KiloBytes
  143. //
  144. i64FreeBytesAvailable.QuadPart /= 1024;
  145. if (NULL == *ppDriveInfo)
  146. {
  147. //
  148. // Allocate one IU_DRIVEINFO struct
  149. //
  150. CleanUpFailedAllocSetHrMsg(*ppDriveInfo = (PIU_DRIVEINFO) HeapAlloc(GetProcessHeap(), 0, sizeof(IU_DRIVEINFO)));
  151. }
  152. else
  153. {
  154. //
  155. // Realloc buffer so we can append
  156. //
  157. PIU_DRIVEINFO pDriveInfoTemp;
  158. if (NULL == (pDriveInfoTemp = (PIU_DRIVEINFO) HeapReAlloc(GetProcessHeap(), 0, *ppDriveInfo, ((*pdwNumDrives)+1) * sizeof(IU_DRIVEINFO))))
  159. {
  160. LOG_Error(_T("E_OUTOFMEMORY"));
  161. SetHrAndGotoCleanUp(E_OUTOFMEMORY);
  162. // Note: *ppDriveInfo still points to previously allocated memory
  163. }
  164. *ppDriveInfo = pDriveInfoTemp; // in case it was moved
  165. }
  166. //
  167. // First copy the drive letter
  168. //
  169. lstrcpyn(((&(*ppDriveInfo)[*pdwNumDrives]))->szDriveStr, pszRootPathName, 4);
  170. //
  171. // Next copy the bytes, but truncate to MAXLONG
  172. //
  173. ((&(*ppDriveInfo)[*pdwNumDrives]))->iKBytes = (i64FreeBytesAvailable.QuadPart > 0x000000007FFFFFFF) ? MAXLONG : (INT) i64FreeBytesAvailable.QuadPart;
  174. //
  175. // increment drive count
  176. //
  177. (*pdwNumDrives)++;
  178. }
  179. }
  180. }
  181. hr = S_OK;
  182. CleanUp:
  183. SafeHeapFree(pszDriveStrBuffer);
  184. if (FAILED(hr))
  185. {
  186. SafeHeapFree(*ppDriveInfo);
  187. *pdwNumDrives = 0;
  188. }
  189. return hr;
  190. }
  191. //
  192. // Code adapted from MSDN SearchTokenGroupsForSID since CheckTokenMembership is Win2K only
  193. //
  194. BOOL IsAdministrator(void)
  195. {
  196. LOG_Block("IsAdministrator");
  197. return (GetLogonGroupInfo() & IU_SECURITY_MASK_ADMINS);
  198. }
  199. DWORD GetLogonGroupInfo(void)
  200. {
  201. DWORD dwRet = 0x0;
  202. LOG_Block("GetLogonGroupInfo");
  203. DWORD dwSize = 0;
  204. DWORD i = 0;
  205. HANDLE hToken = INVALID_HANDLE_VALUE;
  206. PTOKEN_GROUPS pGroupInfo = NULL;
  207. PSID pAdminSID = NULL, pPowerUsrSID = NULL;
  208. SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY;
  209. HRESULT hr; // so we can use CleanUpXxxxx macros
  210. OSVERSIONINFO osvi;
  211. osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  212. if (GetVersionEx(&osvi))
  213. {
  214. if (VER_PLATFORM_WIN32_NT != osvi.dwPlatformId)
  215. {
  216. LOG_Driver(_T("Platform isn't VER_PLATFORM_WIN32_NT - returning TRUE by default"));
  217. dwRet = IU_SECURITY_MASK_ADMINS | IU_SECURITY_MAST_POWERUSERS;
  218. LOG_Out(_T("Non NT system, return TRUE for all groups"));
  219. goto CleanUp;
  220. }
  221. }
  222. else
  223. {
  224. LOG_Error(_T("GetVersionEx:"));
  225. Win32MsgSetHrGotoCleanup(GetLastError());
  226. }
  227. //
  228. // Open a handle to the access token for the calling process.
  229. //
  230. if (!OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &hToken ))
  231. {
  232. LOG_Error(_T("OpenProcessToken:"));
  233. Win32MsgSetHrGotoCleanup(GetLastError());
  234. }
  235. // Call GetTokenInformation to get the buffer size.
  236. if (!GetTokenInformation(hToken, TokenGroups, NULL, dwSize, &dwSize))
  237. {
  238. DWORD dwResult = GetLastError();
  239. if( dwResult != ERROR_INSUFFICIENT_BUFFER )
  240. {
  241. LOG_Error(_T("GetTokenInformation:"));
  242. Win32MsgSetHrGotoCleanup(dwResult);
  243. }
  244. }
  245. // Allocate the buffer.
  246. if (NULL == (pGroupInfo = (PTOKEN_GROUPS) HeapAlloc(GetProcessHeap(), 0, dwSize)))
  247. {
  248. LOG_Error(_T("HeapAlloc"));
  249. goto CleanUp;
  250. }
  251. // Call GetTokenInformation again to get the group information.
  252. if (! GetTokenInformation(hToken, TokenGroups, pGroupInfo,
  253. dwSize, &dwSize ) )
  254. {
  255. LOG_Error(_T("GetTokenInformation:"));
  256. Win32MsgSetHrGotoCleanup(GetLastError());
  257. }
  258. // Create a SID for the BUILTIN\Administrators group.
  259. if (! AllocateAndInitializeSid( &SIDAuth, 2,
  260. SECURITY_BUILTIN_DOMAIN_RID,
  261. DOMAIN_ALIAS_RID_ADMINS,
  262. 0, 0, 0, 0, 0, 0,
  263. &pAdminSID) )
  264. {
  265. LOG_Error(_T("AllocateAndInitializeSid:"));
  266. Win32MsgSetHrGotoCleanup(GetLastError());
  267. }
  268. if (! AllocateAndInitializeSid( &SIDAuth, 2,
  269. SECURITY_BUILTIN_DOMAIN_RID,
  270. DOMAIN_ALIAS_RID_POWER_USERS,
  271. 0, 0, 0, 0, 0, 0,
  272. &pPowerUsrSID) )
  273. {
  274. LOG_Error(_T("AllocateAndInitializeSid:"));
  275. Win32MsgSetHrGotoCleanup(GetLastError());
  276. }
  277. // Loop through the group SIDs looking for the administrator SID.
  278. for(i = 0; i < pGroupInfo->GroupCount; i++)
  279. {
  280. if (EqualSid(pAdminSID, pGroupInfo->Groups[i].Sid) &&
  281. (pGroupInfo->Groups[i].Attributes & SE_GROUP_ENABLED))
  282. {
  283. dwRet |= IU_SECURITY_MASK_ADMINS;
  284. }
  285. if (EqualSid(pPowerUsrSID, pGroupInfo->Groups[i].Sid) &&
  286. (pGroupInfo->Groups[i].Attributes & SE_GROUP_ENABLED))
  287. {
  288. dwRet |= IU_SECURITY_MAST_POWERUSERS;
  289. }
  290. }
  291. CleanUp:
  292. if (pAdminSID)
  293. {
  294. FreeSid(pAdminSID);
  295. }
  296. if (pPowerUsrSID)
  297. {
  298. FreeSid(pPowerUsrSID);
  299. }
  300. SafeHeapFree(pGroupInfo);
  301. if (INVALID_HANDLE_VALUE != hToken)
  302. {
  303. CloseHandle(hToken);
  304. }
  305. LOG_Out(_T("Return 0x%08x"), dwRet);
  306. return dwRet;
  307. }
  308. // ----------------------------------------------------------------------------------
  309. //
  310. // Returns:
  311. // 1 If the NoWindowsUpdate value exists and is != 0 under
  312. // HKEY_CURRENT_USER for NT or HKEY_LOCAL_MACHINE for Win9x.
  313. // 0 If the NoWindowsUpdate value exists and is zero.
  314. // -1 If the NoWindowsUpdate value doesn't exist.
  315. //
  316. // ----------------------------------------------------------------------------------
  317. int IsWindowsUpdateDisabled(void)
  318. {
  319. LOG_Block("IsWindowsUpdateDisabled");
  320. int nRet = -1;
  321. HKEY hKey;
  322. DWORD dwDisabled;
  323. DWORD dwSize = sizeof(dwDisabled);
  324. DWORD dwType;
  325. HKEY hkeyRoot;
  326. OSVERSIONINFO versionInformation;
  327. versionInformation.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  328. GetVersionEx(&versionInformation);
  329. if (versionInformation.dwPlatformId == VER_PLATFORM_WIN32_NT)
  330. {
  331. hkeyRoot = HKEY_CURRENT_USER;
  332. }
  333. else
  334. {
  335. hkeyRoot = HKEY_LOCAL_MACHINE;
  336. }
  337. if ( RegOpenKeyEx( hkeyRoot,
  338. REGPATH_EXPLORER,
  339. NULL,
  340. KEY_QUERY_VALUE,
  341. &hKey) == ERROR_SUCCESS )
  342. {
  343. if ( RegQueryValueEx(hKey,
  344. REGKEY_WINUPD_DISABLED,
  345. NULL,
  346. &dwType,
  347. (LPBYTE)&dwDisabled,
  348. &dwSize) == ERROR_SUCCESS )
  349. {
  350. if ( (dwType == REG_DWORD) && (dwDisabled == 0) )
  351. {
  352. nRet = 0;
  353. }
  354. else
  355. {
  356. nRet = 1;
  357. }
  358. }
  359. RegCloseKey(hKey);
  360. }
  361. LOG_Out(_T("Return: %d"), nRet);
  362. return nRet;
  363. }
  364. // ----------------------------------------------------------------------------------
  365. //
  366. // Returns:
  367. // 1 If the DisableWindowsUpdateAccess value exists and is != 0 under
  368. // HKEY_CURRENT_USER for NT or HKEY_LOCAL_MACHINE for Win9x.
  369. // 0 If the DisableWindowsUpdateAccess value exists and is zero.
  370. // -1 If the DisableWindowsUpdateAccess value doesn't exist.
  371. //
  372. // ----------------------------------------------------------------------------------
  373. int IsWindowsUpdateUserAccessDisabled(void)
  374. {
  375. LOG_Block("IsWindowsUpdateUserAccessDisabled");
  376. int nRet = -1;
  377. HKEY hKey;
  378. DWORD dwDisabled;
  379. DWORD dwSize = sizeof(dwDisabled);
  380. DWORD dwType;
  381. HKEY hkeyRoot;
  382. OSVERSIONINFO versionInformation;
  383. versionInformation.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  384. GetVersionEx(&versionInformation);
  385. if (versionInformation.dwPlatformId == VER_PLATFORM_WIN32_NT)
  386. {
  387. hkeyRoot = HKEY_CURRENT_USER;
  388. }
  389. else
  390. {
  391. hkeyRoot = HKEY_LOCAL_MACHINE;
  392. }
  393. if ( RegOpenKeyEx( hkeyRoot,
  394. REGPATH_POLICY_USERACCESS_DISABLED,
  395. NULL,
  396. KEY_QUERY_VALUE,
  397. &hKey) == ERROR_SUCCESS )
  398. {
  399. if ( RegQueryValueEx(hKey,
  400. REGKEY_WU_USERACCESS_DISABLED,
  401. NULL,
  402. &dwType,
  403. (LPBYTE)&dwDisabled,
  404. &dwSize) == ERROR_SUCCESS )
  405. {
  406. if ( (dwType == REG_DWORD) && (dwDisabled == 0) )
  407. {
  408. nRet = 0;
  409. }
  410. else
  411. {
  412. nRet = 1;
  413. }
  414. }
  415. RegCloseKey(hKey);
  416. }
  417. LOG_Out(_T("Return: %d"), nRet);
  418. if (1 == nRet)
  419. {
  420. LogMessage("Access to Windows Update has been disabled by administrative policy");
  421. }
  422. return nRet;
  423. }
  424. //
  425. // Returns 1 for enabled, 0 for disabled, and -1 for unknown/default (registry doesn't exist)
  426. //
  427. int IsAutoUpdateEnabled(void)
  428. {
  429. LOG_Block("IsAutoUpdateEnabled");
  430. HKEY hSubKey;
  431. DWORD dwType;
  432. ULONG nLen;
  433. DWORD dwAUOptions;
  434. int nRet = -1;
  435. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGPATH_AU, 0, KEY_READ, &hSubKey))
  436. {
  437. nLen = sizeof(dwAUOptions);
  438. if (ERROR_SUCCESS == RegQueryValueEx(hSubKey, REGKEY_AU_OPTIONS, NULL, &dwType, (LPBYTE)&dwAUOptions, &nLen))
  439. {
  440. //
  441. // 1 is disabled, 2 & 3 are enabled
  442. //
  443. nRet = (1 == dwAUOptions ? 0 : 1);
  444. }
  445. RegCloseKey(hSubKey);
  446. }
  447. else
  448. {
  449. LOG_Error(_T("RegOpenKeyEx failed - returning -1"));
  450. }
  451. return nRet;
  452. }