|
|
/*++
Copyright (c) 2001 Microsoft Corporation
Module Name:
winpenet.c
Abstract:
This module contains code to control the startup of the network in the WinPE environment. It relies upon the existence of WINBOM.INI and the following sections: [WinPE.net] Startnet = YES | NO - Specifies whether to start networking. Ipconfig = DHCP | x.x.x.x - Specifies DHCP or a static IP address. SubnetMask = x.x.x.x - SubnetMask for the static IP. Gateway = x.x.x.x - Default gateway for the static IP.
Author:
Adrian Cosma (acosma) - 1/18/2001
Revision History:
--*/
//
// Includes
//
#include "factoryp.h"
#include <winsock2.h>
//
// Defines
//
typedef HRESULT (PASCAL *PRegisterServer)(VOID);
//
// Static strings
//
const static TCHAR DEF_GATEWAY_METRIC[] = _T("1\0"); // Need to NULLCHRs at the end since this goes into a REG_MULTI_SZ.
const static TCHAR REGSTR_TCPIP[] = _T("SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\");
//
// Local function declarations
//
static BOOL InstallNetComponents(VOID); static BOOL RegisterDll(VOID);
//
// Function implementations
//
static BOOL InstallNetComponents(VOID) { TCHAR szCmdLine[MAX_PATH] = NULLSTR; DWORD dwExitCode = 0; BOOL bRet = TRUE;
lstrcpyn(szCmdLine, _T("-winpe"), AS ( szCmdLine ) ) ;
if ( !InvokeExternalApplicationEx(_T("netcfg"), szCmdLine, &dwExitCode, INFINITE, TRUE) ) { FacLogFile(0 | LOG_ERR, IDS_ERR_NETWORKCOMP); bRet = FALSE; } return bRet; }
static BOOL RegisterDll(VOID) { HMODULE hDll = NULL; BOOL bRet = FALSE;
PRegisterServer pRegisterServer = NULL; if ( (hDll = LoadLibrary(_T("netcfgx.dll"))) && (pRegisterServer = (PRegisterServer) GetProcAddress(hDll, "DllRegisterServer")) && (S_OK == pRegisterServer()) ) { FacLogFileStr(3, _T("Succesfully registered netcfg.dll.\n")); bRet = TRUE; } else { FacLogFile(0 | LOG_ERR, IDS_ERR_REGISTERNETCFG); }
if (hDll) FreeLibrary(hDll); return bRet; }
BOOL WinpeNet(LPSTATEDATA lpStateData) { LPTSTR lpszWinBOMPath = lpStateData->lpszWinBOMPath; SC_HANDLE hSCM = NULL; TCHAR szBuf[MAX_WINPE_PROFILE_STRING] = NULLSTR; BOOL bRet = TRUE; // Make sure that the user wants us to do networking.
//
GetPrivateProfileString(INI_KEY_WBOM_WINPE_NET, INI_KEY_WBOM_WINPE_NET_STARTNET, NULLSTR, szBuf, AS(szBuf), lpszWinBOMPath);
// If user does not want to start networking just return success.
//
if ( 0 == LSTRCMPI(szBuf, WBOM_NO) ) return TRUE;
// Register dll.
// Run netcfg -winpe.
// Install network card.
// See if the user wants to use a static IP.
//
if ( RegisterDll() && SetupMiniNT() && InstallNetComponents() && ConfigureNetwork(g_szWinBOMPath) ) { //
// Start Services for networking.
//
if ( hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS) ) { // DHCP also starts tcpip and netbt.
// The workstation service should already be started by the installer.
//
if ( (StartMyService(_T("dhcp"), hSCM) != NO_ERROR) || (StartMyService(_T("nla"), hSCM) != NO_ERROR) ) { FacLogFile(0 | LOG_ERR, IDS_ERR_NETSERVICES); bRet = FALSE; } CloseServiceHandle(hSCM); } else { FacLogFile(0 | LOG_ERR, IDS_ERR_SCM); bRet = FALSE; } } else { FacLogFile(0 | LOG_ERR, IDS_ERR_SETUPNETWORK); bRet = FALSE; } return bRet; }
BOOL DisplayWinpeNet(LPSTATEDATA lpStateData) { return ( !IniSettingExists(lpStateData->lpszWinBOMPath, INI_KEY_WBOM_WINPE_NET, INI_KEY_WBOM_WINPE_NET_STARTNET, INI_VAL_WBOM_NO) ); }
BOOL ConfigureNetwork(LPTSTR lpszWinBOMPath) { TCHAR szBuf[MAX_WINPE_PROFILE_STRING] = NULLSTR; CHAR szBufA[MAX_WINPE_PROFILE_STRING] = { 0 }; TCHAR szReg[MAX_WINPE_PROFILE_STRING] = NULLSTR; TCHAR szIpAddress[MAX_WINPE_PROFILE_STRING] = NULLSTR; TCHAR szSubnetMask[MAX_WINPE_PROFILE_STRING] = NULLSTR; HKEY hKey = NULL; // Reg Key to interfaces.
HKEY hKeyI = NULL; // Reg Key to specific network interface.
DWORD dwDis = 0; TCHAR szRegKey[MAX_PATH] = NULLSTR; DWORD dwEnableDHCP = 0; BOOL fErr = FALSE;
szBuf[0] = NULLCHR; GetPrivateProfileString(INI_KEY_WBOM_WINPE_NET, WBOM_WINPE_NET_IPADDRESS, NULLSTR, szBuf, MAX_WINPE_PROFILE_STRING, lpszWinBOMPath); // Convert the string to ANSI
//
if ( szBuf[0] && WideCharToMultiByte(CP_ACP, 0, szBuf, -1, szBufA, AS(szBufA), NULL, NULL) ) { // If it's DHCP don't do anything. Just return TRUE.
//
if ( 0 == LSTRCMPI(szBuf, _T("DHCP")) ) return TRUE; if ( INADDR_NONE == inet_addr(szBufA) ) { FacLogFile(0 | LOG_ERR, IDS_ERR_INVALIDIP , szBuf); return FALSE; } } else // if there is no IpConfig entry return success (same as DHCP)
return TRUE;
// Save the IpAddress.
lstrcpyn(szIpAddress, szBuf, AS ( szIpAddress ) );
szBuf[0] = NULLCHR; GetPrivateProfileString(INI_KEY_WBOM_WINPE_NET, WBOM_WINPE_NET_SUBNETMASK, NULLSTR, szBuf, MAX_WINPE_PROFILE_STRING, lpszWinBOMPath); // Convert the string to ANSI
//
if ( szBuf[0] && WideCharToMultiByte(CP_ACP,0, szBuf, -1, szBufA, AS(szBufA), NULL, NULL) ) { if ( INADDR_NONE == inet_addr(szBufA) ) { FacLogFile(0 | LOG_ERR, IDS_ERR_INVALIDMASK , szBuf); return FALSE; } } else // If we got this far we need to have a subnet mask
{ FacLogFile(0 | LOG_ERR, IDS_ERR_NOMASK); return FALSE; }
// Save the SubnetMask.
lstrcpyn(szSubnetMask, szBuf, AS ( szSubnetMask ) ); //
// Write the settings to the registry.
//
// Make sure that the strings are terminated by two NULLCHRs.
//
szIpAddress[lstrlen(szIpAddress) + 1] = NULLCHR; szSubnetMask[lstrlen(szSubnetMask) + 1] = NULLCHR;
// Assuming that there is only one interface in the system.
//
if ( (RegCreateKeyEx(HKEY_LOCAL_MACHINE, REGSTR_TCPIP, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dwDis) == ERROR_SUCCESS) && (RegEnumKey(hKey, 0, szRegKey, AS(szRegKey)) == ERROR_SUCCESS) && szRegKey[0] && (RegCreateKeyEx(hKey, szRegKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKeyI, &dwDis) == ERROR_SUCCESS) ) { if ( ERROR_SUCCESS != (RegSetValueEx(hKeyI, _T("IPAddress"), 0, REG_MULTI_SZ, (CONST LPBYTE) szIpAddress, ( lstrlen(szIpAddress) + 2 ) * sizeof(TCHAR))) || ERROR_SUCCESS != (RegSetValueEx(hKeyI, _T("SubnetMask"), 0, REG_MULTI_SZ, (CONST LPBYTE) szSubnetMask, ( lstrlen(szSubnetMask) + 2 ) * sizeof(TCHAR))) || ERROR_SUCCESS != (RegSetValueEx(hKeyI, _T("EnableDHCP"), 0, REG_DWORD, (CONST LPBYTE) &dwEnableDHCP, sizeof(dwEnableDHCP))) ) { FacLogFile(0 | LOG_ERR, IDS_ERR_IPREGISTRY); fErr = TRUE; } else { //
// If the gateway is not specified we don't care. We're just not going to add this
// if it's not there.
//
szBuf[0] = NULLCHR; GetPrivateProfileString(INI_KEY_WBOM_WINPE_NET, WBOM_WINPE_NET_GATEWAY, NULLSTR, szBuf, MAX_WINPE_PROFILE_STRING, lpszWinBOMPath);
if ( szBuf[0] && WideCharToMultiByte(CP_ACP,0, szBuf, -1, szBufA, AS(szBufA), NULL, NULL) ) { if ( INADDR_NONE == inet_addr(szBufA) ) { FacLogFile(0 | LOG_ERR, IDS_ERR_INVALIDGW, szBuf); fErr = TRUE; } else { szBuf[lstrlen(szBuf) + 1] = NULLCHR;
if ( (RegSetValueEx(hKeyI, _T("DefaultGateway"), 0, REG_MULTI_SZ, (CONST LPBYTE) szBuf, ( lstrlen(szBuf) + 2 ) * sizeof(TCHAR)) != ERROR_SUCCESS) || (RegSetValueEx(hKeyI, _T("DefaultGatewayMetric"), 0, REG_MULTI_SZ, (CONST LPBYTE) DEF_GATEWAY_METRIC, ( lstrlen(DEF_GATEWAY_METRIC) + 2 ) * sizeof(TCHAR)) != ERROR_SUCCESS) ) { FacLogFile(0 | LOG_ERR, IDS_ERR_GWREGISTRY); fErr = TRUE; } } } } RegCloseKey(hKeyI); } else { FacLogFile(0 | LOG_ERR, IDS_ERR_IPREGISTRY); } // It is possible that the subkey failed to open so this takes care of a possible leak.
//
if (hKey) RegCloseKey(hKey);
return (!fErr); }
static DWORD WaitForServiceStart(SC_HANDLE schService) { SERVICE_STATUS ssStatus; DWORD dwOldCheckPoint; DWORD dwStartTickCount; DWORD dwWaitTime; DWORD dwStatus = NO_ERROR; if ( schService ) { //
// Service start is now pending.
// Check the status until the service is no longer start pending.
//
if ( QueryServiceStatus( schService, &ssStatus) ) { // Save the tick count and initial checkpoint.
//
dwStartTickCount = GetTickCount(); dwOldCheckPoint = ssStatus.dwCheckPoint;
while (ssStatus.dwCurrentState == SERVICE_START_PENDING) { // Do not wait longer than the wait hint. A good interval is
// one tenth the wait hint, but no less than 1 second and no
// more than 10 seconds.
//
dwWaitTime = ssStatus.dwWaitHint / 10;
if( dwWaitTime < 1000 ) dwWaitTime = 1000; else if ( dwWaitTime > 10000 ) dwWaitTime = 10000;
Sleep( dwWaitTime );
// Check the status again.
//
if (!QueryServiceStatus( schService, // handle to service
&ssStatus) ) // address of structure
break; if ( ssStatus.dwCheckPoint > dwOldCheckPoint ) { // The service is making progress.
//
dwStartTickCount = GetTickCount(); dwOldCheckPoint = ssStatus.dwCheckPoint; } else { if(GetTickCount()-dwStartTickCount > ssStatus.dwWaitHint) { // No progress made within the wait hint
//
break; } } }
if (ssStatus.dwCurrentState == SERVICE_RUNNING) { dwStatus = NO_ERROR; } else { // Set the return value to the last error.
//
dwStatus = GetLastError(); } } } return dwStatus; }
DWORD WaitForServiceStartName(LPTSTR lpszServiceName) { SC_HANDLE hSCM = NULL; SC_HANDLE schService = NULL; DWORD dwStatus = NO_ERROR;
if ( lpszServiceName ) { if ( hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS) ) { if ( schService = OpenService(hSCM, lpszServiceName, SERVICE_ALL_ACCESS) ) { dwStatus = WaitForServiceStart(schService); CloseServiceHandle(schService); } else { dwStatus = GetLastError(); FacLogFile(0 | LOG_ERR, IDS_ERR_SERVICE, lpszServiceName); } CloseServiceHandle(hSCM); } else { dwStatus = GetLastError(); FacLogFile(0 | LOG_ERR, IDS_ERR_SCM); } } else { dwStatus = E_INVALIDARG; } return dwStatus; }
// Start a service.
//
DWORD StartMyService(LPTSTR lpszServiceName, SC_HANDLE schSCManager) { SC_HANDLE schService; DWORD dwStatus = NO_ERROR;
FacLogFileStr(3, _T("Starting service: %s\n"), lpszServiceName); if ( NULL != (schService = OpenService(schSCManager, lpszServiceName, SERVICE_ALL_ACCESS)) && StartService(schService, 0, NULL) ) { dwStatus = WaitForServiceStart(schService); } if ( schService ) CloseServiceHandle(schService);
return dwStatus; }
|