// Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved
// DlgExecQuery.cpp : implementation file
//

#include "precomp.h"
#include "hmmv.h"
#include "hmmvctl.h"
#include <wbemcli.h>
#include "DlgExecQuery.h"
#include "path.h"
#include "hmmverr.h"
#include "htmlhelp.h"
#include "htmtopics.h"
#include "WbemRegistry.h"


#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define QUERY_TIMEOUT 10000


IWbemClassObject *CreateSimpleClass(IWbemServices * pProv, CString *pcsNewClass, CString *pcsParentClass, int &nError, CString &csError );


CTripleStringArray::CTripleStringArray()
{

}


CTripleStringArray::~CTripleStringArray()
{
}


void CTripleStringArray::SetAt(int iElement, LPCTSTR pszQueryName, LPCTSTR pszQueryString, LPCTSTR pszQueryLang)
{
	m_saQueryName.SetAt(iElement, pszQueryName);
	m_saQueryString.SetAt(iElement, pszQueryString);
	m_saQueryLang.SetAt(iElement, pszQueryLang);
}


void CTripleStringArray::GetAt(int iElement, CString& sQueryName, CString& sQueryString, CString& sQueryLang)
{
	sQueryName = m_saQueryName.GetAt(iElement);
	sQueryString = m_saQueryString.GetAt(iElement);
	sQueryLang = m_saQueryLang.GetAt(iElement);
}

void CTripleStringArray::Add(LPCTSTR pszQueryName, LPCTSTR pszQueryString, LPCTSTR pszQueryLang)
{
	m_saQueryName.Add(pszQueryName);
	m_saQueryString.Add(pszQueryString);
	m_saQueryLang.Add(pszQueryLang);
}



int CTripleStringArray::FindQueryName(LPCTSTR pszQueryName)
{
	CString s;
	INT_PTR nElements = GetSize();
	for (int iElement = 0; iElement < nElements; ++iElement) {
		s = GetQueryName(iElement);
		if (s.CompareNoCase(pszQueryName) == 0) {
			return iElement;
		}
	}
	return -1;
}

void CTripleStringArray::RemoveAt(int iElement)
{
	m_saQueryName.RemoveAt(iElement);
	m_saQueryString.RemoveAt(iElement);
	m_saQueryLang.RemoveAt(iElement);
}





/////////////////////////////////////////////////////////////////////////////
// CDlgExecQuery dialog





CDlgExecQuery::CDlgExecQuery(CWBEMViewContainerCtrl* phmmv, CWnd* pParent /*=NULL*/)
: CDialog(CDlgExecQuery::IDD, pParent)
{
	m_phmmv = phmmv;
	m_psel = new CSelection(phmmv);

	SCODE sc = GetQueryList();

	ASSERT(SUCCEEDED(sc));


	//{{AFX_DATA_INIT(CDlgExecQuery)
	//}}AFX_DATA_INIT
}


CDlgExecQuery::~CDlgExecQuery()
{
	delete m_psel;
}

void CDlgExecQuery::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CDlgExecQuery)
	DDX_Control(pDX, IDC_QUERY_LIST, m_lbQueryName);
	DDX_Control(pDX, IDC_EDIT_QUERY_NAME, m_edtQueryName);
	DDX_Control(pDX, IDC_EDIT_QUERY_STRING, m_edtQueryString);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CDlgExecQuery, CDialog)
	//{{AFX_MSG_MAP(CDlgExecQuery)
	ON_BN_CLICKED(IDC_REMOVE_QUERY, OnRemoveQuery)
	ON_BN_CLICKED(IDC_SAVE_QUERY, OnSaveQuery)
	ON_BN_CLICKED(IDC_CLOSE, OnClose)
	ON_LBN_SELCHANGE(IDC_QUERY_LIST, OnSelchangeQueryList)
	ON_LBN_DBLCLK(IDC_QUERY_LIST, OnDblclkQueryList)
	ON_EN_CHANGE(IDC_EDIT_QUERY_NAME, OnChangeEditQueryName)
	ON_EN_CHANGE(IDC_EDIT_QUERY_STRING, OnChangeEditQueryString)
	ON_BN_CLICKED(IDC_HELPBTN, OnHelp)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CDlgExecQuery message handlers


// Use this function to get the query name from the edit controls
// This will trim whitespace before returning.
CString CDlgExecQuery::GetQueryName()
{
	CString sz;
	m_edtQueryName.GetWindowText(sz);
	sz.TrimLeft();
	sz.TrimRight();
	return sz;
}

