📄 ncpa.c
字号:
/*
* Copyright 2004 Gero Kuehn
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* PROJECT: ReactOS Network Control Panel
* FILE: lib/cpl/system/ncpa.c
* PURPOSE: ReactOS Network Control Panel
* PROGRAMMER: Gero Kuehn (reactos.filter@gkware.com)
* UPDATE HISTORY:
* 07-18-2004 Created
*/
/*
* Read this first !
*
* This file contains a first attempt for reactos network configuration
*
* - It is not complete.
* - It does not work the way it works on Windows.
*
* A lot of code that can be found here now, will probably be relocated into the OS core or some
* protocol Co-Installers or Notify Objects later when all the required COM
* and "netcfgx.dll" infrastructure (esp. headers and Interfaces) get implemented step by step.
*
* This code is only a first approach to provide a usable network configuration dialogs for
* the new network support in Reactos.
*
* If you intend to extend this code by more, please contact me to avoid duplicate work.
* There are already resources and code for TCP/IP configuration that are not
* mature enough for committing them to CVS yet.
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <tchar.h>
#include <windows.h>
#include <iphlpapi.h>
#include <commctrl.h>
#include <cpl.h>
#include <debug.h>
#include "resource.h"
#include "ncpa.h"
#define NCF_VIRTUAL 0x1
#define NCF_SOFTWARE_ENUMERATED 0x2
#define NCF_PHYSICAL 0x4
#define NCF_HIDDEN 0x8
#define NCF_NO_SERVICE 0x10
#define NCF_NOT_USER_REMOVABLE 0x20
#define NCF_MULTIPORT_INSTANCED_ADAPTER 0x40
#define NCF_HAS_UI 0x80
#define NCF_FILTER 0x400
#define NCF_NDIS_PROTOCOL 0x4000
typedef void (ENUMREGKEYCALLBACK)(void *pCookie,HKEY hBaseKey,TCHAR *pszSubKey);
static LONG CALLBACK DisplayApplet(VOID);
static INT_PTR CALLBACK NetworkPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
void DisplayTCPIPProperties(HWND hParent,IP_ADAPTER_INFO *pInfo);
HINSTANCE hApplet = 0;
/* Applets */
static APPLET Applets[] =
{
{IDI_CPLSYSTEM, IDS_CPLSYSTEMNAME, IDS_CPLSYSTEMDESCRIPTION, DisplayApplet}
};
/* useful utilities */
static VOID
EnumRegKeys(ENUMREGKEYCALLBACK *pCallback,PVOID pCookie,HKEY hBaseKey,TCHAR *tpszRegPath)
{
HKEY hKey;
INT i;
LONG ret;
TCHAR tpszName[MAX_PATH];
DWORD dwNameLen = sizeof(tpszName);
if(RegOpenKeyEx(hBaseKey,tpszRegPath,0,KEY_ENUMERATE_SUB_KEYS,&hKey)!=ERROR_SUCCESS)
{
DPRINT("EnumRegKeys failed (key not found): %S\n", tpszRegPath);
return;
}
for(i=0;;i++)
{
TCHAR pszNewPath[MAX_PATH];
ret = RegEnumKeyEx(hKey,i,tpszName,&dwNameLen,NULL,NULL,NULL,NULL);
if(ret != ERROR_SUCCESS)
{
DPRINT("EnumRegKeys: RegEnumKeyEx failed for %S (rc 0x%lx)\n", tpszName, ret);
break;
}
_stprintf(pszNewPath,_T("%s\\%s"),tpszRegPath,tpszName);
DPRINT("EnumRegKeys: Calling user supplied enum function\n");
pCallback(pCookie,hBaseKey,pszNewPath);
dwNameLen = sizeof(tpszName);
}
RegCloseKey(hKey);
}
void
InitPropSheetPage(PROPSHEETPAGE *psp, WORD idDlg, DLGPROC DlgProc,LPARAM lParam)
{
ZeroMemory(psp, sizeof(PROPSHEETPAGE));
psp->dwSize = sizeof(PROPSHEETPAGE);
psp->dwFlags = PSP_DEFAULT;
psp->hInstance = hApplet;
psp->pszTemplate = MAKEINTRESOURCE(idDlg);
psp->pfnDlgProc = DlgProc;
psp->lParam = lParam;
}
static BOOL
FindNICClassKeyForCfgInstance(TCHAR *tpszCfgInst,TCHAR *tpszSubKeyOut)
{
int i;
TCHAR tpszSubKey[MAX_PATH];
TCHAR tpszCfgInst2[MAX_PATH];
HKEY hKey;
DWORD dwType,dwSize;
for (i = 0; i < 100; i++)
{
_stprintf(tpszSubKey,_T("SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%04d"),i);
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,tpszSubKey,0,KEY_QUERY_VALUE,&hKey)!=ERROR_SUCCESS)
continue;
dwType = REG_SZ;
dwSize = sizeof(tpszCfgInst2);
if(RegQueryValueEx(hKey,_T("NetCfgInstanceId"),NULL,&dwType,(BYTE*)tpszCfgInst2,&dwSize)!=ERROR_SUCCESS) {
RegCloseKey(hKey);
continue;
}
RegCloseKey(hKey);
if(_tcscmp(tpszCfgInst,tpszCfgInst2)==0) {
_tcscpy(tpszSubKeyOut,tpszSubKey);
return TRUE;
}
}
return FALSE;
}
static void
NICPropertyProtocolCallback(void *pCookie,HKEY hBaseKey,TCHAR *tpszSubKey)
{
HWND hwndDlg;
DWORD dwCharacteristics;
HKEY hKey,hNDIKey;
DWORD dwType,dwSize;
TCHAR tpszDescription[MAX_PATH];
TCHAR tpszNotifyObjectCLSID[MAX_PATH];
TCHAR *tpszSubKeyCopy;
int nIndex;
UNREFERENCED_PARAMETER(hBaseKey);
// CLSID CLSID_NotifObj;
// IUnknown *pUnk = NULL;
// INetCfgComponentControl *pNetCfg;
// INetCfgComponentPropertyUi *pNetCfgPropUI;
hwndDlg = (HWND)pCookie;
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,tpszSubKey,0,KEY_QUERY_VALUE,&hKey)!=ERROR_SUCCESS)
return;
dwType = REG_DWORD;
dwSize = sizeof(dwCharacteristics);
if(RegQueryValueEx(hKey,_T("Characteristics"),NULL,&dwType,(BYTE*)&dwCharacteristics,&dwSize)!= ERROR_SUCCESS)
return;
if(dwCharacteristics & NCF_HIDDEN)
{
RegCloseKey(hKey);
return;
}
dwType = REG_SZ;
dwSize = sizeof(tpszDescription);
if(RegQueryValueEx(hKey,_T("Description"),NULL,&dwType,(BYTE*)tpszDescription,&dwSize)!= ERROR_SUCCESS)
return;
RegOpenKeyEx(hKey,_T("Ndi"),0,KEY_QUERY_VALUE,&hNDIKey);
dwType = REG_SZ;
dwSize = sizeof(tpszNotifyObjectCLSID);
if(RegQueryValueEx(hNDIKey,_T("ClsId"),NULL,&dwType,(BYTE*)tpszNotifyObjectCLSID,&dwSize)!= ERROR_SUCCESS)
;//return;
RegCloseKey(hNDIKey);
//
// This code works on Windows... but not on Reactos
//
// CLSIDFromString(tpszNotifyObjectCLSID,&CLSID_NotifObj);
// CoCreateInstance(&CLSID_NotifObj,NULL,CLSCTX_INPROC_SERVER,&IID_IUnknown,(void**)&pUnk);
// pUnk->lpVtbl->QueryInterface(pUnk,&IID_INetCfgComponentControl,(void**)&pNetCfg);
// pUnk->lpVtbl->QueryInterface(pUnk,&IID_INetCfgComponentPropertyUi,(void**)&pNetCfgPropUI);
{
/*
HRESULT hr;
hr = pNetCfg->lpVtbl->Initialize(pNetCfg,&NetCfgComponent,&NetCfg,FALSE);
hr = pNetCfgPropUI->lpVtbl->QueryPropertyUi(pNetCfgPropUI,(INetCfg*)&NetCfg);
hr = pNetCfgPropUI->lpVtbl->SetContext(pNetCfgPropUI,(INetCfg*)&NetCfgComponent);
DWORD dwNumPages = 10;
HPROPSHEETPAGE *bOut = NULL;
UINT nPages;
hr = pNetCfgPropUI->MergePropPages(&dwNumPages,(BYTE**)&bOut,&nPages,GetDesktopWindow(),NULL);
*/
}
RegCloseKey(hKey);
nIndex = (int) SendDlgItemMessage(hwndDlg,IDC_COMPONENTSLIST,LB_ADDSTRING,0,(LPARAM)tpszDescription);
tpszSubKeyCopy = _tcsdup(tpszSubKey);
SendDlgItemMessage(hwndDlg,IDC_COMPONENTSLIST,LB_SETITEMDATA,nIndex,(LPARAM)tpszSubKeyCopy);
}
static INT_PTR CALLBACK
NICPropertyPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
PROPSHEETPAGE *pPage = (PROPSHEETPAGE *)GetWindowLongPtr(hwndDlg,GWL_USERDATA);
switch(uMsg)
{
case WM_INITDIALOG:
{
TCHAR *tpszCfgInstanceID;
DWORD dwType,dwSize;
TCHAR tpszSubKey[MAX_PATH];
TCHAR tpszDisplayName[MAX_PATH];
HKEY hKey;
pPage = (PROPSHEETPAGE *)lParam;
tpszCfgInstanceID = (TCHAR*)pPage->lParam;
if(!FindNICClassKeyForCfgInstance(tpszCfgInstanceID,tpszSubKey))
{
MessageBox(hwndDlg,_T("NIC Entry not found"),_T("Registry error"),MB_ICONSTOP);
MessageBox(hwndDlg,tpszCfgInstanceID,tpszSubKey,MB_ICONSTOP);
}
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,tpszSubKey,0,KEY_QUERY_VALUE,&hKey)!=ERROR_SUCCESS)
return 0;
dwType = REG_SZ;
dwSize = sizeof(tpszDisplayName);
if(RegQueryValueEx(hKey,_T("DriverDesc"),NULL,&dwType,(BYTE*)tpszDisplayName,&dwSize)!= ERROR_SUCCESS)
return 0;
RegCloseKey(hKey);
SetDlgItemText(hwndDlg,IDC_NETCARDNAME,tpszDisplayName);
EnableWindow(GetDlgItem(hwndDlg,IDC_CONFIGURE),FALSE);
SetWindowLongPtr(hwndDlg,GWL_USERDATA,(DWORD_PTR)lParam);
//SetDlgItemTextA(hwndDlg,IDC_NETCARDNAME,Info[pPage->lParam].Description);
EnumRegKeys(NICPropertyProtocolCallback,hwndDlg,HKEY_LOCAL_MACHINE,_T("System\\CurrentControlSet\\Control\\Network\\{4D36E975-E325-11CE-BFC1-08002BE10318}"));
SendDlgItemMessage(hwndDlg, IDC_COMPONENTSLIST, LB_SETCURSEL, 0, 0);
SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_COMPONENTSLIST, LBN_SELCHANGE), 0);
}
break;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDC_COMPONENTSLIST:
if(HIWORD(wParam)==LBN_SELCHANGE)
{
TCHAR *tpszSubKey;
TCHAR tpszHelpKey[MAX_PATH];
TCHAR tpszHelpText[MAX_PATH];
HKEY hNDIKey;
DWORD dwType,dwSize;
HWND hListBox = GetDlgItem(hwndDlg,IDC_COMPONENTSLIST);
tpszSubKey = (TCHAR*)SendMessage(hListBox,LB_GETITEMDATA,SendMessage(hListBox,LB_GETCURSEL,0,0),0);
if(!tpszSubKey)
break;
_stprintf(tpszHelpKey,_T("%s\\Ndi"),tpszSubKey);
RegOpenKeyEx(HKEY_LOCAL_MACHINE,tpszHelpKey,0,KEY_QUERY_VALUE,&hNDIKey);
dwType = REG_SZ;
dwSize = sizeof(tpszHelpText);
if(RegQueryValueEx(hNDIKey,_T("HelpText"),NULL,&dwType,(BYTE*)tpszHelpText,&dwSize)!= ERROR_SUCCESS)
;//return;
RegCloseKey(hNDIKey);
SetDlgItemText(hwndDlg,IDC_DESCRIPTION,tpszHelpText);
}
if(HIWORD(wParam)!=LBN_DBLCLK)
break;
// drop though
case IDC_PROPERTIES:
{
TCHAR *tpszSubKey = NULL;
TCHAR tpszNDIKey[MAX_PATH];
TCHAR tpszClsIDText[MAX_PATH];
TCHAR *tpszTCPIPClsID = _T("{A907657F-6FDF-11D0-8EFB-00C04FD912B2}");
HKEY hNDIKey;
DWORD dwType,dwSize;
HWND hListBox = GetDlgItem(hwndDlg,IDC_COMPONENTSLIST);
int iListBoxIndex = (int) SendMessage(hListBox,LB_GETCURSEL,0,0);
if(iListBoxIndex != LB_ERR)
tpszSubKey = (TCHAR*)SendMessage(hListBox,LB_GETITEMDATA,iListBoxIndex,0);
if(!tpszSubKey)
break;
_stprintf(tpszNDIKey,_T("%s\\Ndi"),tpszSubKey);
RegOpenKeyEx(HKEY_LOCAL_MACHINE,tpszNDIKey,0,KEY_QUERY_VALUE,&hNDIKey);
dwSize = sizeof(tpszClsIDText);
if(RegQueryValueEx(hNDIKey,_T("ClsId"),NULL,&dwType,(BYTE*)tpszClsIDText,&dwSize)!= ERROR_SUCCESS || dwType != REG_SZ)
;//return;
RegCloseKey(hNDIKey);
if(_tcscmp(tpszTCPIPClsID,tpszClsIDText)==0)
{
IP_ADAPTER_INFO Adapters[64];
IP_ADAPTER_INFO *pAdapter;
TCHAR *tpszCfgInstanceID;
ULONG ulSize = sizeof(Adapters);
memset(&Adapters,0x00,sizeof(Adapters));
if(GetAdaptersInfo(Adapters,&ulSize)!=ERROR_SUCCESS)
break;;
pAdapter = Adapters;
tpszCfgInstanceID = (TCHAR*)pPage->lParam;
while(pAdapter)
{
TCHAR tpszAdapterName[MAX_PATH];
swprintf(tpszAdapterName,L"%S",pAdapter->AdapterName);
DPRINT("IPHLPAPI returned: %S\n", tpszAdapterName);
if(_tcscmp(tpszAdapterName,tpszCfgInstanceID)==0)
{
DisplayTCPIPProperties(hwndDlg,pAdapter);
break;
} else
{
DPRINT("... which is not the TCPIP property sheet\n");
}
pAdapter = pAdapter->Next;
if(!pAdapter)
{
MessageBox(NULL,_T("If you see this, then the IPHLPAPI.DLL probably needs more work because GetAdaptersInfo did not return the expected data."),_T("Error"),MB_ICONSTOP);
}
}
} else
{
MessageBox(NULL,_T("This control panel is incomplete.\r\nUsually, the \"Notify Object\" for this Network component should be invoked here. Reactos lacks the infrastructure to do this right now.\r\n- C++\r\n- DDK Headers for notify objects\r\n- clean header structure, that allow Windows-Compatible COM C++ Code"),_T("Error"),MB_ICONSTOP);
}
}
break;
}
break;
}
return FALSE;
}
static void
DisplayNICProperties(HWND hParent,TCHAR *tpszCfgInstanceID)
{
PROPSHEETPAGE psp[1];
PROPSHEETHEADER psh;
TCHAR tpszSubKey[MAX_PATH];
HKEY hKey;
DWORD dwType = REG_SZ;
TCHAR tpszName[MAX_PATH];
DWORD dwSize = sizeof(tpszName);
// Get the "Name" for this Connection
_stprintf(tpszSubKey,_T("System\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s\\Connection"),tpszCfgInstanceID);
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,tpszSubKey,0,KEY_QUERY_VALUE,&hKey)!=ERROR_SUCCESS)
return;
if(RegQueryValueEx(hKey,_T("Name"),NULL,&dwType,(BYTE*)tpszName,&dwSize)!=ERROR_SUCCESS)
_stprintf(tpszName,_T("[ERROR]"));
else
_tcscat(tpszName,_T(" Properties"));
RegCloseKey(hKey);
ZeroMemory(&psh, sizeof(PROPSHEETHEADER));
psh.dwSize = sizeof(PROPSHEETHEADER);
psh.dwFlags = PSH_PROPSHEETPAGE | PSH_NOAPPLYNOW;
psh.hwndParent = hParent;
psh.hInstance = hApplet;
psh.hIcon = LoadIcon(hApplet, MAKEINTRESOURCE(IDI_CPLSYSTEM));
psh.pszCaption = tpszName;
psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -