852 lines
23 KiB
C++
852 lines
23 KiB
C++
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
// Copyright (C) Microsoft Corporation, 2001.
|
||
|
//
|
||
|
// File: C O M P O N E N T . C P P
|
||
|
//
|
||
|
// Contents: Functions to illustrate
|
||
|
// o How to enumerate network components.
|
||
|
// o How to install protocols, clients and services.
|
||
|
// o How to uninstall protocols, clients and services.
|
||
|
// o How to bind/unbind network components.
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
// Author: Alok Sinha 15-May-01
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
#include "bindview.h"
|
||
|
|
||
|
//
|
||
|
// Function: HandleComponentOperation
|
||
|
//
|
||
|
// Purpose: Do component specific functions.
|
||
|
//
|
||
|
// Arguments:
|
||
|
// hwndOwner [in] Owner window.
|
||
|
// ulSelection [in] Option selected.
|
||
|
// hItem [in] Item selected.
|
||
|
// lParam [in] lParam of the item.
|
||
|
//
|
||
|
// Returns: None.
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
|
||
|
VOID HandleComponentOperation (HWND hwndOwner,
|
||
|
ULONG ulSelection,
|
||
|
HTREEITEM hItem,
|
||
|
LPARAM lParam)
|
||
|
{
|
||
|
switch( ulSelection ) {
|
||
|
|
||
|
case IDI_BIND_TO:
|
||
|
case IDI_UNBIND_FROM:
|
||
|
|
||
|
//
|
||
|
// Bind/unbind components.
|
||
|
//
|
||
|
|
||
|
BindUnbindComponents( hwndOwner,
|
||
|
hItem,
|
||
|
(LPWSTR)lParam,
|
||
|
ulSelection == IDI_BIND_TO );
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Function: BindUnbindComponents
|
||
|
//
|
||
|
// Purpose: Bind/unbind a network component.
|
||
|
//
|
||
|
// Arguments:
|
||
|
// hwndOwner [in] Owner window.
|
||
|
// hItem [in] Item handle of the network component.
|
||
|
// lpszInfId [in] PnpID of the network component.
|
||
|
// fBindTo [in] if TRUE, bind, otherwise unbind.
|
||
|
//
|
||
|
// Returns: None.
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
|
||
|
VOID BindUnbindComponents( HWND hwndOwner,
|
||
|
HTREEITEM hItem,
|
||
|
LPWSTR lpszInfId,
|
||
|
BOOL fBindTo)
|
||
|
{
|
||
|
BIND_UNBIND_INFO BindUnbind;
|
||
|
|
||
|
BindUnbind.lpszInfId = lpszInfId;
|
||
|
BindUnbind.fBindTo = fBindTo;
|
||
|
|
||
|
DialogBoxParam( hInstance,
|
||
|
MAKEINTRESOURCE(IDD_BIND_UNBIND),
|
||
|
hwndOwner,
|
||
|
BindComponentDlg,
|
||
|
(LPARAM)&BindUnbind );
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Function: InstallComponent
|
||
|
//
|
||
|
// Purpose: Install a network component.
|
||
|
//
|
||
|
// Arguments:
|
||
|
// hwndDlg [in] Owner window.
|
||
|
// pguidClass [in] Class GUID of type of network component to install.
|
||
|
//
|
||
|
// Returns: S_OK on success, otherwise and error code.
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
|
||
|
HRESULT InstallComponent (HWND hwndDlg,
|
||
|
const GUID *pguidClass)
|
||
|
{
|
||
|
INetCfg *pnc;
|
||
|
INetCfgClass *pncClass;
|
||
|
INetCfgClassSetup *pncClassSetup;
|
||
|
LPWSTR lpszApp;
|
||
|
OBO_TOKEN obo;
|
||
|
HRESULT hr;
|
||
|
|
||
|
//
|
||
|
// Get INetCfg reference.
|
||
|
//
|
||
|
|
||
|
hr = HrGetINetCfg( TRUE,
|
||
|
APP_NAME,
|
||
|
&pnc,
|
||
|
&lpszApp );
|
||
|
|
||
|
if ( hr == S_OK ) {
|
||
|
|
||
|
//
|
||
|
// Get network component's class reference.
|
||
|
//
|
||
|
|
||
|
hr = pnc->QueryNetCfgClass( pguidClass,
|
||
|
IID_INetCfgClass,
|
||
|
(PVOID *)&pncClass );
|
||
|
|
||
|
if ( hr == S_OK ) {
|
||
|
|
||
|
//
|
||
|
// Get Setup class reference.
|
||
|
//
|
||
|
|
||
|
hr = pncClass->QueryInterface( IID_INetCfgClassSetup,
|
||
|
(LPVOID *)&pncClassSetup );
|
||
|
|
||
|
if ( hr == S_OK ) {
|
||
|
|
||
|
ZeroMemory( &obo,
|
||
|
sizeof(OBO_TOKEN) );
|
||
|
|
||
|
obo.Type = OBO_USER;
|
||
|
|
||
|
//
|
||
|
// Let the network class installer prompt the user to select
|
||
|
// a network component to install.
|
||
|
//
|
||
|
|
||
|
hr = pncClassSetup->SelectAndInstall( hwndDlg,
|
||
|
&obo,
|
||
|
NULL );
|
||
|
|
||
|
if ( (hr == S_OK) || (hr == NETCFG_S_REBOOT) ) {
|
||
|
|
||
|
hr = pnc->Apply();
|
||
|
}
|
||
|
else {
|
||
|
if ( hr != HRESULT_FROM_WIN32(ERROR_CANCELLED) ) {
|
||
|
ErrMsg( hr,
|
||
|
L"Couldn't install the network component." );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ReleaseRef( pncClassSetup );
|
||
|
}
|
||
|
else {
|
||
|
ErrMsg( hr,
|
||
|
L"Couldn't get an interface to setup class." );
|
||
|
}
|
||
|
|
||
|
ReleaseRef( pncClass );
|
||
|
}
|
||
|
else {
|
||
|
ErrMsg( hr,
|
||
|
L"Couldn't get a pointer to class interface." );
|
||
|
}
|
||
|
|
||
|
HrReleaseINetCfg( pnc,
|
||
|
TRUE );
|
||
|
}
|
||
|
else {
|
||
|
if ( (hr == NETCFG_E_NO_WRITE_LOCK) && lpszApp ) {
|
||
|
ErrMsg( hr,
|
||
|
L"%s currently holds the lock, try later.",
|
||
|
lpszApp );
|
||
|
|
||
|
CoTaskMemFree( lpszApp );
|
||
|
}
|
||
|
else {
|
||
|
ErrMsg( hr,
|
||
|
L"Couldn't the get notify object interface." );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Function: InstallSpecifiedComponent
|
||
|
//
|
||
|
// Purpose: Install a network component from an INF file.
|
||
|
//
|
||
|
// Arguments:
|
||
|
// lpszInfFile [in] INF file.
|
||
|
// lpszPnpID [in] PnpID of the network component to install.
|
||
|
// pguidClass [in] Class GUID of the network component.
|
||
|
//
|
||
|
// Returns: None.
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
|
||
|
HRESULT InstallSpecifiedComponent (LPWSTR lpszInfFile,
|
||
|
LPWSTR lpszPnpID,
|
||
|
const GUID *pguidClass)
|
||
|
{
|
||
|
INetCfg *pnc;
|
||
|
LPWSTR lpszApp;
|
||
|
HRESULT hr;
|
||
|
|
||
|
hr = HrGetINetCfg( TRUE,
|
||
|
APP_NAME,
|
||
|
&pnc,
|
||
|
&lpszApp );
|
||
|
|
||
|
if ( hr == S_OK ) {
|
||
|
|
||
|
//
|
||
|
// Install the network component.
|
||
|
//
|
||
|
|
||
|
hr = HrInstallNetComponent( pnc,
|
||
|
lpszPnpID,
|
||
|
pguidClass,
|
||
|
lpszInfFile );
|
||
|
if ( (hr == S_OK) || (hr == NETCFG_S_REBOOT) ) {
|
||
|
|
||
|
hr = pnc->Apply();
|
||
|
}
|
||
|
else {
|
||
|
if ( hr != HRESULT_FROM_WIN32(ERROR_CANCELLED) ) {
|
||
|
ErrMsg( hr,
|
||
|
L"Couldn't install the network component." );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
HrReleaseINetCfg( pnc,
|
||
|
TRUE );
|
||
|
}
|
||
|
else {
|
||
|
if ( (hr == NETCFG_E_NO_WRITE_LOCK) && lpszApp ) {
|
||
|
ErrMsg( hr,
|
||
|
L"%s currently holds the lock, try later.",
|
||
|
lpszApp );
|
||
|
|
||
|
CoTaskMemFree( lpszApp );
|
||
|
}
|
||
|
else {
|
||
|
ErrMsg( hr,
|
||
|
L"Couldn't the get notify object interface." );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Function: ListCompToBindUnbind
|
||
|
//
|
||
|
// Purpose: List all the components that are bound or bindable.
|
||
|
//
|
||
|
// Arguments:
|
||
|
// lpszInfId [in] PnpID of the network component.
|
||
|
// uiType [in] Type of network component.
|
||
|
// hwndTree [in] Tree handle in which to list.
|
||
|
// fBound [in] if TRUE, list components that are bound.
|
||
|
//
|
||
|
// Returns: Number of components listed.
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
|
||
|
DWORD ListCompToBindUnbind (LPWSTR lpszInfId,
|
||
|
UINT uiType,
|
||
|
HWND hwndTree,
|
||
|
BOOL fBound)
|
||
|
{
|
||
|
INetCfg *pnc;
|
||
|
INetCfgComponent *pncc;
|
||
|
IEnumNetCfgComponent *pencc;
|
||
|
INetCfgComponentBindings *pnccb;
|
||
|
INetCfgComponent *pnccToBindUnbind;
|
||
|
LPWSTR lpszApp;
|
||
|
DWORD dwCount;
|
||
|
HRESULT hr;
|
||
|
|
||
|
|
||
|
dwCount = 0;
|
||
|
hr = HrGetINetCfg( TRUE,
|
||
|
APP_NAME,
|
||
|
&pnc,
|
||
|
&lpszApp );
|
||
|
|
||
|
if ( hr == S_OK ) {
|
||
|
|
||
|
//
|
||
|
// Get a reference to the network component selected.
|
||
|
//
|
||
|
|
||
|
hr = pnc->FindComponent( lpszInfId,
|
||
|
&pncc );
|
||
|
|
||
|
if ( hr == S_OK ) {
|
||
|
|
||
|
//
|
||
|
// Get Component Enumerator Interface.
|
||
|
//
|
||
|
|
||
|
hr = HrGetComponentEnum( pnc,
|
||
|
pguidNetClass[uiType],
|
||
|
&pencc );
|
||
|
if ( hr == S_OK ) {
|
||
|
|
||
|
hr = pncc->QueryInterface( IID_INetCfgComponentBindings,
|
||
|
(PVOID *)&pnccb );
|
||
|
if ( hr == S_OK ) {
|
||
|
|
||
|
hr = HrGetFirstComponent( pencc, &pnccToBindUnbind );
|
||
|
|
||
|
while( hr == S_OK ) {
|
||
|
|
||
|
hr = pnccb->IsBoundTo( pnccToBindUnbind );
|
||
|
|
||
|
//
|
||
|
// fBound = TRUE ==> Want to list components that are
|
||
|
// bound.
|
||
|
//
|
||
|
|
||
|
if ( fBound ) {
|
||
|
|
||
|
if ( hr == S_OK ) {
|
||
|
AddToTree( hwndTree,
|
||
|
TVI_ROOT,
|
||
|
pnccToBindUnbind );
|
||
|
dwCount++;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
|
||
|
//
|
||
|
// fBound = FALSE ==> Want to list components that
|
||
|
// are not bound but are bindable.
|
||
|
//
|
||
|
|
||
|
if ( hr == S_FALSE ) {
|
||
|
|
||
|
hr = pnccb->IsBindableTo( pnccToBindUnbind );
|
||
|
|
||
|
if ( hr == S_OK ) {
|
||
|
AddToTree( hwndTree,
|
||
|
TVI_ROOT,
|
||
|
pnccToBindUnbind );
|
||
|
dwCount++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ReleaseRef( pnccToBindUnbind );
|
||
|
|
||
|
hr = HrGetNextComponent( pencc, &pnccToBindUnbind );
|
||
|
}
|
||
|
|
||
|
ReleaseRef( pnccb );
|
||
|
}
|
||
|
else {
|
||
|
ErrMsg( hr,
|
||
|
L"Couldn't get the component binding interface "
|
||
|
L"of %s.",
|
||
|
lpszInfId );
|
||
|
}
|
||
|
|
||
|
ReleaseRef( pencc );
|
||
|
}
|
||
|
else {
|
||
|
ErrMsg( hr,
|
||
|
L"Couldn't get the network component enumerator "
|
||
|
L"interface." );
|
||
|
}
|
||
|
|
||
|
ReleaseRef( pncc );
|
||
|
|
||
|
}
|
||
|
else {
|
||
|
ErrMsg( hr,
|
||
|
L"Couldn't get an interface pointer to %s.",
|
||
|
lpszInfId );
|
||
|
}
|
||
|
|
||
|
HrReleaseINetCfg( pnc,
|
||
|
TRUE );
|
||
|
}
|
||
|
else {
|
||
|
if ( (hr == NETCFG_E_NO_WRITE_LOCK) && lpszApp ) {
|
||
|
ErrMsg( hr,
|
||
|
L"%s currently holds the lock, try later.",
|
||
|
lpszApp );
|
||
|
|
||
|
CoTaskMemFree( lpszApp );
|
||
|
}
|
||
|
else {
|
||
|
ErrMsg( hr,
|
||
|
L"Couldn't get the notify object interface." );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return dwCount;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Function: BindUnbind
|
||
|
//
|
||
|
// Purpose: Bind/unbind a network component.
|
||
|
//
|
||
|
// Arguments:
|
||
|
// lpszInfId [in] PnpID of the network component to bind/unbind.
|
||
|
// hwndTree [in] Tree handle.
|
||
|
// fBind [in] if TRUE, bind, otherwise unbind.
|
||
|
//
|
||
|
// Returns: TRUE on success.
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
|
||
|
BOOL BindUnbind (LPWSTR lpszInfId,
|
||
|
HWND hwndTree,
|
||
|
BOOL fBind)
|
||
|
{
|
||
|
INetCfg *pnc;
|
||
|
INetCfgComponent *pncc;
|
||
|
INetCfgComponentBindings *pnccb;
|
||
|
INetCfgComponent *pnccToBindUnbind;
|
||
|
LPWSTR lpszApp;
|
||
|
HTREEITEM hTreeItem;
|
||
|
TVITEMW tvItem;
|
||
|
HRESULT hr;
|
||
|
BOOL fChange;
|
||
|
|
||
|
|
||
|
hr = HrGetINetCfg( TRUE,
|
||
|
APP_NAME,
|
||
|
&pnc,
|
||
|
&lpszApp );
|
||
|
|
||
|
fChange = FALSE;
|
||
|
|
||
|
if ( hr == S_OK ) {
|
||
|
|
||
|
//
|
||
|
// Get a reference to the network component.
|
||
|
//
|
||
|
|
||
|
hr = pnc->FindComponent( lpszInfId,
|
||
|
&pncc );
|
||
|
if ( hr == S_OK ) {
|
||
|
|
||
|
//
|
||
|
// Get a reference to the component's binding.
|
||
|
//
|
||
|
|
||
|
hr = pncc->QueryInterface( IID_INetCfgComponentBindings,
|
||
|
(PVOID *)&pnccb );
|
||
|
if ( hr == S_OK ) {
|
||
|
|
||
|
//
|
||
|
// Start with the root item.
|
||
|
//
|
||
|
|
||
|
hTreeItem = TreeView_GetRoot( hwndTree );
|
||
|
|
||
|
//
|
||
|
// Bind/unbind the network component with every component
|
||
|
// that is checked.
|
||
|
//
|
||
|
|
||
|
while ( hTreeItem ) {
|
||
|
|
||
|
ZeroMemory( &tvItem,
|
||
|
sizeof(TVITEMW) );
|
||
|
|
||
|
tvItem.hItem = hTreeItem;
|
||
|
tvItem.mask = TVIF_PARAM | TVIF_STATE;
|
||
|
tvItem.stateMask = TVIS_STATEIMAGEMASK;
|
||
|
|
||
|
if ( TreeView_GetItem(hwndTree,
|
||
|
&tvItem) ) {
|
||
|
|
||
|
//
|
||
|
// Is the network component selected?
|
||
|
//
|
||
|
|
||
|
if ( (tvItem.state >> 12) == 2 ) {
|
||
|
|
||
|
//
|
||
|
// Get a reference to the selected component.
|
||
|
//
|
||
|
|
||
|
hr = pnc->FindComponent( (LPWSTR)tvItem.lParam,
|
||
|
&pnccToBindUnbind );
|
||
|
if ( hr == S_OK ) {
|
||
|
|
||
|
if ( fBind ) {
|
||
|
|
||
|
//
|
||
|
// Bind the component to the selected component.
|
||
|
//
|
||
|
|
||
|
hr = pnccb->BindTo( pnccToBindUnbind );
|
||
|
|
||
|
if ( !fChange ) {
|
||
|
fChange = hr == S_OK;
|
||
|
}
|
||
|
|
||
|
if ( hr != S_OK ) {
|
||
|
ErrMsg( hr,
|
||
|
L"%s couldn't be bound to %s.",
|
||
|
lpszInfId, (LPWSTR)tvItem.lParam );
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
//
|
||
|
// Unbind the component from the selected component.
|
||
|
//
|
||
|
|
||
|
hr = pnccb->UnbindFrom( pnccToBindUnbind );
|
||
|
|
||
|
if ( !fChange ) {
|
||
|
fChange = hr == S_OK;
|
||
|
}
|
||
|
|
||
|
if ( hr != S_OK ) {
|
||
|
ErrMsg( hr,
|
||
|
L"%s couldn't be unbound from %s.",
|
||
|
lpszInfId, (LPWSTR)tvItem.lParam );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ReleaseRef( pnccToBindUnbind );
|
||
|
}
|
||
|
else {
|
||
|
ErrMsg( hr,
|
||
|
L"Couldn't get an interface pointer to %s. "
|
||
|
L"%s will not be bound to it.",
|
||
|
(LPWSTR)tvItem.lParam,
|
||
|
lpszInfId );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Get the next item.
|
||
|
//
|
||
|
|
||
|
hTreeItem = TreeView_GetNextSibling( hwndTree,
|
||
|
hTreeItem );
|
||
|
}
|
||
|
|
||
|
ReleaseRef( pnccb );
|
||
|
}
|
||
|
else {
|
||
|
ErrMsg( hr,
|
||
|
L"Couldn't get a binding interface of %s.",
|
||
|
lpszInfId );
|
||
|
}
|
||
|
|
||
|
ReleaseRef( pncc );
|
||
|
}
|
||
|
else {
|
||
|
ErrMsg( hr,
|
||
|
L"Couldn't get an interface pointer to %s.",
|
||
|
lpszInfId );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If one or more network components have been bound/unbound,
|
||
|
// apply the changes.
|
||
|
//
|
||
|
|
||
|
if ( fChange ) {
|
||
|
hr = pnc->Apply();
|
||
|
|
||
|
fChange = hr == S_OK;
|
||
|
}
|
||
|
|
||
|
HrReleaseINetCfg( pnc,
|
||
|
TRUE );
|
||
|
}
|
||
|
else {
|
||
|
if ( (hr == NETCFG_E_NO_WRITE_LOCK) && lpszApp ) {
|
||
|
ErrMsg( hr,
|
||
|
L"%s currently holds the lock, try later.",
|
||
|
lpszApp );
|
||
|
|
||
|
CoTaskMemFree( lpszApp );
|
||
|
}
|
||
|
else {
|
||
|
ErrMsg( hr,
|
||
|
L"Couldn't get the notify object interface." );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return fChange;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Function: ListInstalledComponents
|
||
|
//
|
||
|
// Purpose: List installed network components of specific class.
|
||
|
//
|
||
|
// Arguments:
|
||
|
// hwndTree [in] Tree handle in which to list.
|
||
|
// pguidClass [in] Class GUID of the network compoent class.
|
||
|
//
|
||
|
// Returns: None.
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
|
||
|
VOID ListInstalledComponents (HWND hwndTree,
|
||
|
const GUID *pguidClass)
|
||
|
{
|
||
|
INetCfg *pnc;
|
||
|
IEnumNetCfgComponent *pencc;
|
||
|
INetCfgComponent *pncc;
|
||
|
LPWSTR lpszApp;
|
||
|
HTREEITEM hTreeItem;
|
||
|
HRESULT hr;
|
||
|
|
||
|
|
||
|
hr = HrGetINetCfg( FALSE,
|
||
|
APP_NAME,
|
||
|
&pnc,
|
||
|
&lpszApp );
|
||
|
|
||
|
if ( hr == S_OK ) {
|
||
|
|
||
|
//
|
||
|
// Get Component Enumerator Interface.
|
||
|
//
|
||
|
|
||
|
hr = HrGetComponentEnum( pnc,
|
||
|
pguidClass,
|
||
|
&pencc );
|
||
|
if ( hr == S_OK ) {
|
||
|
|
||
|
hr = HrGetFirstComponent( pencc, &pncc );
|
||
|
|
||
|
while( hr == S_OK ) {
|
||
|
|
||
|
//
|
||
|
// Add an item to the tree for the network component.
|
||
|
//
|
||
|
|
||
|
hTreeItem = AddToTree( hwndTree,
|
||
|
TVI_ROOT,
|
||
|
pncc );
|
||
|
|
||
|
ReleaseRef( pncc );
|
||
|
|
||
|
hr = HrGetNextComponent( pencc, &pncc );
|
||
|
}
|
||
|
|
||
|
ReleaseRef( pencc );
|
||
|
}
|
||
|
else {
|
||
|
ErrMsg( hr,
|
||
|
L"Failed to get the network component enumerator." );
|
||
|
}
|
||
|
|
||
|
HrReleaseINetCfg( pnc, FALSE );
|
||
|
}
|
||
|
else {
|
||
|
if ( (hr == NETCFG_E_NO_WRITE_LOCK) && lpszApp ) {
|
||
|
ErrMsg( hr,
|
||
|
L"%s currently holds the lock, try later.",
|
||
|
lpszApp );
|
||
|
|
||
|
CoTaskMemFree( lpszApp );
|
||
|
}
|
||
|
else {
|
||
|
ErrMsg( hr,
|
||
|
L"Couldn't get the notify object interface." );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Function: UninstallComponent
|
||
|
//
|
||
|
// Purpose: Uninstall a network component.
|
||
|
//
|
||
|
// Arguments:
|
||
|
// lpszInfId [in] PnpID of the network component to uninstall.
|
||
|
//
|
||
|
// Returns: S_OK on success, otherwise an error code.
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
|
||
|
HRESULT UninstallComponent (LPWSTR lpszInfId)
|
||
|
{
|
||
|
INetCfg *pnc;
|
||
|
INetCfgComponent *pncc;
|
||
|
INetCfgClass *pncClass;
|
||
|
INetCfgClassSetup *pncClassSetup;
|
||
|
LPWSTR lpszApp;
|
||
|
GUID guidClass;
|
||
|
OBO_TOKEN obo;
|
||
|
HRESULT hr;
|
||
|
|
||
|
hr = HrGetINetCfg( TRUE,
|
||
|
APP_NAME,
|
||
|
&pnc,
|
||
|
&lpszApp );
|
||
|
|
||
|
if ( hr == S_OK ) {
|
||
|
|
||
|
//
|
||
|
// Get a reference to the network component to uninstall.
|
||
|
//
|
||
|
|
||
|
hr = pnc->FindComponent( lpszInfId,
|
||
|
&pncc );
|
||
|
|
||
|
if ( hr == S_OK ) {
|
||
|
|
||
|
//
|
||
|
// Get the class GUID.
|
||
|
//
|
||
|
|
||
|
hr = pncc->GetClassGuid( &guidClass );
|
||
|
|
||
|
if ( hr == S_OK ) {
|
||
|
|
||
|
//
|
||
|
// Get a reference to component's class.
|
||
|
//
|
||
|
|
||
|
hr = pnc->QueryNetCfgClass( &guidClass,
|
||
|
IID_INetCfgClass,
|
||
|
(PVOID *)&pncClass );
|
||
|
if ( hr == S_OK ) {
|
||
|
|
||
|
//
|
||
|
// Get the setup interface.
|
||
|
//
|
||
|
|
||
|
hr = pncClass->QueryInterface( IID_INetCfgClassSetup,
|
||
|
(LPVOID *)&pncClassSetup );
|
||
|
|
||
|
if ( hr == S_OK ) {
|
||
|
|
||
|
//
|
||
|
// Uninstall the component.
|
||
|
//
|
||
|
|
||
|
ZeroMemory( &obo,
|
||
|
sizeof(OBO_TOKEN) );
|
||
|
|
||
|
obo.Type = OBO_USER;
|
||
|
|
||
|
hr = pncClassSetup->DeInstall( pncc,
|
||
|
&obo,
|
||
|
NULL );
|
||
|
if ( (hr == S_OK) || (hr == NETCFG_S_REBOOT) ) {
|
||
|
|
||
|
hr = pnc->Apply();
|
||
|
|
||
|
if ( (hr != S_OK) && (hr != NETCFG_S_REBOOT) ) {
|
||
|
ErrMsg( hr,
|
||
|
L"Couldn't apply the changes after"
|
||
|
L" uninstalling %s.",
|
||
|
lpszInfId );
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
ErrMsg( hr,
|
||
|
L"Failed to uninstall %s.",
|
||
|
lpszInfId );
|
||
|
}
|
||
|
|
||
|
ReleaseRef( pncClassSetup );
|
||
|
}
|
||
|
else {
|
||
|
ErrMsg( hr,
|
||
|
L"Couldn't get an interface to setup class." );
|
||
|
}
|
||
|
|
||
|
ReleaseRef( pncClass );
|
||
|
}
|
||
|
else {
|
||
|
ErrMsg( hr,
|
||
|
L"Couldn't get a pointer to class interface "
|
||
|
L"of %s.",
|
||
|
lpszInfId );
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
ErrMsg( hr,
|
||
|
L"Couldn't get the class guid of %s.",
|
||
|
lpszInfId );
|
||
|
}
|
||
|
|
||
|
ReleaseRef( pncc );
|
||
|
}
|
||
|
else {
|
||
|
ErrMsg( hr,
|
||
|
L"Couldn't get an interface pointer to %s.",
|
||
|
lpszInfId );
|
||
|
}
|
||
|
|
||
|
HrReleaseINetCfg( pnc,
|
||
|
TRUE );
|
||
|
}
|
||
|
else {
|
||
|
if ( (hr == NETCFG_E_NO_WRITE_LOCK) && lpszApp ) {
|
||
|
ErrMsg( hr,
|
||
|
L"%s currently holds the lock, try later.",
|
||
|
lpszApp );
|
||
|
|
||
|
CoTaskMemFree( lpszApp );
|
||
|
}
|
||
|
else {
|
||
|
ErrMsg( hr,
|
||
|
L"Couldn't get the notify object interface." );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|