void CDlgExecQuery::OnOK()
{
	if(GetDlgItem(IDC_SAVE_QUERY)->IsWindowEnabled() && GetQueryName().GetLength() > 0)
	{
		int nRet = MessageBox(_T("Do you want to save the query before executing?"), _T("Save Query Before Execute"), MB_YESNOCANCEL);
		switch(nRet)
		{
		case IDYES:
			OnSaveQuery();
			break;
		case IDNO:
			break;
		case IDCANCEL:
			return;
		}
	}
	// TODO: Add extra validation here
	m_sQueryName = GetQueryName();
	m_edtQueryString.GetWindowText(m_sQueryString);

	m_sQueryString.Replace(_T("\r\n"), _T(" "));
	m_sQueryString.Replace(_T("\n\r"), _T(" "));
	m_sQueryString.Replace(_T("\r"), _T(" "));
	m_sQueryString.Replace(_T("\n"), _T(" "));

	CDialog::OnOK();
}

void CDlgExecQuery::OnCancel()
{
	OnClose();
}


BOOL CDlgExecQuery::OnInitDialog()
{
	CDialog::OnInitDialog();

	// TODO: Add extra initialization here
	INT_PTR nEntries = m_tsa.GetSize();
	for (int iEntry = 0; iEntry < nEntries; ++iEntry) {
		m_lbQueryName.AddString(m_tsa.GetQueryName(iEntry));
	}

	CWnd* pwndButton = GetDlgItem(IDOK);
	pwndButton->EnableWindow(FALSE);

	pwndButton = GetDlgItem(IDC_REMOVE_QUERY);
	pwndButton->EnableWindow(FALSE);


	pwndButton = GetDlgItem(IDC_SAVE_QUERY);
	pwndButton->EnableWindow(FALSE);

	m_edtQueryName.LimitText(63);
	m_edtQueryString.LimitText(1023);

	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}




SCODE CDlgExecQuery::GetQueryList()
{

	SCODE sc;


	// Find all the associations that reference the current object.
	CString sQuery;
	sQuery = _T("select * from Win32_wmiQuery");

	IEnumWbemClassObject* pEnum = NULL;
	CBSTR bsQuery(sQuery);
	CBSTR bsQueryLang(_T("WQL"));

	CString sNameSpace = m_phmmv->GetNameSpace();
	sc = m_psel->SetNamespace(sNameSpace);
	if (FAILED(sc)) {
		ASSERT(FALSE);
		return E_FAIL;
	}





	IWbemServices* psvc = m_psel->GetHmmServices();
	if (psvc == NULL) {
		ASSERT(FALSE);
		return E_FAIL;
	}



	sc = psvc->ExecQuery((BSTR) bsQueryLang, (BSTR) bsQuery, WBEM_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY, NULL, &pEnum);

#if 0
	if (FAILED(sc)) {
		HmmvErrorMsg(IDS_ERR_REFQUERY_FAILED,  sc,   FALSE,  NULL, _T(__FILE__),  __LINE__);
		return;
	}
#endif //0



	COleVariant varQueryName;
	COleVariant varQueryString;
	COleVariant varQueryLang;

	COleVariant varPropnameQueryName;
	COleVariant varPropnameQueryString;
	COleVariant varPropnameQueryLang;

	varPropnameQueryName = _T("key");
	varPropnameQueryString = _T("sQueryString");
	varPropnameQueryLang = _T("sQueryLanguage");

	CString sQueryName;
	CString sQueryString;
	CString sQueryLang;

	CIMTYPE cimtype;

	IWbemClassObject* pco;
	while (TRUE) {

		unsigned long nReturned;
		pco = NULL;
		sc = pEnum->Next(QUERY_TIMEOUT, 1, &pco, &nReturned);

		if (sc==WBEM_S_TIMEDOUT || sc==S_OK) {
			if (nReturned > 0) {
				// Add to list here
				ASSERT(nReturned == 1);

				sc = pco->Get(varPropnameQueryName.bstrVal, 0, &varQueryName, &cimtype, NULL);
				if (FAILED(sc) || (varQueryName.vt!=VT_BSTR)) {
					varQueryName = _T("");
				}

				sc = pco->Get(varPropnameQueryString.bstrVal, 0, &varQueryString, &cimtype, NULL);
				if (FAILED(sc) || (varQueryString.vt != VT_BSTR)) {
					varQueryString = _T("");
				}

				sc = pco->Get(varPropnameQueryLang.bstrVal, 0, &varQueryLang, &cimtype, NULL);
				if (FAILED(sc) || (varQueryLang.vt != VT_BSTR)) {
					varQueryLang = _T("");
				}


				sQueryName = varQueryName.bstrVal;
				sQueryString = varQueryString.bstrVal;
				sQueryLang = varQueryLang.bstrVal;
				m_tsa.Add(sQueryName, sQueryString, sQueryLang);

				pco->Release();
			}

		}
		else {
			break;
		}
	}

	pEnum->Release();
	return S_OK;
}



