Hello,
I wrote a similar post earlier and someone asked me to produce code. By the
time I got back to it though my original post disappeared. So I am
reposting it.
To make a long story short I do a connection to Wmi via COM. I am reading
network card data. When I retrieve the data after a query it is stored in a
VARIANT. Well, when I iterate through the Variant/query results I
eventually get error: "Access violation at address .... Read of address
0000ffff". I can't seem to figure out the problem even though the code
makes it through 1 of 8 network cards(some virtual) on my system. Here is
the code originally requested. But beaware it needs the "wbemuuid.lib" and
"Wbemidl.h" files to work. I can send them via E-mail in zipped format if
requested.
******************************H FILE***************************************
//--------------------------------------------------------------------------
-
#ifndef Unit1H
#define Unit1H
//--------------------------------------------------------------------------
-
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include "Wbemidl.h"
//--------------------------------------------------------------------------
-
class TForm1 : public TForm
{
__published: // IDE-managed Components
TButton *Button1;
TMemo *Memo1;
TButton *Button2;
TEdit *Edit_wmi_query;
TEdit *Edit_wmi_root;
void __fastcall Button1Click(TObject *Sender);
void __fastcall FormClose(TObject *Sender, TCloseAction &Action);
void __fastcall Button2Click(TObject *Sender);
private: // User declarations
HRESULT hres;
IWbemServices *pSvc;// = NULL;
IWbemLocator *pLoc;// = NULL;
IEnumWbemClassObject* pEnumerator;
IWbemClassObject *pclsObj;
TStringList *FieldList;
void __fastcall InitializeCOM(void);
void __fastcall InitializeCOMSecurity(void);
void __fastcall InitializeCOMLocator(void);
void __fastcall ConnectToWmiRoot(AnsiString Path);
void __fastcall SetCOMSecurity(void);
void __fastcall ExecuteCOMQuery(AnsiString Query);
void __fastcall RetrieveCOMQueryData(void);
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//--------------------------------------------------------------------------
-
extern PACKAGE TForm1 *Form1;
//--------------------------------------------------------------------------
-
#endif
******************************CPP
FILE***************************************
#include <vcl.h>
#pragma hdrstop
#include <comobj.hpp>
#include "Unit1.h"
# pragma comment(lib, "wbemuuid.lib")
//--------------------------------------------------------------------------
-
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//--------------------------------------------------------------------------
-
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
CoInitFlags=COINIT_MULTITHREADED;
FieldList = new TStringList;
}
//--------------------------------------------------------------------------
-
void __fastcall TForm1::Button1Click(TObject *Sender)
{
InitializeCOM();
InitializeCOMSecurity();
InitializeCOMLocator();
ConnectToWmiRoot(Edit_wmi_root->Text);
SetCOMSecurity();
}
//--------------------------------------------------------------------------
-
void __fastcall TForm1::Button2Click(TObject *Sender)
{
Form1->Memo1->Lines->Add(" ");
Form1->Memo1->Lines->Add("----------------------------------------------");
ExecuteCOMQuery(Edit_wmi_query->Text);
RetrieveCOMQueryData();
}
//--------------------------------------------------------------------------
-
void __fastcall TForm1::InitializeCOM(void)
{
// Step 1: --------------------------------------------------
// Initialize COM. ------------------------------------------
Form1->Memo1->Lines->Add("Initializing COM Library.....");
HRESULT hres;
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hres))
{
Form1->Memo1->Lines->Add("Failed to initialize COM library. Error
code = 0x");
// << hex << hres);// << endl;
return; // Program has failed.
}
Form1->Memo1->Lines->Add("Initialized COM Library");
}
//--------------------------------------------------------------------------
-
void __fastcall TForm1::InitializeCOMSecurity(void)
{
// 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 ------------------------
Form1->Memo1->Lines->Add("Initializing Security.....");
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))
{
Form1->Memo1->Lines->Add("Failed to initialize security. Error code
= 0x");
// << hex << hres << endl;
CoUninitialize();
return; // Program has failed.
}
Form1->Memo1->Lines->Add("Initialized Security.....");
}
//--------------------------------------------------------------------------
-
void __fastcall TForm1::InitializeCOMLocator(void)
{
// Step 3: ---------------------------------------------------
// Obtain the initial locator to WMI -------------------------
Form1->Memo1->Lines->Add("Obtaining IWbemLocator object.....");
// IWbemLocator *pLoc = NULL;
hres = CoCreateInstance(
CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID *) &pLoc);
if (FAILED(hres))
{
Form1->Memo1->Lines->Add("Failed to create IWbemLocator object.");
CoUninitialize();
return; // Program has failed.
}
Form1->Memo1->Lines->Add("Obtained IWbemLocator object.....");
}
//--------------------------------------------------------------------------
-
void __fastcall TForm1::ConnectToWmiRoot(AnsiString Path)
{
Form1->Memo1->Lines->Add("Connecting to " + Path + " WMI namespace");
// Step 4: -----------------------------------------------------
// Connect to WMI through the IWbemLocator::ConnectServer method
// Connect to the root\cimv2 namespace with
// the current user and obtain pointer pSvc
// to make IWbemServices calls.
hres = pLoc->ConnectServer(
WideString(L"ROOT\\CIMV2"), // 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
&pSvc // pointer to IWbemServices proxy
);
if (FAILED(hres))
{
Form1->Memo1->Lines->Add("Could not connect. Error code = 0x");
pLoc->Release();
CoUninitialize();
return; // Program has failed.
}
Form1->Memo1->Lines->Add("Connected to ROOT\\CIMV2 WMI namespace");
}
//--------------------------------------------------------------------------
-
void __fastcall TForm1::SetCOMSecurity(void)
{
// Step 5: --------------------------------------------------
// Set security levels on the proxy -------------------------
Form1->Memo1->Lines->Add("Setting Security Levels.....");
hres = CoSetProxyBlanket(
pSvc, // 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))
{
Form1->Memo1->Lines->Add("Could not set proxy blanket. Error code =
0x");
pSvc->Release();
pLoc->Release();
CoUninitialize();
return; // Program has failed.
}
Form1->Memo1->Lines->Add("Setted Security Levels.....");
}
//--------------------------------------------------------------------------
-
void __fastcall TForm1::ExecuteCOMQuery(AnsiString Query)
{
// Step 6: --------------------------------------------------
// Use the IWbemServices pointer to make requests of WMI ----
// For example, get the name of the operating system
Form1->Memo1->Lines->Add("Testing.......");
pEnumerator = NULL;
hres = pSvc->ExecQuery(
WideString("WQL"),
WideString(Query),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator);
if (FAILED(hres))
{
Form1->Memo1->Lines->Add("Query for operating system name failed.");
pSvc->Release();
pLoc->Release();
CoUninitialize();
return ; // Program has failed.
}
}
//--------------------------------------------------------------------------
-
void __fastcall TForm1::RetrieveCOMQueryData(void)
{
// Step 7: -------------------------------------------------
// Get the data from the query in step 6 -------------------
ULONG uReturn = 0;
HRESULT hr;
int a = 0;
long Type;
VARIANT vtProp;
VariantInit(&vtProp);
VariantClear(&vtProp);
//Add KNOWN fieldnames from query:
//
msdn.microsoft.com/library/default.asp
i/win32_networkadapter.asp
FieldList->Clear();
FieldList->Add("AdapterType");
FieldList->Add("AutoSense");
FieldList->Add("Availability");
FieldList->Add("Caption");
FieldList->Add("ConfigManagerErrorCode");
FieldList->Add("ConfigManagerUserConfig");
FieldList->Add("CreationClassName");
FieldList->Add("Description");
FieldList->Add("DeviceID");
FieldList->Add("ErrorCleared");
FieldList->Add("ErrorDescription");
FieldList->Add("Index");
FieldList->Add("InstallDate");
FieldList->Add("Installed");
FieldList->Add("LastErrorCode");
FieldList->Add("MACAddress");
FieldList->Add("Manufacturer");
FieldList->Add("MaxNumberControlled");
FieldList->Add("MaxSpeed");
FieldList->Add("Name");
FieldList->Add("NetworkAddresses");
FieldList->Add("PermanentAddress");
FieldList->Add("PNPDeviceID");
FieldList->Add("PowerManagementCapabilities");
FieldList->Add("PowerManagementSupported");
FieldList->Add("ProductName");
FieldList->Add("ServiceName");
FieldList->Add("Speed");
FieldList->Add("Status");
FieldList->Add("StatusInfo");
FieldList->Add("SystemCreationClassName");
FieldList->Add("SystemName");
FieldList->Add("TimeOfLastReset");
while (pEnumerator)
{
Form1->Memo1->Lines->Add(" NEW CARD NEW CARD NEW CARD NEW CARD NEW
CARD NEW CARD ");
hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
if(0 == uReturn)
{
break;
}
a = 0;
while(a < FieldList->Count){
pclsObj->Get(WideString(FieldList->Strings[a]).c_bstr(), 0,
&vtProp, &Type, 0);
//Type is determined by a digit as in:
//
msdn.microsoft.com/library/default.asp
i/cimtype_enumeration.asp
switch (Type ) {
case 8 :
Form1->Memo1->Lines->Add(FieldList->Strings[a]);
Form1->Memo1->Lines->Add(vtProp.bstrVal);
Form1->Memo1->Lines->Add("
...........................");
VariantClear(&vtProp);
break;
}
a++;
}
}
}
//--------------------------------------------------------------------------
-
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
// Cleanup
// ========
delete FieldList;
if(pSvc){pSvc->Release();};
if(pLoc){pLoc->Release();};
if(pEnumerator){pEnumerator->Release();};
if(pclsObj){pclsObj->Release();};
CoUninitialize();
}
//--------------------------------------------------------------------------
-