|
|
//==============================================================;
//
// This source code is only intended as a supplement to
// existing Microsoft documentation.
//
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
// PURPOSE.
//
// Copyright (C) 1999 Microsoft Corporation. All Rights Reserved.
//
//
//==============================================================;
#include <stdio.h>
#include "People.h"
#include <commctrl.h>
#include <comdef.h>
#include <windowsx.h>
const GUID CPeoplePoweredVehicle::thisGuid = { 0x2974380d, 0x4c4b, 0x11d2, { 0x89, 0xd8, 0x0, 0x0, 0x21, 0x47, 0x31, 0x28 } };
const GUID CBicycleFolder::thisGuid = { 0xef163732, 0x9353, 0x11d2, { 0x99, 0x67, 0x0, 0x80, 0xc7, 0xdc, 0xb3, 0xdc } }; const GUID CSkateboardFolder::thisGuid = { 0xef163733, 0x9353, 0x11d2, { 0x99, 0x67, 0x0, 0x80, 0xc7, 0xdc, 0xb3, 0xdc } }; const GUID CIceSkateFolder::thisGuid = { 0xf6c660b0, 0x9353, 0x11d2, { 0x99, 0x67, 0x0, 0x80, 0xc7, 0xdc, 0xb3, 0xdc } };
const GUID CBicycle::thisGuid = { 0xef163734, 0x9353, 0x11d2, { 0x99, 0x67, 0x0, 0x80, 0xc7, 0xdc, 0xb3, 0xdc } }; const GUID CSkateboard::thisGuid = { 0xef163735, 0x9353, 0x11d2, { 0x99, 0x67, 0x0, 0x80, 0xc7, 0xdc, 0xb3, 0xdc } }; const GUID CIceSkate::thisGuid = { 0xf6c660b1, 0x9353, 0x11d2, { 0x99, 0x67, 0x0, 0x80, 0xc7, 0xdc, 0xb3, 0xdc } };
#define WM_WMI_CONNECTED WM_APP // only sent to CBicycleFolder::m_connectHwnd
#define WM_REFRESH_EVENT WM_APP+1 // only sent to CBicycleFolder::m_connectHwnd
//==============================================================
//
// CEventSink implementation
//
class CEventSink : public IWbemObjectSink { public: CEventSink(HWND hwnd) : m_hwnd(hwnd){} ~CEventSink(){};
STDMETHOD_(SCODE, Indicate)(long lObjectCount, IWbemClassObject **pObjArray) { // Not actually using the pObjArray. Just need a trigger for the
// refresh.
::SendMessage(m_hwnd, WM_REFRESH_EVENT, 0, 0); return S_OK; }
STDMETHOD_(SCODE, SetStatus)(long lFlags, HRESULT hResult, BSTR strParam, IWbemClassObject *pObjParam) { // SetStatus() may be called to indicate that your query becomes
// invalid or valid again ussually caused by multithreading 'situations'.
return S_OK; }
// IUnknown members
STDMETHODIMP QueryInterface(REFIID riid, LPVOID* ppv) { if(riid == IID_IUnknown || riid == IID_IWbemObjectSink) { *ppv = this;
// you're handing out a copy of yourself so account for it.
AddRef(); return S_OK; } else { return E_NOINTERFACE; } } STDMETHODIMP_(ULONG) AddRef(void) { return InterlockedIncrement(&m_lRef); } STDMETHODIMP_(ULONG) Release(void) { // InterlockedDecrement() helps with thread safety.
int lNewRef = InterlockedDecrement(&m_lRef); // when all the copies are released...
if(lNewRef == 0) { // kill thyself.
delete this; }
return lNewRef; }
private: long m_lRef; HWND m_hwnd; };
//==============================================================
//
// CPeoplePoweredVehicle implementation
//
//
//----------------------------------------------------------
#define TEMP_BUF 255
bool CBicycleFolder::ErrorString(HRESULT hr, TCHAR *errMsg, UINT errSize) { TCHAR szError[TEMP_BUF] = {0}; TCHAR szFacility[TEMP_BUF] = {0}; IWbemStatusCodeText * pStatus = NULL;
// initialize buffers.
memset(errMsg, 0, errSize * sizeof(TCHAR));
HRESULT hr1 = CoInitialize(NULL); SCODE sc1 = CoCreateInstance(CLSID_WbemStatusCodeText, 0, CLSCTX_INPROC_SERVER, IID_IWbemStatusCodeText, (LPVOID *) &pStatus);
// loaded OK?
if(sc1 == S_OK) { BSTR bstr; sc1 = pStatus->GetErrorCodeText(hr, 0, 0, &bstr); if(sc1 == S_OK) { #ifdef UNICODE
wcsncpy(szError, bstr, TEMP_BUF-1); #else
wcstombs(szError, bstr, TEMP_BUF-1); #endif UNICODE
SysFreeString(bstr); bstr = 0; }
sc1 = pStatus->GetFacilityCodeText(hr, 0, 0, &bstr); if(sc1 == S_OK) { #ifdef UNICODE
wcsncpy(szFacility, bstr, TEMP_BUF-1); #else
wcstombs(szFacility, bstr, TEMP_BUF-1); #endif UNICODE
SysFreeString(bstr); bstr = 0; }
// RELEASE
pStatus->Release(); pStatus = NULL; } else { ::MessageBox(NULL, _T("WBEM error features not available. Upgrade WMI to a newer build."), _T("Internal Error"), MB_ICONSTOP|MB_OK); }
// if not msgs returned....
if(_tcslen(szFacility) == 0 || _tcslen(szError) == 0) { // format the error nbr as a reasonable default.
_stprintf(errMsg, _T("Error code: 0x%08X"), hr); } else { // format a readable msg.
_stprintf(errMsg, _T("%s: %s"), szFacility, szError); }
if(hr1 == S_OK) CoUninitialize();
return (SUCCEEDED(sc1) && SUCCEEDED(hr1)); }
CPeoplePoweredVehicle::CPeoplePoweredVehicle() { children[0] = new CBicycleFolder; children[1] = new CSkateboardFolder; children[2] = new CIceSkateFolder; }
CPeoplePoweredVehicle::~CPeoplePoweredVehicle() { for (int n = 0; n < NUMBER_OF_CHILDREN; n++) delete children[n]; }
HRESULT CPeoplePoweredVehicle::OnExpand(IConsoleNameSpace *pConsoleNameSpace, IConsole *pConsole, HSCOPEITEM parent) { SCOPEDATAITEM sdi;
if (!bExpanded) { // create the child nodes, then expand them
for (int n = 0; n < NUMBER_OF_CHILDREN; n++) { ZeroMemory(&sdi, sizeof(SCOPEDATAITEM) ); sdi.mask = SDI_STR | // Displayname is valid
SDI_PARAM | // lParam is valid
SDI_IMAGE | // nImage is valid
SDI_OPENIMAGE | // nOpenImage is valid
SDI_PARENT | // relativeID is valid
SDI_CHILDREN; // cChildren is valid
sdi.relativeID = (HSCOPEITEM)parent; sdi.nImage = children[n]->GetBitmapIndex(); sdi.nOpenImage = INDEX_OPENFOLDER; sdi.displayname = MMC_CALLBACK; sdi.lParam = (LPARAM)children[n]; // The cookie
sdi.cChildren = 0;
HRESULT hr = pConsoleNameSpace->InsertItem( &sdi );
_ASSERT( SUCCEEDED(hr) ); } }
return S_OK; }
CBicycleFolder::CBicycleFolder() : m_connectHwnd(0), m_threadId(0), m_thread(0), m_doWork(0), m_threadCmd(CT_CONNECT), m_running(false), m_ptrReady(0), m_pStream(0), m_realWMI(0), m_pResultData(0), m_pStubSink(0), m_pUnsecApp(0) { WNDCLASS wndClass;
ZeroMemory(&wndClass, sizeof(WNDCLASS));
wndClass.lpfnWndProc = WindowProc; wndClass.lpszClassName = _T("connectthreadwindow"); wndClass.hInstance = g_hinst;
ATOM atom = RegisterClass(&wndClass); m_connectHwnd = CreateWindow( _T("connectthreadwindow"), // pointer to registered class name
NULL, // pointer to window name
0, // window style
0, // horizontal position of window
0, // vertical position of window
0, // window width
0, // window height
NULL, // handle to parent or owner window
NULL, // handle to menu or child-window identifier
g_hinst, // handle to application instance
(void *)this); // pointer to window-creation data
if (m_connectHwnd) SetWindowLong(m_connectHwnd, GWL_USERDATA, (LONG)this);
InitializeCriticalSection(&m_critSect); m_doWork = CreateEvent(NULL, FALSE, FALSE, NULL); m_ptrReady = CreateEvent(NULL, FALSE, FALSE, NULL);
EnterCriticalSection(&m_critSect); // NOTE: I'm connecting real early. You may want to connect from some other place.
m_threadCmd = CT_CONNECT; SetEvent(m_doWork); m_thread = CreateThread(NULL, 0, ThreadProc, (void *)this, 0, &m_threadId);
LeaveCriticalSection(&m_critSect); }
CBicycleFolder::~CBicycleFolder() { EmptyChildren(); if(m_pResultData) { m_pResultData->Release(); m_pResultData = 0; }
if(m_pStubSink) { IWbemServices *service = 0; HRESULT hr = GetPtr(&service); if(SUCCEEDED(hr)) { service->CancelAsyncCall(m_pStubSink); service->Release(); service = 0; } m_pStubSink->Release(); m_pStubSink = NULL; }
if(m_pUnsecApp) { m_pUnsecApp->Release(); m_pUnsecApp = 0; }
StopThread();
if(m_connectHwnd != NULL) DestroyWindow(m_connectHwnd);
UnregisterClass(_T("connectthreadwindow"), NULL); DeleteCriticalSection(&m_critSect); }
void CBicycleFolder::StopThread() { EnterCriticalSection(&m_critSect); m_running = false;
if (m_thread != NULL) { m_threadCmd = CT_EXIT; SetEvent(m_doWork); WaitForSingleObject(m_ptrReady, 10000);
CloseHandle(m_thread);
m_thread = NULL; } LeaveCriticalSection(&m_critSect); }
LRESULT CALLBACK CBicycleFolder::WindowProc( HWND hwnd, // handle to window
UINT uMsg, // message identifier
WPARAM wParam, // first message parameter
LPARAM lParam) // second message parameter
{ CBicycleFolder *pThis = (CBicycleFolder *)GetWindowLong(hwnd, GWL_USERDATA);
switch (uMsg) { case WM_WMI_CONNECTED: if(pThis != NULL) { IWbemServices *service = 0; HRESULT hr = pThis->GetPtr(&service); if(SUCCEEDED(hr)) { pThis->RegisterEventSink(service); pThis->EnumChildren(service);
// m_pResultData gets set when an onShow has happened. If set, the user already wants
// to see equipment but the connection was slower than the UI. Catchup now.
if(pThis->m_pResultData) pThis->DisplayChildren();
// done with the marshaled service ptr.
service->Release(); service = 0; } } else { TCHAR errMsg[255] = {0}; pThis->ErrorString((HRESULT)wParam, errMsg, 255);
MessageBox(hwnd, errMsg, _T("WMI Snapin Sample"), MB_OK|MB_ICONSTOP); }
break;
case WM_REFRESH_EVENT: if(pThis != NULL) { IWbemServices *service = 0; HRESULT hr = pThis->GetPtr(&service); if(SUCCEEDED(hr)) { pThis->EmptyChildren(); pThis->EnumChildren(service); pThis->DisplayChildren();
// done with the marshaled service ptr.
service->Release(); service = 0; } } break;
} //endswitch
return DefWindowProc(hwnd, uMsg, wParam, lParam); }
void CBicycleFolder::RegisterEventSink(IWbemServices *service) { //NOTE: this logic is from the Wmi documentation,
// "Security Considerations with Asynchronous Calls" so you can
// follow along.
// allocate the sink if its not already allocated.
if(m_pStubSink == 0) { CEventSink *pEventSink = 0; IUnknown* pStubUnk = 0;
// create the 'real' sink.
pEventSink = new CEventSink(m_connectHwnd); pEventSink->AddRef();
// create an unsecapp object.
CoCreateInstance(CLSID_UnsecuredApartment, NULL, CLSCTX_LOCAL_SERVER, IID_IUnsecuredApartment, (void**)&m_pUnsecApp);
// give the 'real' sink to the unsecapp to manage. Get a 'pStubUnk' in return.
m_pUnsecApp->CreateObjectStub(pEventSink, &pStubUnk);
// from that pUnk, get a wrapper to your original sink.
pStubUnk->QueryInterface(IID_IWbemObjectSink, (void **)&m_pStubSink); pStubUnk->Release();
// release the 'real' sink cuz m_pStubSink "owns" it now.
long ref = pEventSink->Release(); }
HRESULT hRes = S_OK; BSTR qLang = SysAllocString(L"WQL"); BSTR query = SysAllocString(L"select * from __InstanceCreationEvent where TargetInstance isa \"Bicycle\"");
// execute the query. For *Async, the last parm is a sink object
// that will be sent the resultset instead of returning the normal
// enumerator object.
if(SUCCEEDED(hRes = service->ExecNotificationQueryAsync(qLang, query, 0L, NULL, m_pStubSink))) { OutputDebugString(_T("Executed filter query\n")); } else { OutputDebugString(_T("ExecQuery() failed\n"));
} //endif ExecQuery()
SysFreeString(qLang); SysFreeString(query); }
void CBicycleFolder::EmptyChildren(void) { if(m_pResultData) { HRESULT hr = m_pResultData->DeleteAllRsltItems();
int last = m_children.GetSize(); for (int n = 0; n < last; n++) { if (m_children[n] != NULL) delete m_children[n]; } m_children.RemoveAll(); } }
bool CBicycleFolder::EnumChildren(IWbemServices *service) { IEnumWbemClassObject *pEnumBikes = NULL; HRESULT hr = S_OK;
// get the list of bicycles...
if(SUCCEEDED(hr = service->CreateInstanceEnum((bstr_t)L"Bicycle", WBEM_FLAG_SHALLOW, NULL, &pEnumBikes))) { // NOTE: pBike MUST be set to NULL for Next().
IWbemClassObject *pBike = NULL; CBicycle *pBikeInst = 0;
ULONG uReturned = 1;
while((SUCCEEDED(hr = pEnumBikes->Next(-1, 1, &pBike, &uReturned))) && (uReturned != 0)) { // Add the bike...
pBikeInst = new CBicycle(this, pBike);
m_children.Add(pBikeInst);
// Done with this object. pBikeInst "owns" it now.
if(pBike) { pBike->Release();
// NOTE: pBike MUST be reset to NULL for Next().
pBike = NULL; }
} // endwhile
// Done with this enumerator.
if (pEnumBikes) { pEnumBikes->Release(); pEnumBikes = NULL; } } // endif CreateInstanceEnum()
return SUCCEEDED(hr); }
HRESULT CBicycleFolder::GetPtr(IWbemServices **ptr) { HRESULT hr = E_FAIL; m_threadCmd = CT_GET_PTR; SetEvent(m_doWork); WaitForSingleObject(m_ptrReady, 10000); if(ptr && m_pStream) { *ptr = 0; hr = CoGetInterfaceAndReleaseStream(m_pStream, IID_IWbemServices, (void**)ptr); } return hr; }
DWORD WINAPI CBicycleFolder::ThreadProc(LPVOID lpParameter) { CBicycleFolder *pThis = (CBicycleFolder *)lpParameter; HRESULT hr = S_OK;
CoInitialize(NULL);
while(true) { WaitForSingleObject(pThis->m_doWork, -1);
switch(pThis->m_threadCmd) { case CT_CONNECT: { IWbemLocator *pLocator = 0; HRESULT hr;
// Create an instance of the WbemLocator interface.
hr = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *)&pLocator);
if(SUCCEEDED(hr)) { hr = pLocator->ConnectServer(L"root\\Vehicles",// Network
NULL, // User
NULL, // Password
NULL, // Locale
0, // Security Flags
NULL, // Authority
NULL, // Context
&pThis->m_realWMI); // Namespace
// tell the callback the result of the connection.
if(pThis->m_connectHwnd) PostMessage(pThis->m_connectHwnd, WM_WMI_CONNECTED, hr, 0); } } break;
case CT_GET_PTR: if(pThis->m_realWMI != NULL) { hr = CoMarshalInterThreadInterfaceInStream(IID_IWbemServices, pThis->m_realWMI, &(pThis->m_pStream)); }
SetEvent(pThis->m_ptrReady); break;
case CT_EXIT: if(pThis->m_realWMI != NULL) { pThis->m_realWMI->Release(); pThis->m_realWMI = 0; } SetEvent(pThis->m_ptrReady); return 0; break;
} //endswitch
} //endwhile(true)
return 0; }
HRESULT CBicycleFolder::DisplayChildren(void) { // insert items here
RESULTDATAITEM rdi; HRESULT hr = S_OK; int last = m_children.GetSize(); CBicycle *pBike = 0;
// create the child nodes, then expand them
for (int n = 0; n < last; n++) { pBike = (CBicycle *)m_children[n];
ZeroMemory(&rdi, sizeof(RESULTDATAITEM) ); rdi.mask = RDI_STR | // Displayname is valid
RDI_IMAGE | // nImage is valid
RDI_PARAM;
rdi.nImage = pBike->GetBitmapIndex(); rdi.str = MMC_CALLBACK; rdi.nCol = 0; rdi.lParam = (LPARAM)pBike;
if(m_pResultData) hr = m_pResultData->InsertItem( &rdi );
_ASSERT( SUCCEEDED(hr) ); } return hr; }
HRESULT CBicycleFolder::OnShow(IConsole *pConsole, BOOL bShow, HSCOPEITEM scopeitem) { HRESULT hr = S_OK;
IHeaderCtrl *pHeaderCtrl = NULL;
if (bShow) { hr = pConsole->QueryInterface(IID_IHeaderCtrl, (void **)&pHeaderCtrl); _ASSERT( SUCCEEDED(hr) );
hr = pConsole->QueryInterface(IID_IResultData, (void **)&m_pResultData); _ASSERT( SUCCEEDED(hr) );
// Set the column headers in the results pane
hr = pHeaderCtrl->InsertColumn(0, L"Name", LVCFMT_LEFT, 150); _ASSERT( S_OK == hr );
hr = pHeaderCtrl->InsertColumn(1, L"Owner", LVCFMT_LEFT, 200); _ASSERT( S_OK == hr );
if(m_pResultData) { hr = m_pResultData->DeleteAllRsltItems(); _ASSERT( SUCCEEDED(hr) );
if(!bExpanded) { hr = DisplayChildren(); }
pHeaderCtrl->Release(); } }
return hr; }
CIceSkateFolder::CIceSkateFolder() { for (int n = 0; n < NUMBER_OF_CHILDREN; n++) { children[n] = new CIceSkate(n + 1); } }
CIceSkateFolder::~CIceSkateFolder() { for (int n = 0; n < NUMBER_OF_CHILDREN; n++) if (children[n]) { delete children[n]; } }
HRESULT CIceSkateFolder::OnShow(IConsole *pConsole, BOOL bShow, HSCOPEITEM scopeitem) { HRESULT hr = S_OK;
IHeaderCtrl *pHeaderCtrl = NULL; IResultData *pResultData = NULL;
if (bShow) { hr = pConsole->QueryInterface(IID_IHeaderCtrl, (void **)&pHeaderCtrl); _ASSERT( SUCCEEDED(hr) );
hr = pConsole->QueryInterface(IID_IResultData, (void **)&pResultData); _ASSERT( SUCCEEDED(hr) );
// Set the column headers in the results pane
hr = pHeaderCtrl->InsertColumn( 0, L"Name ", 0, MMCLV_AUTO ); _ASSERT( S_OK == hr );
// insert items here
RESULTDATAITEM rdi;
hr = pResultData->DeleteAllRsltItems(); _ASSERT( SUCCEEDED(hr) );
if (!bExpanded) { // create the child nodes, then expand them
for (int n = 0; n < NUMBER_OF_CHILDREN; n++) { ZeroMemory(&rdi, sizeof(RESULTDATAITEM) ); rdi.mask = RDI_STR | // Displayname is valid
RDI_IMAGE | // nImage is valid
RDI_PARAM;
rdi.nImage = children[n]->GetBitmapIndex(); rdi.str = MMC_CALLBACK; rdi.nCol = 0; rdi.lParam = (LPARAM)children[n];
hr = pResultData->InsertItem( &rdi );
_ASSERT( SUCCEEDED(hr) ); } }
pHeaderCtrl->Release(); pResultData->Release(); }
return hr; }
//================================================
CSkateboardFolder::CSkateboardFolder() { for (int n = 0; n < NUMBER_OF_CHILDREN; n++) { children[n] = new CSkateboard(n + 1); } }
CSkateboardFolder::~CSkateboardFolder() { for (int n = 0; n < NUMBER_OF_CHILDREN; n++) if (children[n]) { delete children[n]; } }
HRESULT CSkateboardFolder::OnShow(IConsole *pConsole, BOOL bShow, HSCOPEITEM scopeitem) { HRESULT hr = S_OK;
IHeaderCtrl *pHeaderCtrl = NULL; IResultData *pResultData = NULL;
if (bShow) { hr = pConsole->QueryInterface(IID_IHeaderCtrl, (void **)&pHeaderCtrl); _ASSERT( SUCCEEDED(hr) );
hr = pConsole->QueryInterface(IID_IResultData, (void **)&pResultData); _ASSERT( SUCCEEDED(hr) );
// Set the column headers in the results pane
hr = pHeaderCtrl->InsertColumn( 0, L"Name ", 0, MMCLV_AUTO ); _ASSERT( S_OK == hr );
// insert items here
RESULTDATAITEM rdi;
hr = pResultData->DeleteAllRsltItems(); _ASSERT( SUCCEEDED(hr) );
if (!bExpanded) { // create the child nodes, then expand them
for (int n = 0; n < NUMBER_OF_CHILDREN; n++) { ZeroMemory(&rdi, sizeof(RESULTDATAITEM) ); rdi.mask = RDI_STR | // Displayname is valid
RDI_IMAGE | // nImage is valid
RDI_PARAM;
rdi.nImage = children[n]->GetBitmapIndex(); rdi.str = MMC_CALLBACK; rdi.nCol = 0; rdi.lParam = (LPARAM)children[n];
hr = pResultData->InsertItem( &rdi );
_ASSERT( SUCCEEDED(hr) ); } }
pHeaderCtrl->Release(); pResultData->Release(); }
return hr; }
//=====================================================
const _TCHAR *CSkateboard::GetDisplayName(int nCol) { static _TCHAR buf[128];
_stprintf(buf, _T("Skateboard #%d"), id);
return buf; }
//=====================================================
const _TCHAR *CIceSkate::GetDisplayName(int nCol) { static _TCHAR buf[128];
_stprintf(buf, _T("Ice Skate #%d"), id);
return buf; }
//========================================
CBicycle::CBicycle(CBicycleFolder *parent, IWbemClassObject *inst) : m_parent(parent), m_inst(inst) { if(m_inst) m_inst->AddRef(); }
// helper values for calling GetDisplayName().
#define NAME_COL 0
#define OWNER_COL 1
#define COLOR_COL 2
#define MATERIAL_COL 3
const _TCHAR *CBicycle::GetDisplayName(int nCol) { static _TCHAR buf[128];
// Get the corresponding property for nCol. This is in-proc local copy
// so its pretty fast even if IWbemServices is a remote connection.
if(m_inst) { VARIANT pVal; WCHAR propName[10] = {0};
VariantInit(&pVal);
switch(nCol) { case 0: wcscpy(propName, L"Name"); break;
case 1: wcscpy(propName, L"Owner"); break;
// these wont be needed by MMC but its makes this routine more useful
// internal to the class.
case 2: wcscpy(propName, L"Color"); break;
case 3: wcscpy(propName, L"Material"); break;
} //endswitch
if(m_inst->Get(propName, 0L, &pVal, NULL, NULL) == S_OK) { bstr_t temp(pVal); _tcscpy(buf, (LPTSTR)temp); }
VariantClear(&pVal); } //endif (m_inst)
return buf; }
bool CBicycle::GetGirls(void) { VARIANT_BOOL retval = VARIANT_FALSE; // Here's how to get/interpret a VT_BOOL property.
if(m_inst) { VARIANT pVal; if(m_inst->Get(L"Girls", 0L, &pVal, NULL, NULL) == S_OK) { retval = V_BOOL(&pVal); }
VariantClear(&pVal); } //endif (m_inst)
return (retval == VARIANT_TRUE); }
void CBicycle::LoadSurfaces(HWND hwndDlg, BYTE iSurface) { HWND hCombo = GetDlgItem(hwndDlg, IDC_PEOPLE_SURFACE); HRESULT hr = E_FAIL; IWbemQualifierSet *qualSet = 0; int selected = 0;
// qualifiers only exist on the class definition. m_inst is a instance.
IWbemClassObject *pClass = 0; IWbemServices *service = 0;
if(SUCCEEDED(m_parent->GetPtr(&service))) { hr = service->GetObject((bstr_t)L"Bicycle", 0,0, &pClass, 0);
if(SUCCEEDED(hr = pClass->GetPropertyQualifierSet((bstr_t)L"Surface", &qualSet))) { VARIANT vList; VariantInit(&vList); if(SUCCEEDED(hr = qualSet->Get((bstr_t)L"Values", 0, &vList, 0))) { SAFEARRAY *pma = V_ARRAY(&vList); long lLowerBound = 0, lUpperBound = 0 ; UINT idx = 0;
SafeArrayGetLBound(pma, 1, &lLowerBound); SafeArrayGetUBound(pma, 1, &lUpperBound);
for(long x = lLowerBound; x <= lUpperBound; x++) { BSTR vSurface;
SafeArrayGetElement(pma, &x, &vSurface); // NOTE: taking advantage of the bstr_t's conversion operators.
// really cleans up the code.
bstr_t temp(vSurface);
UINT idx = ComboBox_AddString(hCombo, (LPTSTR)temp); ComboBox_SetItemData(hCombo, idx, x);
// is this the one we want to select?
if(iSurface == x) { selected = x; }
} //endfor
VariantClear(&vList); ComboBox_SetCurSel(hCombo, selected); }
qualSet->Release(); qualSet = 0; } //endif GetPropertyQualifierSet()
service->Release();
} //endif GetPtr()
}
const TCHAR *CBicycle::ConvertSurfaceValue(BYTE val) { // Convert a enum to a string using the Value{} array.
static TCHAR temp[128] = {0};
return temp; }
HRESULT CBicycle::PutProperty(LPWSTR propName, LPTSTR str) { HRESULT hr = E_FAIL; if(m_inst) { VARIANT pVal; bstr_t temp(str);
VariantInit(&pVal); V_BSTR(&pVal) = temp; V_VT(&pVal) = VT_BSTR;
hr = m_inst->Put(propName, 0L, &pVal, 0);
VariantClear(&pVal); } //endif (m_inst)
return hr; }
HRESULT CBicycle::PutProperty(LPWSTR propName, BYTE val) { HRESULT hr = E_FAIL; if(m_inst) { VARIANT pVal;
VariantInit(&pVal); V_UI1(&pVal) = val; V_VT(&pVal) = VT_UI1;
hr = m_inst->Put(propName, 0L, &pVal, 0);
VariantClear(&pVal); } //endif (m_inst)
return hr; }
HRESULT CBicycle::PutProperty(LPWSTR propName, bool val) { HRESULT hr = E_FAIL; if(m_inst) { VARIANT pVal;
VariantInit(&pVal); V_BOOL(&pVal) = (val?VARIANT_TRUE: VARIANT_FALSE); V_VT(&pVal) = VT_BOOL;
hr = m_inst->Put(propName, 0L, &pVal, 0);
VariantClear(&pVal);
} //endif (m_inst)
return hr; }
// handle anything special when the user clicks Apply or Ok
// on the property sheet. This sample directly accesses the
// operated-on object, so there's nothing special do to...
HRESULT CBicycle::OnPropertyChange() { return S_OK; }
HRESULT CBicycle::OnSelect(IConsole *pConsole, BOOL bScope, BOOL bSelect) { IConsoleVerb *pConsoleVerb;
HRESULT hr = pConsole->QueryConsoleVerb(&pConsoleVerb); _ASSERT(SUCCEEDED(hr));
// can't get to properties (via the standard methods) unless
// we tell MMC to display the Properties menu item and
// toolbar button, this wil give the user a visual cue that
// there's "something" to do
hr = pConsoleVerb->SetVerbState(MMC_VERB_PROPERTIES, ENABLED, TRUE);
pConsoleVerb->Release();
return S_OK; }
// Implement the dialog proc
BOOL CALLBACK CBicycle::DialogProc( HWND hwndDlg, // handle to dialog box
UINT uMsg, // message
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
) { static CBicycle *pBike = NULL;
switch (uMsg) { case WM_INITDIALOG: { // catch the "this" pointer so we can actually operate on the object
pBike = reinterpret_cast<CBicycle *>(reinterpret_cast<PROPSHEETPAGE *>(lParam)->lParam);
SetDlgItemText(hwndDlg, IDC_PEOPLE_NAME, pBike->GetDisplayName(NAME_COL)); SetDlgItemText(hwndDlg, IDC_PEOPLE_COLOR, pBike->GetDisplayName(COLOR_COL)); SetDlgItemText(hwndDlg, IDC_PEOPLE_MATERIAL, pBike->GetDisplayName(MATERIAL_COL)); SetDlgItemText(hwndDlg, IDC_PEOPLE_OWNER, pBike->GetDisplayName(OWNER_COL));
Button_SetCheck(GetDlgItem(hwndDlg, IDC_PEOPLE_GIRLS), (pBike->GetGirls()? BST_CHECKED: BST_UNCHECKED));
VARIANT pVal; VariantInit(&pVal); if(SUCCEEDED(pBike->m_inst->Get((bstr_t)L"Surface", 0L, &pVal, NULL, NULL))) { pBike->m_iSurface = V_UI1(&pVal); pBike->LoadSurfaces(hwndDlg, pBike->m_iSurface); VariantClear(&pVal); }
} break;
case WM_COMMAND: // turn the Apply button on
if (HIWORD(wParam) == EN_CHANGE || HIWORD(wParam) == CBN_SELCHANGE) SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0); break;
case WM_DESTROY: // tell MMC that we're done with the property sheet (we got this
// handle in CreatePropertyPages
MMCFreeNotifyHandle(pBike->m_ppHandle); break;
case WM_NOTIFY: switch(((NMHDR *)lParam)->code) { case PSN_APPLY: { bool changed = false; TCHAR temp[50] = {0}; HRESULT hr = S_OK;
HWND hWnd = GetDlgItem(hwndDlg, IDC_PEOPLE_NAME); if(hWnd && Edit_GetModify(hWnd)) { GetWindowText(hWnd, temp, 50); changed |= SUCCEEDED(pBike->PutProperty(L"Name", temp)); }
hWnd = GetDlgItem(hwndDlg, IDC_PEOPLE_COLOR); if(hWnd && Edit_GetModify(hWnd)) { GetWindowText(hWnd, temp, 50); changed |= SUCCEEDED(pBike->PutProperty(L"Color", temp)); }
hWnd = GetDlgItem(hwndDlg, IDC_PEOPLE_MATERIAL); if(hWnd && Edit_GetModify(hWnd)) { GetWindowText(hWnd, temp, 50); changed |= SUCCEEDED(pBike->PutProperty(L"Material", temp)); }
hWnd = GetDlgItem(hwndDlg, IDC_PEOPLE_OWNER); if(hWnd && Edit_GetModify(hWnd)) { GetWindowText(hWnd, temp, 50); changed |= SUCCEEDED(hr = pBike->PutProperty(L"Owner", temp)); }
hWnd = GetDlgItem(hwndDlg, IDC_PEOPLE_SURFACE);
if(hWnd) { BYTE newValue = ComboBox_GetCurSel(hWnd); if(newValue != pBike->m_iSurface) { changed |= SUCCEEDED(pBike->PutProperty(L"Surface", newValue)); } }
hWnd = GetDlgItem(hwndDlg, IDC_PEOPLE_GIRLS); if(hWnd) { bool checked = (Button_GetState(hWnd) & BST_CHECKED); bool wasChecked = pBike->GetGirls(); // did it change?
if(checked != wasChecked) { changed |= SUCCEEDED(pBike->PutProperty(L"Girls", checked)); } }
// if any property changed, write it back to WMI.
if(changed) { IWbemServices *service = 0; // dialogs run in their own thread so use the marshaling helper
// get a useable IWbemServices ptr.
// NOTE: IWbemClassObjects are in-proc so they DONT need to be
// marshaled.
if(SUCCEEDED(pBike->m_parent->GetPtr(&service))) { service->PutInstance(pBike->m_inst, WBEM_FLAG_CREATE_OR_UPDATE, 0, 0); service->Release(); HRESULT hr = MMCPropertyChangeNotify(pBike->m_ppHandle, (long)pBike); } } } break; } // endswitch (((NMHDR *)lParam)->code)
break;
} // endswitch (uMsg)
return DefWindowProc(hwndDlg, uMsg, wParam, lParam); }
HRESULT CBicycle::HasPropertySheets() { // say "yes" when MMC asks if we have pages
return S_OK; }
HRESULT CBicycle::CreatePropertyPages(IPropertySheetCallback *lpProvider, LONG_PTR handle) { PROPSHEETPAGE psp; HPROPSHEETPAGE hPage = NULL;
// cache this handle so we can call MMCPropertyChangeNotify
m_ppHandle = handle;
// create the property page for this node.
// NOTE: if your node has multiple pages, put the following
// in a loop and create multiple pages calling
// lpProvider->AddPage() for each page.
psp.dwSize = sizeof(PROPSHEETPAGE); psp.dwFlags = PSP_DEFAULT | PSP_USETITLE; psp.hInstance = g_hinst; psp.pszTemplate = MAKEINTRESOURCE(IDD_PROPPAGE_PEOPLE); psp.pfnDlgProc = DialogProc; psp.lParam = reinterpret_cast<LPARAM>(this); psp.pszTitle = MAKEINTRESOURCE(IDS_BIKE_TITLE);
hPage = CreatePropertySheetPage(&psp); _ASSERT(hPage);
return lpProvider->AddPage(hPage); }
HRESULT CBicycle::GetWatermarks(HBITMAP *lphWatermark, HBITMAP *lphHeader, HPALETTE *lphPalette, BOOL *bStretch) { return S_FALSE; }
|