void CDlgExecQuery::OnSaveQuery()
{
	m_sQueryName = GetQueryName();
	m_edtQueryString.GetWindowText(m_sQueryString);

	int iEntry = m_tsa.FindQueryName(m_sQueryName);

	if(iEntry >= 0)
	{
		CString sOldQueryName, sOldQueryString, sOldQueryLang;
		m_tsa.GetAt(iEntry, sOldQueryName, sOldQueryString, sOldQueryLang);
		if(0 == m_sQueryString.CompareNoCase(sOldQueryString))
		{
			GetDlgItem(IDC_SAVE_QUERY)->EnableWindow(FALSE);
			return;
		}

		if(IDYES != MessageBox(_T("Replace existing saved query?"), _T("Replace Query"), MB_YESNO))
			return;
	}

	SCODE sc;


	BOOL bClassExists = m_psel->ClassExists(_T("Win32_wmiQuery"));
	if (!bClassExists) {
		CreateWmiQueryClass();
	}


	// TODO: Add your control notification handler code here
	BOOL bCreateNewQuery = FALSE;
	if (iEntry >= 0) {
		m_tsa.SetAt(iEntry, m_sQueryName, m_sQueryString, _T("WQL"));


		CString sPath;
//		sPath = _T("ROOT\\CIMV2:Win32_wmiQuery.key=\"");
		sPath = _T("Win32_wmiQuery.key=\"");
		sPath += m_sQueryName;
		sPath += _T("\"");
		sc = m_psel->SelectPath(sPath, TRUE);
	}
	else {
		sc = m_psel->SpawnInstance(_T("Win32_wmiQuery"), TRUE);
		if (SUCCEEDED(sc)) {
			m_tsa.Add(m_sQueryName, m_sQueryString, _T("WQL"));
			bCreateNewQuery = TRUE;
		}
		else {
			return;
		}
	}



	IWbemClassObject* pco = m_psel->GetClassObject();
	ASSERT(pco != NULL);
	if (pco == NULL) {
		return;
	}


	COleVariant varPropnameQueryName;
	COleVariant varPropnameQueryString;
	COleVariant varPropnameQueryLang;

	varPropnameQueryName = _T("key");
	varPropnameQueryString = _T("sQueryString");
	varPropnameQueryLang = _T("sQueryLanguage");

	COleVariant varQueryName;
	COleVariant varQueryString;
	COleVariant varQueryLang;



	varQueryName = m_sQueryName;
	varQueryString = m_sQueryString;
	varQueryLang = _T("WQL");


	sc = pco->Put(varPropnameQueryName.bstrVal, 0, &varQueryName, NULL);
	sc = pco->Put(varPropnameQueryString.bstrVal, 0, &varQueryString, NULL);
	sc = pco->Put(varPropnameQueryLang.bstrVal, 0, &varQueryLang, NULL);
	sc = m_psel->SaveClassObject();


	if (bCreateNewQuery) {
		int iSel = m_lbQueryName.AddString(m_sQueryName);
		m_lbQueryName.SetCurSel(iSel);
		m_lbQueryName.UpdateWindow();
	}
	// Allow the user to remove the selected item.
	CWnd* pwndButton = GetDlgItem(IDC_REMOVE_QUERY);
	pwndButton->EnableWindow(TRUE);
	GetDlgItem(IDC_SAVE_QUERY)->EnableWindow(FALSE);

}


