You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
496 lines
15 KiB
496 lines
15 KiB
//==============================================================;
|
|
//
|
|
// 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 "stdafx.h"
|
|
#include <Shlwapi.h>
|
|
#include <Shlobj.H>
|
|
|
|
#include "StatNode.h"
|
|
#include "logsrvc.h"
|
|
|
|
const GUID CStaticNode::thisGuid = { 0x39874fe4, 0x258d, 0x46f2, { 0xb4, 0x42, 0xe, 0xa0, 0xda, 0x2c, 0xbe, 0xf8 } };
|
|
|
|
|
|
//==============================================================
|
|
//
|
|
// CStaticNode implementation
|
|
//
|
|
//
|
|
CStaticNode::CStaticNode()
|
|
{
|
|
children[0] = new CLogService(this);
|
|
}
|
|
|
|
CStaticNode::~CStaticNode()
|
|
{
|
|
//Note that CStaticNode's children are already deleted when the snap-in
|
|
//receives the MMCN_REMOVE_CHILDREN notification.
|
|
}
|
|
|
|
|
|
const _TCHAR *CStaticNode::GetDisplayName(int nCol)
|
|
{
|
|
static _TCHAR szDisplayName[256] = {0};
|
|
LoadString(g_hinst, IDS_SNAPINNAME, szDisplayName, sizeof(szDisplayName));
|
|
|
|
_tcscat(szDisplayName, _T(" ("));
|
|
_tcscat(szDisplayName, snapInData.m_host);
|
|
_tcscat(szDisplayName, _T(")"));
|
|
|
|
return szDisplayName;
|
|
}
|
|
|
|
HRESULT CStaticNode::OnExpand(IConsoleNameSpace2 *pConsoleNameSpace2, IConsole *pConsole, HSCOPEITEM parent)
|
|
{
|
|
SCOPEDATAITEM sdi;
|
|
|
|
//The HSCOPEITEM passed into OnExpand is the handle of our static node, so cache it
|
|
//if it doesn't already exist.
|
|
if (GetHandle() == NULL) {
|
|
SetHandle((HANDLE)parent);
|
|
}
|
|
|
|
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 |
|
|
SDI_CHILDREN;
|
|
|
|
sdi.relativeID = (HSCOPEITEM)parent;
|
|
sdi.nImage = children[n]->GetBitmapIndex();
|
|
sdi.nOpenImage = INDEX_OPENFOLDER;
|
|
sdi.displayname = MMC_TEXTCALLBACK;
|
|
sdi.lParam = (LPARAM)children[n]; // The cookie
|
|
sdi.cChildren = 0; // no child scope items, so remove "+" sign
|
|
|
|
HRESULT hr = pConsoleNameSpace2->InsertItem( &sdi );
|
|
|
|
children[n]->SetHandle((HANDLE)sdi.ID);
|
|
|
|
_ASSERT( SUCCEEDED(hr) );
|
|
}
|
|
}
|
|
|
|
//Set bExpanded flag to TRUE
|
|
bExpanded = TRUE;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT CStaticNode::OnRemoveChildren()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
for (int n = 0; n < NUMBER_OF_CHILDREN; n++)
|
|
if (children[n]) {
|
|
delete children[n];
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CStaticNode::CreatePropertyPages(IPropertySheetCallback *lpProvider, LONG_PTR handle)
|
|
{
|
|
PROPSHEETPAGE psp;
|
|
HPROPSHEETPAGE hPage = NULL;
|
|
|
|
psp.dwSize = sizeof(PROPSHEETPAGE);
|
|
psp.dwFlags = PSP_DEFAULT;
|
|
psp.hInstance = g_hinst;
|
|
psp.pszTemplate = MAKEINTRESOURCE(IDD_CHOOSER_CHOOSE_MACHINE);
|
|
psp.pfnDlgProc = DialogProc;
|
|
psp.lParam = reinterpret_cast<LPARAM>(&snapInData);
|
|
psp.pszTitle = MAKEINTRESOURCE(IDS_SELECT_COMPUTER);
|
|
|
|
hPage = CreatePropertySheetPage(&psp);
|
|
_ASSERT(hPage);
|
|
|
|
return lpProvider->AddPage(hPage);
|
|
}
|
|
|
|
HRESULT CStaticNode::HasPropertySheets()
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CStaticNode::GetWatermarks(HBITMAP *lphWatermark,
|
|
HBITMAP *lphHeader,
|
|
HPALETTE *lphPalette,
|
|
BOOL *bStretch)
|
|
{
|
|
*lphHeader = (HBITMAP)LoadImage(g_hinst, MAKEINTRESOURCE(IDB_HEADER), IMAGE_BITMAP, 0, 0, 0);
|
|
*lphWatermark = (HBITMAP)LoadImage(g_hinst, MAKEINTRESOURCE(IDB_WATERMARK), IMAGE_BITMAP, 0, 0, 0);
|
|
*bStretch = FALSE;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
BOOL CALLBACK CStaticNode::DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
static privateData *pData = NULL;
|
|
static HWND m_hwndCheckboxOverride;
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
pData = reinterpret_cast<privateData *>(reinterpret_cast<PROPSHEETPAGE *>(lParam)->lParam);
|
|
|
|
SendDlgItemMessage(hwndDlg, IDC_CHOOSER_RADIO_LOCAL_MACHINE, BM_SETCHECK, pData->m_fIsRadioLocalMachine, 0L);
|
|
SendDlgItemMessage(hwndDlg, IDC_CHOOSER_RADIO_SPECIFIC_MACHINE, BM_SETCHECK, !pData->m_fIsRadioLocalMachine, 0L);
|
|
|
|
EnableWindow(GetDlgItem(hwndDlg, IDC_CHOOSER_EDIT_MACHINE_NAME), !pData->m_fIsRadioLocalMachine);
|
|
EnableWindow(GetDlgItem(hwndDlg, IDC_CHOOSER_BUTTON_BROWSE_MACHINENAMES), !pData->m_fIsRadioLocalMachine);
|
|
|
|
m_hwndCheckboxOverride = ::GetDlgItem(hwndDlg, IDC_CHOOSER_CHECK_OVERRIDE_MACHINE_NAME);
|
|
|
|
// fill in the supplied machine name (could be us, need to check here first)
|
|
if (*pData->m_host != '\0')
|
|
{
|
|
::SetWindowText(GetDlgItem(hwndDlg, IDC_CHOOSER_EDIT_MACHINE_NAME), pData->m_host);
|
|
::SendMessage(GetDlgItem(hwndDlg, IDC_CHOOSER_RADIO_SPECIFIC_MACHINE), BM_CLICK, 0, 0);
|
|
}
|
|
|
|
|
|
return TRUE;
|
|
|
|
case WM_COMMAND:
|
|
switch (wParam)
|
|
{
|
|
case IDC_CHOOSER_RADIO_LOCAL_MACHINE:
|
|
pData->m_fIsRadioLocalMachine = TRUE;
|
|
EnableWindow(GetDlgItem(hwndDlg, IDC_CHOOSER_EDIT_MACHINE_NAME), FALSE);
|
|
EnableWindow(GetDlgItem(hwndDlg, IDC_CHOOSER_BUTTON_BROWSE_MACHINENAMES), FALSE);
|
|
break;
|
|
|
|
case IDC_CHOOSER_RADIO_SPECIFIC_MACHINE:
|
|
pData->m_fIsRadioLocalMachine = FALSE;
|
|
EnableWindow(GetDlgItem(hwndDlg, IDC_CHOOSER_EDIT_MACHINE_NAME), TRUE);
|
|
EnableWindow(GetDlgItem(hwndDlg, IDC_CHOOSER_BUTTON_BROWSE_MACHINENAMES), TRUE);
|
|
break;
|
|
|
|
case IDC_CHOOSER_BUTTON_BROWSE_MACHINENAMES:
|
|
{
|
|
// Fall back to IE-style browser
|
|
BROWSEINFO bi;
|
|
LPITEMIDLIST lpItemIdList;
|
|
LPMALLOC lpMalloc;
|
|
|
|
if (SUCCEEDED(SHGetSpecialFolderLocation(hwndDlg, CSIDL_NETWORK, &lpItemIdList)))
|
|
{
|
|
_TCHAR szBrowserCaption[MAX_PATH];
|
|
LoadString(g_hinst, IDS_COMPUTER_BROWSER_CAPTION, szBrowserCaption, sizeof(szBrowserCaption));
|
|
|
|
bi.hwndOwner = hwndDlg;
|
|
bi.pidlRoot = lpItemIdList;
|
|
bi.pszDisplayName = pData->m_host;
|
|
bi.lpszTitle = szBrowserCaption;
|
|
bi.ulFlags = BIF_BROWSEFORCOMPUTER | BIF_EDITBOX | BIF_VALIDATE;
|
|
bi.lpfn = BrowseCallbackProc;
|
|
bi.lParam = NULL;
|
|
bi.iImage = NULL;
|
|
|
|
if (SHBrowseForFolder(&bi) != NULL)
|
|
{
|
|
if (*pData->m_host != '\0')
|
|
{
|
|
::SetWindowText(GetDlgItem(hwndDlg,
|
|
IDC_CHOOSER_EDIT_MACHINE_NAME), pData->m_host);
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(SHGetMalloc(&lpMalloc)))
|
|
{
|
|
lpMalloc->Free(lpItemIdList);
|
|
lpMalloc->Release();
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case IDC_CHOOSER_CHECK_OVERRIDE_MACHINE_NAME:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case WM_NOTIFY:
|
|
switch (((LPNMHDR)lParam)->code) {
|
|
case PSN_SETACTIVE:
|
|
PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_FINISH);
|
|
break;
|
|
|
|
case PSN_WIZFINISH:
|
|
if (pData->m_fIsRadioLocalMachine) {
|
|
// Return string with local computer name to the caller
|
|
GetLocalComputerName(pData->m_host);
|
|
|
|
} else {
|
|
// Get the machine name from the edit window
|
|
GetWindowText(GetDlgItem(hwndDlg, IDC_CHOOSER_EDIT_MACHINE_NAME),
|
|
pData->m_host, sizeof(pData->m_host));
|
|
|
|
//if the user didn't enter anything, we need to
|
|
//get the local computer name first. Since
|
|
//GetLocalComputerName takes care of putting everything
|
|
//into uppercase, we can break from this case
|
|
if (*pData->m_host == '\0')
|
|
{
|
|
GetLocalComputerName(pData->m_host);
|
|
break;
|
|
}
|
|
|
|
//Put machine name in uppercase
|
|
static _TCHAR sztemp[MAX_PATH];
|
|
int n =0;
|
|
while (pData->m_host[n] != '\0')
|
|
{
|
|
sztemp[n] = toupper(pData->m_host[n]);
|
|
n++;
|
|
}
|
|
sztemp[n] = '\0';
|
|
_tcscpy(pData->m_host, sztemp);
|
|
}
|
|
|
|
// Save the override flag if the caller asked for it
|
|
pData->m_fAllowOverrideMachineNameOut =
|
|
SendMessage(m_hwndCheckboxOverride, BM_GETCHECK, 0, 0) == BST_CHECKED ? TRUE : FALSE;
|
|
|
|
break;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
HRESULT CStaticNode::OnAddMenuItems(IContextMenuCallback *pContextMenuCallback, long *pInsertionsAllowed)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CONTEXTMENUITEM menuItemsNew[] =
|
|
{
|
|
{
|
|
L"Select Computer", L"Select new computer to manage",
|
|
IDM_SELECT_COMPUTER, CCM_INSERTIONPOINTID_PRIMARY_TOP, 0, CCM_SPECIAL_DEFAULT_ITEM
|
|
},
|
|
{ NULL, NULL, 0, 0, 0 }
|
|
};
|
|
|
|
// Loop through and add each of the menu items, we
|
|
// want to add to new menu, so see if it is allowed.
|
|
if (*pInsertionsAllowed)
|
|
{
|
|
for (LPCONTEXTMENUITEM m = menuItemsNew; m->strName; m++)
|
|
{
|
|
hr = pContextMenuCallback->AddItem(m);
|
|
|
|
if (FAILED(hr))
|
|
break;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CStaticNode::OnMenuCommand(IConsole *pConsole, IConsoleNameSpace2 *pConsoleNameSpace2, long lCommandID, IDataObject *pDataObject)
|
|
{
|
|
|
|
HRESULT hr = S_FALSE;
|
|
|
|
USES_CONVERSION;
|
|
|
|
switch (lCommandID)
|
|
{
|
|
case IDM_SELECT_COMPUTER:
|
|
|
|
// Fall back to IE-style browser
|
|
BROWSEINFO bi;
|
|
LPITEMIDLIST lpItemIdList;
|
|
LPMALLOC lpMalloc;
|
|
|
|
HWND hWnd;
|
|
hr = pConsole->GetMainWindow(&hWnd);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
|
|
if (SUCCEEDED(SHGetSpecialFolderLocation(hWnd, CSIDL_NETWORK, &lpItemIdList)))
|
|
{
|
|
_TCHAR szBrowserCaption[MAX_PATH];
|
|
_TCHAR szUserSelection[MAX_PATH];
|
|
|
|
LoadString(g_hinst, IDS_COMPUTER_NEW_BROWSER_CAPTION, szBrowserCaption, sizeof(szBrowserCaption));
|
|
|
|
|
|
//Add machine name to browser caption
|
|
_tcscat(szBrowserCaption, _T("\nCurrent computer is "));
|
|
_tcscat(szBrowserCaption, snapInData.m_host);
|
|
|
|
bi.hwndOwner = hWnd;
|
|
bi.pidlRoot = lpItemIdList;
|
|
bi.pszDisplayName = szUserSelection;
|
|
bi.lpszTitle = szBrowserCaption;
|
|
bi.ulFlags = BIF_BROWSEFORCOMPUTER | BIF_EDITBOX | BIF_VALIDATE;
|
|
bi.lpfn = BrowseCallbackProc;
|
|
bi.lParam = NULL;
|
|
bi.iImage = NULL;
|
|
|
|
if (SHBrowseForFolder(&bi) != NULL)
|
|
{
|
|
//Check to see if user chose a new machine. If yes,
|
|
//we'll need to remove the Log Service Node and then
|
|
//reinsert it. As a result, Event Viewer will reinsert
|
|
//its node under the Log Service Node and request the
|
|
//MMC_SPAPIN_MACHINE_NAME clipboard format from us.
|
|
if ( (_tcscmp(szUserSelection, getHost())) )
|
|
{
|
|
//Store the new machine name
|
|
static privateData *pData = NULL;
|
|
pData = &snapInData;
|
|
if (*szUserSelection == 0) //Retrieve local computer name first
|
|
GetLocalComputerName(szUserSelection);
|
|
|
|
_tcscpy(pData->m_host, szUserSelection);
|
|
|
|
//Put machine name in uppercase
|
|
static _TCHAR sztemp[MAX_PATH];
|
|
int n =0;
|
|
while (pData->m_host[n] != '\0')
|
|
{
|
|
sztemp[n] = toupper(pData->m_host[n]);
|
|
n++;
|
|
}
|
|
sztemp[n] = '\0';
|
|
_tcscpy(pData->m_host, sztemp);
|
|
|
|
//Now reinsert the Log Service Node
|
|
hr = ReinsertChildNodes(pConsole, pConsoleNameSpace2);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
if (SUCCEEDED(SHGetMalloc(&lpMalloc)))
|
|
{
|
|
lpMalloc->Free(lpItemIdList);
|
|
lpMalloc->Release();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
int CALLBACK CStaticNode::BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
|
|
{
|
|
|
|
switch (uMsg)
|
|
{
|
|
case BFFM_VALIDATEFAILED:
|
|
|
|
|
|
::MessageBox(hwnd, _T("The selected computer isn't on the network. Try again."), _T("Invalid drive specification"),
|
|
MB_OK | MB_ICONEXCLAMATION | MB_APPLMODAL);
|
|
|
|
return 1; //Don't dismiss the Browse dialog
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
HRESULT CStaticNode::ReinsertChildNodes(IConsole *pConsole, IConsoleNameSpace2 *pConsoleNameSpace2)
|
|
{
|
|
HRESULT hr = S_FALSE;
|
|
USES_CONVERSION;
|
|
|
|
//First we change the display name of the static node
|
|
SCOPEDATAITEM sdi;
|
|
|
|
LPOLESTR wszName = NULL;
|
|
const _TCHAR *pszName = GetDisplayName();
|
|
wszName = (LPOLESTR)T2COLE(pszName);
|
|
|
|
HSCOPEITEM hStaticNode = (HSCOPEITEM)GetHandle();
|
|
|
|
ZeroMemory (&sdi, sizeof(SCOPEDATAITEM));
|
|
sdi.mask = SDI_STR;
|
|
sdi.displayname = wszName;
|
|
sdi.ID = hStaticNode;
|
|
|
|
hr = pConsoleNameSpace2->SetItem(&sdi);
|
|
|
|
if (S_OK != hr)
|
|
return E_FAIL;
|
|
|
|
//check to see if the static node has already been expanded. If it hasn't,
|
|
//there's nothing else we need to do.
|
|
|
|
if (bExpanded)
|
|
{
|
|
//Delete children of static node
|
|
for (int n = 0; n < NUMBER_OF_CHILDREN; n++)
|
|
{
|
|
if (children[n])
|
|
{
|
|
hr = pConsoleNameSpace2->DeleteItem((HSCOPEITEM)(children[n]->GetHandle()), TRUE);
|
|
_ASSERT(SUCCEEDED(hr));
|
|
}
|
|
}
|
|
|
|
//Reinsert the children of the static node. This will
|
|
//result in the Event Viewer snap-in reinserting its own node under ours.
|
|
//First set bExpanded flag to FALSE so that the code that inserts
|
|
//the children is executed.
|
|
bExpanded = FALSE;
|
|
OnExpand(pConsoleNameSpace2, pConsole, hStaticNode);
|
|
|
|
if (S_OK != hr)
|
|
return E_FAIL;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
CStaticNode::GetLocalComputerName( _TCHAR *szComputerName)
|
|
{
|
|
|
|
static _TCHAR szbuf[MAX_PATH];
|
|
static _TCHAR szbuflower[MAX_PATH];
|
|
|
|
DWORD dw = sizeof(szbuf);
|
|
|
|
::GetComputerName(&szbuf[0], &dw);
|
|
|
|
int n =0;
|
|
|
|
//Put each character of machine name in uppercase
|
|
while (szbuf[n] != '\0')
|
|
{
|
|
szbuflower[n] = toupper(szbuf[n]);
|
|
n++;
|
|
}
|
|
szbuflower[n] = '\0';
|
|
|
|
|
|
_tcscpy( szComputerName, _T("\\\\") );
|
|
_tcscat( szComputerName, &szbuflower[0] );
|
|
}
|