Source code of Windows XP (NT5)
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.

2044 lines
56 KiB

  1. /****************************************************************************
  2. *
  3. * icfg32.cpp
  4. *
  5. * Microsoft Confidential
  6. * Copyright (c) 1992-1998 Microsoft Corporation
  7. * All rights reserved
  8. *
  9. * This module provides the implementation of the methods for
  10. * the NT specific functionality of inetcfg
  11. *
  12. * 6/5/97 ChrisK Inherited from AmnonH
  13. *
  14. ***************************************************************************/
  15. #define INITGUID
  16. #include <windows.h>
  17. #include <wtypes.h>
  18. #include <cfgapi.h>
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <setupapi.h>
  22. #include <basetyps.h>
  23. #include <devguid.h>
  24. #include <lmsname.h>
  25. #include "debug.h"
  26. const DWORD INFINSTALL_PRIMARYINSTALL = 0x00000001;
  27. const DWORD INFINSTALL_INPROCINTERP = 0x00000002;
  28. #define REG_DATA_EXTRA_SPACE 255
  29. DWORD (WINAPI *pfnNetSetupReviewBindings)(HWND hwndParent,
  30. DWORD dwBindFlags);
  31. DWORD (WINAPI *pfnNetSetupComponentInstall)(HWND hwndParent,
  32. PCWSTR pszInfOption,
  33. PCWSTR pszInfName,
  34. PCWSTR pszInstallPath,
  35. PCWSTR plszInfSymbols,
  36. DWORD dwInstallFlags,
  37. PDWORD dwReturn);
  38. DWORD (WINAPI *pfnNetSetupComponentRemove)(HWND hwndParent,
  39. PCWSTR pszInfOption,
  40. DWORD dwInstallFlags,
  41. PDWORD pdwReturn);
  42. DWORD (WINAPI *pfnNetSetupComponentProperties)(HWND hwndParent,
  43. PCWSTR pszInfOption,
  44. DWORD dwInstallFlags,
  45. PDWORD pdwReturn);
  46. DWORD (WINAPI *pfnNetSetupFindHardwareComponent)(PCWSTR pszInfOption,
  47. PWSTR pszInfName,
  48. PDWORD pcchInfName,
  49. PWSTR pszRegBase, // optional, may be NULL
  50. PDWORD pcchRegBase ); // optional, NULL if pszRegBase is NULL
  51. DWORD (WINAPI *pfnNetSetupFindSoftwareComponent)(PCWSTR pszInfOption,
  52. PWSTR pszInfName,
  53. PDWORD pcchInfName,
  54. PWSTR pszRegBase = NULL,
  55. PDWORD pcchRegBase = NULL);
  56. DWORD (WINAPI *pfnRegCopyTree)();
  57. HINSTANCE g_hNetcfgInst = NULL;
  58. LPWSTR g_wszInstallPath = 0;
  59. DWORD g_dwLastError = ERROR_SUCCESS;
  60. extern DWORD EnumerateTapiModemPorts(DWORD dwBytes, LPSTR szPortsBuf,
  61. BOOL bWithDelay = FALSE);
  62. typedef struct tagFunctionTableEntry {
  63. LPVOID *pfn;
  64. LPSTR szEntryPoint;
  65. } FunctionTableEntry;
  66. #define REGISTRY_NT_CURRENTVERSION "SOFTWARE\\MICROSOFT\\WINDOWS NT\\CurrentVersion"
  67. FunctionTableEntry NetcfgTable[] = {
  68. { (LPVOID *) &pfnNetSetupComponentInstall, "NetSetupComponentInstall" },
  69. { (LPVOID *) &pfnNetSetupFindSoftwareComponent, "NetSetupFindSoftwareComponent" },
  70. { (LPVOID *) &pfnNetSetupReviewBindings, "NetSetupReviewBindings" },
  71. { (LPVOID *) &pfnNetSetupComponentRemove, "NetSetupComponentRemove" },
  72. { (LPVOID *) &pfnNetSetupComponentProperties, "NetSetupComponentProperties" },
  73. { (LPVOID *) &pfnNetSetupFindHardwareComponent, "NetSetupFindHardwareComponent" },
  74. { 0, 0 }
  75. };
  76. typedef struct tagNetSetup
  77. {
  78. WCHAR szOption[16];
  79. WCHAR szInfName[16];
  80. } NETSETUP;
  81. NETSETUP g_netsetup[] = { L"WKSTA", L"OEMNSVWK.INF",
  82. L"SRV", L"OEMNSVSV.INF",
  83. L"NETBIOS", L"OEMNSVNB.INF",
  84. L"RPCLOCATE", L"OEMNSVRP.INF" };
  85. #define NSERVICES (sizeof g_netsetup / sizeof g_netsetup[0])
  86. inline stricmp(LPSTR s1, LPSTR s2) {
  87. while(*s1 && *s2) {
  88. char c1, c2;
  89. c1 = islower(*s1) ? toupper(*s1) : *s1;
  90. c2 = islower(*s2) ? toupper(*s2) : *s2;
  91. if(c1 != c2)
  92. {
  93. break;
  94. }
  95. s1++; s2++;
  96. }
  97. return(*s1 - *s2);
  98. }
  99. //+----------------------------------------------------------------------------
  100. //
  101. // Function: LoadLibraryToFunctionTable
  102. //
  103. // Synopsis: Load structure with function pointers from FunctionTable
  104. //
  105. // Arguments: pTab - array of function to be loaded
  106. // szDLL - name of DLL to load function from
  107. //
  108. // Returns: Handle to szDLL (NULL indicates failure)
  109. //
  110. // History: 6/5/97 Chrisk Inherited
  111. //
  112. //-----------------------------------------------------------------------------
  113. HINSTANCE
  114. LoadLibraryToFunctionTable(FunctionTableEntry *pTab, LPSTR szDLL)
  115. {
  116. HINSTANCE hInst;
  117. Dprintf("ICFGNT: LoadLibraryToFunctionTable\n");
  118. hInst = LoadLibrary(szDLL);
  119. if(hInst == 0)
  120. {
  121. return(hInst);
  122. }
  123. while(pTab->pfn) {
  124. *pTab->pfn = (LPVOID) GetProcAddress(hInst, pTab->szEntryPoint);
  125. if(*pTab->pfn == 0)
  126. {
  127. FreeLibrary(hInst);
  128. return(0);
  129. }
  130. pTab++;
  131. }
  132. return(hInst);
  133. }
  134. //+----------------------------------------------------------------------------
  135. //
  136. // Function: LoadNetcfg
  137. //
  138. // Synopsis: Load netcfg.dll and function poiners
  139. //
  140. // Arguments: none
  141. //
  142. // Returns: ERROR_SUCCESS if sucessfull and !ERROR_SUCCESS otherwise
  143. //
  144. // History: 6/5/97 ChrisK Inherited
  145. //
  146. //-----------------------------------------------------------------------------
  147. DWORD
  148. LoadNetcfg()
  149. {
  150. if(g_hNetcfgInst == NULL)
  151. {
  152. g_hNetcfgInst = LoadLibraryToFunctionTable(NetcfgTable,
  153. "NETCFG.DLL");
  154. }
  155. if(g_hNetcfgInst == NULL)
  156. {
  157. return(!ERROR_SUCCESS);
  158. }
  159. else
  160. {
  161. return(ERROR_SUCCESS);
  162. }
  163. }
  164. //+----------------------------------------------------------------------------
  165. //
  166. // Function: IcfgSetInstallSourcePath
  167. //
  168. // Synopsis: Set the path that will be used to install system components
  169. //
  170. // Arguments: lpszSourcePath - path to be used as install source (ANSI)
  171. //
  172. // Returns: HRESULT - S_OK is success
  173. //
  174. // History: 6/5/97 ChrisK Inherited
  175. //
  176. //-----------------------------------------------------------------------------
  177. HRESULT WINAPI
  178. IcfgSetInstallSourcePath(LPSTR lpszSourcePath)
  179. {
  180. Dprintf("ICFGNT: IcfgSetInstallSourcePath\n");
  181. if(g_wszInstallPath)
  182. {
  183. HeapFree(GetProcessHeap(), 0, (LPVOID) g_wszInstallPath);
  184. }
  185. DWORD dwLen = lstrlen(lpszSourcePath);
  186. g_wszInstallPath = (LPWSTR) HeapAlloc(GetProcessHeap(), 0, dwLen * 2 + 2);
  187. if(g_wszInstallPath == 0)
  188. {
  189. return(g_dwLastError = ERROR_OUTOFMEMORY);
  190. }
  191. mbstowcs(g_wszInstallPath, lpszSourcePath, dwLen + 1);
  192. return(ERROR_SUCCESS);
  193. }
  194. //+----------------------------------------------------------------------------
  195. //
  196. // Function: GetLocationOfSetupFiles
  197. //
  198. // Synopsis: Get the location of the files used to install windows.
  199. //
  200. // Arguments: hwndParent - handle of parent window
  201. //
  202. // Returns: win32 error code
  203. //
  204. // History: ChrisK 6/30/97 Created
  205. //-----------------------------------------------------------------------------
  206. DWORD GetLocationOfSetupFiles(HWND hwndParent)
  207. {
  208. DWORD dwRC = ERROR_SUCCESS;
  209. HKEY hkey = NULL;
  210. HINF hInf = INVALID_HANDLE_VALUE;
  211. UINT DiskId = 0;
  212. CHAR TagFile[128];
  213. CHAR lpBuffer[MAX_PATH];
  214. DWORD dwLen = MAX_PATH;
  215. lpBuffer[0] = '\0';
  216. if( ERROR_SUCCESS == RegOpenKey( HKEY_LOCAL_MACHINE,
  217. REGISTRY_NT_CURRENTVERSION,
  218. &hkey))
  219. {
  220. hInf = SetupOpenMasterInf();
  221. if (hInf == INVALID_HANDLE_VALUE)
  222. {
  223. dwRC = GetLastError();
  224. goto GetLocationOfSetupFilesExit;
  225. }
  226. if (!SetupGetSourceFileLocation(hInf,NULL,"RASCFG.DLL",&DiskId,NULL,0,NULL))
  227. {
  228. dwRC = GetLastError();
  229. goto GetLocationOfSetupFilesExit;
  230. }
  231. if (!SetupGetSourceInfo(hInf,DiskId,SRCINFO_TAGFILE,TagFile,MAX_PATH,NULL))
  232. {
  233. dwRC = GetLastError();
  234. goto GetLocationOfSetupFilesExit;
  235. }
  236. SetupCloseInfFile(hInf);
  237. hInf = INVALID_HANDLE_VALUE;
  238. if( RegQueryValueEx( hkey,
  239. "SourcePath",
  240. NULL,
  241. NULL,
  242. (LPBYTE)lpBuffer,
  243. &dwLen) == 0)
  244. {
  245. RegCloseKey( hkey );
  246. hkey = NULL;
  247. // Ask the user to provide the drive\path of the sources. We pass this information
  248. // down to NetSetupComponentInstall so that the user is not prompted several times
  249. // for the same information. If the path is correct (IDF_CHECKFIRST) then the user
  250. // is not prompted at all.
  251. if( (dwRC = SetupPromptForDisk(hwndParent,
  252. NULL,
  253. NULL,
  254. lpBuffer,
  255. "RASCFG.DLL",
  256. TagFile, // tag file
  257. IDF_CHECKFIRST,
  258. lpBuffer,
  259. MAX_PATH,
  260. &dwLen
  261. )) != DPROMPT_SUCCESS )
  262. {
  263. Dprintf("ICFG: Install: SetupPromptForDisk failed.\n");
  264. dwRC = GetLastError();
  265. goto GetLocationOfSetupFilesExit;
  266. }
  267. }
  268. // If we failed to get SourcePath from registry, then prompt the user once and use
  269. // this information for subsequent installs.
  270. else
  271. {
  272. if( (dwRC = SetupPromptForDisk(hwndParent,
  273. NULL,
  274. NULL,
  275. NULL,
  276. "RASCFG.DLL",
  277. TagFile, // tag file
  278. IDF_CHECKFIRST,
  279. lpBuffer,
  280. MAX_PATH,
  281. &dwLen
  282. )) != DPROMPT_SUCCESS )
  283. {
  284. Dprintf("ICFG: Install: SetupPromptForDisk failed.\n");
  285. dwRC = GetLastError();
  286. goto GetLocationOfSetupFilesExit;
  287. }
  288. }
  289. }
  290. GetLocationOfSetupFilesExit:
  291. if (ERROR_SUCCESS == dwRC)
  292. {
  293. IcfgSetInstallSourcePath(lpBuffer);
  294. }
  295. if (INVALID_HANDLE_VALUE != hInf)
  296. {
  297. SetupCloseInfFile(hInf);
  298. hInf = NULL;
  299. }
  300. if (NULL != hkey)
  301. {
  302. RegCloseKey(hkey);
  303. }
  304. return dwRC;
  305. }
  306. //+----------------------------------------------------------------------------
  307. //
  308. // Function: InstallNTNetworking
  309. //
  310. // Synopsis: Install NT Server, workstation, netbios, and RPC locator
  311. // services as needed
  312. //
  313. // Arguemtns: hwndParent - parent window
  314. //
  315. // Returns: win32 error code
  316. //
  317. // History: ChrisK 6/27/97 Created
  318. //
  319. //-----------------------------------------------------------------------------
  320. DWORD InstallNTNetworking(HWND hwndParent)
  321. {
  322. DWORD dwRC = ERROR_SUCCESS;
  323. UINT index = 0;
  324. DWORD cchInfName = MAX_PATH;
  325. WCHAR pszInfName[MAX_PATH+1];
  326. SC_HANDLE hscman, hsvc;
  327. DWORD dwReturn;
  328. Dprintf("ICFGNT.DLL: InstallNTNetworking.\n");
  329. Assert(NULL == hwndParent || IsWindow(hwndParent));
  330. if(ERROR_SUCCESS != (dwRC = LoadNetcfg()))
  331. {
  332. Dprintf("ICFGNT.DLL: Failed load Netcfg API's, error %d\n",dwRC);
  333. goto InstallNTNetworkingExit;
  334. }
  335. //
  336. // Check for and install services
  337. //
  338. for (index = 0; index < NSERVICES; index++)
  339. {
  340. Dprintf("ICFGNT.DLL: Check service %d\n",index);
  341. //
  342. // Install service if it is not installed
  343. //
  344. if(pfnNetSetupFindSoftwareComponent(
  345. g_netsetup[index].szOption, // OPTION
  346. pszInfName, // INF Name
  347. &cchInfName,
  348. NULL,
  349. NULL) != ERROR_SUCCESS )
  350. {
  351. if (0 == g_wszInstallPath || 0 == lstrlenW(g_wszInstallPath))
  352. {
  353. GetLocationOfSetupFiles(hwndParent);
  354. }
  355. Dprintf("ICFGNT.DLL: Need service %d.\n",index);
  356. if((dwRC = pfnNetSetupComponentInstall(
  357. hwndParent,
  358. g_netsetup[index].szOption, // OPTION
  359. g_netsetup[index].szInfName, // INF Name
  360. g_wszInstallPath, // Install path optional
  361. NULL, // symbols, optional
  362. 2, // INFINSTALL_INPROCINTERP
  363. &dwReturn)) != ERROR_SUCCESS )
  364. {
  365. Dprintf("ICFGNT.DLL: Installing service %d failed with error %d.\n",
  366. index,
  367. dwRC);
  368. goto InstallNTNetworkingExit;
  369. }
  370. if (!lstrcmpiW(g_netsetup[index].szOption, L"WKSTA"))
  371. {
  372. // if we installed the Workstation service, then we should disable
  373. // Netlogon service. We need to do this because netlogon service should
  374. // not be set to autostart if the user has not joined a domain.
  375. //
  376. hscman = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS | GENERIC_WRITE );
  377. if( hscman == NULL)
  378. {
  379. dwRC = GetLastError();
  380. Dprintf("ICFGNT.DLL: Failed to open serviceManager, error %d\n",dwRC);
  381. goto InstallNTNetworkingExit;
  382. }
  383. hsvc = OpenService( hscman, SERVICE_NETLOGON, SERVICE_CHANGE_CONFIG );
  384. if ( hsvc == NULL)
  385. {
  386. dwRC = GetLastError();
  387. Dprintf("ICFGNT.DLL: Failed to open service, error %d\n",dwRC);
  388. goto InstallNTNetworkingExit;
  389. }
  390. ChangeServiceConfig( hsvc, SERVICE_NO_CHANGE, SERVICE_DEMAND_START, SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
  391. CloseServiceHandle(hsvc);
  392. CloseServiceHandle(hscman);
  393. }
  394. }
  395. }
  396. InstallNTNetworkingExit:
  397. return dwRC;
  398. }
  399. //+----------------------------------------------------------------------------
  400. //
  401. // Function: GetRegValue
  402. //
  403. // Synopsis: Dynamically allocate memory and read value from registry
  404. //
  405. // Arguments: hKey - handle to key to be read
  406. // lpValueName - pointer to value name to be read
  407. // lpData - pointer to pointer to data
  408. //
  409. // Returns: Win32 error, ERROR_SUCCESS is it worked
  410. //
  411. // History: 6/5/97 ChrisK Inherited
  412. //
  413. //-----------------------------------------------------------------------------
  414. inline LONG GetRegValue(HKEY hKey, LPSTR lpValueName, LPBYTE *lpData)
  415. {
  416. LONG dwError;
  417. DWORD cbData;
  418. Dprintf("ICFGNT: GetRegValue\n");
  419. dwError = RegQueryValueExA(hKey,
  420. lpValueName,
  421. NULL,
  422. NULL,
  423. NULL,
  424. &cbData);
  425. if(dwError != ERROR_SUCCESS)
  426. {
  427. return(dwError);
  428. }
  429. //
  430. // Allocate space and buffer incase we need to add more info later
  431. // see turn off the printing binding
  432. //
  433. *lpData = (LPBYTE) GlobalAlloc(GPTR,cbData + REG_DATA_EXTRA_SPACE);
  434. if(*lpData == 0)
  435. {
  436. return(ERROR_OUTOFMEMORY);
  437. }
  438. dwError = RegQueryValueExA(hKey,
  439. lpValueName,
  440. NULL,
  441. NULL,
  442. *lpData,
  443. &cbData);
  444. if(dwError != ERROR_SUCCESS)
  445. {
  446. GlobalFree(*lpData);
  447. }
  448. return(dwError);
  449. }
  450. //+----------------------------------------------------------------------------
  451. //
  452. // Function: ParseNetSetupReturn
  453. //
  454. // Synopsis: Interprit return values from NetSetup* functions
  455. //
  456. // Arguments: dwReturn - return value from NetSetup* function
  457. //
  458. // Returns: fReboot - TRUE means reboot required
  459. // fBindReview - TRUE means binding review is required
  460. //
  461. // History: 6/5/97 ChrisK Inherited
  462. //
  463. //-----------------------------------------------------------------------------
  464. inline void
  465. ParseNetSetupReturn(DWORD dwReturn, BOOL &fReboot, BOOL &fBindReview)
  466. {
  467. Dprintf("ICFGNT: ParseNetSetupReturn\n");
  468. if(dwReturn == 0 || dwReturn == 4)
  469. {
  470. fBindReview = TRUE;
  471. }
  472. if(dwReturn == 0 || dwReturn == 5)
  473. {
  474. fReboot = TRUE;
  475. }
  476. }
  477. //+----------------------------------------------------------------------------
  478. //
  479. // Function: ReviewBindings
  480. //
  481. // Synopsis: Force WinNT to review network bindings
  482. //
  483. // Arguments: hwndParent - handle to parent window
  484. //
  485. // Returns: win32 error code (ERROR_SUCCESS means it worked)
  486. //
  487. // History: 6/5/97 ChrisK Inherited
  488. //
  489. //-----------------------------------------------------------------------------
  490. DWORD
  491. ReviewBindings(HWND hwndParent)
  492. {
  493. DWORD dwErr;
  494. Dprintf("ICFGNT: ReviewBindings\n");
  495. dwErr = LoadNetcfg();
  496. if(dwErr != ERROR_SUCCESS)
  497. {
  498. return(dwErr);
  499. }
  500. return(pfnNetSetupReviewBindings(hwndParent, 0));
  501. }
  502. //+----------------------------------------------------------------------------
  503. //
  504. // Function: CallModemInstallWizard
  505. //
  506. // Synopsis: Invoke modem install wizard via SetupDi interfaces
  507. //
  508. // Arguments: hwnd - handle to parent window
  509. //
  510. // Returns: TRUE - success, FALSE - failed
  511. //
  512. // History: 6/5/97 ChrisK Inherited
  513. //
  514. //-----------------------------------------------------------------------------
  515. //
  516. // The following code was stolen from RAS
  517. //
  518. BOOL
  519. CallModemInstallWizard(HWND hwnd)
  520. /* call the Modem.Cpl install wizard to enable the user to install one or more modems
  521. **
  522. ** Return TRUE if the wizard was successfully invoked, FALSE otherwise
  523. **
  524. */
  525. {
  526. HDEVINFO hdi;
  527. BOOL fReturn = FALSE;
  528. // Create a modem DeviceInfoSet
  529. Dprintf("ICFGNT: CallModemInstallWizard\n");
  530. hdi = SetupDiCreateDeviceInfoList((LPGUID)&GUID_DEVCLASS_MODEM, hwnd);
  531. if (hdi)
  532. {
  533. SP_INSTALLWIZARD_DATA iwd;
  534. // Initialize the InstallWizardData
  535. ZeroMemory(&iwd, sizeof(iwd));
  536. iwd.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
  537. iwd.ClassInstallHeader.InstallFunction = DIF_INSTALLWIZARD;
  538. iwd.hwndWizardDlg = hwnd;
  539. // Set the InstallWizardData as the ClassInstallParams
  540. if (SetupDiSetClassInstallParams(hdi, NULL, (PSP_CLASSINSTALL_HEADER)&iwd, sizeof(iwd)))
  541. {
  542. // Call the class installer to invoke the installation
  543. // wizard.
  544. if (SetupDiCallClassInstaller(DIF_INSTALLWIZARD, hdi, NULL))
  545. {
  546. // Success. The wizard was invoked and finished.
  547. // Now cleanup.
  548. fReturn = TRUE;
  549. SetupDiCallClassInstaller(DIF_DESTROYWIZARDDATA, hdi, NULL);
  550. }
  551. }
  552. // Clean up
  553. SetupDiDestroyDeviceInfoList(hdi);
  554. }
  555. return fReturn;
  556. }
  557. //+----------------------------------------------------------------------------
  558. //
  559. // Function: IsDialableISDNAdapters
  560. //
  561. // Synopsis: Some ISDN adapters can be installed as RAS devices, but not as
  562. // unimodem devices, so we have to walk through the rest of the
  563. // TAPI devices looking for these.
  564. //
  565. // Arguments: None
  566. //
  567. // Returns: TRUE - there is a device available
  568. //
  569. // History: 7/22/97 ChrisK Created
  570. //
  571. //-----------------------------------------------------------------------------
  572. #define REG_TAPIDEVICES "software\\microsoft\\ras\\tapi devices"
  573. LPSTR szAddress = "Address";
  574. LPSTR szUsage = "Usage";
  575. LPSTR szMediaType = "Media Type";
  576. BOOL IsDialableISDNAdapters()
  577. {
  578. BOOL bRC = FALSE;
  579. HKEY hkey = NULL, hsubkey = NULL;
  580. DWORD dwIdx = 0;
  581. CHAR szBuffer[MAX_PATH + 1];
  582. CHAR szSubKey[MAX_PATH + 1];
  583. LPBYTE lpData = NULL;
  584. LPSTR lpsUsage = NULL;
  585. szBuffer[0] = '\0';
  586. //
  587. // Open TAPI device key
  588. //
  589. if (ERROR_SUCCESS != RegOpenKey(HKEY_LOCAL_MACHINE,
  590. REG_TAPIDEVICES,
  591. &hkey))
  592. {
  593. Dprintf("ICFGNT Can not open TAPI key.\n");
  594. goto IsDialableISDNAdaptersExit;
  595. }
  596. //
  597. // Scan for non unimodem device
  598. //
  599. while (FALSE == bRC)
  600. {
  601. szBuffer[0] = '\0';
  602. if (ERROR_SUCCESS != RegEnumKey(hkey,dwIdx,szBuffer,MAX_PATH))
  603. {
  604. goto IsDialableISDNAdaptersExit;
  605. }
  606. Dprintf("ICFGNT sub key (%s) found.\n",szBuffer);
  607. if (0 != lstrcmpi(szBuffer,"unimodem"))
  608. {
  609. //
  610. // Open other TAPI device reg key
  611. //
  612. szSubKey[0] = '\0';
  613. wsprintf(szSubKey,"%s\\%s",REG_TAPIDEVICES,szBuffer);
  614. Dprintf("ICFGNT opening (%s).\n",szSubKey);
  615. if (ERROR_SUCCESS != RegOpenKey(HKEY_LOCAL_MACHINE,
  616. szSubKey,
  617. &hsubkey))
  618. {
  619. Dprintf("ICFGNT Can not open TAPI SUB key.\n");
  620. goto IsDialableISDNAdaptersExit;
  621. }
  622. if (ERROR_SUCCESS != GetRegValue(hsubkey,szUsage,&lpData))
  623. {
  624. Dprintf("ICFGNT Can not get TAPI SUB key.\n");
  625. goto IsDialableISDNAdaptersExit;
  626. }
  627. //
  628. // Scan for "client"
  629. //
  630. lpsUsage = (LPSTR)lpData;
  631. while (*lpsUsage != '\0')
  632. {
  633. if(NULL != strstr(lpsUsage, "Client"))
  634. {
  635. Dprintf("ICFGNT client found for device.\n");
  636. //
  637. // We found a client device, now check that it is ISDN
  638. //
  639. GlobalFree(lpData);
  640. lpData = NULL;
  641. if (ERROR_SUCCESS != GetRegValue(hsubkey,szMediaType,&lpData))
  642. {
  643. Dprintf("ICFGNT Can not get TAPI SUB value key.\n");
  644. goto IsDialableISDNAdaptersExit;
  645. }
  646. if (0 == lstrcmpi((LPSTR)lpData,"ISDN"))
  647. {
  648. Dprintf("ICFGNT ISDN media type found.\n");
  649. //
  650. // This is a valid dial-out ISDN device!!! Wahoo!!
  651. //
  652. bRC = TRUE;
  653. }
  654. else
  655. {
  656. Dprintf("ICFGNT ISDN media type NOT found.\n");
  657. }
  658. }
  659. else
  660. {
  661. lpsUsage += lstrlen(lpsUsage)+1;
  662. }
  663. }
  664. if (lpData)
  665. {
  666. GlobalFree(lpData);
  667. lpData = NULL;
  668. lpsUsage = NULL;
  669. }
  670. }
  671. //
  672. // Move to the next REG key
  673. //
  674. dwIdx++;
  675. }
  676. IsDialableISDNAdaptersExit:
  677. if (hkey)
  678. {
  679. RegCloseKey(hkey);
  680. hkey = NULL;
  681. }
  682. if (hsubkey)
  683. {
  684. RegCloseKey(hsubkey);
  685. hsubkey = NULL;
  686. }
  687. if (lpData)
  688. {
  689. GlobalFree(lpData);
  690. lpData = NULL;
  691. lpsUsage = NULL;
  692. }
  693. return bRC;
  694. }
  695. //+----------------------------------------------------------------------------
  696. //
  697. // Function: IcfgNeedModem
  698. //
  699. // Synopsis: Check system configuration to determine if there is at least
  700. // one physical modem installed
  701. //
  702. // Arguments: dwfOptions - currently not used
  703. //
  704. // Returns: HRESULT - S_OK if successfull
  705. // lpfNeedModem - TRUE if no modems are available
  706. //
  707. // History: 6/5/97 ChrisK Inherited
  708. //
  709. //-----------------------------------------------------------------------------
  710. LPSTR szRasUnimodemSubKey =
  711. "Software\\Microsoft\\ras\\TAPI DEVICES\\Unimodem";
  712. HRESULT WINAPI
  713. IcfgNeedModemNT4 (DWORD dwfOptions, LPBOOL lpfNeedModem)
  714. {
  715. //
  716. // Ras is insatlled, and ICW wants to know if it needs to
  717. // install a modem.
  718. //
  719. *lpfNeedModem = TRUE;
  720. //
  721. // ChrisK 7/22/97
  722. // Added return code in order to provide centralized place to check
  723. // for ISDN installations
  724. //
  725. HRESULT hRC = ERROR_SUCCESS;
  726. //
  727. // Check what modems are available to RAS
  728. //
  729. HKEY hUnimodem;
  730. LONG dwError;
  731. Dprintf("ICFGNT: IcfgNeedModem\n");
  732. dwError = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  733. szRasUnimodemSubKey,
  734. 0,
  735. KEY_READ,
  736. &hUnimodem);
  737. if(dwError != ERROR_SUCCESS)
  738. {
  739. goto IcfgNeedModemExit;
  740. }
  741. else
  742. {
  743. LPBYTE lpData;
  744. dwError = GetRegValue(hUnimodem, szUsage, &lpData);
  745. if(dwError != ERROR_SUCCESS)
  746. goto IcfgNeedModemExit;
  747. LPBYTE lpData2;
  748. dwError = GetRegValue(hUnimodem, szAddress, &lpData2);
  749. if(dwError != ERROR_SUCCESS)
  750. {
  751. hRC = dwError;
  752. goto IcfgNeedModemExit;
  753. }
  754. else
  755. {
  756. //
  757. // Try finding a Client or ClientAndServer Modem
  758. // Also, make sure all modems have corresponding TAPI devices
  759. //
  760. LPSTR pUsage = (LPSTR) lpData;
  761. LPSTR pAddress = (LPSTR) lpData2;
  762. char portsbuf[1000];
  763. dwError = EnumerateTapiModemPorts(sizeof(portsbuf), portsbuf);
  764. if(dwError)
  765. {
  766. hRC = dwError;
  767. goto IcfgNeedModemExit;
  768. }
  769. while(*pUsage != '\0') {
  770. if(lstrcmp(pUsage, "Client") == 0 ||
  771. lstrcmp(pUsage, "ClientAndServer") == 0 ||
  772. lstrcmp(pUsage, "ClientAndServerAndRouter") == 0)
  773. {
  774. *lpfNeedModem = FALSE;
  775. }
  776. //
  777. // Make sure a corresponding TAPI port exists
  778. //
  779. LPSTR pPorts = portsbuf;
  780. while(*pPorts != '\0')
  781. if(stricmp(pAddress, pPorts) == 0)
  782. {
  783. break;
  784. }
  785. else
  786. {
  787. pPorts += lstrlen(pPorts) + 1;
  788. }
  789. if(*pPorts == '\0')
  790. {
  791. hRC = ERROR_INTERNAL_ERROR;
  792. goto IcfgNeedModemExit;
  793. }
  794. pUsage += lstrlen(pUsage) + 1;
  795. pAddress += lstrlen(pAddress) + 1;
  796. }
  797. }
  798. }
  799. IcfgNeedModemExit:
  800. //
  801. // If there was some problem finding a typical dial out device,
  802. // then try again and check for dialing ISDN devices.
  803. //
  804. if (ERROR_SUCCESS != hRC ||
  805. FALSE != *lpfNeedModem)
  806. {
  807. if (IsDialableISDNAdapters())
  808. {
  809. hRC = ERROR_SUCCESS;
  810. *lpfNeedModem = FALSE;
  811. }
  812. }
  813. return(hRC);
  814. }
  815. //+----------------------------------------------------------------------------
  816. //
  817. // Function: IcfgInstallModem
  818. //
  819. // Synopsis:
  820. // This function is called when ICW verified that RAS is installed,
  821. // but no modems are avilable. It needs to make sure a modem is availble.
  822. // There are two possible scenarios:
  823. //
  824. // a. There are no modems installed. This happens when someone deleted
  825. // a modem after installing RAS. In this case we need to run the modem
  826. // install wizard, and configure the newly installed modem to be a RAS
  827. // dialout device.
  828. //
  829. // b. There are modems installed, but non of them is configured as a dial out
  830. // device. In this case, we silently convert them to be DialInOut devices,
  831. // so ICW can use them.
  832. //
  833. // Arguments: hwndParent - handle to parent window
  834. // dwfOptions - not used
  835. //
  836. // Returns: lpfNeedsStart - not used
  837. //
  838. // History: 6/5/97 ChrisK Inherited
  839. //
  840. //-----------------------------------------------------------------------------
  841. HRESULT WINAPI
  842. IcfgInstallModemNT4 (HWND hwndParent, DWORD dwfOptions, LPBOOL lpfNeedsStart)
  843. {
  844. //
  845. // Check what modems are available to RAS
  846. //
  847. HKEY hUnimodem;
  848. LONG dwError;
  849. BOOL fInstallModem = FALSE;
  850. Dprintf("ICFGNT: IcfgInstallModem\n");
  851. dwError = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  852. szRasUnimodemSubKey,
  853. 0,
  854. KEY_READ,
  855. &hUnimodem);
  856. if(dwError != ERROR_SUCCESS)
  857. {
  858. fInstallModem = TRUE;
  859. }
  860. else
  861. {
  862. LPBYTE lpData;
  863. dwError = GetRegValue(hUnimodem, szUsage, &lpData);
  864. if(dwError != ERROR_SUCCESS)
  865. {
  866. fInstallModem = TRUE;
  867. }
  868. else
  869. {
  870. // Make sure at least one modem exists
  871. if(*lpData == '\0')
  872. {
  873. fInstallModem = TRUE;
  874. }
  875. }
  876. }
  877. if(fInstallModem)
  878. {
  879. //
  880. // Fire up the modem install wizard
  881. //
  882. if(!CallModemInstallWizard(hwndParent))
  883. {
  884. return(g_dwLastError = GetLastError());
  885. }
  886. //
  887. // Now configure the new modem to be a dial out device.
  888. //
  889. //
  890. // Install ras again with unattneded file!
  891. //
  892. return(ERROR_SUCCESS);
  893. }
  894. else
  895. {
  896. //
  897. // We need to reconfigure dial in devices to be dialinout
  898. //
  899. //
  900. // install ras again with unattended file!
  901. //
  902. return(ERROR_SUCCESS);
  903. }
  904. }
  905. //+----------------------------------------------------------------------------
  906. //
  907. // Function: IcfgNeedInetComponets
  908. //
  909. // Synopsis: Check to see if the components marked in the options are
  910. // installed on the system
  911. //
  912. // Arguements: dwfOptions - set of bit flag indicating which components to
  913. // check for
  914. //
  915. // Returns; HRESULT - S_OK if successfull
  916. // lpfNeedComponents - TRUE is some components are not installed
  917. //
  918. // History: 6/5/97 ChrisK Inherited
  919. //
  920. //-----------------------------------------------------------------------------
  921. HRESULT WINAPI
  922. IcfgNeedInetComponentsNT4(DWORD dwfOptions, LPBOOL lpfNeedComponents) {
  923. DWORD dwErr;
  924. //
  925. // Assume need nothing
  926. //
  927. *lpfNeedComponents = FALSE;
  928. Dprintf("ICFGNT: IcfgNeedInetComponents\n");
  929. dwErr = LoadNetcfg();
  930. if(dwErr != ERROR_SUCCESS)
  931. {
  932. return(g_dwLastError = dwErr); // Shouldn't we map to hResult?
  933. }
  934. WCHAR wszInfNameBuf[512];
  935. DWORD cchInfName = sizeof(wszInfNameBuf) / sizeof(WCHAR);
  936. if(dwfOptions & ICFG_INSTALLTCP)
  937. {
  938. dwErr = pfnNetSetupFindSoftwareComponent(L"TC",
  939. wszInfNameBuf,
  940. &cchInfName,
  941. 0,
  942. 0);
  943. if(dwErr != ERROR_SUCCESS)
  944. *lpfNeedComponents = TRUE;
  945. }
  946. if(dwfOptions & ICFG_INSTALLRAS)
  947. {
  948. dwErr = pfnNetSetupFindSoftwareComponent(L"RAS",
  949. wszInfNameBuf,
  950. &cchInfName,
  951. 0,
  952. 0);
  953. if(dwErr != ERROR_SUCCESS)
  954. *lpfNeedComponents = TRUE;
  955. }
  956. if(dwfOptions & ICFG_INSTALLMAIL)
  957. {
  958. // How do we do this?
  959. }
  960. return(ERROR_SUCCESS);
  961. }
  962. //+----------------------------------------------------------------------------
  963. //
  964. // Function: GenerateRasUnattendedFile
  965. //
  966. // Synopsis: Create the file that will provide RAS setup the necessary
  967. // setting to install in an unattended mode
  968. //
  969. // Arguments: wszTmpFile - name of file to create
  970. // szPortsBuf
  971. //
  972. // Returns: FALSE - failure, TRUE - success
  973. //
  974. // History: 6/5/97 ChrisK Inherited
  975. //
  976. //-----------------------------------------------------------------------------
  977. BOOL
  978. GenerateRasUnattendedFile(LPWSTR wszTmpFile, LPSTR szPortsBuf)
  979. {
  980. WCHAR wszTmpPath[MAX_PATH+1];
  981. WCHAR wszTmpShortPath[MAX_PATH+1];
  982. //
  983. // Create temporary file name and convert to non-wide form
  984. //
  985. Dprintf("ICFGNT: GenerateRasUnattendedFile\n");
  986. if (GetTempPathW(MAX_PATH, wszTmpPath) == 0)
  987. {
  988. return(FALSE);
  989. }
  990. //
  991. // always attempt to create the temp dir as the temp dir may not exist if
  992. // the user logs in with a roaming profile
  993. //
  994. CreateDirectoryW(wszTmpPath, NULL);
  995. //
  996. // need to convert this to a short path since pfnNetSetupComponentInstall()
  997. // doesn't like to have a long path in the InfSymbols param.
  998. //
  999. if (!GetShortPathNameW(wszTmpPath, wszTmpShortPath, MAX_PATH))
  1000. {
  1001. return FALSE;
  1002. }
  1003. if (GetTempFileNameW(wszTmpPath, L"icw", 0, wszTmpFile) == 0)
  1004. {
  1005. return(FALSE);
  1006. }
  1007. //
  1008. // need to convert the temp filename to shortpath too!
  1009. //
  1010. if (!GetShortPathNameW(wszTmpFile, wszTmpShortPath, MAX_PATH))
  1011. {
  1012. return FALSE;
  1013. }
  1014. wcscpy(wszTmpFile, wszTmpShortPath);
  1015. char szTmpFile[MAX_PATH+1];
  1016. wcstombs(szTmpFile, wszTmpFile, wcslen(wszTmpFile) + 1);
  1017. #if 0
  1018. /*
  1019. FILE *fp = fopen(szTmpFile, "w");
  1020. if(fp == 0)
  1021. {
  1022. return(FALSE);
  1023. }
  1024. fprintf(fp, "[RemoteAccessParameters]\n");
  1025. fprintf(fp, "PortSections = ");
  1026. LPSTR szPorts = szPortsBuf;
  1027. while(*szPorts) {
  1028. if(szPorts != szPortsBuf)
  1029. {
  1030. fprintf(fp, ",");
  1031. }
  1032. fprintf(fp, "%s", szPorts);
  1033. szPorts += lstrlen(szPorts) + 1;
  1034. }
  1035. fprintf(fp, "\n");
  1036. fprintf(fp, "DialoutProtocols = TCP/IP\n");
  1037. fprintf(fp, "\n");
  1038. fprintf(fp, "[Modem]\n");
  1039. fprintf(fp, "InstallModem=ModemSection\n");
  1040. fprintf(fp, "\n");
  1041. szPorts = szPortsBuf;
  1042. while(*szPorts) {
  1043. fprintf(fp, "[%s]\n", szPorts);
  1044. fprintf(fp, "PortName = %s\n", szPorts);
  1045. fprintf(fp, "DeviceType = Modem\n");
  1046. fprintf(fp, "PortUsage = DialOut\n");
  1047. fprintf(fp, "\n");
  1048. szPorts += lstrlen(szPorts) + 1;
  1049. }
  1050. fprintf(fp, "[ModemSection]\n");
  1051. fclose(fp);
  1052. */
  1053. #else
  1054. //
  1055. // Open the file for writing, bail on fail.
  1056. //
  1057. BOOL bRet = FALSE;
  1058. HANDLE hFile = CreateFile(szTmpFile,GENERIC_WRITE,0,NULL,OPEN_EXISTING,
  1059. FILE_ATTRIBUTE_NORMAL,NULL);
  1060. if (INVALID_HANDLE_VALUE == hFile)
  1061. {
  1062. return FALSE;
  1063. }
  1064. LPSTR szPorts = szPortsBuf;
  1065. char szFileBuf[MAX_PATH];
  1066. DWORD dwWrite;
  1067. lstrcpy(szFileBuf, "[RemoteAccessParameters]\nPortSections = ");
  1068. if (!WriteFile(hFile, szFileBuf, lstrlen(szFileBuf), &dwWrite, NULL))
  1069. {
  1070. goto closefile;
  1071. }
  1072. while (*szPorts)
  1073. {
  1074. //
  1075. // Delimit each item with a comma
  1076. //
  1077. if (szPorts != szPortsBuf)
  1078. {
  1079. lstrcpy(szFileBuf, ",");
  1080. if (!WriteFile(hFile, szFileBuf, lstrlen(szFileBuf), &dwWrite, NULL))
  1081. {
  1082. goto closefile;
  1083. }
  1084. }
  1085. //
  1086. // Write each port
  1087. //
  1088. wsprintf(szFileBuf, "%s", szPorts);
  1089. if (!WriteFile(hFile, szFileBuf, lstrlen(szFileBuf), &dwWrite, NULL))
  1090. {
  1091. goto closefile;
  1092. }
  1093. szPorts += lstrlen(szPorts) + 1;
  1094. }
  1095. //
  1096. // Write DialoutProtocol TCP/IP and InstallModem
  1097. //
  1098. lstrcpy(szFileBuf, "\nDialoutProtocols = TCP/IP\n\n[Modem]\nInstallModem=ModemSection\n\n");
  1099. if (!WriteFile(hFile, szFileBuf, lstrlen(szFileBuf), &dwWrite, NULL))
  1100. {
  1101. goto closefile;
  1102. }
  1103. //
  1104. // Enumerate ports again
  1105. //
  1106. szPorts = szPortsBuf;
  1107. while (*szPorts)
  1108. {
  1109. //
  1110. // Write PortName section and entry
  1111. //
  1112. wsprintf(szFileBuf, "[%s]\n", szPorts);
  1113. if (!WriteFile(hFile, szFileBuf, lstrlen(szFileBuf), &dwWrite, NULL))
  1114. {
  1115. goto closefile;
  1116. }
  1117. wsprintf(szFileBuf, "PortName = %s\n", szPorts);
  1118. if (!WriteFile(hFile, szFileBuf, lstrlen(szFileBuf), &dwWrite, NULL))
  1119. {
  1120. goto closefile;
  1121. }
  1122. //
  1123. // Write DeviceType and PortUsage entry for each port
  1124. //
  1125. lstrcpy(szFileBuf, "DeviceType = Modem\nPortUsage = DialOut\n\n");
  1126. if (!WriteFile(hFile, szFileBuf, lstrlen(szFileBuf), &dwWrite, NULL))
  1127. {
  1128. goto closefile;
  1129. }
  1130. szPorts += lstrlen(szPorts) + 1;
  1131. }
  1132. lstrcpy(szFileBuf, "[ModemSection]\n");
  1133. if (!WriteFile(hFile, szFileBuf, lstrlen(szFileBuf), &dwWrite, NULL))
  1134. {
  1135. goto closefile;
  1136. }
  1137. bRet = TRUE;
  1138. closefile:
  1139. CloseHandle(hFile);
  1140. #endif
  1141. return(bRet);
  1142. }
  1143. //+----------------------------------------------------------------------------
  1144. //
  1145. // Function: InstallRAS
  1146. //
  1147. // Synopsis: Invoke unattended RAS installation
  1148. //
  1149. // Arguments: hwndParent - handle to parent window
  1150. // szFile - name of unattended settings file
  1151. // szSection -
  1152. //
  1153. // Returns: DWORD - win32 error
  1154. // pdwReturn - return code from last parameter of
  1155. // pfnNetSetupComponentInstall
  1156. //
  1157. // History: 6/5/97 ChrisK Inherited
  1158. //
  1159. //-----------------------------------------------------------------------------
  1160. DWORD
  1161. InstallRAS(HWND hwndParent, LPWSTR szFile, LPWSTR szSection, LPDWORD pdwReturn)
  1162. {
  1163. WCHAR InfSymbols[1024];
  1164. LPWSTR szInfSymbols = InfSymbols;
  1165. Dprintf("ICFGNT: InstallRAS\n");
  1166. DWORD dwRC = InstallNTNetworking(hwndParent);
  1167. if (ERROR_SUCCESS != dwRC)
  1168. {
  1169. return dwRC;
  1170. }
  1171. LPWSTR szString1 = L"!STF_GUI_UNATTENDED";
  1172. wcscpy(szInfSymbols, szString1);
  1173. szInfSymbols += wcslen(szString1) + 1;
  1174. LPWSTR szString2 = L"YES";
  1175. wcscpy(szInfSymbols, szString2);
  1176. szInfSymbols += wcslen(szString2) + 1;
  1177. LPWSTR szString3 = L"!STF_UNATTENDED";
  1178. wcscpy(szInfSymbols, szString3);
  1179. szInfSymbols += wcslen(szString3) + 1;
  1180. //
  1181. // Unattneded file.
  1182. //
  1183. wcscpy(szInfSymbols, szFile);
  1184. szInfSymbols += wcslen(szFile) + 1;
  1185. LPWSTR szString4 = L"!STF_UNATTENDED_SECTION";
  1186. wcscpy(szInfSymbols, szString4);
  1187. szInfSymbols += wcslen(szString4) + 1;
  1188. //
  1189. // Unattnded section
  1190. //
  1191. wcscpy(szInfSymbols, szSection);
  1192. szInfSymbols += wcslen(szSection) + 1;
  1193. *szInfSymbols++ = 0;
  1194. *szInfSymbols++ = 0;
  1195. return(pfnNetSetupComponentInstall(hwndParent,
  1196. L"RAS",
  1197. L"OEMNSVRA.INF",
  1198. g_wszInstallPath,
  1199. InfSymbols,
  1200. INFINSTALL_INPROCINTERP, // Install Flags
  1201. pdwReturn));
  1202. }
  1203. //+----------------------------------------------------------------------------
  1204. //
  1205. // Function: IcfgInstallInetComponents
  1206. //
  1207. // Synopsis: Install the components as specified by the dwfOptions values
  1208. //
  1209. // Arguments hwndParent - handle to parent window
  1210. // dwfOptions - set of bit flags indicating which components to
  1211. // install
  1212. //
  1213. // Returns: HRESULT - S_OK if success
  1214. // lpfNeedsReboot - TRUE if reboot is required
  1215. //
  1216. // History: 6/5/97 ChrisK Inherited
  1217. //
  1218. //-----------------------------------------------------------------------------
  1219. HRESULT WINAPI
  1220. IcfgInstallInetComponentsNT4(HWND hwndParent, DWORD dwfOptions, LPBOOL lpfNeedsRestart)
  1221. {
  1222. DWORD dwErr;
  1223. DWORD dwReturn;
  1224. BOOL fNeedsReview;
  1225. BOOL fNeedsRestart;
  1226. BOOL fDoReview = FALSE;
  1227. WCHAR wszInfNameBuf[512];
  1228. DWORD cchInfName = sizeof(wszInfNameBuf) / sizeof(WCHAR);
  1229. Dprintf("ICFGNT: IcfgInstallInetComponents\n");
  1230. //
  1231. // Assume don't need restart
  1232. //
  1233. *lpfNeedsRestart = FALSE;
  1234. dwErr = LoadNetcfg();
  1235. if(dwErr != ERROR_SUCCESS)
  1236. {
  1237. return(g_dwLastError = dwErr); // Review: Shouldn't we map to hResult?
  1238. }
  1239. if(dwfOptions & ICFG_INSTALLTCP)
  1240. {
  1241. dwErr = pfnNetSetupFindSoftwareComponent(L"TC",
  1242. wszInfNameBuf,
  1243. &cchInfName,
  1244. 0,
  1245. 0);
  1246. if(dwErr != ERROR_SUCCESS)
  1247. {
  1248. dwErr = pfnNetSetupComponentInstall(hwndParent,
  1249. L"TC",
  1250. L"OEMNXPTC.INF",
  1251. g_wszInstallPath,
  1252. L"\0\0",
  1253. INFINSTALL_INPROCINTERP, // Install Flags
  1254. &dwReturn);
  1255. if(dwErr != ERROR_SUCCESS)
  1256. {
  1257. return(g_dwLastError = dwErr); // Review: Shouldn't we map to hResult?
  1258. }
  1259. ParseNetSetupReturn(dwReturn, fNeedsRestart, fNeedsReview);
  1260. if(fNeedsRestart)
  1261. {
  1262. *lpfNeedsRestart = TRUE;
  1263. }
  1264. if(fNeedsReview)
  1265. {
  1266. fDoReview = TRUE;
  1267. }
  1268. }
  1269. }
  1270. if(dwfOptions & ICFG_INSTALLRAS)
  1271. {
  1272. dwErr = pfnNetSetupFindSoftwareComponent(L"RAS",
  1273. wszInfNameBuf,
  1274. &cchInfName,
  1275. 0,
  1276. 0);
  1277. if(dwErr != ERROR_SUCCESS)
  1278. {
  1279. //
  1280. // Before we install RAS, we have to make have to make sure a modem
  1281. // is installed, because RAS will try to run the modem detection wizard
  1282. // in unattneded mode if there are no modems, and we don't want that.
  1283. //
  1284. // The way we do that is we enumerate devices through TAPI, and if there are
  1285. // no modems installed, we call the modem install wizard. Only after
  1286. // we make sure a modem was installed, we call ras install.
  1287. //
  1288. DWORD DoTapiModemsExist(LPBOOL pfTapiModemsExist);
  1289. char portsbuf[1000];
  1290. dwErr = EnumerateTapiModemPorts(sizeof(portsbuf), portsbuf);
  1291. if(dwErr)
  1292. return(g_dwLastError = dwErr);
  1293. if(*portsbuf == 0)
  1294. {
  1295. if(!CallModemInstallWizard(hwndParent))
  1296. {
  1297. //
  1298. // if CallModemInstallWizard returned FALSE and
  1299. // GetLastError() is ERROR_SUCCESS, it is actually
  1300. // a user cancelled case
  1301. //
  1302. if (ERROR_SUCCESS == (g_dwLastError = GetLastError()))
  1303. g_dwLastError = ERROR_CANCELLED;
  1304. return(g_dwLastError);
  1305. }
  1306. //
  1307. // In this invocation of EnumerateTapiModemPorts
  1308. // we have to wait for a 1 second before we start
  1309. // enumerating the modems - hence set the last parameter
  1310. // to TRUE -- VetriV
  1311. //
  1312. dwErr = EnumerateTapiModemPorts(sizeof(portsbuf), portsbuf,
  1313. TRUE);
  1314. if(dwErr)
  1315. {
  1316. return(g_dwLastError = dwErr);
  1317. }
  1318. if(*portsbuf == 0)
  1319. {
  1320. return(g_dwLastError = ERROR_CANCELLED);
  1321. }
  1322. }
  1323. WCHAR wszUnattFile[MAX_PATH];
  1324. if(!GenerateRasUnattendedFile(wszUnattFile, portsbuf))
  1325. {
  1326. return(g_dwLastError = GetLastError());
  1327. }
  1328. dwErr = InstallRAS(hwndParent,
  1329. wszUnattFile,
  1330. L"RemoteAccessParameters",
  1331. &dwReturn);
  1332. DeleteFileW(wszUnattFile);
  1333. if(dwErr != ERROR_SUCCESS)
  1334. {
  1335. return(g_dwLastError = dwErr); // Review: Shouldn't we map to hResult?
  1336. }
  1337. ParseNetSetupReturn(dwReturn, fNeedsRestart, fNeedsReview);
  1338. if(fNeedsRestart)
  1339. {
  1340. *lpfNeedsRestart = TRUE;
  1341. }
  1342. if(fNeedsReview)
  1343. {
  1344. fDoReview = TRUE;
  1345. }
  1346. }
  1347. }
  1348. if(fDoReview)
  1349. {
  1350. return(g_dwLastError = ReviewBindings(hwndParent)); // Review: Shouldn't we map to hresult?
  1351. }
  1352. else
  1353. {
  1354. return(ERROR_SUCCESS);
  1355. }
  1356. }
  1357. //+----------------------------------------------------------------------------
  1358. //
  1359. // Function: IcfgIsFileSharingTurnedOn
  1360. //
  1361. // Synopsis: Check network bindings to determine if "Server" service is
  1362. // bound to ndiswan adapter
  1363. //
  1364. // Arguments: dwfDriverType -
  1365. //
  1366. // Returns: HRESULT - S_OK is success
  1367. // lpfSharingOn - TRUE if sharing is bound
  1368. //
  1369. // History: 6/5/97 ChrisK Inherited
  1370. //
  1371. //-----------------------------------------------------------------------------
  1372. LPSTR szLanManServerSubKey = "SYSTEM\\CurrentControlSet\\Services\\LanmanServer\\Linkage";
  1373. LPSTR szBind = "Bind";
  1374. LPSTR szExport = "Export";
  1375. LPSTR szRoute = "Route";
  1376. LPSTR szLanManServerDisabledSubKey = "SYSTEM\\CurrentControlSet\\Services\\LanmanServer\\Linkage\\Disabled";
  1377. LPSTR szNdisWan4 = "NdisWan";
  1378. struct BINDDATA
  1379. {
  1380. CHAR *startb;
  1381. CHAR *currb;
  1382. CHAR *starte;
  1383. CHAR *curre;
  1384. CHAR *startr;
  1385. CHAR *currr;
  1386. } net_bindings;
  1387. HRESULT WINAPI
  1388. IcfgIsFileSharingTurnedOn(DWORD dwfDriverType, LPBOOL lpfSharingOn)
  1389. {
  1390. HRESULT hr = ERROR_SUCCESS;
  1391. HKEY hKey = NULL;
  1392. LPBYTE lpData = NULL;
  1393. CHAR *p;
  1394. Dprintf("ICFGNT: IcfgIsFileSharingTurnedOn\n");
  1395. Assert(lpfSharingOn);
  1396. if (NULL == lpfSharingOn)
  1397. {
  1398. hr = ERROR_INVALID_PARAMETER;
  1399. goto IcfgIsFileSharingTurnedOnExit;
  1400. }
  1401. *lpfSharingOn = FALSE;
  1402. //
  1403. // Open lanmanServer registry key
  1404. //
  1405. if (ERROR_SUCCESS != RegOpenKey(HKEY_LOCAL_MACHINE,
  1406. szLanManServerSubKey,
  1407. &hKey))
  1408. {
  1409. Dprintf("ICFGNT: Failed to open lanmanServer key\n");
  1410. goto IcfgIsFileSharingTurnedOnExit;
  1411. }
  1412. if (ERROR_SUCCESS != GetRegValue(hKey, szBind, &lpData))
  1413. {
  1414. Dprintf("ICFGNT: Failed to read binding information\n");
  1415. goto IcfgIsFileSharingTurnedOnExit;
  1416. }
  1417. Assert(lpData);
  1418. //
  1419. // Look for a particular string in the data returned
  1420. // Note: data is terminiated with two NULLs
  1421. //
  1422. p = (CHAR *)lpData;
  1423. while (*p)
  1424. {
  1425. if (strstr( p, szNdisWan4))
  1426. {
  1427. Dprintf("ICFGNT: NdisWan4 binding found in %s\n",p);
  1428. *lpfSharingOn = TRUE;
  1429. break;
  1430. }
  1431. p += (lstrlen( p ) + 1);
  1432. }
  1433. IcfgIsFileSharingTurnedOnExit:
  1434. if (hKey)
  1435. {
  1436. RegCloseKey(hKey);
  1437. hKey = NULL;
  1438. }
  1439. if (lpData)
  1440. {
  1441. GlobalFree(lpData);
  1442. lpData = NULL;
  1443. }
  1444. return hr;
  1445. }
  1446. //+----------------------------------------------------------------------------
  1447. //
  1448. // Function: MoveNextBinding
  1449. //
  1450. // Synopsis: Move to the next string in a MULTISZ data buffer
  1451. //
  1452. // Arguments: lpcBinding - pointer to address of current buffer position
  1453. //
  1454. // Returns: lpcBinding - pointer to next string
  1455. //
  1456. // History: 6/5/97 ChrisK Created
  1457. //
  1458. //-----------------------------------------------------------------------------
  1459. inline void MoveNextBinding(CHAR **lplpcBinding)
  1460. {
  1461. Dprintf("ICFGNT: MoveNextBinding\n");
  1462. Assert(lplpcBinding && *lplpcBinding);
  1463. if (lplpcBinding && *lplpcBinding)
  1464. {
  1465. *lplpcBinding += (lstrlen(*lplpcBinding)+1);
  1466. }
  1467. else
  1468. {
  1469. Dprintf("ICFGNT: MoveNextBinding received invalid parameter\n");
  1470. }
  1471. }
  1472. //+----------------------------------------------------------------------------
  1473. //
  1474. // Function: CompactLinkage
  1475. //
  1476. // Synopsis: Compact a list of Multi_SZ data
  1477. //
  1478. // Arguments: lpBinding - point to the string of an Multi_Sz list that should
  1479. // be over written
  1480. //
  1481. // Returns: none
  1482. //
  1483. // History: 6/5/97 ChrisK Created
  1484. //
  1485. //-----------------------------------------------------------------------------
  1486. inline void CompactLinkage(CHAR *lpBinding)
  1487. {
  1488. Dprintf("ICFGNT: CompactLinkage\n");
  1489. Assert(lpBinding && *lpBinding);
  1490. CHAR *lpLast = lpBinding;
  1491. BOOL fNULLChar = FALSE;
  1492. MoveNextBinding(&lpBinding);
  1493. //
  1494. // ChrisK Olympus 6311 6/11/97
  1495. // Do not compact on a per string basis. This causes the data to become
  1496. // corrupted if the string being removed is shorter than the string being
  1497. // added. Instead compact on a per character basis, since those are always
  1498. // the same size (on a given machine).
  1499. //
  1500. while (!fNULLChar || *lpBinding)
  1501. {
  1502. if (NULL == *lpBinding)
  1503. {
  1504. fNULLChar = TRUE;
  1505. }
  1506. else
  1507. {
  1508. fNULLChar = FALSE;
  1509. }
  1510. *lpLast++ = *lpBinding++;
  1511. }
  1512. //while (*lpBinding)
  1513. //{
  1514. // lstrcpy(lpLast,lpBinding);
  1515. // lpLast = lpBinding;
  1516. // MoveNextBinding(&lpBinding);
  1517. //}
  1518. //
  1519. // Add second terminating NULL
  1520. //
  1521. *lpLast = '\0';
  1522. }
  1523. //+----------------------------------------------------------------------------
  1524. //
  1525. // Function: SizeOfMultiSz
  1526. //
  1527. // Synopsis: determine the total size of a Multi_sz list, including
  1528. // terminating NULLs
  1529. //
  1530. // Arguments: s - pointer to list
  1531. //
  1532. // Returns: DWORD - size of s
  1533. //
  1534. // History: 6/5/97 ChrisK created
  1535. //
  1536. //-----------------------------------------------------------------------------
  1537. DWORD SizeOfMultiSz(CHAR *s)
  1538. {
  1539. Dprintf("ICFGNT: SizeOfMultiSz\n");
  1540. Assert(s);
  1541. DWORD dwLen = 0;
  1542. //
  1543. // total size of all strings
  1544. //
  1545. //
  1546. // ChrisK Olympus 6311 6/11/97
  1547. // Add special case for empty MultiSZ strings
  1548. //
  1549. //
  1550. // Special case for empty MultiSz.
  1551. // Note: even "empty" MultiSZ strings still have the two null terminating characters
  1552. //
  1553. if (!(*s))
  1554. {
  1555. //
  1556. // Make sure we actually have two terminating NULLs in this case.
  1557. //
  1558. Assert(s[1] == '\0');
  1559. //
  1560. // Count terminating NULL.
  1561. //
  1562. dwLen = 1;
  1563. }
  1564. while (*s)
  1565. {
  1566. dwLen += lstrlen(s) + 1;
  1567. s += lstrlen(s) + 1;
  1568. }
  1569. //
  1570. // plus one for the extra terminating NULL
  1571. //
  1572. dwLen++;
  1573. Dprintf("ICFGNT: SizeOfMultiSz returns %d\n", dwLen);
  1574. return dwLen;
  1575. }
  1576. //+----------------------------------------------------------------------------
  1577. //
  1578. // Function: WriteBindings
  1579. //
  1580. // Synopsis: Write the data from a BINDDATA structure to the key given
  1581. //
  1582. // Arguments: bd - BINDDATA structure with data to be written
  1583. // hKey - handle of registry key to get data
  1584. //
  1585. // Returns: win32 error code
  1586. //
  1587. // History: 6/5/97 ChrisK created
  1588. //
  1589. //-----------------------------------------------------------------------------
  1590. DWORD WriteBindings(BINDDATA bd, HKEY hKey)
  1591. {
  1592. DWORD dwRC = ERROR_SUCCESS;
  1593. DWORD dwSize;
  1594. Assert (hKey &&
  1595. bd.startb &&
  1596. bd.starte &&
  1597. bd.startr);
  1598. Dprintf("ICFGNT: WriteBindings\n");
  1599. //
  1600. // Bind
  1601. //
  1602. dwSize = SizeOfMultiSz(bd.startb);
  1603. if (ERROR_SUCCESS != (dwRC = RegSetValueEx(hKey,
  1604. szBind,
  1605. NULL,
  1606. REG_MULTI_SZ,
  1607. (LPBYTE)bd.startb,
  1608. dwSize)))
  1609. {
  1610. Dprintf("ICFGNT: Failed to write Bind key\n");
  1611. goto WriteBindingsExit;
  1612. }
  1613. //
  1614. // Export
  1615. //
  1616. dwSize = SizeOfMultiSz(bd.starte);
  1617. if (ERROR_SUCCESS != (dwRC = RegSetValueEx(hKey,
  1618. szExport,
  1619. NULL,
  1620. REG_MULTI_SZ,
  1621. (LPBYTE)bd.starte,
  1622. dwSize)))
  1623. {
  1624. Dprintf("ICFGNT: Failed to write export key\n");
  1625. goto WriteBindingsExit;
  1626. }
  1627. //
  1628. // Route
  1629. //
  1630. dwSize = SizeOfMultiSz(bd.startr);
  1631. if (ERROR_SUCCESS != (dwRC = RegSetValueEx(hKey,
  1632. szRoute,
  1633. NULL,
  1634. REG_MULTI_SZ,
  1635. (LPBYTE)bd.startr,
  1636. dwSize)))
  1637. {
  1638. Dprintf("ICFGNT: Failed to write route key\n");
  1639. goto WriteBindingsExit;
  1640. }
  1641. WriteBindingsExit:
  1642. return dwRC;
  1643. }
  1644. //+----------------------------------------------------------------------------
  1645. //
  1646. // Function: IcfgTurnOffFileSharing
  1647. //
  1648. // Synopsis; Disable the binding between the "server" net service and the
  1649. // ndiswan4 device
  1650. //
  1651. // Arguments: dwfDriverType -
  1652. // hwndParent - parent window
  1653. //
  1654. // Returns: HRESULT - S_OK if success
  1655. //
  1656. // History: 6/5/97 ChrisK Inherited
  1657. //
  1658. //-----------------------------------------------------------------------------
  1659. HRESULT WINAPI
  1660. IcfgTurnOffFileSharing(DWORD dwfDriverType, HWND hwndParent)
  1661. {
  1662. BINDDATA LinkData = {NULL, NULL, NULL, NULL, NULL, NULL};
  1663. BINDDATA DisData = {NULL, NULL, NULL, NULL, NULL, NULL};
  1664. HKEY hKeyLink = NULL;
  1665. HKEY hKeyDis = NULL;
  1666. HRESULT hr = ERROR_SUCCESS;
  1667. BOOL bUpdateReg = FALSE;
  1668. Dprintf("ICFGNT: IcfgTurnOffFileSharing\n");
  1669. Assert(hwndParent);
  1670. if (NULL == hwndParent)
  1671. {
  1672. hr = ERROR_INVALID_PARAMETER;
  1673. goto IcfgTurnOffFileSharingExit;
  1674. }
  1675. //
  1676. // Open Keys and read binding data
  1677. //
  1678. if (ERROR_SUCCESS != RegOpenKey(HKEY_LOCAL_MACHINE,
  1679. szLanManServerSubKey,
  1680. &hKeyLink))
  1681. {
  1682. Dprintf("ICFGNT: failed to open linkdata key\n");
  1683. goto IcfgTurnOffFileSharingExit;
  1684. }
  1685. if (ERROR_SUCCESS != RegOpenKey(HKEY_LOCAL_MACHINE,
  1686. szLanManServerDisabledSubKey,
  1687. &hKeyDis))
  1688. {
  1689. Dprintf("ICFGNT: failed to open linkdata key\n");
  1690. goto IcfgTurnOffFileSharingExit;
  1691. }
  1692. GetRegValue(hKeyLink,szBind,(LPBYTE*)&LinkData.startb);
  1693. GetRegValue(hKeyLink,szExport,(LPBYTE*)&LinkData.starte);
  1694. GetRegValue(hKeyLink,szRoute,(LPBYTE*)&LinkData.startr);
  1695. GetRegValue(hKeyDis,szBind,(LPBYTE*)&DisData.startb);
  1696. GetRegValue(hKeyDis,szExport,(LPBYTE*)&DisData.starte);
  1697. GetRegValue(hKeyDis,szRoute,(LPBYTE*)&DisData.startr);
  1698. //
  1699. // Initialize all current pointers
  1700. //
  1701. LinkData.currb = LinkData.startb;
  1702. LinkData.curre = LinkData.starte;
  1703. LinkData.currr = LinkData.startr;
  1704. DisData.currb = DisData.startb;
  1705. while (*DisData.currb)
  1706. {
  1707. MoveNextBinding(&DisData.currb);
  1708. }
  1709. DisData.curre = DisData.starte;
  1710. while (*DisData.curre)
  1711. {
  1712. MoveNextBinding(&DisData.curre);
  1713. }
  1714. DisData.currr = DisData.startr;
  1715. while (*DisData.currr)
  1716. {
  1717. MoveNextBinding(&DisData.currr);
  1718. }
  1719. //
  1720. // Scan linkages for NdisWan4 bindings
  1721. //
  1722. while (*LinkData.currb)
  1723. {
  1724. if (strstr(LinkData.currb, szNdisWan4))
  1725. {
  1726. Dprintf("ICFGNT: server binding found in %s\n",LinkData.currb);
  1727. //
  1728. // move binding to disabled list
  1729. //
  1730. lstrcpy(DisData.currb,LinkData.currb);
  1731. lstrcpy(DisData.curre,LinkData.curre);
  1732. lstrcpy(DisData.currr,LinkData.currr);
  1733. //
  1734. // Advanve current pointers in DisData
  1735. //
  1736. MoveNextBinding(&DisData.currb);
  1737. MoveNextBinding(&DisData.curre);
  1738. MoveNextBinding(&DisData.currr);
  1739. //
  1740. // Compact remaining linkage
  1741. //
  1742. CompactLinkage(LinkData.currb);
  1743. CompactLinkage(LinkData.curre);
  1744. CompactLinkage(LinkData.currr);
  1745. bUpdateReg = TRUE;
  1746. }
  1747. else
  1748. {
  1749. //
  1750. // Advance to next binding
  1751. //
  1752. MoveNextBinding(&LinkData.currb);
  1753. MoveNextBinding(&LinkData.curre);
  1754. MoveNextBinding(&LinkData.currr);
  1755. }
  1756. }
  1757. if (bUpdateReg)
  1758. {
  1759. WriteBindings(LinkData,hKeyLink);
  1760. WriteBindings(DisData,hKeyDis);
  1761. RegCloseKey(hKeyDis);
  1762. hKeyDis = NULL;
  1763. RegCloseKey(hKeyLink);
  1764. hKeyLink = NULL;
  1765. #if defined(_DEBUG)
  1766. Dprintf("ICFGNT: ReviewBindings returnded %d\n",ReviewBindings(hwndParent));
  1767. #else
  1768. ReviewBindings(hwndParent);
  1769. #endif
  1770. }
  1771. IcfgTurnOffFileSharingExit:
  1772. if (hKeyDis)
  1773. {
  1774. RegCloseKey(hKeyDis);
  1775. hKeyDis = NULL;
  1776. }
  1777. if (hKeyLink)
  1778. {
  1779. RegCloseKey(hKeyLink);
  1780. hKeyLink = NULL;
  1781. }
  1782. return hr;
  1783. }