void CDlgExecQuery::OnRemoveQuery()
{
	m_sQueryName = GetQueryName();
	m_edtQueryString.GetWindowText(m_sQueryString);


	SCODE sc;

	// TODO: Add your control notification handler code here
	int iEntry = m_tsa.FindQueryName(m_sQueryName);
	if (iEntry >= 0) {
		m_tsa.SetAt(iEntry, m_sQueryName, m_sQueryString, _T("WQL"));
		CString sPath;
		sPath = _T("Win32_wmiQuery.key=\"");
		sPath += m_sQueryName;
		sPath += _T("\"");

		sc = m_psel->SelectPath(sPath, TRUE);
		if (SUCCEEDED(sc)) {
			sc = m_psel->DeleteInstance();
		}
		m_tsa.RemoveAt(iEntry);

		int iString = m_lbQueryName.FindString(0, m_sQueryName);
		if (iString >= 0) {
			m_lbQueryName.DeleteString(iString);
			int nCount = m_lbQueryName.GetCount();
			if(nCount <= 0)
			{
				GetDlgItem(IDC_REMOVE_QUERY)->EnableWindow(FALSE);
				GetDlgItem(IDOK)->EnableWindow(FALSE);
				m_edtQueryName.SetWindowText(_T(""));
				m_edtQueryString.SetWindowText(_T(""));
			}
			else
			{
				m_lbQueryName.SetCurSel(min(iString, nCount-1));
				OnSelchangeQueryList();
			}

		}

	}
}

void CDlgExecQuery::OnClose()
{
	if(GetDlgItem(IDC_SAVE_QUERY)->IsWindowEnabled() && GetQueryName().GetLength() > 0)
	{
		int nRet = MessageBox(_T("Do you want to save the query before closing?"), _T("Save Query Before Closing"), MB_YESNOCANCEL);
		switch(nRet)
		{
		case IDYES:
			OnSaveQuery();
			break;
		case IDNO:
			break;
		case IDCANCEL:
			return;
		}
	}
	EndDialog(IDCANCEL);
}





BOOL SetProperty(IWbemServices * pProv, IWbemClassObject * pInst,
 LPCTSTR pszProperty, LPCTSTR pszPropertyValue)

{
	SCODE sc;
	CString sProperty(pszProperty);
	CString sPropertyValue(pszPropertyValue);

    VARIANTARG var;
	VariantInit(&var);
    var.vt = VT_BSTR;
    var.bstrVal = sPropertyValue.AllocSysString ( );
    if(var.bstrVal == NULL)
	{
        return WBEM_E_FAILED;
	}

	BSTR bstrTemp = sProperty.AllocSysString ( );
    sc = pInst->Put(bstrTemp ,WBEM_FLAG_USE_AMENDED_QUALIFIERS, &var,NULL);
	::SysFreeString(bstrTemp);
	if (sc != S_OK)
		{
			CString csUserMsg = _T("Cannot Put ");
			csUserMsg += pszProperty;
			HmmvErrorMsgStr(csUserMsg,  sc,   FALSE,  NULL, _T(__FILE__),  __LINE__);

	}


	VariantClear(&var);
	return TRUE;
}




//***************************************************************************
//
// CreateSimpleClass
//
// Purpose: This creates a new class with a class name and parent.
//
//***************************************************************************

