/////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2000, Microsoft Corp. All rights reserved. // // FILE // // proxynode.cpp // // SYNOPSIS // // Defines the class ProxyNode. // // MODIFICATION HISTORY // // 02/19/2000 Original version. // /////////////////////////////////////////////////////////////////////////////// #include #include #include #include ////////// // From mmcutility.cpp ////////// HRESULT IfServiceInstalled( LPCWSTR lpszMachine, LPCWSTR lpszService, BOOL* pBool ); ////////// // Helper function to get the NT build number of a machine. ////////// LONG GetBuildNumber(LPCWSTR machineName, PLONG buildNum) throw () { const WCHAR KEY[] = L"Software\\Microsoft\\Windows NT\\CurrentVersion"; const WCHAR VALUE[] = L"CurrentBuildNumber"; LONG error; HKEY hklm = HKEY_LOCAL_MACHINE; // Only do a remote connect when machineName is specified. CRegKey remote; if (machineName && machineName[0]) { error = RegConnectRegistryW( machineName, HKEY_LOCAL_MACHINE, &remote.m_hKey ); if (error) { return error; } hklm = remote; } CRegKey currentVersion; error = currentVersion.Open(hklm, KEY, KEY_READ); if (error) { return error; } WCHAR data[16]; DWORD dataLen = sizeof(data); error = currentVersion.QueryValue(data, VALUE, &dataLen); if (error) { return error; } *buildNum = _wtol(data); return NO_ERROR; } inline ProxyNode::Connector::Connector() { } void ProxyNode::Connector::BeginConnect( ProxyNode& owner, SnapInView& view, IDataObject* parentData, HSCOPEITEM parentId ) throw () { node = &owner; nameSpace = view.getNameSpace(); dataObject = parentData; relativeID = parentId; Start(); } LPARAM ProxyNode::Connector::DoWork() throw () { return static_cast(node->connect(dataObject)); } void ProxyNode::Connector::OnComplete(LPARAM result) throw () { node->setConnectResult( nameSpace, relativeID, static_cast(result) ); } ProxyNode::ProxyNode( SnapInView& view, IDataObject* parentData, HSCOPEITEM parentId ) : SnapInPreNamedItem(IDS_PROXY_NODE), state(CONNECTING), title(IDS_PROXY_VIEW_TITLE), body(IDS_PROXY_VIEW_BODY) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); // Begin the connect action. worker.BeginConnect(*this, view, parentData, parentId); } HRESULT ProxyNode::getResultViewType( LPOLESTR* ppViewType, long* pViewOptions ) throw () { // Set our result view to the MessageView control. *pViewOptions = MMC_VIEW_OPTIONS_NOLISTVIEWS; return StringFromCLSID(CLSID_MessageView, ppViewType); } HRESULT ProxyNode::onExpand( SnapInView& view, HSCOPEITEM itemId, BOOL expanded ) { if (!expanded || state != CONNECTED) { return S_FALSE; } SCOPEDATAITEM sdi; memset(&sdi, 0, sizeof(sdi)); sdi.mask = SDI_STR | SDI_PARAM | SDI_IMAGE | SDI_OPENIMAGE | SDI_CHILDREN | SDI_PARENT; sdi.displayname = MMC_CALLBACK; sdi.cChildren = 0; sdi.relativeID = itemId; // Create the ProxyPolicies node ... policies = new (AfxThrow) ProxyPolicies(connection); // ... and insert. sdi.nImage = IMAGE_CLOSED_PROXY_POLICY_NODE; sdi.nOpenImage = IMAGE_OPEN_PROXY_POLICY_NODE; sdi.lParam = (LPARAM)(SnapInDataItem*)policies; CheckError(view.getNameSpace()->InsertItem(&sdi)); policies->setScopeId(sdi.ID); // Create the ServerGroups node ... groups = new (AfxThrow) ServerGroups(connection); // ... and insert. sdi.nImage = IMAGE_CLOSED_SERVER_GROUP_NODE; sdi.nOpenImage = IMAGE_OPEN_SERVER_GROUPS_NODE; sdi.lParam = (LPARAM)(SnapInDataItem*)groups; CheckError(view.getNameSpace()->InsertItem(&sdi)); groups->setScopeId(sdi.ID); // All went well. state = EXPANDED; return S_OK; } HRESULT ProxyNode::onShow( SnapInView& view, HSCOPEITEM itemId, BOOL selected ) { if (!selected) { return S_FALSE; } // Get the IMessageView interface ... CComPtr unk; CheckError(view.getConsole()->QueryResultView(&unk)); CComPtr msgView; CheckError(unk->QueryInterface( __uuidof(IMessageView), (PVOID*)&msgView )); // ... and set our information. We don't care if this fails. msgView->SetIcon(Icon_Information); msgView->SetTitleText(title); msgView->SetBodyText(body); return S_OK; } HRESULT ProxyNode::onContextHelp(SnapInView& view) throw () { return view.displayHelp(L"ias_ops.chm::/sag_ias_crp_node.htm"); } ProxyNode::State ProxyNode::connect(IDataObject* dataObject) throw () { HGLOBAL global = NULL; // We'll assume that the node is suppressed until we've verified that the // target machine (1) has IAS installed and (2) supports proxy policies. State newState = SUPPRESSED; try { // Extract the machine name from the parentData. UINT cf = RegisterClipboardFormatW(L"MMC_SNAPIN_MACHINE_NAME"); ExtractData( dataObject, (CLIPFORMAT)cf, 4096, &global ); PCWSTR machine = (PCWSTR)global; // Get the build number of the machine. LONG error, buildNum; error = GetBuildNumber(machine, &buildNum); if (error) { AfxThrowOleException(HRESULT_FROM_WIN32(error)); } // If the machine supports proxy policies, ... if (buildNum >= 2220) { // ... ensure that IAS is actually installed. BOOL installed; CheckError(IfServiceInstalled(machine, L"IAS", &installed)); if (installed) { connection.connect(machine); newState = CONNECTED; } } } catch (...) { // Something went wrong. newState = FAILED; } GlobalFree(global); return newState; } void ProxyNode::setConnectResult( IConsoleNameSpace2* nameSpace, HSCOPEITEM relativeID, State newState ) throw () { // Don't add the node if we're suppressed. if (newState != SUPPRESSED) { SCOPEDATAITEM sdi; ZeroMemory(&sdi, sizeof(SCOPEDATAITEM)); sdi.mask = SDI_STR | SDI_IMAGE | SDI_OPENIMAGE | SDI_CHILDREN | SDI_PARENT | SDI_PARAM; sdi.displayname = MMC_CALLBACK; sdi.lParam = (LPARAM)this; sdi.relativeID = relativeID; if (newState == CONNECTED) { sdi.nImage = IMAGE_CLOSED_PROXY_NODE; sdi.nOpenImage = IMAGE_OPEN_PROXY_NODE; sdi.cChildren = 2; } else { sdi.nImage = IMAGE_CLOSED_BAD_PROXY_NODE; sdi.nOpenImage = IMAGE_OPEN_BAD_PROXY_NODE; } nameSpace->InsertItem(&sdi); } // We don't update the state until everything is finished. state = newState; }