#include #include #include #include #include #include "objbase.h" #include "Wbemidl.h" #include "wincred.h" extern "C" { UINT g_CIMOSType = 0; UINT g_CIMOSProductSuite = 0; UINT g_CIMProcessorArchitecture = 0; WCHAR g_CIMOSVersion[MAX_PATH]; WCHAR g_CIMOSBuildNumber[MAX_PATH]; WCHAR g_CIMServicePackMajorVersion[MAX_PATH]; WCHAR g_CIMServicePackMinorVersion[MAX_PATH]; BOOL g_CIMAttempted = FALSE; BOOL g_CIMSucceeded = FALSE; HRESULT WINAPI UpdateVersionInfoGlobals(LPCWSTR pwszMachine, LPCWSTR pwszUserName, LPCWSTR pwszPassword); } // // SetSecurity - set the Proxy Blanket on an IUnknown* interface so that it can be used by WMI // cross-machine calls. // // Okay for any of pwszDomainName, pwszUserName or pwszPassword to be NULL. // // deonb 12/20/2001 // HRESULT WINAPI SetSecurity(IN OUT IUnknown* pUnk, IN USHORT* pwszDomainName, IN USHORT* pwszUserName, IN USHORT* pwszPassword) { HRESULT hr = S_OK; COAUTHIDENTITY authident; authident.Domain = pwszDomainName; authident.DomainLength = pwszDomainName ? wcslen(pwszDomainName) : 0; authident.Password = pwszPassword; authident.PasswordLength = pwszPassword ? wcslen(pwszPassword) : 0; authident.User = pwszUserName; authident.UserLength = pwszUserName ? wcslen(pwszUserName) : 0; authident.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; hr = CoSetProxyBlanket(pUnk, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONATE, &authident, EOAC_NONE); return hr; } #define FImplies(a,b) (!(a) || (b)) HRESULT WINAPI UpdateVersionInfoGlobalsFromWMI(LPCWSTR pwszMachine, LPCWSTR pwszUserName, LPCWSTR pwszPassword) { HRESULT hr = S_OK; g_CIMAttempted = TRUE; g_CIMSucceeded = FALSE; hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); if (FAILED(hr) && (RPC_E_CHANGED_MODE != hr)) { return hr; } // Create an instance of the WbemLocator interface. IWbemLocator *pIWbemLocator = NULL; hr = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &pIWbemLocator); if (FAILED(hr)) { return hr; } IWbemServices *pIWbemServices; // If already connected, release m_pIWbemServices. // Using the locator, connect to CIMOM in the given namespace. BSTR pNamespace = NULL; BSTR pDomain = NULL; BSTR pUserName = NULL; BSTR pFQUserName= NULL; BSTR pPassword = NULL; do { WCHAR szPath[MAX_PATH]; wsprintf(szPath, L"\\\\%s\\root\\cimv2", !pwszMachine ? L"." : pwszMachine); pNamespace = SysAllocString(szPath); if ( (szPath) && (!pNamespace) ) { hr = E_OUTOFMEMORY; break; } if (pwszUserName) { WCHAR szUserNameExtract[MAX_PATH]; WCHAR szDomainNameExtract[MAX_PATH]; // Break a domain\username type of username up into a seperate domain and username // It doesn't do this for username@domain format, but it doesn't matter since // the API using this (CoSetProxyBlanket) accepts names in username@domain format DWORD dwErr = CredUIParseUserName(pwszUserName, szUserNameExtract, MAX_PATH, szDomainNameExtract, MAX_PATH); hr = HRESULT_FROM_WIN32(dwErr); if (FAILED(hr)) { break; } pDomain = SysAllocString(szDomainNameExtract); pUserName = SysAllocString(szUserNameExtract); pFQUserName = SysAllocString(pwszUserName); if ( (!FImplies(szDomainNameExtract, pDomain)) || (!FImplies(szUserNameExtract, pUserName)) || (!FImplies(pwszUserName, pFQUserName)) ) { hr = E_OUTOFMEMORY; break; } } pPassword = SysAllocString(pwszPassword); if (!FImplies(pwszPassword, pPassword)) { hr = E_OUTOFMEMORY; break; } } while (FALSE); if (FAILED(hr)) { SysFreeString(pPassword); SysFreeString(pUserName); SysFreeString(pFQUserName); SysFreeString(pDomain); SysFreeString(pNamespace); return hr; } hr = pIWbemLocator->ConnectServer(pNamespace, pFQUserName, // username pPassword, // password 0L, // locale 0L, // securityFlags NULL, // authority (domain for NTLM) NULL, // context &pIWbemServices); if (SUCCEEDED(hr)) { hr = SetSecurity(pIWbemServices, pDomain, pUserName, pPassword); if (SUCCEEDED(hr)) { IEnumWbemClassObject *pEnum = NULL; BSTR bstrWQL = SysAllocString(L"WQL"); BSTR bstrPath = SysAllocString(L"select * from Win32_OperatingSystem"); VARIANT varOSType; VARIANT varOSVersion; VARIANT varOSProductSuite; VARIANT varOSBuildNumber; VARIANT varServicePackMajorVersion; VARIANT varServicePackMinorVersion; VARIANT varArchitecture; hr = pIWbemServices->ExecQuery(bstrWQL, bstrPath, WBEM_FLAG_FORWARD_ONLY, NULL, &pEnum); if (SUCCEEDED(hr)) { hr = SetSecurity(pEnum, pDomain, pUserName, pPassword); } if (SUCCEEDED(hr)) { IWbemClassObject *pNSClass; ULONG uReturned; hr = pEnum->Next(WBEM_INFINITE, 1, &pNSClass, &uReturned ); if (SUCCEEDED(hr)) { if (uReturned) { do { g_CIMSucceeded = TRUE; CIMTYPE ctpeType; hr = pNSClass->Get(L"OSType", NULL, &varOSType, &ctpeType, NULL); if (SUCCEEDED(hr)) { hr = VariantChangeType(&varOSType, &varOSType, 0, VT_UINT); if (SUCCEEDED(hr)) { g_CIMOSType = varOSType.uintVal; } } if (FAILED(hr)) { g_CIMSucceeded = FALSE; break; } hr = pNSClass->Get(L"Version", NULL, &varOSVersion, &ctpeType, NULL); if (SUCCEEDED(hr)) { hr = VariantChangeType(&varOSVersion, &varOSVersion, 0, VT_BSTR); if (SUCCEEDED(hr)) { wcscpy(g_CIMOSVersion, varOSVersion.bstrVal); } } if (FAILED(hr)) { g_CIMSucceeded = FALSE; break; } hr = pNSClass->Get(L"OSProductSuite", NULL, &varOSProductSuite, &ctpeType, NULL); if (SUCCEEDED(hr)) { // // if the return type is VT_NULL, leave g_CIMOSProductSuite value alone (0) if (VT_NULL != varOSProductSuite.vt) { hr = VariantChangeType(&varOSProductSuite, &varOSProductSuite, 0, VT_UINT); if (SUCCEEDED(hr)) { g_CIMOSProductSuite = varOSProductSuite.uintVal; } } } if (FAILED(hr)) { g_CIMSucceeded = FALSE; break; } hr = pNSClass->Get(L"BuildNumber", NULL, &varOSBuildNumber, &ctpeType, NULL); if (SUCCEEDED(hr)) { hr = VariantChangeType(&varOSBuildNumber, &varOSBuildNumber, 0, VT_BSTR); if (SUCCEEDED(hr)) { wcscpy(g_CIMOSBuildNumber, varOSBuildNumber.bstrVal); } } if (FAILED(hr)) { g_CIMSucceeded = FALSE; break; } hr = pNSClass->Get(L"ServicePackMajorVersion", NULL, &varServicePackMajorVersion, &ctpeType, NULL); if (SUCCEEDED(hr)) { hr = VariantChangeType(&varServicePackMajorVersion, &varServicePackMajorVersion, 0, VT_BSTR); if (SUCCEEDED(hr)) { wcscpy(g_CIMServicePackMajorVersion, varServicePackMajorVersion.bstrVal); } } if (FAILED(hr)) { g_CIMSucceeded = FALSE; break; } hr = pNSClass->Get(L"ServicePackMinorVersion", NULL, &varServicePackMinorVersion, &ctpeType, NULL); if (SUCCEEDED(hr)) { hr = VariantChangeType(&varServicePackMinorVersion, &varServicePackMinorVersion, 0, VT_BSTR); if (SUCCEEDED(hr)) { wcscpy(g_CIMServicePackMinorVersion, varServicePackMinorVersion.bstrVal); } } if (FAILED(hr)) { g_CIMSucceeded = FALSE; break; } } while (FALSE); } else { hr = E_UNEXPECTED; } pNSClass->Release(); } pEnum->Release(); } SysFreeString(bstrPath); if (SUCCEEDED(hr)) { bstrPath = SysAllocString(L"select * from Win32_Processor"); hr = pIWbemServices->ExecQuery(bstrWQL, bstrPath, WBEM_FLAG_FORWARD_ONLY, NULL, &pEnum); if (SUCCEEDED(hr)) { hr = SetSecurity(pEnum, pDomain, pUserName, pPassword); } if (SUCCEEDED(hr)) { IWbemClassObject *pNSClass; ULONG uReturned; hr = pEnum->Next(WBEM_INFINITE, 1, &pNSClass, &uReturned ); if (SUCCEEDED(hr)) { if (uReturned) { CIMTYPE ctpeType; hr = pNSClass->Get(L"Architecture", NULL, &varArchitecture, &ctpeType, NULL); if (SUCCEEDED(hr)) { hr = VariantChangeType(&varArchitecture, &varArchitecture, 0, VT_UINT); if (SUCCEEDED(hr)) { g_CIMProcessorArchitecture = varArchitecture.uintVal; } else { g_CIMSucceeded = FALSE; } } else { g_CIMSucceeded = FALSE; } } else { hr = E_UNEXPECTED; } pNSClass->Release(); } pEnum->Release(); } SysFreeString(bstrPath); } SysFreeString(bstrWQL); pIWbemServices->Release(); } //hr = CoSetProxyBlanket(pIWbemServices.., if (SUCCEEDED(hr)) } //hr = pIWbemLocator->ConnectServer.., if (SUCCEEDED(hr)) SysFreeString(pPassword); SysFreeString(pUserName); SysFreeString(pFQUserName); SysFreeString(pDomain); SysFreeString(pNamespace); CoUninitialize(); // Translate any WMI errors into Win32 errors: switch (hr) { case WBEM_E_NOT_FOUND: hr = HRESULT_FROM_WIN32(ERROR_HOST_UNREACHABLE); break; case WBEM_E_ACCESS_DENIED: hr = E_ACCESSDENIED; break; case WBEM_E_PROVIDER_FAILURE: hr = E_FAIL; break; case WBEM_E_TYPE_MISMATCH: case WBEM_E_INVALID_CONTEXT: case WBEM_E_INVALID_PARAMETER: hr = E_INVALIDARG; break; case WBEM_E_OUT_OF_MEMORY: hr = E_OUTOFMEMORY; break; } if ( (hr == S_OK) && (!g_CIMSucceeded) ) { return E_FAIL; } else { return hr; } } HRESULT WINAPI UpdateVersionInfoGlobalsFromLocalMachine() { HRESULT hr = S_OK; BOOL fFailed = FALSE; do { OSVERSIONINFOEX osv; ZeroMemory(&osv, sizeof(OSVERSIONINFOEX)); osv.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); if (!GetVersionEx( reinterpret_cast(&osv))) { fFailed = TRUE; break; } g_CIMOSType = 18; // WINNT g_CIMOSProductSuite = osv.wSuiteMask; #if defined(_X86_) g_CIMProcessorArchitecture = 0; #elif defined(_IA64_) g_CIMProcessorArchitecture = 6; #else fFailed = TRUE; break; #endif wsprintf(g_CIMOSVersion, L"%d.%d.%d", osv.dwMajorVersion, osv.dwMinorVersion, osv.dwBuildNumber); wsprintf(g_CIMOSBuildNumber, L"%d", osv.dwBuildNumber); wsprintf(g_CIMServicePackMajorVersion, L"%d", osv.wServicePackMajor); wsprintf(g_CIMServicePackMinorVersion, L"%d", osv.wServicePackMinor); g_CIMSucceeded = TRUE; g_CIMAttempted = TRUE; } while (FALSE); if (fFailed) { return UpdateVersionInfoGlobalsFromWMI(NULL, NULL, NULL); } return hr; } HRESULT WINAPI UpdateVersionInfoGlobals(LPCWSTR pwszMachine, LPCWSTR pwszUserName, LPCWSTR pwszPassword) { HRESULT hr = S_OK; HRESULT hrWMI = S_OK; if (pwszMachine) { return UpdateVersionInfoGlobalsFromWMI(pwszMachine, pwszUserName, pwszPassword); } else // Resolve locally { hr = UpdateVersionInfoGlobalsFromLocalMachine(); #ifdef DBG UINT CIMOSType = g_CIMOSType; UINT CIMOSProductSuite = g_CIMOSProductSuite; UINT CIMProcessorArchitecture = g_CIMProcessorArchitecture; WCHAR CIMOSVersion[MAX_PATH]; WCHAR CIMOSBuildNumber[MAX_PATH]; WCHAR CIMServicePackMajorVersion[MAX_PATH]; WCHAR CIMServicePackMinorVersion[MAX_PATH]; wcsncpy(CIMOSVersion, g_CIMOSVersion, MAX_PATH); wcsncpy(CIMOSBuildNumber, g_CIMOSBuildNumber, MAX_PATH); wcsncpy(CIMServicePackMajorVersion, g_CIMServicePackMajorVersion, MAX_PATH); wcsncpy(CIMServicePackMinorVersion, g_CIMServicePackMinorVersion, MAX_PATH); hrWMI = UpdateVersionInfoGlobalsFromWMI(pwszMachine, NULL, NULL); if(SUCCEEDED(hr) && SUCCEEDED(hrWMI)) { if ( (CIMOSType != g_CIMOSType) || ( (CIMOSProductSuite & ~VER_SUITE_SINGLEUSERTS) != (g_CIMOSProductSuite & ~VER_SUITE_SINGLEUSERTS) ) || (CIMProcessorArchitecture != g_CIMProcessorArchitecture) || (0 != wcsncmp(CIMOSVersion, g_CIMOSVersion, MAX_PATH)) || (0 != wcsncmp(CIMOSBuildNumber, g_CIMOSBuildNumber, MAX_PATH)) || (0 != wcsncmp(CIMServicePackMajorVersion, g_CIMServicePackMajorVersion, MAX_PATH)) || (0 != wcsncmp(CIMServicePackMinorVersion, g_CIMServicePackMinorVersion, MAX_PATH)) ) { WCHAR szAssertText[4096]; wsprintf(szAssertText, L"NETSH.EXE: ASSERT - mismatch between GetVersionInfoEx and WMI information:\r\n" L"CIMOSType: %x vs. %x\r\n" L"CIMOSProductSuite: %x vs. %x\r\n" L"CIMProcessorArchitecture: %x vs %x\r\n" L"CIMOSVersion: %s vs. %s\r\n" L"CIMOSBuildNumber: %s vs. %s\r\n" L"CIMServicePackMajorVersion: %s vs. %s\r\n" L"CIMServicePackMinorVersion: %s vs. %s\r\n", CIMOSType, g_CIMOSType, CIMOSProductSuite, g_CIMOSProductSuite, CIMProcessorArchitecture, g_CIMProcessorArchitecture, CIMOSVersion, g_CIMOSVersion, CIMOSBuildNumber, g_CIMOSBuildNumber, CIMServicePackMajorVersion, g_CIMServicePackMajorVersion, CIMServicePackMinorVersion, g_CIMServicePackMinorVersion); ASSERTMSG((PCHAR)(szAssertText), FALSE); } } #endif return hr; } }