IWbemClassObject *CreateSimpleClass
(IWbemServices * pProv, CString *pcsNewClass, CString *pcsParentClass, int &nError,
CString &csError )
{
	IWbemClassObject *pNewClass = NULL;
    IWbemClassObject *pParentClass = NULL;

   	SCODE sc;


	BSTR bstrTemp =  pcsNewClass->AllocSysString();
	sc = pProv -> GetObject
		(bstrTemp ,0,NULL, &pNewClass,NULL);
	::SysFreeString(bstrTemp);

	if (sc == S_OK)
	{
		pNewClass->Release();
		CString csUserMsg =
			_T("An error occured creating the class ") + *pcsNewClass;
		csUserMsg +=
			_T(":  Class ") + *pcsNewClass;
		csUserMsg += _T(" already exists");
		HmmvErrorMsgStr(csUserMsg,  sc,   FALSE,  NULL, _T(__FILE__),  __LINE__);

		return NULL;

	}

	if (pcsParentClass  && (pcsParentClass->GetLength() > 0))
	{
		bstrTemp = pcsParentClass->AllocSysString();
		sc = pProv -> GetObject
			(bstrTemp,0,NULL, &pParentClass,NULL);
		::SysFreeString(bstrTemp);
	}
	else
	{
		sc = pProv -> GetObject
			(NULL,0,NULL, &pParentClass,NULL);
	}

	if (sc != S_OK)
	{
		if (pcsParentClass)
		{
			CString csUserMsg =
				_T("An error occured creating the class ") + *pcsNewClass;
			csUserMsg +=
				_T(":  Cannot create the new class because the parent class object \"") + *pcsParentClass + _T("\" does not exist.");

			HmmvErrorMsgStr(csUserMsg,  sc,   FALSE,  NULL, _T(__FILE__),  __LINE__);

		}
		else
		{
			CString csUserMsg =
				_T("An error occured creating the class ") + *pcsNewClass +  _T(" .");
			HmmvErrorMsgStr(csUserMsg,  sc,   FALSE,  NULL, _T(__FILE__),  __LINE__);


		}
		return NULL;
	}


	if (pcsParentClass)
	{
		sc = pParentClass->SpawnDerivedClass(0,&pNewClass);
	}
	else
	{
		pNewClass = pParentClass;
		pNewClass->AddRef();
		sc = S_OK;
	}

	if (sc != S_OK)
	{
		pParentClass->Release();
		CString csUserMsg =
			_T("An error occured creating the class ") + *pcsNewClass;
		if (pcsParentClass)
		{
			csUserMsg +=
				_T(":  Cannot spawn derived class of ") + *pcsParentClass;
		}
		else
		{
			csUserMsg +=
				_T(":  Cannot spawn derived class");
		}
		HmmvErrorMsgStr(csUserMsg,  S_OK,   FALSE,  NULL, _T(__FILE__),  __LINE__);


		return NULL;
	}

	pParentClass->Release();


	// Init class __Class Property
	SetProperty (pProv, pNewClass, _T("__Class"), (LPCTSTR) *pcsNewClass );
	SetProperty(pProv, pNewClass, _T("key"), (LPCTSTR) _T(""));
	SetProperty(pProv, pNewClass, _T("sQueryString"), _T(""));
	SetProperty(pProv, pNewClass, _T("sQueryLanguage"), _T(""));


	COleVariant varKey;
	varKey = _T("key");

	IWbemQualifierSet* pqs = NULL;
	sc = pNewClass->GetPropertyQualifierSet(varKey.bstrVal, &pqs);
	if (SUCCEEDED(sc)) {
		LONG lFlavor = 0;
		lFlavor |= WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE;
		lFlavor |= WBEM_FLAVOR_FLAG_PROPAGATE_TO_DERIVED_CLASS;

		COleVariant varValue;
		varValue.ChangeType(VT_BOOL);
		varValue.boolVal = VARIANT_TRUE;
		sc = pqs->Put(varKey.bstrVal, &varValue, lFlavor);
		pqs->Release();
	}



	sc = pProv->PutClass(pNewClass,0,NULL,NULL);

	if (sc != S_OK)
	{
		CString csUserMsg=
		_T("An error occured creating the class ") + *pcsNewClass;
		csUserMsg += _T(":  Cannot PutClass on ") + *pcsNewClass;

		HmmvErrorMsgStr(csUserMsg,  sc,   FALSE,  NULL, _T(__FILE__),  __LINE__);

		return NULL;
	}
	else
	{
		pNewClass->Release();
		pNewClass = NULL;
		BSTR bstrTemp = pcsNewClass->AllocSysString();
		sc = pProv -> GetObject
		(bstrTemp,0,NULL,&pNewClass,NULL);
		::SysFreeString(bstrTemp);

		if (sc != S_OK)
		{
			CString csUserMsg=
					_T("An error occured creating the class ") + *pcsNewClass;
			csUserMsg +=
					_T(":  Cannot get the new class.\"") ;


			HmmvErrorMsgStr(csUserMsg,  sc,   FALSE,  NULL, _T(__FILE__),  __LINE__);

			return NULL;
		}
		return pNewClass;
	}
}



SCODE CDlgExecQuery::CreateWmiQueryClass()
{
	IWbemClassObject* pcoClass;

	CString sNewClass(_T("Win32_wmiQuery"));
	CString sError;
	int nError;


	pcoClass = ::CreateSimpleClass(m_psel->GetHmmServices(), &sNewClass, NULL, nError, sError);


	pcoClass->Release();
	return S_OK;
}

void CDlgExecQuery::OnSelchangeQueryList()
{
	int nPos = m_lbQueryName.GetCurSel();
	if (nPos < 0) {
		return;
	}

	CString sKey;
	m_lbQueryName.GetText(nPos, sKey);

	int iQueryName = m_tsa.FindQueryName(sKey);
	if (iQueryName >= 0) {
		m_tsa.GetAt(iQueryName, m_sQueryName, m_sQueryString, m_sQueryLang);
		m_edtQueryName.SetWindowText(m_sQueryName);
		m_edtQueryString.SetWindowText(m_sQueryString);

		CWnd* pwndButton = GetDlgItem(IDOK);
		pwndButton->EnableWindow(TRUE);

		// Allow the user to remove the selected item.
		pwndButton = GetDlgItem(IDC_REMOVE_QUERY);
		pwndButton->EnableWindow(TRUE);

		// The item has not yet been modified, so don't save.
		pwndButton = GetDlgItem(IDC_SAVE_QUERY);
		pwndButton->EnableWindow(FALSE);



	}

}

