//---------------------------------------------------------------------------- // // Copyright (c) 1997-1999 Microsoft Corporation // All rights reserved. // // File Name: // netreg.cpp // // Description: // This file contains the calls to the Network Component Object interfaces // to find out what network clients, services and protocols are installed // on the current machine and what their settings are. // //---------------------------------------------------------------------------- #include "pch.h" #include "netreg.h" // // Constants // const static INT MAX_GUID_STRING = 40; const static INT MAX_NUM_NET_COMPONENTS = 128; const static INT BUFFER_SIZE = 4096; // // Registry fields used to read settings for network components // const static TCHAR REGVAL_DOMAIN[] = _T("Domain"); const static TCHAR REGVAL_INTERFACES[] = _T("Interfaces"); const static TCHAR REGVAL_ENABLE_DHCP[] = _T("EnableDHCP"); const static TCHAR REGVAL_IPADDRESS[] = _T("IPAddress"); const static TCHAR REGVAL_SUBNETMASK[] = _T("SubnetMask"); const static TCHAR REGVAL_DEFAULTGATEWAY[] = _T("DefaultGateway"); const static TCHAR REGVAL_NAMESERVER[] = _T("NameServer"); const static TCHAR REGVAL_WINS[] = _T("SYSTEM\\CurrentControlSet\\Services\\NetBT\\Parameters\\Interfaces\\Tcpip_"); const static TCHAR REGVAL_NAMESERVERLIST[] = _T("NameServerList"); const static TCHAR REGKEY_MSCLIENT_LOCATION[] = _T("SOFTWARE\\Microsoft\\Rpc\\NameService"); const static TCHAR REGVAL_NAME_SERVICE_PROVIDER[] = _T("Protocol"); const static TCHAR REGVAL_NETWORK_ADDRESS[] = _T("NetworkAddress"); const static TCHAR REGVAL_ADAPTERS[] = _T("Adapters"); const static TCHAR REGVAL_PKT_TYPE[] = _T("PktType"); const static TCHAR REGVAL_NETWORK_NUMBER[] = _T("NetworkNumber"); const static TCHAR REGVAL_VIRTUAL_NETWORK_NUMBER[] = _T("VirtualNetworkNumber"); //---------------------------------------------------------------------------- // // Function: ReadNetworkRegistrySettings // // Purpose: In general, this function reads in all the necessary networking // settings and sets the internal variables appropriately. This includes // determining how many network adapters there are, what // client/services/protocols are installed and loading their individual // settings. // // When reads from the registry fail, it just moves on to try and get the // next setting. The failed one is just left with its default. In this // way if just one registry entry is broken all the other data will be // obtained rather than just quiting the function. // // Arguments: VOID // // Returns: HRESULT returns status of success or failure of the function // //---------------------------------------------------------------------------- EXTERN_C HRESULT ReadNetworkRegistrySettings( VOID ) { HRESULT hr = S_OK; INetCfg* pNetCfg = NULL; // // Always force a Custom net setting if they are reading from the registry // because I don't want to write the code to see if their current net // configuration is a typical one (when 99.9% of the time it won't be) // NetSettings.iNetworkingMethod = CUSTOM_NETWORKING; hr = InitializeInterfaces( &pNetCfg ); if( FAILED( hr ) ) { return( E_FAIL ); } hr = GetNetworkAdapterSettings( pNetCfg ); if( FAILED( hr ) ) { ReleaseInterfaces( pNetCfg ); return( E_FAIL ); } // // Purposely not catching return values here. Call each one to try and // grab as many parameters as we can. If we hit an error just move on // and try to grab the next value. // GetClientsInstalled( pNetCfg ); GetServicesInstalled( pNetCfg ); GetProtocolsInstalled( pNetCfg ); ReleaseInterfaces( pNetCfg ); GetDomainOrWorkgroup(); return( S_OK ); } //---------------------------------------------------------------------------- // // Function: GetNetworkAdapterSettings // // Purpose: Determines how many network cards are installed and gets there // PnP Ids. It then stores these in the appropriate global variables. // // Arguments: INetCfg *pNetCfg - pointer to a NetCfg object that is already // created and initialized // // Returns: HRESULT returns status of success or failure of the function // //---------------------------------------------------------------------------- static HRESULT GetNetworkAdapterSettings( INetCfg *pNetCfg ) { UINT i; INetCfgComponent* arrayComp[MAX_NUM_NET_COMPONENTS]; IEnumNetCfgComponent* pEnum = NULL; INetCfgClass* pNetCfgClass = NULL; INetCfgComponent* pNetCfgComp = NULL; NETWORK_ADAPTER_NODE* pPreviousNode = NULL; NETWORK_ADAPTER_NODE* pCurrentNode = NULL; HRESULT hr = S_OK; DWORD dwCharacteristics = 0; ULONG iCount = 0; hr = InitializeComInterface( &GUID_DEVCLASS_NET, pNetCfg, pNetCfgClass, pEnum, arrayComp, &iCount ); if( FAILED( hr ) ) { return( hr ); } // // delete the entire list of Network Adapters so we can start fresh // DeleteList( NetSettings.NetworkAdapterHead ); NetSettings.NetworkAdapterHead = NULL; NetSettings.iNumberOfNetworkCards = 0; AssertMsg( iCount <= MAX_NUM_NET_COMPONENTS, "Too many network components to work with" ); for( i = 0; i < iCount; i++ ) { pNetCfgComp = arrayComp[i]; hr = ChkInterfacePointer( pNetCfgComp, IID_INetCfgComponent ); if( FAILED( hr ) ) { UninitializeComInterface( pNetCfgClass, pEnum ); return( hr ); } hr = pNetCfgComp->GetCharacteristics( &dwCharacteristics ); if( FAILED( hr ) ) { UninitializeComInterface( pNetCfgClass, pEnum ); return( hr ); } // // If this is a physical adapter // if( dwCharacteristics & NCF_PHYSICAL ) { NetSettings.iNumberOfNetworkCards++; hr = SetupAdapter( &pCurrentNode, pNetCfgComp ); if( FAILED( hr ) ) { UninitializeComInterface( pNetCfgClass, pEnum ); return( hr ); } // // Adjust pointers to maintain the doubly linked-list // pCurrentNode->previous = pPreviousNode; if( pPreviousNode != NULL ) { pPreviousNode->next = pCurrentNode; } pPreviousNode = pCurrentNode; } if( pNetCfgComp ) { pNetCfgComp->Release(); } } // // if there is a network card in this machine, set the current network card // to be the first one, else zero out the values // if( NetSettings.iNumberOfNetworkCards > 0 ) { NetSettings.iCurrentNetworkCard = 1; NetSettings.pCurrentAdapter = NetSettings.NetworkAdapterHead; } else { NetSettings.iCurrentNetworkCard = 0; NetSettings.NetworkAdapterHead = NULL; NetSettings.pCurrentAdapter = NULL; } UninitializeComInterface( pNetCfgClass, pEnum ); return( S_OK ); } //---------------------------------------------------------------------------- // // Function: GetClientsInstalled // // Purpose: For each client, it finds out if it is installed on the current // system and if it is then it reads its settings from the registry // // Arguments: INetCfg *pNetCfg - pointer to a NetCfg object that is already // created and initialized // // Returns: HRESULT returns status of success or failure of the function // //---------------------------------------------------------------------------- static HRESULT GetClientsInstalled( INetCfg *pNetCfg ) { INetCfgComponent* arrayComp[MAX_NUM_NET_COMPONENTS]; IEnumNetCfgComponent* pEnum = NULL; INetCfgClass* pNetCfgClass = NULL; INetCfgComponent* pNetCfgComp = NULL; HRESULT hr = S_OK; ULONG iCount = 0; LPWSTR pszwDisplayName = NULL; HKEY hKey; UINT i; NETWORK_COMPONENT* pMsClientComponent = NULL; NETWORK_COMPONENT* pNetwareComponent = NULL; // // Initialize each of the pointers to point into its proper place in the // global network component list // pMsClientComponent = FindNode( MS_CLIENT_POSITION ); pNetwareComponent = FindNode( NETWARE_CLIENT_POSITION ); hr = InitializeComInterface( &GUID_DEVCLASS_NETCLIENT, pNetCfg, pNetCfgClass, pEnum, arrayComp, &iCount ); if( FAILED( hr ) ) { return( hr ); } for( i = 0; i < iCount; i++ ) { pNetCfgComp = arrayComp[i]; hr = ChkInterfacePointer( pNetCfgComp, IID_INetCfgComponent ); if( FAILED( hr ) ) { UninitializeComInterface( pNetCfgClass, pEnum ); return( hr ); } hr = pNetCfgComp->GetDisplayName( &pszwDisplayName ); if( FAILED( hr ) ) { UninitializeComInterface( pNetCfgClass, pEnum ); return( hr ); } if( lstrcmpi( pMsClientComponent->StrComponentName, pszwDisplayName ) == 0 ) { // // set the component to Installed // pMsClientComponent->bInstalled = TRUE; hr = pNetCfgComp->OpenParamKey( &hKey ); if( FAILED( hr ) ) { UninitializeComInterface( pNetCfgClass, pEnum ); return( hr ); } // // grab Ms Client settings from the registry // ReadMsClientSettingsFromRegistry( &hKey ); RegCloseKey( hKey ); } else if( lstrcmpi( pNetwareComponent->StrComponentName, pszwDisplayName ) == 0 ) { // // set the component to Installed // pNetwareComponent->bInstalled = TRUE; hr = pNetCfgComp->OpenParamKey( &hKey ); if( FAILED( hr ) ) { UninitializeComInterface( pNetCfgClass, pEnum ); return( hr ); } // // grab Netware settings from the registry // ReadNetwareSettingsFromRegistry( &hKey ); RegCloseKey( hKey ); } CoTaskMemFree( pszwDisplayName ); if( pNetCfgComp ) { pNetCfgComp->Release(); } } UninitializeComInterface( pNetCfgClass, pEnum ); return( S_OK ); } //---------------------------------------------------------------------------- // // Function: GetServicesInstalled // // Purpose: For each service, it finds out if it is installed on the current // system and if it is then it sets its component to Installed = TRUE // // Arguments: INetCfg *pNetCfg - pointer to a NetCfg object that is already // created and initialized // // Returns: HRESULT returns status of success or failure of the function // //---------------------------------------------------------------------------- static HRESULT GetServicesInstalled( INetCfg *pNetCfg ) { INetCfgComponent* arrayComp[MAX_NUM_NET_COMPONENTS]; IEnumNetCfgComponent* pEnum = NULL; INetCfgClass* pNetCfgClass = NULL; INetCfgComponent* pNetCfgComp = NULL; LPWSTR pszwDisplayName = NULL; HRESULT hr = S_OK; ULONG iCount = 0; UINT i; NETWORK_COMPONENT* pFilePrintSharingComponent = NULL; NETWORK_COMPONENT* pPacketSchedulingComponent = NULL; // // Initialize each of the pointers to point into its proper place in the // global network component list // pFilePrintSharingComponent = FindNode( FILE_AND_PRINT_SHARING_POSITION ); pPacketSchedulingComponent = FindNode( PACKET_SCHEDULING_POSITION ); hr = InitializeComInterface( &GUID_DEVCLASS_NETCLIENT, pNetCfg, pNetCfgClass, pEnum, arrayComp, &iCount ); if( FAILED( hr ) ) { return( hr ); } for( i = 0; i < iCount; i++ ) { pNetCfgComp = arrayComp[i]; hr = ChkInterfacePointer( pNetCfgComp, IID_INetCfgComponent ); if( FAILED( hr ) ) { UninitializeComInterface( pNetCfgClass, pEnum ); return( hr ); } hr = pNetCfgComp->GetDisplayName( &pszwDisplayName ); if( FAILED( hr ) ) { UninitializeComInterface( pNetCfgClass, pEnum ); return( hr ); } if( lstrcmpi( pFilePrintSharingComponent->StrComponentName, pszwDisplayName ) == 0 ) { // // only have to set the component to Installed, no settings to read // pFilePrintSharingComponent->bInstalled = TRUE; } else if( lstrcmpi( pPacketSchedulingComponent->StrComponentName, pszwDisplayName ) == 0 ) { // // only have to set the component to Installed, no settings to read // pPacketSchedulingComponent->bInstalled = TRUE; } CoTaskMemFree( pszwDisplayName ); if( pNetCfgComp ) { pNetCfgComp->Release(); } } UninitializeComInterface( pNetCfgClass, pEnum ); return( S_OK ); } //---------------------------------------------------------------------------- // // Function: GetProtocolsInstalled // // Purpose: For each protocol, it finds out if it is installed on the current // system and if it is then it reads its settings from the registry // // Arguments: INetCfg *pNetCfg - pointer to a NetCfg object that is already // created and initialized // // Returns: HRESULT returns status of success or failure of the function // //---------------------------------------------------------------------------- static HRESULT GetProtocolsInstalled( INetCfg *pNetCfg ) { INetCfgComponent* arrayComp[MAX_NUM_NET_COMPONENTS]; IEnumNetCfgComponent* pEnum = NULL; INetCfgClass* pNetCfgClass = NULL; INetCfgComponent* pNetCfgComp = NULL; LPWSTR pszwDisplayName = NULL; HKEY hKey = NULL; HRESULT hr = S_OK; ULONG iCount = 0; UINT i; NETWORK_COMPONENT* pTcpipComponent = NULL; NETWORK_COMPONENT* pIpxComponent = NULL; NETWORK_COMPONENT* pNetBeuiComponent = NULL; NETWORK_COMPONENT* pDlcComponent = NULL; NETWORK_COMPONENT* pNetworkMonitorComponent = NULL; NETWORK_COMPONENT* pAppletalkComponent = NULL; // // Initialize each of the pointers to point into its proper place in the // global network component list // pTcpipComponent = FindNode( TCPIP_POSITION ); pIpxComponent = FindNode( IPX_POSITION ); pNetBeuiComponent = FindNode( NETBEUI_POSITION ); pDlcComponent = FindNode( DLC_POSITION ); pNetworkMonitorComponent = FindNode( NETWORK_MONITOR_AGENT_POSITION ); pAppletalkComponent = FindNode( APPLETALK_POSITION ); hr = InitializeComInterface( &GUID_DEVCLASS_NETTRANS, pNetCfg, pNetCfgClass, pEnum, arrayComp, &iCount ); if( FAILED( hr ) ) { return( hr ); } for( i = 0; i < iCount; i++ ) { pNetCfgComp = arrayComp[i]; hr = ChkInterfacePointer( pNetCfgComp, IID_INetCfgComponent ); if( FAILED( hr ) ) { UninitializeComInterface( pNetCfgClass, pEnum ); return( hr ); } hr = pNetCfgComp->GetDisplayName( &pszwDisplayName ); if( FAILED( hr ) ) { UninitializeComInterface( pNetCfgClass, pEnum ); return( hr ); } if( lstrcmpi( pTcpipComponent->StrComponentName, pszwDisplayName ) == 0 ) { // // set the component to Installed // pTcpipComponent->bInstalled = TRUE; hr = pNetCfgComp->OpenParamKey( &hKey ); if( SUCCEEDED( hr ) ) { // // grab TCP/IP settings from the registry // ReadTcpipSettingsFromRegistry( &hKey ); } RegCloseKey( hKey ); } else if( lstrcmpi( pIpxComponent->StrComponentName, pszwDisplayName ) == 0 ) { // // set the component to Installed // pIpxComponent->bInstalled = TRUE; hr = pNetCfgComp->OpenParamKey( &hKey ); if( SUCCEEDED( hr ) ) { // grab IPX settings from the registry ReadIpxSettingsFromRegistry( &hKey ); } RegCloseKey( hKey ); } else if( lstrcmpi( pNetBeuiComponent->StrComponentName, pszwDisplayName ) == 0 ) { // // only have to set the component to Installed, no settings to read // pNetBeuiComponent->bInstalled = TRUE; } else if( lstrcmpi( pDlcComponent->StrComponentName, pszwDisplayName ) == 0 ) { // // only have to set the component to Installed, no settings to read // pDlcComponent->bInstalled = TRUE; } else if( lstrcmpi( pNetworkMonitorComponent->StrComponentName, pszwDisplayName ) == 0 ) { // // only have to set the component to Installed, no settings to read // pNetworkMonitorComponent->bInstalled = TRUE; } else if( lstrcmpi( pAppletalkComponent->StrComponentName, pszwDisplayName ) == 0 ) { // // set the component to Installed // pAppletalkComponent->bInstalled = TRUE; hr = pNetCfgComp->OpenParamKey( &hKey ); if( SUCCEEDED( hr ) ) { // grab Appletalk settings from the registry ReadAppletalkSettingsFromRegistry( &hKey ); } RegCloseKey( hKey ); } CoTaskMemFree( pszwDisplayName ); if( pNetCfgComp ) { pNetCfgComp->Release(); } } UninitializeComInterface( pNetCfgClass, pEnum ); return( S_OK ); } //---------------------------------------------------------------------------- // // Function: GetDomainOrWorkgroup // // Purpose: Find out if this machine is a member of a workgroup or domain and // then fill the global structs with the proper name. // // Arguments: VOID // // Returns: VOID // //---------------------------------------------------------------------------- static VOID GetDomainOrWorkgroup( VOID ) { BOOL bDomain = FALSE; TCHAR szDomainOrWorkgroup[MAX_WORKGROUP_LENGTH + 1] = _T(""); // // Get the domain/workgoup // if( LSA_SUCCESS( GetDomainMembershipInfo( &bDomain, szDomainOrWorkgroup ) ) ) { if( bDomain ) { lstrcpyn( NetSettings.DomainName, szDomainOrWorkgroup, AS(NetSettings.DomainName) ); NetSettings.bWorkgroup = FALSE; } else { lstrcpyn( NetSettings.WorkGroupName, szDomainOrWorkgroup, AS(NetSettings.WorkGroupName) ); NetSettings.bWorkgroup = TRUE; } } } //---------------------------------------------------------------------------- // // Function: SetupAdapter // // Purpose: Allocates and initializes a new Network adapter struct, then reads // the adapter's PnP Id and it's GUID. // // Arguments: // // Returns: HRESULT returns status of success or failure of the function // On failure, the caller of this function is responsible for calling // UninitializeComInterface() //---------------------------------------------------------------------------- static HRESULT SetupAdapter( NETWORK_ADAPTER_NODE **ppCurrentNode, INetCfgComponent *pNetCfgComp ) { HRESULT hr = S_OK; LPWSTR pszwPnPID = NULL; *ppCurrentNode = (NETWORK_ADAPTER_NODE *)malloc( sizeof( NETWORK_ADAPTER_NODE ) ); if (*ppCurrentNode == NULL) return (E_FAIL); // // Initialize all the Network namelists to 0s // ZeroOut( *ppCurrentNode ); // // Set all network card settings to their default values // ResetNetworkAdapter( *ppCurrentNode ); if( NetSettings.iNumberOfNetworkCards == 1 ) { NetSettings.NetworkAdapterHead = *ppCurrentNode; } // // Get the Plug and Play Id // hr = pNetCfgComp->GetId( &pszwPnPID ); if( SUCCEEDED( hr ) ) { hr=StringCchCopy( (*ppCurrentNode)->szPlugAndPlayID, AS((*ppCurrentNode)->szPlugAndPlayID), pszwPnPID ); CoTaskMemFree( pszwPnPID ); } // // Get the Guid for this network adapter // hr = pNetCfgComp->GetInstanceGuid( &((*ppCurrentNode)->guid) ); if( FAILED( hr ) ) { // // this call failed so any call to the registry will fail since it // needs this guid // return( hr ); } return( S_OK ); } //---------------------------------------------------------------------------- // // Function: ReadNetwareSettingsFromRegistry // // Purpose: Read in registry settings on Netware and fill the global structs // with the appropriate values // // Arguments: HKEY *hKey // // Returns: HRESULT returns status of success or failure of the function // //---------------------------------------------------------------------------- static VOID ReadNetwareSettingsFromRegistry( IN HKEY *hKey ) { REGSAM SecurityAccess = KEY_QUERY_VALUE; // ISSUE-2002/02/28-stelo- write this function } //---------------------------------------------------------------------------- // // Function: ReadMsClientSettingsFromRegistry // // Purpose: Read in registry settings on MS Client and fill the global structs // with the appropriate values // // Arguments: HKEY *hKey // // Returns: HRESULT returns status of success or failure of the function // //---------------------------------------------------------------------------- static VOID ReadMsClientSettingsFromRegistry( IN HKEY *hKey ) { HKEY hNameServiceKey = NULL; REGSAM SecurityAccess = KEY_QUERY_VALUE; DWORD dwSize = 0; TCHAR szBuffer[BUFFER_SIZE]; // ISSUE-2002/02/28-stelo- I don't use the hKey passed in. For some reason, the Network // component objects don't point to the section of the registry I need // to read from. Is this a bug with Network Component Objects? dwSize = sizeof( szBuffer ); if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, REGKEY_MSCLIENT_LOCATION, 0, SecurityAccess, &hNameServiceKey ) != ERROR_SUCCESS ) { // // need this key to read in other MS Client values so bail if we // can't get it // return; } if( RegQueryValueEx( hNameServiceKey, REGVAL_NAME_SERVICE_PROVIDER, NULL, NULL, (LPBYTE) szBuffer, &dwSize ) == ERROR_SUCCESS ) { if ( LSTRCMPI(szBuffer, _T("ncacn_ip_tcp")) == 0 ) { NetSettings.NameServiceProvider = MS_CLIENT_DCE_CELL_DIR_SERVICE; dwSize = sizeof( szBuffer ); if( RegQueryValueEx( hNameServiceKey, REGVAL_NETWORK_ADDRESS, 0, NULL, (LPBYTE) szBuffer, &dwSize) == ERROR_SUCCESS ) { lstrcpyn( NetSettings.szNetworkAddress, szBuffer, MAX_NETWORK_ADDRESS_LENGTH + 1 ); } } else { NetSettings.NameServiceProvider = MS_CLIENT_WINDOWS_LOCATOR; } } RegCloseKey( hNameServiceKey ); } //---------------------------------------------------------------------------- // // Function: ReadAppletalkSettingsFromRegistry // // Purpose: Read in registry settings on Appletalk and fill the global structs // with the appropriate values // // Arguments: HKEY *hKey // // Returns: HRESULT returns status of success or failure of the function // //---------------------------------------------------------------------------- static VOID ReadAppletalkSettingsFromRegistry( IN HKEY *hKey ) { REGSAM SecurityAccess = KEY_QUERY_VALUE; // ISSUE-2002/02/28-stelo- write this function } //---------------------------------------------------------------------------- // // Function: ReadIpxSettingsFromRegistry // // Purpose: Read in registry settings on IPX and fill the global structs // with the appropriate values // // Arguments: HKEY *hKey // // Returns: HRESULT returns status of success or failure of the function // //---------------------------------------------------------------------------- static VOID ReadIpxSettingsFromRegistry( IN HKEY *hKey ) { REGSAM SecurityAccess = KEY_QUERY_VALUE; HKEY hIpxAdaptersKey = NULL; HKEY hNetworkAdapterKey = NULL; DWORD dwSize = 0; NETWORK_ADAPTER_NODE *pNetAdapter = NULL; WCHAR szStringGuid[MAX_GUID_STRING]; TCHAR szBuffer[BUFFER_SIZE]; if( RegOpenKeyEx( *hKey, REGVAL_ADAPTERS, 0, SecurityAccess, &hIpxAdaptersKey ) != ERROR_SUCCESS ) { // // need this key to read in other IPX values so bail if we can't get it // return; } dwSize = sizeof( szBuffer ); if( RegQueryValueEx( *hKey, REGVAL_VIRTUAL_NETWORK_NUMBER, 0, NULL, (LPBYTE) szBuffer, &dwSize ) == ERROR_SUCCESS ) { lstrcpyn( NetSettings.szInternalNetworkNumber, szBuffer, MAX_INTERNAL_NET_NUMBER_LEN + 1 ); } // // For each Network Adapter, load its IPX settings // for( pNetAdapter = NetSettings.NetworkAdapterHead; pNetAdapter; pNetAdapter = pNetAdapter->next ) { StringFromGUID2( pNetAdapter->guid, szStringGuid, StrBuffSize( szStringGuid ) ); if( RegOpenKeyEx( hIpxAdaptersKey, szStringGuid, 0, SecurityAccess, &hNetworkAdapterKey ) == ERROR_SUCCESS ) { dwSize = sizeof( szBuffer ); if( RegQueryValueEx( hNetworkAdapterKey, REGVAL_PKT_TYPE, 0, NULL, (LPBYTE) szBuffer, &dwSize) == ERROR_SUCCESS ) { lstrcpyn( pNetAdapter->szFrameType, _T("0x"), AS(pNetAdapter->szFrameType) ); lstrcatn( pNetAdapter->szFrameType, szBuffer, MAX_FRAMETYPE_LEN ); } dwSize = sizeof( szBuffer ); if( RegQueryValueEx( hNetworkAdapterKey, REGVAL_NETWORK_NUMBER, 0, NULL, (LPBYTE) szBuffer, &dwSize) == ERROR_SUCCESS ) { lstrcpyn( pNetAdapter->szNetworkNumber, szBuffer, MAX_NET_NUMBER_LEN + 1 ); } } } } //---------------------------------------------------------------------------- // // Function: ReadTcpipSettingsFromRegistry // // Purpose: Read in registry settings on TCP/IP and fill the global structs // with the appropriate values // // Arguments: HKEY *hKey - // // Returns: HRESULT returns status of success or failure of the function // //---------------------------------------------------------------------------- static VOID ReadTcpipSettingsFromRegistry( IN HKEY *hKey ) { HKEY hTcpipInterfaceKey = NULL; REGSAM SecurityAccess = KEY_QUERY_VALUE; NETWORK_ADAPTER_NODE *pNetAdapter = NULL; if( RegOpenKeyEx( *hKey, REGVAL_INTERFACES, 0, SecurityAccess, &hTcpipInterfaceKey ) != ERROR_SUCCESS ) { // // need this key to read in all other TCP/IP values so bail if we can't get it // return; } // // For each Network Adapter, load its TCP/IP settings // for( pNetAdapter = NetSettings.NetworkAdapterHead; pNetAdapter; pNetAdapter = pNetAdapter->next ) { ReadAdapterSpecificTcpipSettings( hTcpipInterfaceKey, pNetAdapter ); } // ISSUE-2002/20/28-stelo -not reading in LM Hosts setting } //---------------------------------------------------------------------------- // // Function: ReadAdapterSpecificTcpipSettings // // Purpose: Reads network adapter specific TCP/IP settings and populates the // pNetAdapter structure with their values. // // Arguments: // IN HKEY hTcpipInterfaceKey - handle to the TCP/IP settings portion of // the registry // IN OUT NETWORK_ADAPTER_NODE *pNetAdapter - ptr to structure to load the // TCP/IP values into // // Returns: VOID // //---------------------------------------------------------------------------- static VOID ReadAdapterSpecificTcpipSettings( IN HKEY hTcpipInterfaceKey, IN OUT NETWORK_ADAPTER_NODE *pNetAdapter ) { DWORD dwDHCP = 0; DWORD dwSize = 0; DWORD dwSize2 = 0; REGSAM SecurityAccess = KEY_QUERY_VALUE; HKEY hNetworkAdapterKey = NULL; LPTSTR lpszBuffer = NULL; LPTSTR lpszBuffer2 = NULL; TCHAR szStringGuid[MAX_GUID_STRING]; // // Make sure we can allocate big enough buffers... // lpszBuffer = (LPTSTR) MALLOC( BUFFER_SIZE * sizeof(TCHAR) ); if ( !lpszBuffer ) { // Unable to allocate memory... bail! return; } lpszBuffer2 = (LPTSTR) MALLOC( BUFFER_SIZE * sizeof(TCHAR) ); if ( !lpszBuffer2 ) { // Unable to allocate memory... bail! FREE( lpszBuffer ); return; } StringFromGUID2( pNetAdapter->guid, szStringGuid, StrBuffSize( szStringGuid ) ); if( RegOpenKeyEx( hTcpipInterfaceKey, szStringGuid, 0, SecurityAccess, &hNetworkAdapterKey ) == ERROR_SUCCESS ) { dwSize = sizeof( dwDHCP ); if( RegQueryValueEx( hNetworkAdapterKey, REGVAL_ENABLE_DHCP, 0, NULL, (LPBYTE) &dwDHCP, &dwSize ) == ERROR_SUCCESS ) { if( dwDHCP == 1 ) { pNetAdapter->bObtainIPAddressAutomatically = TRUE; } else { pNetAdapter->bObtainIPAddressAutomatically = FALSE; } } if( ! pNetAdapter->bObtainIPAddressAutomatically ) { TCHAR *pszIpAddresses; TCHAR *pszSubnetAddresses; TCHAR *pszGatewayAddresses; TCHAR *pszDnsAddresses; TCHAR *pszWinsAddresses; TCHAR szWinsRegPath[MAX_INILINE_LEN + 1] = _T(""); HKEY hWinsKey = NULL; HRESULT hrCat; dwSize = BUFFER_SIZE * sizeof(TCHAR); dwSize2 = BUFFER_SIZE * sizeof(TCHAR); if( (RegQueryValueEx( hNetworkAdapterKey, REGVAL_IPADDRESS, 0, NULL, (LPBYTE) lpszBuffer, &dwSize ) == ERROR_SUCCESS) && (RegQueryValueEx( hNetworkAdapterKey, REGVAL_SUBNETMASK, 0, NULL, (LPBYTE) lpszBuffer2, &dwSize2 ) == ERROR_SUCCESS ) ) { pszIpAddresses = lpszBuffer; // contains the IP Addresses pszSubnetAddresses = lpszBuffer2; // contains the Subnet Masks if( *pszIpAddresses != _T('\0') && *pszSubnetAddresses != _T('\0') ) { // // Add the IP and Subnet masks to their namelists // do { TcpipAddNameToNameList( &pNetAdapter->Tcpip_IpAddresses, pszIpAddresses ); TcpipAddNameToNameList( &pNetAdapter->Tcpip_SubnetMaskAddresses, pszSubnetAddresses ); } while( GetNextIp( &pszIpAddresses ) && GetNextIp( &pszSubnetAddresses ) ); } } dwSize = BUFFER_SIZE * sizeof(TCHAR); if( RegQueryValueEx( hNetworkAdapterKey, REGVAL_DEFAULTGATEWAY, 0, NULL, (LPBYTE) lpszBuffer, &dwSize ) == ERROR_SUCCESS ) { pszGatewayAddresses = lpszBuffer; // contains the Gateway Addresses if( *pszGatewayAddresses != _T('\0') ) { // // Add the Gateways to its namelist // do { AddNameToNameList( &pNetAdapter->Tcpip_GatewayAddresses, pszGatewayAddresses ); } while( GetNextIp( &pszGatewayAddresses ) ); } } // // Get the DNS IPs // dwSize = BUFFER_SIZE * sizeof(TCHAR); if( RegQueryValueEx( hNetworkAdapterKey, REGVAL_NAMESERVER, 0, NULL, (LPBYTE) lpszBuffer, &dwSize ) == ERROR_SUCCESS ) { pszDnsAddresses = lpszBuffer; // Contains the DNS addresses if( *pszDnsAddresses != _T('\0') ) { TCHAR szDnsBuffer[MAX_INILINE_LEN + 1]; NetSettings.bObtainDNSServerAutomatically = FALSE; // // Loop grabbing the DNS IPs and inserting them into // its namelist // while( GetCommaDelimitedEntry( szDnsBuffer, &pszDnsAddresses ) ) { TcpipAddNameToNameList( &pNetAdapter->Tcpip_DnsAddresses, szDnsBuffer ); } } } // // Get the WINS server list // // Have to jump to different location in the registry to read // the WINS data // // // Build up the WINS registry path // lstrcpyn( szWinsRegPath, REGVAL_WINS, AS(szWinsRegPath) ); hrCat=StringCchCat( szWinsRegPath, AS(szWinsRegPath), szStringGuid ); // // Grab all the WINS values from the registry // if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, szWinsRegPath, 0, SecurityAccess, &hWinsKey ) != ERROR_SUCCESS ) { // // need this key to read in the WINS values so bail if we // can't get it // return; } dwSize = BUFFER_SIZE * sizeof(TCHAR); if( RegQueryValueEx( hWinsKey, REGVAL_NAMESERVERLIST, NULL, NULL, (LPBYTE) lpszBuffer, &dwSize ) == ERROR_SUCCESS ) { pszWinsAddresses = lpszBuffer; if( *pszWinsAddresses != _T('\0') ) { // // Add the WINS IPs to the namelist // do { AddNameToNameList( &pNetAdapter->Tcpip_WinsAddresses, pszWinsAddresses ); } while( GetNextIp( &pszWinsAddresses ) ); } } // // Get the Domain // dwSize = BUFFER_SIZE * sizeof(TCHAR); if( RegQueryValueEx( hNetworkAdapterKey, REGVAL_DOMAIN, 0, NULL, (LPBYTE) lpszBuffer, &dwSize ) == ERROR_SUCCESS ) { lstrcpyn( pNetAdapter->szDNSDomainName, lpszBuffer, MAX_DNS_DOMAIN_LENGTH + 1 ); } // ISSUE-2002/20/28-stelo- not reading the NetBiosOption } } } //---------------------------------------------------------------------------- // // Function: GetNextIp // // Purpose: Gets the next string in a multi-NULL terminated string // // Arguments: TCHAR *ppszString - pointer to the current string // // Returns: BOOL - TRUE if ppszString points to the IP string // FALSE if there are no more IP strings left // TCHAR *ppszString - on TRUE, points to the next IP string // - on FALSE, points to NULL // //---------------------------------------------------------------------------- static BOOL GetNextIp( IN OUT TCHAR **ppszString ) { while( **ppszString != _T('\0') ) { (*ppszString)++; } // // check that Char after the one we are currently looking at to see if it // is the true end of the string(s) // if( *( (*ppszString) + 1 ) == _T('\0') ) { // // 2 NULLs in a row signify there are no more IPs to read // return( FALSE ); } else { // // Advance one more so we go past the \0 and point to the first char // of the new IP address // (*ppszString)++; return( TRUE ); } } //---------------------------------------------------------------------------- // // Function: GetDomainMembershipInfo // // Purpose: Gets the domain/workgroup for the machine it is running on. // Assumes enough space is already allocated in szName for the copy. // // Arguments: BOOL* bDomainMember - if TRUE, then the contents of szName is a Domain // if FALSE, then the contents of szName is a Workgroup // // Returns: NTSTATUS - returns success or failure of the function // //---------------------------------------------------------------------------- static NTSTATUS GetDomainMembershipInfo( OUT BOOL* bDomainMember, OUT TCHAR *szName ) { NTSTATUS ntstatus; POLICY_PRIMARY_DOMAIN_INFO* ppdi; LSA_OBJECT_ATTRIBUTES loa; LSA_HANDLE hLsa = 0; loa.Length = sizeof(LSA_OBJECT_ATTRIBUTES); loa.RootDirectory = NULL; loa.ObjectName = NULL; loa.Attributes = 0; loa.SecurityDescriptor = NULL; loa.SecurityQualityOfService = NULL; ntstatus = LsaOpenPolicy( NULL, &loa, POLICY_VIEW_LOCAL_INFORMATION, &hLsa ); if( LSA_SUCCESS( ntstatus ) ) { ntstatus = LsaQueryInformationPolicy( hLsa, PolicyPrimaryDomainInformation, (VOID **) &ppdi ); if( LSA_SUCCESS( ntstatus ) ) { if( ppdi->Sid > 0 ) { *bDomainMember = TRUE; } else { *bDomainMember = FALSE; } lstrcpyn( szName, ppdi->Name.Buffer, AS(szName) ); } LsaClose( hLsa ); } return( ntstatus ); } //---------------------------------------------------------------------------- // // Function: InitializeComInterface // // Purpose: Obtains the INetCfgClass interface and enumerates all the // components. Handles cleanup of all interfaces if failure // returned. // // Arguments: // const GUID* pGuid - pointer to GUID representing the class of // components represented by the returned pointer // INetCfg* pNetCfg - pointer to initialized INetCfg interface // INetCfgClass** ppNetCfgClass - output parameter pointing to // the interface requested by the GUID // IEnumNetCfgComponent *pEnum - output param that points to an // IEnumNetCfgComponent to get to each individual INetCfgComponent // INetCfgComponent *arrayComp[MAX_NUM_NET_COMPONENTS] - array of all // the INetCfgComponents that correspond to the the given GUID // ULONG* pCount - the number of INetCfgComponents in the array // // Returns: HRESULT - returns status of success or failure of the function // //---------------------------------------------------------------------------- static HRESULT InitializeComInterface( const GUID *pGuid, INetCfg *pNetCfg, INetCfgClass *pNetCfgClass, IEnumNetCfgComponent *pEnum, INetCfgComponent *arrayComp[MAX_NUM_NET_COMPONENTS], ULONG* pCount ) { HRESULT hr; HRESULT TempHr; // // Obtain the INetCfgClass interface pointer // hr = GetClass( pGuid, pNetCfg, &pNetCfgClass ); // // Check validity of the pointer we got back from GetClass // TempHr = ChkInterfacePointer( pNetCfgClass, IID_INetCfgClass ); if( FAILED( hr ) || FAILED( TempHr ) ) { ReleaseInterfaces( pNetCfg ); return( E_FAIL ); } // // Retrieve the enumerator interface // hr = pNetCfgClass->EnumComponents( &pEnum ); if( FAILED( hr ) || FAILED( ChkInterfacePointer( pEnum, IID_IEnumNetCfgComponent ) ) ) { if( pNetCfgClass ) { pNetCfgClass->Release(); } ReleaseInterfaces( pNetCfg ); return( E_FAIL ); } hr = pEnum->Next( MAX_NUM_NET_COMPONENTS, &arrayComp[0], pCount ); if( FAILED( hr ) ) { if( pEnum ) { pEnum->Release(); } if( pNetCfgClass ) { pNetCfgClass->Release(); } ReleaseInterfaces( pNetCfg ); return( E_FAIL ); } return( S_OK ); } //---------------------------------------------------------------------------- // // Function: UninitializeComInterface // // Purpose: To release the Net Config object interfaces. // // Arguments: INetCfgClass *pNetCfgClass - the INetCfgClass to be released // IEnumNetCfgComponent *pEnum - the IEnumNetCfgComponent to be released // // Returns: VOID // //---------------------------------------------------------------------------- static VOID UninitializeComInterface( INetCfgClass *pNetCfgClass, IEnumNetCfgComponent *pEnum ) { if( pNetCfgClass ) { pNetCfgClass->Release(); } if( pEnum ) { pEnum->Release(); } } //---------------------------------------------------------------------------- // // Function: InitializeInterfaces // // Purpose: Initializes COM, creates, and initializes the NetCfg // // Arguments: INetCfg** ppNetCfg - output param that is the created and // initialized INetCfg interface // // Returns: HRESULT - returns status of success or failure of the function // //---------------------------------------------------------------------------- static HRESULT InitializeInterfaces( INetCfg** ppNetCfg ) { HRESULT hr = S_OK; hr = CoInitializeEx( NULL, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE ); if( FAILED( hr ) ) { return( hr ); } hr = CreateAndInitNetCfg( ppNetCfg ); return( hr ); } //---------------------------------------------------------------------------- // // Function: CreateAndInitNetCfg // // Purpose: Instantiate and initalize an INetCfg interface // // Arguments: INetCfg** ppNetCfg - output parameter that is the initialized // INetCfg interface // // Returns: HRESULT - returns status of success or failure of the function // //---------------------------------------------------------------------------- static HRESULT CreateAndInitNetCfg( INetCfg** ppNetCfg ) { HRESULT hr = S_OK; INetCfg* pNetCfg = NULL; if( ( ppNetCfg == NULL ) || IsBadWritePtr( ppNetCfg, sizeof(ppNetCfg) ) ) { return( E_INVALIDARG ); } *ppNetCfg = NULL; hr = CoCreateInstance( CLSID_CNetCfg, NULL, CLSCTX_INPROC_SERVER, IID_INetCfg, reinterpret_cast(&pNetCfg) ); if( FAILED( hr ) ) { return( hr ); } *ppNetCfg = pNetCfg; // // Initialize the INetCfg object. // hr = (*ppNetCfg)->Initialize( NULL ); if( FAILED( hr ) ) { (*ppNetCfg)->Release(); CoUninitialize(); return( hr ); } return( hr ); } //---------------------------------------------------------------------------- // // Function: ReleaseInterfaces // // Purpose: Uninitializes the NetCfg object and releases the interfaces // // Arguments: INetCfg* pNetCfg - the INetCfg interface to be released // // Returns: VOID // //---------------------------------------------------------------------------- static VOID ReleaseInterfaces( INetCfg* pNetCfg ) { HRESULT hr = S_OK; // // Check validity of the pNetCfg interface pointer // hr = ChkInterfacePointer( pNetCfg, IID_INetCfg ); if( FAILED( hr ) ) { return; } if( pNetCfg != NULL ) { pNetCfg->Uninitialize(); pNetCfg->Release(); } CoUninitialize(); return; } //---------------------------------------------------------------------------- // // Function: ChkInterfacePointer // // Purpose: Checks if an interface pointer is valid and if it can query itself // // Arguments: IUnknown* pInterface - interface pointer to check // REFIID IID_IInterface - the IID of parameter 1 // // Returns: HRESULT - returns status of success or failure of the function // //---------------------------------------------------------------------------- static HRESULT ChkInterfacePointer( IUnknown* pInterface, REFIID IID_IInterface ) { HRESULT hr = S_OK; IUnknown* pResInterface = NULL; if( (pInterface == NULL) || IsBadReadPtr( pInterface, sizeof(pInterface) ) ) { hr = E_INVALIDARG; return( hr ); } hr = pInterface->QueryInterface( IID_IInterface, (void**)&pResInterface ); if( FAILED( hr ) ) { return( hr ); } if( pInterface != pResInterface ) { hr = E_FAIL; pResInterface->Release(); return( hr ); } pResInterface->Release(); return( S_OK ); } //---------------------------------------------------------------------------- // // Function: GetClass // // Purpose: Retrieves INetCfgClass for the specified pGuid // // Arguments: const GUID* pGuid - pointer to GUID representing the class of // components represented by the returned pointer // INetCfg* pNetCfg - pointer to initialized INetCfg interface // INetCfgClass** ppNetCfgClass - output parameter pointing to // the interface requested by the GUID // // Returns: HRESULT - returns status of success or failure of the function // //---------------------------------------------------------------------------- static HRESULT GetClass( const GUID* pGuid, INetCfg* pNetCfg, INetCfgClass** ppNetCfgClass ) { HRESULT hr = S_OK; INetCfgClass* pNetCfgClass = NULL; hr = ChkInterfacePointer( pNetCfg, IID_INetCfg ); if( FAILED( hr ) ) { return( E_INVALIDARG ); } if( IsBadWritePtr( ppNetCfgClass, sizeof(ppNetCfgClass) ) ) { return( E_INVALIDARG ); } hr = pNetCfg->QueryNetCfgClass( pGuid, IID_INetCfgClass, (void**)&pNetCfgClass ); if( FAILED( hr ) ) { return( hr ); } *ppNetCfgClass = pNetCfgClass; return( hr ); }