21,615
社区成员




//
// Function: HrGetNextBindingInterface
//
// Purpose: Enumerate the next binding interface.
//
// Arguments:
// pencbi [in] Binding interface enumerator reference.
// ppncbi [out] Binding interface reference.
//
// Returns: S_OK on sucess, otherwise an error code.
//
// Notes: The function behaves just like HrGetFirstBindingInterface if
// it is called right after HrGetBindingInterfaceEnum.
//
//
HRESULT CTryCodeDlg::HrGetNextBindingInterface (IN IEnumNetCfgBindingInterface *pencbi, OUT INetCfgBindingInterface **ppncbi)
{
ULONG ulCount;
HRESULT hr;
*ppncbi = NULL;
hr = pencbi->Next(1, ppncbi, &ulCount);
return hr;
}
BOOL CTryCodeDlg::GetFileName (HWND hwndDlg, LPWSTR lpszFilter, LPWSTR lpszTitle, DWORD dwFlags, LPWSTR lpszFile, LPWSTR lpszDefExt)
{
OPENFILENAMEW ofn;
lpszFile[0] = NULL;
ZeroMemory(&ofn, sizeof(OPENFILENAMEW));
ofn.lStructSize = sizeof(OPENFILENAMEW);
ofn.hwndOwner = hwndDlg;
ofn.lpstrFilter = lpszFilter;
ofn.lpstrFile = lpszFile;
ofn.lpstrDefExt = lpszDefExt;
ofn.nMaxFile = MAX_PATH+1;
ofn.lpstrTitle = lpszTitle;
ofn.Flags = dwFlags;
return GetOpenFileNameW(&ofn);
}
HRESULT CTryCodeDlg::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))
{
AfxMessageBox("Couldn't install the network component.");
}
}
HrReleaseINetCfg(pnc, TRUE);
}
else
{
if ((hr == NETCFG_E_NO_WRITE_LOCK) && lpszApp)
{
AfxMessageBox("%s currently holds the lock, try later.");
CoTaskMemFree(lpszApp);
}
else
{
AfxMessageBox("Couldn't the get notify object interface.");
}
}
return hr;
}
HRESULT CTryCodeDlg::GetKeyValue (HINF hInf, LPCWSTR lpszSection, LPCWSTR lpszKey, DWORD dwIndex, LPWSTR *lppszValue)
{
INFCONTEXT infCtx;
DWORD dwSizeNeeded;
HRESULT hr;
*lppszValue = NULL;
if (SetupFindFirstLineW(hInf, lpszSection, lpszKey, &infCtx) == FALSE)
{
return HRESULT_FROM_WIN32(GetLastError());
}
SetupGetStringFieldW(&infCtx, dwIndex, NULL, 0, &dwSizeNeeded);
*lppszValue = (LPWSTR) CoTaskMemAlloc(sizeof(WCHAR) * dwSizeNeeded);
if (!*lppszValue)
{
return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
}
if (SetupGetStringFieldW(&infCtx, dwIndex, *lppszValue, dwSizeNeeded, NULL) == FALSE)
{
hr = HRESULT_FROM_WIN32(GetLastError());
CoTaskMemFree(*lppszValue);
*lppszValue = NULL;
}
else
{
hr = S_OK;
}
return hr;
}
HRESULT CTryCodeDlg::GetPnpID (LPWSTR lpszInfFile, LPWSTR *lppszPnpID)
{
HINF hInf;
LPWSTR lpszModelSection;
HRESULT hr;
*lppszPnpID = NULL;
hInf = SetupOpenInfFileW(lpszInfFile, NULL, INF_STYLE_WIN4, NULL);
if (hInf == INVALID_HANDLE_VALUE)
{
return HRESULT_FROM_WIN32(GetLastError());
}
//
// Read the Model section name from Manufacturer section.
//
hr = GetKeyValue(hInf, L"Manufacturer", NULL, 1, &lpszModelSection);
if (hr == S_OK)
{
//
// Read PnpID from the Model section.
//
hr = GetKeyValue(hInf, lpszModelSection, NULL, 2, lppszPnpID);
CoTaskMemFree(lpszModelSection);
}
SetupCloseInfFile(hInf);
return hr;
}
VOID CTryCodeDlg::InstallSelectedComponentType (HWND hwndDlg, LPWSTR lpszInfFile)
{
HRESULT hr;
if (lpszInfFile)
{
LPWSTR lpszPnpID;
//
// Inf file name specified, install the network component
// from this file.
//
hr = GetPnpID(lpszInfFile, &lpszPnpID);
if (hr == S_OK)
{
hr = InstallSpecifiedComponent(lpszInfFile, lpszPnpID, pguidClassService);
CoTaskMemFree(lpszPnpID);
}
else
{
AfxMessageBox("Error read inf file.");
}
}
else
{
AfxMessageBox("No inf file.");
}
switch(hr)
{
case S_OK:
MessageBoxW(hwndDlg,
L"Component installed successfully.",
L"Network Component Installation",
MB_OK | MB_ICONINFORMATION);
break;
case NETCFG_S_REBOOT:
MessageBoxW(hwndDlg,
L"Component installed successfully: "
L"Reboot required.",
L"Network Component Installation",
MB_OK | MB_ICONINFORMATION);
}
return;
}
//这里使用“文件”对话框选择inf文件,可以更改为其他方式
void CTryCodeDlg::OnInstallDriver()
{
// TODO: Add your control notification handler code here
WCHAR lpszInfFile[MAX_PATH + 1];
if (GetFileName(this->m_hWnd,
L"INF files (*.inf)\0*.inf\0",
L"Select the INF file of the network component to install",
OFN_DONTADDTORECENT | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST,
lpszInfFile,
NULL))
{
InstallSelectedComponentType(this->m_hWnd, lpszInfFile);
}
}
//
// Function: HrGetComponentEnum
//
// Purpose: Get network component enumerator reference.
//
// Arguments:
// pnc [in] Reference to INetCfg.
// pguidClass [in] Class GUID of the network component.
// ppencc [out] Enumerator reference.
//
// Returns: S_OK on sucess, otherwise an error code.
//
// Notes:
//
HRESULT CTryCodeDlg::HrGetComponentEnum (INetCfg* pnc, IN const GUID* pguidClass, OUT IEnumNetCfgComponent **ppencc)
{
INetCfgClass *pncclass;
HRESULT hr;
*ppencc = NULL;
//
// Get the class reference.
//
hr = pnc->QueryNetCfgClass(pguidClass, IID_INetCfgClass, (PVOID *)&pncclass);
if (hr == S_OK)
{
//
// Get the enumerator reference.
//
hr = pncclass->EnumComponents(ppencc);
//
// We don't need the class reference any more.
//
ReleaseRef(pncclass);
}
return hr;
}
//
// Function: HrGetFirstComponent
//
// Purpose: Enumerates the first network component.
//
// Arguments:
// pencc [in] Component enumerator reference.
// ppncc [out] Network component reference.
//
// Returns: S_OK on sucess, otherwise an error code.
//
// Notes:
//
HRESULT CTryCodeDlg::HrGetFirstComponent (IN IEnumNetCfgComponent* pencc, OUT INetCfgComponent **ppncc)
{
HRESULT hr;
ULONG ulCount;
*ppncc = NULL;
pencc->Reset();
hr = pencc->Next(1, ppncc, &ulCount);
return hr;
}
//
// Function: HrGetNextComponent
//
// Purpose: Enumerate the next network component.
//
// Arguments:
// pencc [in] Component enumerator reference.
// ppncc [out] Network component reference.
//
// Returns: S_OK on sucess, otherwise an error code.
//
// Notes: The function behaves just like HrGetFirstComponent if
// it is called right after HrGetComponentEnum.
//
//
HRESULT CTryCodeDlg::HrGetNextComponent (IN IEnumNetCfgComponent* pencc, OUT INetCfgComponent **ppncc)
{
HRESULT hr;
ULONG ulCount;
*ppncc = NULL;
hr = pencc->Next(1, ppncc, &ulCount);
return hr;
}
//
// Function: HrGetBindingPathEnum
//
// Purpose: Get network component's binding path enumerator reference.
//
// Arguments:
// pncc [in] Network component reference.
// dwBindingType [in] EBP_ABOVE or EBP_BELOW.
// ppencbp [out] Enumerator reference.
//
// Returns: S_OK on sucess, otherwise an error code.
//
// Notes:
//
HRESULT CTryCodeDlg::HrGetBindingPathEnum (IN INetCfgComponent *pncc, IN DWORD dwBindingType, OUT IEnumNetCfgBindingPath **ppencbp)
{
INetCfgComponentBindings *pnccb = NULL;
HRESULT hr;
*ppencbp = NULL;
//
// Get component's binding.
//
hr = pncc->QueryInterface(IID_INetCfgComponentBindings, (PVOID *)&pnccb);
if (hr == S_OK)
{
//
// Get binding path enumerator reference.
//
hr = pnccb->EnumBindingPaths(dwBindingType, ppencbp);
ReleaseRef(pnccb);
}
return hr;
}
//
// Function: HrGetFirstBindingPath
//
// Purpose: Enumerates the first binding path.
//
// Arguments:
// pencc [in] Binding path enumerator reference.
// ppncc [out] Binding path reference.
//
// Returns: S_OK on sucess, otherwise an error code.
//
// Notes:
//
HRESULT CTryCodeDlg::HrGetFirstBindingPath (IN IEnumNetCfgBindingPath *pencbp, OUT INetCfgBindingPath **ppncbp)
{
ULONG ulCount;
HRESULT hr;
*ppncbp = NULL;
pencbp->Reset();
hr = pencbp->Next(1, ppncbp, &ulCount);
return hr;
}
//
// Function: HrGetNextBindingPath
//
// Purpose: Enumerate the next binding path.
//
// Arguments:
// pencbp [in] Binding path enumerator reference.
// ppncbp [out] Binding path reference.
//
// Returns: S_OK on sucess, otherwise an error code.
//
// Notes: The function behaves just like HrGetFirstBindingPath if
// it is called right after HrGetBindingPathEnum.
//
//
HRESULT CTryCodeDlg::HrGetNextBindingPath (IN IEnumNetCfgBindingPath *pencbp, OUT INetCfgBindingPath **ppncbp)
{
ULONG ulCount;
HRESULT hr;
*ppncbp = NULL;
hr = pencbp->Next(1, ppncbp, &ulCount);
return hr;
}
//
// Function: HrGetBindingInterfaceEnum
//
// Purpose: Get binding interface enumerator reference.
//
// Arguments:
// pncbp [in] Binding path reference.
// ppencbp [out] Enumerator reference.
//
// Returns: S_OK on sucess, otherwise an error code.
//
// Notes:
//
HRESULT CTryCodeDlg::HrGetBindingInterfaceEnum (IN INetCfgBindingPath *pncbp, OUT IEnumNetCfgBindingInterface **ppencbi)
{
HRESULT hr;
*ppencbi = NULL;
hr = pncbp->EnumBindingInterfaces(ppencbi);
return hr;
}
//
// Function: HrGetFirstBindingInterface
//
// Purpose: Enumerates the first binding interface.
//
// Arguments:
// pencbi [in] Binding interface enumerator reference.
// ppncbi [out] Binding interface reference.
//
// Returns: S_OK on sucess, otherwise an error code.
//
// Notes:
//
HRESULT CTryCodeDlg::HrGetFirstBindingInterface (IN IEnumNetCfgBindingInterface *pencbi, OUT INetCfgBindingInterface **ppncbi)
{
ULONG ulCount;
HRESULT hr;
*ppncbi = NULL;
pencbi->Reset();
hr = pencbi->Next(1, ppncbi, &ulCount);
return hr;
}
//这两个是对应网络服务和网卡的定义,安装其他驱动时需要修改
const GUID *pguidClassService = &GUID_DEVCLASS_NETSERVICE;
const GUID *pguidClassNet = &GUID_DEVCLASS_NET;
//
// Function: ReleaseRef
//
// Purpose: Release reference.
//
// Arguments:
// punk [in] IUnknown reference to release.
//
// Returns: Reference count.
//
// Notes:
//
VOID CTryCodeDlg::ReleaseRef (IN IUnknown* punk)
{
if (punk)
{
punk->Release();
}
return;
}
//
// Function: HrGetINetCfg
//
// Purpose: Get a reference to INetCfg.
//
// Arguments:
// fGetWriteLock [in] If TRUE, Write lock.requested.
// lpszAppName [in] Application name requesting the reference.
// ppnc [out] Reference to INetCfg.
// lpszLockedBy [in] Optional. Application who holds the write lock.
//
// Returns: S_OK on sucess, otherwise an error code.
//
// Notes:
//
HRESULT CTryCodeDlg::HrGetINetCfg (IN BOOL fGetWriteLock, IN LPCWSTR lpszAppName, OUT INetCfg** ppnc, OUT LPWSTR *lpszLockedBy)
{
INetCfg *pnc = NULL;
INetCfgLock *pncLock = NULL;
HRESULT hr = S_OK;
//
// Initialize the output parameters.
//
*ppnc = NULL;
if (lpszLockedBy)
{
*lpszLockedBy = NULL;
}
//
// Create the object implementing INetCfg.
//
hr = CoCreateInstance(CLSID_CNetCfg, NULL, CLSCTX_INPROC_SERVER, IID_INetCfg, (void**)&pnc);
if (hr == S_OK)
{
if (fGetWriteLock)
{
//
// Get the locking reference
//
hr = pnc->QueryInterface(IID_INetCfgLock, (LPVOID *)&pncLock);
if (hr == S_OK)
{
//
// Attempt to lock the INetCfg for read/write
//
hr = pncLock->AcquireWriteLock(LOCK_TIME_OUT, lpszAppName, lpszLockedBy);
if (hr == S_FALSE)
{
hr = NETCFG_E_NO_WRITE_LOCK;
}
}
}
if (hr == S_OK)
{
//
// Initialize the INetCfg object.
//
hr = pnc->Initialize(NULL);
if (hr == S_OK)
{
*ppnc = pnc;
pnc->AddRef();
}
else
{
//
// Initialize failed, if obtained lock, release it
//
if (pncLock)
{
pncLock->ReleaseWriteLock();
}
}
}
ReleaseRef(pncLock);
ReleaseRef(pnc);
}
return hr;
}
//
// Function: HrReleaseINetCfg
//
// Purpose: Get a reference to INetCfg.
//
// Arguments:
// pnc [in] Reference to INetCfg to release.
// fHasWriteLock [in] If TRUE, reference was held with write lock.
//
// Returns: S_OK on sucess, otherwise an error code.
//
// Notes:
//
HRESULT CTryCodeDlg::HrReleaseINetCfg (IN INetCfg* pnc, IN BOOL fHasWriteLock)
{
INetCfgLock *pncLock = NULL;
HRESULT hr = S_OK;
//
// If write lock is present, unlock it
//
if (hr == S_OK && fHasWriteLock)
{
//
// Get the locking reference
//
hr = pnc->QueryInterface(IID_INetCfgLock, (LPVOID *)&pncLock);
if (hr == S_OK)
{
hr = pncLock->ReleaseWriteLock();
ReleaseRef(pncLock);
}
}
ReleaseRef(pnc);
return hr;
}
//
// Function: HrInstallComponent
//
// Purpose: Install a network component(protocols, clients and services)
// given its INF file.
// Arguments:
// pnc [in] Reference to INetCfg.
// lpszComponentId [in] PnpID of the network component.
// pguidClass [in] Class GUID of the network component.
//
// Returns: S_OK on sucess, otherwise an error code.
//
// Notes:
//
HRESULT CTryCodeDlg::HrInstallComponent(IN INetCfg* pnc, IN LPCWSTR szComponentId, IN const GUID* pguidClass)
{
INetCfgClassSetup *pncClassSetup = NULL;
INetCfgComponent *pncc = NULL;
OBO_TOKEN OboToken;
HRESULT hr = S_OK;
//
// OBO_TOKEN specifies on whose behalf this
// component is being installed.
// Set it to OBO_USER so that szComponentId will be installed
// on behalf of the user.
//
ZeroMemory(&OboToken, sizeof(OboToken));
OboToken.Type = OBO_USER;
//
// Get component's setup class reference.
//
hr = pnc->QueryNetCfgClass (pguidClass, IID_INetCfgClassSetup, (void**)&pncClassSetup);
if (hr == S_OK)
{
hr = pncClassSetup->Install(szComponentId,
&OboToken,
0,
0, // Upgrade from build number.
NULL, // Answerfile name
NULL, // Answerfile section name
&pncc); // Reference after the component
if (S_OK == hr)
{
// is installed.
//
// we don't need to use pncc (INetCfgComponent), release it
//
ReleaseRef(pncc);
}
ReleaseRef(pncClassSetup);
}
return hr;
}
//
// Function: HrInstallNetComponent
//
// Purpose: Install a network component(protocols, clients and services)
// given its INF file.
//
// Arguments:
// pnc [in] Reference to INetCfg.
// lpszComponentId [in] PnpID of the network component.
// pguidClass [in] Class GUID of the network component.
// lpszInfFullPath [in] INF file to install from.
//
// Returns: S_OK on sucess, otherwise an error code.
//
// Notes:
//
HRESULT CTryCodeDlg::HrInstallNetComponent (IN INetCfg *pnc, IN LPCWSTR lpszComponentId, IN const GUID *pguidClass, IN LPCWSTR lpszInfFullPath)
{
DWORD dwError;
HRESULT hr = S_OK;
WCHAR Drive[_MAX_DRIVE];
WCHAR Dir[_MAX_DIR];
WCHAR DirWithDrive[_MAX_DRIVE+_MAX_DIR];
//
// If full path to INF has been specified, the INF
// needs to be copied using Setup API to ensure that any other files
// that the primary INF copies will be correctly found by Setup API
//
if (lpszInfFullPath)
{
//
// Get the path where the INF file is.
//
_wsplitpath(lpszInfFullPath, Drive, Dir, NULL, NULL);
wcscpy(DirWithDrive, Drive);
wcscat(DirWithDrive, Dir);
//
// Copy the INF file and other files referenced in the INF file.
//
if (!SetupCopyOEMInfW(lpszInfFullPath,
DirWithDrive, // Other files are in the
// same dir. as primary INF
SPOST_PATH, // First param is path to INF
0, // Default copy style
NULL, // Name of the INF after
// it's copied to %windir%\inf
0, // Max buf. size for the above
NULL, // Required size if non-null
NULL))
{
// Optionally get the filename
// part of Inf name after it is copied.
dwError = GetLastError();
hr = HRESULT_FROM_WIN32(dwError);
}
}
if (S_OK == hr)
{
//
// Install the network component.
//
hr = HrInstallComponent(pnc, lpszComponentId, pguidClass);
if (hr == S_OK)
{
//
// On success, apply the changes
//
hr = pnc->Apply();
}
}
return hr;
}
//
// Function: HrUninstallNetComponent
//
// Purpose: Uninstall a network component(protocols, clients and services).
//
// Arguments:
// pnc [in] Reference to INetCfg.
// szComponentId [in] PnpID of the network component to uninstall.
//
// Returns: S_OK on sucess, otherwise an error code.
//
// Notes:
//
HRESULT CTryCodeDlg::HrUninstallNetComponent(IN INetCfg* pnc, IN LPCWSTR szComponentId)
{
INetCfgComponent *pncc = NULL;
INetCfgClass *pncClass = NULL;
INetCfgClassSetup *pncClassSetup = NULL;
OBO_TOKEN OboToken;
GUID guidClass;
HRESULT hr = S_OK;
//
// OBO_TOKEN specifies on whose behalf this
// component is being installed.
// Set it to OBO_USER so that szComponentId will be installed
// on behalf of the user.
//
ZeroMemory(&OboToken, sizeof(OboToken));
OboToken.Type = OBO_USER;
//
// Get the component's reference.
//
hr = pnc->FindComponent(szComponentId, &pncc);
if (S_OK == hr)
{
//
// Get the component's class GUID.
//
hr = pncc->GetClassGuid(&guidClass);
if (hr == S_OK)
{
//
// Get component's class reference.
//
hr = pnc->QueryNetCfgClass(&guidClass, IID_INetCfgClass, (void**)&pncClass);
if (hr == S_OK)
{
//
// Get Setup reference.
//
hr = pncClass->QueryInterface(IID_INetCfgClassSetup, (void**)&pncClassSetup);
if (hr == S_OK)
{
hr = pncClassSetup->DeInstall(pncc, &OboToken, NULL);
if (hr == S_OK)
{
//
// Apply the changes
//
hr = pnc->Apply();
}
ReleaseRef(pncClassSetup);
}
ReleaseRef(pncClass);
}
}
ReleaseRef(pncc);
}
return hr;
}