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