Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

438 lines
14 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. winpenet.c
  5. Abstract:
  6. This module contains code to control the startup of the network in the WinPE environment.
  7. It relies upon the existence of WINBOM.INI and the following sections:
  8. [WinPE.net]
  9. Startnet = YES | NO - Specifies whether to start networking.
  10. Ipconfig = DHCP | x.x.x.x - Specifies DHCP or a static IP address.
  11. SubnetMask = x.x.x.x - SubnetMask for the static IP.
  12. Gateway = x.x.x.x - Default gateway for the static IP.
  13. Author:
  14. Adrian Cosma (acosma) - 1/18/2001
  15. Revision History:
  16. --*/
  17. //
  18. // Includes
  19. //
  20. #include "factoryp.h"
  21. #include <winsock2.h>
  22. //
  23. // Defines
  24. //
  25. typedef HRESULT (PASCAL *PRegisterServer)(VOID);
  26. //
  27. // Static strings
  28. //
  29. const static TCHAR DEF_GATEWAY_METRIC[] = _T("1\0"); // Need to NULLCHRs at the end since this goes into a REG_MULTI_SZ.
  30. const static TCHAR REGSTR_TCPIP[] = _T("SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\");
  31. //
  32. // Local function declarations
  33. //
  34. static BOOL InstallNetComponents(VOID);
  35. static BOOL RegisterDll(VOID);
  36. //
  37. // Function implementations
  38. //
  39. static BOOL InstallNetComponents(VOID)
  40. {
  41. TCHAR szCmdLine[MAX_PATH] = NULLSTR;
  42. DWORD dwExitCode = 0;
  43. BOOL bRet = TRUE;
  44. lstrcpyn(szCmdLine, _T("-winpe"), AS ( szCmdLine ) ) ;
  45. if ( !InvokeExternalApplicationEx(_T("netcfg"), szCmdLine, &dwExitCode, INFINITE, TRUE) )
  46. {
  47. FacLogFile(0 | LOG_ERR, IDS_ERR_NETWORKCOMP);
  48. bRet = FALSE;
  49. }
  50. return bRet;
  51. }
  52. static BOOL RegisterDll(VOID)
  53. {
  54. HMODULE hDll = NULL;
  55. BOOL bRet = FALSE;
  56. PRegisterServer pRegisterServer = NULL;
  57. if ( (hDll = LoadLibrary(_T("netcfgx.dll"))) &&
  58. (pRegisterServer = (PRegisterServer) GetProcAddress(hDll, "DllRegisterServer")) &&
  59. (S_OK == pRegisterServer()) )
  60. {
  61. FacLogFileStr(3, _T("Succesfully registered netcfg.dll.\n"));
  62. bRet = TRUE;
  63. }
  64. else
  65. {
  66. FacLogFile(0 | LOG_ERR, IDS_ERR_REGISTERNETCFG);
  67. }
  68. if (hDll)
  69. FreeLibrary(hDll);
  70. return bRet;
  71. }
  72. BOOL WinpeNet(LPSTATEDATA lpStateData)
  73. {
  74. LPTSTR lpszWinBOMPath = lpStateData->lpszWinBOMPath;
  75. SC_HANDLE hSCM = NULL;
  76. TCHAR szBuf[MAX_WINPE_PROFILE_STRING] = NULLSTR;
  77. BOOL bRet = TRUE;
  78. // Make sure that the user wants us to do networking.
  79. //
  80. GetPrivateProfileString(INI_KEY_WBOM_WINPE_NET, INI_KEY_WBOM_WINPE_NET_STARTNET, NULLSTR, szBuf, AS(szBuf), lpszWinBOMPath);
  81. // If user does not want to start networking just return success.
  82. //
  83. if ( 0 == LSTRCMPI(szBuf, WBOM_NO) )
  84. return TRUE;
  85. // Register dll.
  86. // Run netcfg -winpe.
  87. // Install network card.
  88. // See if the user wants to use a static IP.
  89. //
  90. if ( RegisterDll() &&
  91. SetupMiniNT() &&
  92. InstallNetComponents() &&
  93. ConfigureNetwork(g_szWinBOMPath)
  94. )
  95. {
  96. //
  97. // Start Services for networking.
  98. //
  99. if ( hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS) )
  100. {
  101. // DHCP also starts tcpip and netbt.
  102. // The workstation service should already be started by the installer.
  103. //
  104. if ( (StartMyService(_T("dhcp"), hSCM) != NO_ERROR) ||
  105. (StartMyService(_T("nla"), hSCM) != NO_ERROR)
  106. )
  107. {
  108. FacLogFile(0 | LOG_ERR, IDS_ERR_NETSERVICES);
  109. bRet = FALSE;
  110. }
  111. else if ( IsRemoteBoot() )
  112. {
  113. // If this was a remote boot, tell NetBT to reload the WINS addresses...
  114. // ISSUE-2002/09/26-acosma,brucegr - Can DHCP say its started before we get an address?
  115. //
  116. ForceNetbtRegistryRead();
  117. }
  118. CloseServiceHandle(hSCM);
  119. }
  120. else
  121. {
  122. FacLogFile(0 | LOG_ERR, IDS_ERR_SCM);
  123. bRet = FALSE;
  124. }
  125. }
  126. else
  127. {
  128. FacLogFile(0 | LOG_ERR, IDS_ERR_SETUPNETWORK);
  129. bRet = FALSE;
  130. }
  131. return bRet;
  132. }
  133. BOOL DisplayWinpeNet(LPSTATEDATA lpStateData)
  134. {
  135. return ( !IniSettingExists(lpStateData->lpszWinBOMPath, INI_KEY_WBOM_WINPE_NET, INI_KEY_WBOM_WINPE_NET_STARTNET, INI_VAL_WBOM_NO) );
  136. }
  137. BOOL ConfigureNetwork(LPTSTR lpszWinBOMPath)
  138. {
  139. TCHAR szBuf[MAX_WINPE_PROFILE_STRING] = NULLSTR;
  140. CHAR szBufA[MAX_WINPE_PROFILE_STRING] = { 0 };
  141. TCHAR szReg[MAX_WINPE_PROFILE_STRING] = NULLSTR;
  142. TCHAR szIpAddress[MAX_WINPE_PROFILE_STRING] = NULLSTR;
  143. TCHAR szSubnetMask[MAX_WINPE_PROFILE_STRING] = NULLSTR;
  144. HKEY hKey = NULL; // Reg Key to interfaces.
  145. HKEY hKeyI = NULL; // Reg Key to specific network interface.
  146. DWORD dwDis = 0;
  147. TCHAR szRegKey[MAX_PATH] = NULLSTR;
  148. DWORD dwEnableDHCP = 0;
  149. BOOL fErr = FALSE;
  150. szBuf[0] = NULLCHR;
  151. GetPrivateProfileString(INI_KEY_WBOM_WINPE_NET, WBOM_WINPE_NET_IPADDRESS, NULLSTR, szBuf, MAX_WINPE_PROFILE_STRING, lpszWinBOMPath);
  152. // Convert the string to ANSI
  153. //
  154. if ( szBuf[0] &&
  155. WideCharToMultiByte(CP_ACP, 0, szBuf, -1, szBufA, AS(szBufA), NULL, NULL) )
  156. {
  157. // If it's DHCP don't do anything. Just return TRUE.
  158. //
  159. if ( 0 == LSTRCMPI(szBuf, _T("DHCP")) )
  160. return TRUE;
  161. if ( INADDR_NONE == inet_addr(szBufA) )
  162. {
  163. FacLogFile(0 | LOG_ERR, IDS_ERR_INVALIDIP , szBuf);
  164. return FALSE;
  165. }
  166. }
  167. else // if there is no IpConfig entry return success (same as DHCP)
  168. return TRUE;
  169. // Save the IpAddress.
  170. lstrcpyn(szIpAddress, szBuf, AS ( szIpAddress ) );
  171. szBuf[0] = NULLCHR;
  172. GetPrivateProfileString(INI_KEY_WBOM_WINPE_NET, WBOM_WINPE_NET_SUBNETMASK, NULLSTR, szBuf, MAX_WINPE_PROFILE_STRING, lpszWinBOMPath);
  173. // Convert the string to ANSI
  174. //
  175. if ( szBuf[0] &&
  176. WideCharToMultiByte(CP_ACP,0, szBuf, -1, szBufA, AS(szBufA), NULL, NULL) )
  177. {
  178. if ( INADDR_NONE == inet_addr(szBufA) )
  179. {
  180. FacLogFile(0 | LOG_ERR, IDS_ERR_INVALIDMASK , szBuf);
  181. return FALSE;
  182. }
  183. }
  184. else // If we got this far we need to have a subnet mask
  185. {
  186. FacLogFile(0 | LOG_ERR, IDS_ERR_NOMASK);
  187. return FALSE;
  188. }
  189. // Save the SubnetMask.
  190. lstrcpyn(szSubnetMask, szBuf, AS ( szSubnetMask ) );
  191. //
  192. // Write the settings to the registry.
  193. //
  194. // Make sure that the strings are terminated by two NULLCHRs.
  195. //
  196. szIpAddress[lstrlen(szIpAddress) + 1] = NULLCHR;
  197. szSubnetMask[lstrlen(szSubnetMask) + 1] = NULLCHR;
  198. // Assuming that there is only one interface in the system.
  199. //
  200. if ( (RegCreateKeyEx(HKEY_LOCAL_MACHINE, REGSTR_TCPIP, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dwDis) == ERROR_SUCCESS) &&
  201. (RegEnumKey(hKey, 0, szRegKey, AS(szRegKey)) == ERROR_SUCCESS) &&
  202. szRegKey[0] &&
  203. (RegCreateKeyEx(hKey, szRegKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKeyI, &dwDis) == ERROR_SUCCESS) )
  204. {
  205. if ( ERROR_SUCCESS != (RegSetValueEx(hKeyI, _T("IPAddress"), 0, REG_MULTI_SZ, (CONST LPBYTE) szIpAddress, ( lstrlen(szIpAddress) + 2 ) * sizeof(TCHAR))) ||
  206. ERROR_SUCCESS != (RegSetValueEx(hKeyI, _T("SubnetMask"), 0, REG_MULTI_SZ, (CONST LPBYTE) szSubnetMask, ( lstrlen(szSubnetMask) + 2 ) * sizeof(TCHAR))) ||
  207. ERROR_SUCCESS != (RegSetValueEx(hKeyI, _T("EnableDHCP"), 0, REG_DWORD, (CONST LPBYTE) &dwEnableDHCP, sizeof(dwEnableDHCP))) )
  208. {
  209. FacLogFile(0 | LOG_ERR, IDS_ERR_IPREGISTRY);
  210. fErr = TRUE;
  211. }
  212. else
  213. {
  214. //
  215. // If the gateway is not specified we don't care. We're just not going to add this
  216. // if it's not there.
  217. //
  218. szBuf[0] = NULLCHR;
  219. GetPrivateProfileString(INI_KEY_WBOM_WINPE_NET, WBOM_WINPE_NET_GATEWAY, NULLSTR, szBuf, MAX_WINPE_PROFILE_STRING, lpszWinBOMPath);
  220. if ( szBuf[0] &&
  221. WideCharToMultiByte(CP_ACP,0, szBuf, -1, szBufA, AS(szBufA), NULL, NULL) )
  222. {
  223. if ( INADDR_NONE == inet_addr(szBufA) )
  224. {
  225. FacLogFile(0 | LOG_ERR, IDS_ERR_INVALIDGW, szBuf);
  226. fErr = TRUE;
  227. }
  228. else
  229. {
  230. szBuf[lstrlen(szBuf) + 1] = NULLCHR;
  231. if ( (RegSetValueEx(hKeyI, _T("DefaultGateway"), 0, REG_MULTI_SZ, (CONST LPBYTE) szBuf, ( lstrlen(szBuf) + 2 ) * sizeof(TCHAR)) != ERROR_SUCCESS) ||
  232. (RegSetValueEx(hKeyI, _T("DefaultGatewayMetric"), 0, REG_MULTI_SZ, (CONST LPBYTE) DEF_GATEWAY_METRIC, ( lstrlen(DEF_GATEWAY_METRIC) + 2 ) * sizeof(TCHAR)) != ERROR_SUCCESS) )
  233. {
  234. FacLogFile(0 | LOG_ERR, IDS_ERR_GWREGISTRY);
  235. fErr = TRUE;
  236. }
  237. }
  238. }
  239. }
  240. RegCloseKey(hKeyI);
  241. }
  242. else
  243. {
  244. FacLogFile(0 | LOG_ERR, IDS_ERR_IPREGISTRY);
  245. }
  246. // It is possible that the subkey failed to open so this takes care of a possible leak.
  247. //
  248. if (hKey)
  249. RegCloseKey(hKey);
  250. return (!fErr);
  251. }
  252. static DWORD WaitForServiceStart(SC_HANDLE schService)
  253. {
  254. SERVICE_STATUS ssStatus;
  255. DWORD dwOldCheckPoint;
  256. DWORD dwStartTickCount;
  257. DWORD dwWaitTime;
  258. DWORD dwStatus = NO_ERROR;
  259. if ( schService )
  260. {
  261. //
  262. // Service start is now pending.
  263. // Check the status until the service is no longer start pending.
  264. //
  265. if ( QueryServiceStatus( schService, &ssStatus) )
  266. {
  267. // Save the tick count and initial checkpoint.
  268. //
  269. dwStartTickCount = GetTickCount();
  270. dwOldCheckPoint = ssStatus.dwCheckPoint;
  271. while (ssStatus.dwCurrentState == SERVICE_START_PENDING)
  272. {
  273. // Do not wait longer than the wait hint. A good interval is
  274. // one tenth the wait hint, but no less than 1 second and no
  275. // more than 10 seconds.
  276. //
  277. dwWaitTime = ssStatus.dwWaitHint / 10;
  278. if( dwWaitTime < 1000 )
  279. dwWaitTime = 1000;
  280. else if ( dwWaitTime > 10000 )
  281. dwWaitTime = 10000;
  282. Sleep( dwWaitTime );
  283. // Check the status again.
  284. //
  285. if (!QueryServiceStatus(
  286. schService, // handle to service
  287. &ssStatus) ) // address of structure
  288. break;
  289. if ( ssStatus.dwCheckPoint > dwOldCheckPoint )
  290. {
  291. // The service is making progress.
  292. //
  293. dwStartTickCount = GetTickCount();
  294. dwOldCheckPoint = ssStatus.dwCheckPoint;
  295. }
  296. else
  297. {
  298. if(GetTickCount()-dwStartTickCount > ssStatus.dwWaitHint)
  299. {
  300. // No progress made within the wait hint
  301. //
  302. break;
  303. }
  304. }
  305. }
  306. if (ssStatus.dwCurrentState == SERVICE_RUNNING)
  307. {
  308. dwStatus = NO_ERROR;
  309. }
  310. else
  311. {
  312. // Set the return value to the last error.
  313. //
  314. dwStatus = GetLastError();
  315. }
  316. }
  317. }
  318. return dwStatus;
  319. }
  320. DWORD WaitForServiceStartName(LPTSTR lpszServiceName)
  321. {
  322. SC_HANDLE hSCM = NULL;
  323. SC_HANDLE schService = NULL;
  324. DWORD dwStatus = NO_ERROR;
  325. if ( lpszServiceName )
  326. {
  327. if ( hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS) )
  328. {
  329. if ( schService = OpenService(hSCM, lpszServiceName, SERVICE_ALL_ACCESS) )
  330. {
  331. dwStatus = WaitForServiceStart(schService);
  332. CloseServiceHandle(schService);
  333. }
  334. else
  335. {
  336. dwStatus = GetLastError();
  337. FacLogFile(0 | LOG_ERR, IDS_ERR_SERVICE, lpszServiceName);
  338. }
  339. CloseServiceHandle(hSCM);
  340. }
  341. else
  342. {
  343. dwStatus = GetLastError();
  344. FacLogFile(0 | LOG_ERR, IDS_ERR_SCM);
  345. }
  346. }
  347. else
  348. {
  349. dwStatus = E_INVALIDARG;
  350. }
  351. return dwStatus;
  352. }
  353. // Start a service.
  354. //
  355. DWORD StartMyService(LPTSTR lpszServiceName, SC_HANDLE schSCManager)
  356. {
  357. SC_HANDLE schService;
  358. DWORD dwStatus = NO_ERROR;
  359. FacLogFileStr(3, _T("Starting service: %s\n"), lpszServiceName);
  360. if ( NULL != (schService = OpenService(schSCManager, lpszServiceName, SERVICE_ALL_ACCESS)) &&
  361. StartService(schService, 0, NULL) )
  362. {
  363. dwStatus = WaitForServiceStart(schService);
  364. }
  365. if ( schService )
  366. CloseServiceHandle(schService);
  367. return dwStatus;
  368. }