void CDlgExecQuery::OnDblclkQueryList()
{
	// TODO: Add your control notification handler code here

}

BOOL CDlgExecQuery::HasQuery()
{

	CString s;
	s = GetQueryName();
	if (s.IsEmpty()) {
		return FALSE;
	}

	m_edtQueryString.GetWindowText(s);
	if (s.IsEmpty()) {
		return FALSE;
	}
	return TRUE;
}


void CDlgExecQuery::OnChangeEditQueryName()
{
	// TODO: If this is a RICHEDIT control, the control will not
	// send this notification unless you override the CDialog::OnInitDialog()
	// function and call CRichEditCtrl().SetEventMask()
	// with the ENM_CHANGE flag ORed into the mask.

	// TODO: Add your control notification handler code here

	// Disable Save if there is no name or no query string
	GetDlgItem(IDC_SAVE_QUERY)->EnableWindow(GetQueryName().GetLength() && m_edtQueryString.GetWindowTextLength());

	// Don't let the user remove a query until it is saved
	GetDlgItem(IDC_REMOVE_QUERY)->EnableWindow(FALSE);
}

void CDlgExecQuery::OnChangeEditQueryString()
{
	// TODO: If this is a RICHEDIT control, the control will not
	// send this notification unless you override the CDialog::OnInitDialog()
	// function and call CRichEditCtrl().SetEventMask()
	// with the ENM_CHANGE flag ORed into the mask.

	// Disable Save if there is no name or no query string
	GetDlgItem(IDC_SAVE_QUERY)->EnableWindow(GetQueryName().GetLength() && m_edtQueryString.GetWindowTextLength());

	// Disable Save Execute if there is no query string
	GetDlgItem(IDOK)->EnableWindow(m_edtQueryString.GetWindowTextLength());

	// Don't let the user remove a query until it is saved
	GetDlgItem(IDC_REMOVE_QUERY)->EnableWindow(FALSE);
}

CString GetSDKDirectory()
{
	CString csHmomWorkingDir;
	HKEY hkeyLocalMachine;
	LONG lResult;
	lResult = RegConnectRegistry(NULL, HKEY_LOCAL_MACHINE, &hkeyLocalMachine);
	if (lResult != ERROR_SUCCESS) {
		return "";
	}

	HKEY hkeyHmomCwd;
	lResult = RegOpenKeyEx(
				hkeyLocalMachine,
				_T("SOFTWARE\\Microsoft\\Wbem"),
				0,
				KEY_READ | KEY_QUERY_VALUE,
				&hkeyHmomCwd);

	if (lResult != ERROR_SUCCESS) {
		RegCloseKey(hkeyLocalMachine);
		return "";
	}

	unsigned long lcbValue = 1024;
	LPTSTR pszWorkingDir = csHmomWorkingDir.GetBuffer(lcbValue);

	unsigned long lType;
	lResult = RegQueryValueEx(
				hkeyHmomCwd,
				_T("SDK Directory"),
				NULL,
				&lType,
				(unsigned char*) (void*) pszWorkingDir,
				&lcbValue);


	csHmomWorkingDir.ReleaseBuffer();
	RegCloseKey(hkeyHmomCwd);
	RegCloseKey(hkeyLocalMachine);

	if (lResult != ERROR_SUCCESS)
	{
		csHmomWorkingDir.Empty();
	}

	return csHmomWorkingDir;
}

void CDlgExecQuery::OnHelp()
{
	CString csPath;
	WbemRegString(SDK_HELP, csPath);

	CString csData = idh_wqlquerytool;

	HWND hWnd = NULL;
	try
	{
		HWND hWnd = HtmlHelp(::GetDesktopWindow(),(LPCTSTR) csPath,HH_DISPLAY_TOPIC,(DWORD_PTR) (LPCTSTR) csData);
		if (!hWnd)
			MessageBox(L"Unable to launch the help file", L"Error launching help file.");
	}

	catch( ... )
	{
		// Handle any exceptions here.
		MessageBox(L"Unable to launch the help file", L"Error launching help file.");
	}
}