Hotfix Check
- Why need this?
在做NB专案的过程中,经验发现微软的hotfix有时真的很有效。有些bug,看了好长时间都没有进展,不经意间发现装上微软的hotfix问题就消失了J。所以在不同部门讨论问题的时候我们通常会新统一check driver的版本以及hotfix,driver的版本我已经写过一篇文章了,这回我介绍如何查看系统的hotfix。
- How to implement?
经过几番对msdn的搜索我发现WMI中有这样一个class Win32_QuickFixEngineering,它包含hotfix相关的信息。我们来看看该class的原型:
class Win32_QuickFixEngineering : CIM_LogicalElement
{
string Caption;
string CSName;
string Description;
string FixComments;
string HotFixID;
datetime InstallDate;
string InstalledBy;
string InstalledOn;
string Name;
string ServicePackInEffect;
string Status;
};
我们可以查询HotFixID&FixComments获得相关的hotfix 信息,该class会有些限制,具体请参考MSDN的说明。下面我将给出获取hotfix sample code:
void CheckHotFix::GetHotFix(OUT std::list<CString>& list)
{
HRESULT hres;
BSTR bstrNameSpace = SysAllocString(L"ROOT//CIMV2");
BSTR bstrWQL = SysAllocString(L"WQL");
BSTR bstrQuery = SysAllocString(L"SELECT * FROM Win32_QuickFixEngineering");
// Step 1: --------------------------------------------------
// Initialize COM. ------------------------------------------
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hres))
{
MessageBox(_T("Failed to initialize COM library./n"),_T("MSG"),MB_ICONINFORMATION);
return; // Program has failed.
}
// Step 2: --------------------------------------------------
// Set general COM security levels --------------------------
// Note: If you are using Windows 2000, you need to specify -
// the default authentication credentials for a user by using
// a SOLE_AUTHENTICATION_LIST structure in the pAuthList ----
// parameter of CoInitializeSecurity ------------------------
hres = CoInitializeSecurity(
NULL,
-1, // COM authentication
NULL, // Authentication services
NULL, // Reserved
RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication
RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation
NULL, // Authentication info
EOAC_NONE, // Additional capabilities
NULL // Reserved
);
if (FAILED(hres))
{
cout << "Failed to initialize security. Error code = 0x"
<< hex << hres << endl;
CoUninitialize();
return 1; // Program has failed.
}
// Step 3: ---------------------------------------------------
// Obtain the initial locator to WMI -------------------------
IWbemLocator *pLoc1 = NULL;
hres = CoCreateInstance(
CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID *) &pLoc1);
if (FAILED(hres))
{
MessageBox(_T("Failed to create IWbemLocator object./n"),_T("MSG"),MB_ICONINFORMATION);
CoUninitialize();
return; // Program has failed.
}
// Step 4: -----------------------------------------------------
// Connect to WMI through the IWbemLocator::ConnectServer method
IWbemServices *pSvc1 = NULL;
// Connect to the root/cimv2 namespace with
// the current user and obtain pointer pSvc
// to make IWbemServices calls.
hres = pLoc1->ConnectServer(
bstrNameSpace, // Object path of WMI namespace
NULL, // User name. NULL = current user
NULL, // User password. NULL = current
0, // Locale. NULL indicates current
NULL, // Security flags.
0, // Authority (e.g. Kerberos)
0, // Context object
&pSvc1 // pointer to IWbemServices proxy
);
if (FAILED(hres))
{
//add by peterhu 2008-02-27
//if failed to give user a message to reffer
MessageBox(_T("Could not connect. Error./n" ),_T("MSG"),MB_ICONINFORMATION);
pLoc1->Release();
CoUninitialize();
return; // Program has failed.
}
// Step 5: --------------------------------------------------
// Set security levels on the proxy -------------------------
hres = CoSetProxyBlanket(
pSvc1, // Indicates the proxy to set
RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx
RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx
NULL, // Server principal name
RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx
RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
NULL, // client identity
EOAC_NONE // proxy capabilities
);
if (FAILED(hres))
{
//add by peterhu 2008-02-27
//if failed to give user a message to reffer
MessageBox(_T("Could not set proxy blanket./n" ),_T("MSG"),MB_ICONINFORMATION);
pSvc1->Release();
pLoc1->Release();
CoUninitialize();
return; // Program has failed.
}
// Step 6: --------------------------------------------------
// Use the IWbemServices pointer to make requests of WMI ----
// For example, get the name of the operating system
IEnumWbemClassObject* pEnumerator = NULL;
hres = pSvc1->ExecQuery(
bstrWQL,
bstrQuery,
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator);
if (FAILED(hres))
{
//add by peterhu 2008-02-27
//if failed to give user a message to reffer
MessageBox(_T("Query for operating system name failed./n" ),_T("MSG"),MB_ICONINFORMATION);
pSvc1->Release();
pLoc1->Release();
CoUninitialize();
return ; // Program has failed.
}
// Step 7: -------------------------------------------------
// Get the data from the query in step 6 -------------------
IWbemClassObject *pclsObj;
ULONG uReturn = 0;
CString csTemp;
int iResult = 0;
while (pEnumerator)
{
HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
&pclsObj, &uReturn);
if(0 == uReturn)
{
break;
}
VARIANT vtProp;
CString strHotfixID;
CString strFixComments;
// Get the value of the HotFixID property
hr = pclsObj->Get(L"HotFixID", 0, &vtProp, 0, 0);
strHotfixID = vtProp.bstrVal;
// Get the value of the FixComments property
hr = pclsObj->Get(L"FixComments",0,&vtProp,0,0);
strFixComments = vtProp.bstrVal;
VariantClear(&vtProp);
strFixComments.ReleaseBuffer();
if(!strFixComments.IsEmpty())
{
strHotfixID.Append(_T("-"));
strHotfixID += strFixComments;
}
strHotfixID.ReleaseBuffer();
if(!strHotfixID.IsEmpty())
{
strHotfixID.Append(_T("/r/n"));
list.push_back(strHotfixID);
}
}
// Cleanup
// ========
pSvc1->Release();
pLoc1->Release();
pEnumerator->Release();
pclsObj->Release();
CoUninitialize();
}
That’s all!
Peter