PageRenderTime 58ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/Visual Studio 2008/CppCheckOSBitness/CppCheckOSBitness.cpp

#
C++ | 406 lines | 224 code | 48 blank | 134 comment | 31 complexity | 5edc4db78f95daf982e5e7c44b3fc3a6 MD5 | raw file
  1. /****************************** Module Header ******************************\
  2. Module Name: CppCheckOSBitness.cpp
  3. Project: CppCheckOSBitness
  4. Copyright (c) Microsoft Corporation.
  5. The code sample demonstrates how to determine whether the operating system
  6. of the current machine or any remote machine is a 64-bit operating system.
  7. This source is subject to the Microsoft Public License.
  8. See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL.
  9. All other rights reserved.
  10. THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
  11. EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
  12. WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
  13. \***************************************************************************/
  14. #include <stdio.h>
  15. #include <windows.h>
  16. #pragma region Is64BitOS (IsWow64Process)
  17. typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
  18. LPFN_ISWOW64PROCESS fnIsWow64Process = NULL;
  19. //
  20. // FUNCTION: SafeIsWow64Process(HANDLE, PBOOL)
  21. //
  22. // PURPOSE: This is a wrapper of the IsWow64Process API. It determines
  23. // whether the specified process is running under WOW64. IsWow64Process
  24. // does not exist prior to Windows XP with SP2 and Window Server 2003 with
  25. // SP1. For compatibility with operating systems that do not support
  26. // IsWow64Process, call GetProcAddress to detect whether IsWow64Process is
  27. /// implemented in Kernel32.dll. If GetProcAddress succeeds, it is safe to
  28. // call IsWow64Process dynamically. Otherwise, WOW64 is not present.
  29. //
  30. // PARAMETERS:
  31. // * hProcess - A handle to the process.
  32. // * Wow64Process - A pointer to a value that is set to TRUE if the process
  33. // is running under WOW64. If the process is running under 32-bit Windows,
  34. // the value is set to FALSE. If the process is a 64-bit application
  35. // running under 64-bit Windows, the value is also set to FALSE.
  36. //
  37. // RETURN VALUE: If the function succeeds, the return value is TRUE.If
  38. // IsWow64Process does not exist in kernel32.dll, or the function fails,
  39. // the return value is FALSE.
  40. //
  41. BOOL WINAPI SafeIsWow64Process(HANDLE hProcess, PBOOL Wow64Process)
  42. {
  43. if (fnIsWow64Process == NULL)
  44. {
  45. // IsWow64Process is not available on all supported versions of
  46. // Windows. Use GetModuleHandle to get a handle to the DLL that
  47. // contains the function, and GetProcAddress to get a pointer to the
  48. // function if available.
  49. HMODULE hModule = GetModuleHandle(L"kernel32.dll");
  50. if (hModule == NULL)
  51. {
  52. return FALSE;
  53. }
  54. fnIsWow64Process = reinterpret_cast<LPFN_ISWOW64PROCESS>(
  55. GetProcAddress(hModule, "IsWow64Process"));
  56. if (fnIsWow64Process == NULL)
  57. {
  58. return FALSE;
  59. }
  60. }
  61. return fnIsWow64Process(hProcess, Wow64Process);
  62. }
  63. //
  64. // FUNCTION: Is64BitOS()
  65. //
  66. // PURPOSE: The function determines whether the current operating system is
  67. // a 64-bit operating system.
  68. //
  69. // RETURN VALUE: The function returns TRUE if the operating system is
  70. // 64-bit; otherwise, it returns FALSE.
  71. //
  72. BOOL Is64BitOS()
  73. {
  74. #if defined(_WIN64)
  75. return TRUE; // 64-bit programs run only on Win64
  76. #elif defined(_WIN32)
  77. // 32-bit programs run on both 32-bit and 64-bit Windows
  78. BOOL f64bitOS = FALSE;
  79. return (SafeIsWow64Process(GetCurrentProcess(), &f64bitOS) && f64bitOS);
  80. #else
  81. return FALSE; // 64-bit Windows does not support Win16
  82. #endif
  83. }
  84. #pragma endregion
  85. #pragma region Is64BitOS (WMI)
  86. #include <wbemidl.h>
  87. #pragma comment(lib, "wbemuuid.lib")
  88. #include <strsafe.h>
  89. #include <comdef.h>
  90. #include <wincred.h>
  91. //
  92. // FUNCTION: Is64BitOS(LPCWSTR, LPCWSTR, LPCWSTR)
  93. //
  94. // PURPOSE: The function determines whether the operating system of the
  95. // current machine of any remote machine is a 64-bit operating system
  96. // through Windows Management Instrumentation (WMI).
  97. //
  98. // PARAMETERS:
  99. // * pszMachineName - the full computer name or IP address of the target
  100. // machine. "." or NULL means the local machine.
  101. // * pszUserName - the user name you need for a connection. A null value
  102. // indicates the current security context. If the user name is from a
  103. // domain other than the current domain, the string should contain the
  104. // domain name and user name, separated by a backslash: string 'username'
  105. // = "DomainName\\UserName".
  106. // * pszPassword - the password for the specified user.
  107. //
  108. // RETURN VALUE: The function returns true if the operating system is
  109. // 64-bit; otherwise, it returns false.
  110. //
  111. // EXCEPTION: If this function fails, it throws a C++ exception which
  112. // contains the HRESULT of the failure. For example,
  113. // WBEM_E_LOCAL_CREDENTIALS (0x80041064) is thrown when user credentials
  114. // (pszUserName, pszPassword) are specified for local connections.
  115. // COR_E_UNAUTHORIZEDACCESS (0x80070005) is thrown because of incorrect
  116. // user name or password.
  117. // RPC_S_SERVER_UNAVAILABLE (0x800706BA) is usually caused by the firewall
  118. // on the target machine that blocks the WMI connection or some network
  119. // problem.
  120. //
  121. // EXAMPLE CALL:
  122. // try
  123. // {
  124. // f64bitOS = Is64BitOS(L".", NULL, NULL);
  125. // wprintf(L"Current OS %s 64-bit.\n",
  126. // f64bitOS ? L"is" : L"is not");
  127. // }
  128. // catch (HRESULT hr)
  129. // {
  130. // wprintf(L"Is64BitOS failed with HRESULT 0x%08lx\n", hr);
  131. // }
  132. //
  133. BOOL Is64BitOS(LPCWSTR pszMachineName, LPCWSTR pszUserName, LPCWSTR pszPassword)
  134. {
  135. BOOL f64bitOS = FALSE;
  136. HRESULT hr = S_OK;
  137. IWbemLocator *pLoc = NULL;
  138. IWbemServices *pSvc = NULL;
  139. IEnumWbemClassObject *pEnumerator = NULL;
  140. // Initialize COM parameters with a call to CoInitializeEx.
  141. hr = CoInitializeEx(0, COINIT_MULTITHREADED);
  142. if (FAILED(hr))
  143. {
  144. throw hr;
  145. }
  146. // Initialize COM process security by calling CoInitializeSecurity.
  147. hr = CoInitializeSecurity(
  148. NULL,
  149. -1, // COM authentication
  150. NULL, // Authentication services
  151. NULL, // Reserved
  152. RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication
  153. RPC_C_IMP_LEVEL_IDENTIFY, // Default Impersonation
  154. NULL, // Authentication info
  155. EOAC_NONE, // Additional capabilities
  156. NULL // Reserved
  157. );
  158. if (FAILED(hr))
  159. {
  160. goto Cleanup;
  161. }
  162. // Obtain the initial locator to WMI by calling CoCreateInstance.
  163. hr = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER,
  164. IID_IWbemLocator, reinterpret_cast<LPVOID *>(&pLoc));
  165. if (FAILED(hr))
  166. {
  167. goto Cleanup;
  168. }
  169. // Connect to WMI through the IWbemLocator::ConnectServer method.
  170. // User credentials cannot be used for local connections.
  171. if (pszMachineName == NULL)
  172. {
  173. pszMachineName = L".";
  174. }
  175. wchar_t szPath[200];
  176. hr = StringCchPrintf(szPath, ARRAYSIZE(szPath), L"\\\\%s\\root\\cimv2",
  177. pszMachineName);
  178. if (FAILED(hr))
  179. {
  180. goto Cleanup;
  181. }
  182. hr = pLoc->ConnectServer(
  183. _bstr_t(szPath), // Path of the WMI namespace
  184. _bstr_t(pszUserName), // User name
  185. _bstr_t(pszPassword), // User password
  186. NULL, // Locale
  187. NULL, // Security flags
  188. NULL, // Authority
  189. NULL, // Context object
  190. &pSvc // IWbemServices proxy
  191. );
  192. if (FAILED(hr))
  193. {
  194. goto Cleanup;
  195. }
  196. // If you plan to connect to the remote with a different user name and
  197. // password than the one you are currently using, build a COAUTHIDENTITY
  198. // struct that can be used for setting security on proxy.
  199. COAUTHIDENTITY *userAcct = NULL;
  200. COAUTHIDENTITY authIdent;
  201. wchar_t szDomain[CREDUI_MAX_USERNAME_LENGTH + 1];
  202. wchar_t szUser[CREDUI_MAX_USERNAME_LENGTH + 1];
  203. if (pszUserName != NULL)
  204. {
  205. ZeroMemory(&authIdent, sizeof(authIdent));
  206. LPCWSTR slash = wcschr(pszUserName, L'\\');
  207. if (slash == NULL)
  208. {
  209. // No domain info is available in the user name.
  210. // Leave authIdent's Domain and DomainLength fields blank.
  211. authIdent.User = (USHORT *)pszUserName;
  212. authIdent.UserLength = wcslen(pszUserName);
  213. }
  214. else
  215. {
  216. StringCchCopy(szUser, CREDUI_MAX_USERNAME_LENGTH + 1, slash + 1);
  217. authIdent.User = (USHORT *)szUser;
  218. authIdent.UserLength = wcslen(szUser);
  219. StringCchCopyN(szDomain, CREDUI_MAX_USERNAME_LENGTH + 1,
  220. pszUserName, slash - pszUserName);
  221. authIdent.Domain = (USHORT *)szDomain;
  222. authIdent.DomainLength = slash - pszUserName;
  223. }
  224. authIdent.Password = (USHORT *)pszPassword;
  225. authIdent.PasswordLength = wcslen(pszPassword);
  226. authIdent.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
  227. userAcct = &authIdent;
  228. }
  229. // Set security levels on the WMI connection.
  230. hr = CoSetProxyBlanket(
  231. pSvc, // Indicates the proxy to set
  232. RPC_C_AUTHN_DEFAULT, // RPC_C_AUTHN_xxx
  233. RPC_C_AUTHZ_DEFAULT, // RPC_C_AUTHZ_xxx
  234. COLE_DEFAULT_PRINCIPAL, // Server principal name
  235. RPC_C_AUTHN_LEVEL_PKT_PRIVACY, // RPC_C_AUTHN_LEVEL_xxx
  236. RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
  237. userAcct, // Client identity
  238. EOAC_NONE // Proxy capabilities
  239. );
  240. if (FAILED(hr))
  241. {
  242. goto Cleanup;
  243. }
  244. // Use the IWbemServices pointer to make requests of WMI. Query
  245. // Win32_Processor.AddressWidth which dicates the current operating mode
  246. // of the processor (on a 32-bit OS, it would be 32; on a 64-bit OS, it
  247. // would be 64).
  248. // Note: Win32_Processor.DataWidth indicates the capability of the
  249. // processor. On a 64-bit processor, it is 64.
  250. // Note: Win32_OperatingSystem.OSArchitecture tells the bitness of OS
  251. // too. On a 32-bit OS, it would be "32-bit". However, it is only
  252. // available on Windows Vista and newer OS.
  253. hr = pSvc->ExecQuery(bstr_t(L"WQL"),
  254. bstr_t(L"SELECT AddressWidth FROM Win32_Processor"),
  255. WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
  256. NULL, &pEnumerator);
  257. if (FAILED(hr))
  258. {
  259. goto Cleanup;
  260. }
  261. // Secure the enumerator proxy.
  262. hr = CoSetProxyBlanket(
  263. pEnumerator, // Indicates the proxy to set
  264. RPC_C_AUTHN_DEFAULT, // RPC_C_AUTHN_xxx
  265. RPC_C_AUTHZ_DEFAULT, // RPC_C_AUTHZ_xxx
  266. COLE_DEFAULT_PRINCIPAL, // Server principal name
  267. RPC_C_AUTHN_LEVEL_PKT_PRIVACY, // RPC_C_AUTHN_LEVEL_xxx
  268. RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
  269. userAcct, // Client identity
  270. EOAC_NONE // Proxy capabilities
  271. );
  272. if (FAILED(hr))
  273. {
  274. goto Cleanup;
  275. }
  276. // Get the data from the above query.
  277. IWbemClassObject *pclsObj = NULL;
  278. ULONG uReturn = 0;
  279. while (pEnumerator)
  280. {
  281. // Get one object.
  282. HRESULT hrTmp = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
  283. if (0 == uReturn)
  284. {
  285. break;
  286. }
  287. VARIANT vtProp;
  288. // Get the value of the AddressWidth property.
  289. hrTmp = pclsObj->Get(L"AddressWidth", 0, &vtProp, 0, 0);
  290. if (SUCCEEDED(hrTmp))
  291. {
  292. if (vtProp.intVal == 64)
  293. {
  294. f64bitOS = TRUE;
  295. }
  296. VariantClear(&vtProp);
  297. }
  298. pclsObj->Release();
  299. pclsObj = NULL;
  300. }
  301. Cleanup:
  302. // Centralized cleanup for all allocated resources.
  303. if (pLoc)
  304. {
  305. pLoc->Release();
  306. pLoc = NULL;
  307. }
  308. if (pSvc)
  309. {
  310. pSvc->Release();
  311. pSvc = NULL;
  312. }
  313. if (pEnumerator)
  314. {
  315. pEnumerator->Release();
  316. pEnumerator = NULL;
  317. }
  318. CoUninitialize();
  319. // Throw the error if something failed in the function.
  320. if (FAILED(hr))
  321. {
  322. throw hr;
  323. }
  324. return f64bitOS;
  325. }
  326. #pragma endregion
  327. int wmain(int argc, wchar_t* argv[])
  328. {
  329. // Solution 1. Is64BitOS (IsWow64Process)
  330. // Determine whether the current operating system is a 64 bit operating
  331. // system.
  332. BOOL f64bitOS = Is64BitOS();
  333. wprintf(L"Current OS is %s64-bit\n", f64bitOS ? L"" : L"not ");
  334. // Solution 2. Is64BitOS (WMI)
  335. // Determine whether the current operating system is a 64 bit operating
  336. // system through WMI. Note: The first solution of using IsWow64Process
  337. // is the preferred way to detect OS bitness of the current system
  338. // because it is much easier and faster. The WMI solution is useful when
  339. // you want to find this information on a remote system.
  340. try
  341. {
  342. // If you want to get the OS bitness information of a remote system,
  343. // configure the system for remote connections of WMI
  344. // (http://msdn.microsoft.com/en-us/library/aa389290.aspx), and
  345. // replace the parameters (L".", NULL, NULL) with the remote computer
  346. // name and credentials for the connection.
  347. f64bitOS = Is64BitOS(L".", NULL, NULL);
  348. wprintf(L"Current OS is %s64-bit\n", f64bitOS ? L"" : L"not ");
  349. }
  350. catch (HRESULT hr)
  351. {
  352. wprintf(L"Is64BitOS failed with HRESULT 0x%08lx\n", hr);
  353. }
  354. return 0;
  355. }