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.

4808 lines
110 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. winntsif.c
  5. Abstract:
  6. winntsif.c is responsible for filling in the nt setup answer file with data from
  7. the win9xupg system being upgraded. This data is then used during unattended setup
  8. to control the installation of various portions of the winnt system.
  9. This is a rewrite and rationalization of the old unattend.c file.
  10. Author:
  11. Marc R. Whitten (marcw) 16-Feb-1998
  12. Revision History:
  13. ovidiut 14-Mar-2000 Added random admin password for GUI setup
  14. marcw 29-Aug-1999 ID mapping for NICs.
  15. marcw 08-Mar-1999 Migration dlls can handle section\keys.
  16. marcw 23-Sep-1998 DLC fix
  17. --*/
  18. #include "pch.h"
  19. #define DBG_WINNTSIF "WinntSif"
  20. /*++
  21. Macro Expansion List Description:
  22. WINNTSIF_SECTIONS lists all of the sections in winnt.sif that will be populated by the
  23. winntsif processing code. The engine will enumerate each section in this list and then
  24. process the settings associated with that section.
  25. Line Syntax:
  26. STRSECTION(SectionName,SettingsList)
  27. FUNSECTION(SectionFunction,SettingsList)
  28. Arguments:
  29. SectionName - This is a string containing the name of the section that is processed.
  30. SectionFunction - This is an enumeration function that is called for sections that will
  31. have multiple instances. This function returns a new section name each
  32. time it is called, until there are no more instances to process.
  33. At that time, this function returns NULL, ending the processing if the
  34. associated section settings.
  35. SettingsList - A list of settings associated with each function. Each of these settings
  36. will be processed for the given section (or multiple sections in the case
  37. of FUNSECTION lines..) See the description of the <X>_SECTION_SETTINGS
  38. macro for more details on these settings.
  39. Variables Generated From List:
  40. g_SectionList
  41. --*/
  42. /*++
  43. Macro Expansion List Description:
  44. <X>_SECTION_SETTINGS lists the settings to be processed for the section X. Each section in the
  45. WINNTSIF_SECTIONS macro above contains a list of these settings..
  46. Line Syntax:
  47. FUNDATA(CreationFunction,SettingName,DataFunction)
  48. STRDATA(CreationFunction,SettingName,DataString)
  49. REGDATA(CreationFunction,SettingName,RegKey,RegValue)
  50. Arguments:
  51. CreationFunction - This is an optional boolean function which returns TRUE if the setting should
  52. be written, FALSE if it should be skipped.
  53. SettingName - A string containing the name of the setting being processed.
  54. DataFunction - A Function which returns the string data to be written for the specified setting,
  55. or NULL if nothing is to be written.
  56. DataString - The actual string to write for the data of the setting.
  57. RegKey/RegValue - The Key and value to use to retrieve the data to be written for the setting from
  58. the registry.
  59. Variables Generated From List:
  60. Used with WINNTSIF_SECTIONS to generate g_SectionList.
  61. --*/
  62. #define WINNTSIF_SECTIONS \
  63. STRSECTION(WINNT_DATA,DATA_SECTION_SETTINGS) \
  64. STRSECTION(S_UNATTENDED,UNATTENDED_SECTION_SETTINGS) \
  65. STRSECTION(S_GUIUNATTENDED,GUIUNATTENDED_SECTION_SETTINGS) \
  66. STRSECTION(S_USERDATA,USERDATA_SECTION_SETTINGS) \
  67. STRSECTION(S_DISPLAY,DISPLAY_SECTION_SETTINGS) \
  68. FUNSECTION(pNetAdapterSections,FUNDATA(NULL,S_INFID,pGetNetAdapterPnpId)) \
  69. STRSECTION(S_NETWORKING,NETWORKING_SECTION_SETTINGS) \
  70. STRSECTION(S_PAGE_IDENTIFICATION,IDENTIFICATION_SECTION_SETTINGS) \
  71. STRSECTION(S_PAGE_NETPROTOCOLS,NETPROTOCOLS_SECTION_SETTINGS) \
  72. STRSECTION(S_MS_NWIPX,FUNDATA(NULL,S_ADAPTERSECTIONS,pGetAdaptersWithIpxBindings)) \
  73. FUNSECTION(pIpxAdapterSections,IPX_ADAPTER_SECTION_SETTINGS) \
  74. FUNSECTION(pHomenetSection, HOMENET_SECTION_SETTINGS) \
  75. STRSECTION(S_MS_TCPIP,TCPIP_SECTION_SETTINGS) \
  76. FUNSECTION(pTcpAdapterSections,TCP_ADAPTER_SECTION_SETTINGS) \
  77. STRSECTION(S_PAGE_NETCLIENTS,NETCLIENTS_SECTION_SETTINGS) \
  78. STRSECTION(S_SERVICESTARTTYPES,SERVICESTARTTYPES_SECTION_SETTINGS) \
  79. STRSECTION(S_PAGE_NETSERVICES,NETSERVICES_SECTION_SETTINGS) \
  80. STRSECTION(S_NETOPTIONALCOMPONENTS,NETOPTIONALCOMPONENTS_SECTION_SETTINGS) \
  81. STRSECTION(S_MSRASCLI,STRDATA(pIsRasInstalled,S_PARAMSSECTION,S_PARAMSRASCLI)) \
  82. STRSECTION(S_PARAMSRASCLI,PARAMSRASCLI_SECTION_SETTINGS) \
  83. FUNSECTION(pRasPortSections,RASPORT_SECTION_SETTINGS) \
  84. STRSECTION(S_MS_NWCLIENT,NWCLIENT_SECTION_SETTINGS) \
  85. FUNSECTION(pBindingSections,FUNDATA(NULL,NULL,NULL)) \
  86. STRSECTION(S_REGIONALSETTINGS,REGIONALSETTINGS_SECTION_SETTINGS) \
  87. #if 0
  88. // this was moved to winnt32 dll as part of Setup components update
  89. STRSECTION(WINNT_WIN95UPG_95_DIR_A,FUNDATA(NULL,WINNT_WIN95UPG_NTKEY_A,pGetReplacementDll)) \
  90. #endif
  91. //
  92. // [Data]
  93. //
  94. #define DATA_SECTION_SETTINGS \
  95. FUNDATA(NULL,WINNT_D_MIGTEMPDIR,pGetTempDir) \
  96. FUNDATA(NULL,WINNT_D_WIN9XSIF,pGetWin9xSifDir) \
  97. STRDATA(NULL,WINNT_U_UNATTENDMODE,WINNT_A_DEFAULTHIDE) \
  98. FUNDATA(NULL,WINNT_D_INSTALLDIR,pGetWinDir) \
  99. FUNDATA(NULL,WINNT_D_WIN9XBOOTDRIVE,pGetWin9xBootDrive) \
  100. FUNDATA(NULL,WINNT_D_GUICODEPAGEOVERRIDE,pGetGuiCodePage) \
  101. FUNDATA(NULL,WINNT_D_BACKUP_LIST,pBackupFileList) \
  102. FUNDATA(NULL,WINNT_D_ROLLBACK_MOVE,pUninstallMoveFileList) \
  103. FUNDATA(NULL,WINNT_D_ROLLBACK_DELETE,pUninstallDelFileList) \
  104. FUNDATA(NULL,WINNT_D_ROLLBACK_DELETE_DIR,pUninstallDelDirList) \
  105. FUNDATA(NULL,S_ROLLBACK_MK_DIRS,pUninstallMkDirList) \
  106. //
  107. // [Unattended]
  108. //
  109. #define UNATTENDED_SECTION_SETTINGS \
  110. STRDATA(NULL,S_NOWAITAFTERTEXTMODE,S_ONE) \
  111. STRDATA(NULL,S_NOWAITAFTERGUIMODE,S_ONE) \
  112. STRDATA(NULL,S_CONFIRMHARDWARE,S_NO) \
  113. FUNDATA(NULL,S_KEYBOARDLAYOUT,pGetKeyboardLayout) \
  114. FUNDATA(NULL,S_KEYBOARDHARDWARE,pGetKeyboardHardware)
  115. //
  116. // [GuiUnattended]
  117. //
  118. #define GUIUNATTENDED_SECTION_SETTINGS \
  119. FUNDATA(NULL,S_TIMEZONE,pGetTimeZone) \
  120. STRDATA(NULL,S_SERVERTYPE,S_STANDALONE) \
  121. FUNDATA(NULL,WINNT_US_ADMINPASS,pSetAdminPassword)
  122. //
  123. // [UserData]
  124. //
  125. #define USERDATA_SECTION_SETTINGS \
  126. FUNDATA(NULL,S_FULLNAME,pGetFullName) \
  127. REGDATA(NULL,S_ORGNAME,S_WINDOWS_CURRENTVERSION,S_REGISTEREDORGANIZATION) \
  128. FUNDATA(NULL,S_COMPUTERNAME,pGetComputerName) \
  129. //
  130. // [Display]
  131. //
  132. #define DISPLAY_SECTION_SETTINGS \
  133. FUNDATA(NULL,S_BITSPERPEL,pGetBitsPerPixel) \
  134. FUNDATA(NULL,S_XRESOLUTION,pGetXResolution) \
  135. FUNDATA(NULL,S_YRESOLUTION,pGetYResolution) \
  136. FUNDATA(NULL,S_VREFRESH,pGetVerticalRefreshRate) \
  137. //
  138. // [Networking]
  139. //
  140. #define NETWORKING_SECTION_SETTINGS \
  141. STRDATA(pIsNetworkingInstalled,S_PROCESSPAGESECTIONS,S_YES) \
  142. STRDATA(pIsNetworkingInstalled,S_UPGRADEFROMPRODUCT,S_WINDOWS95) \
  143. FUNDATA(pIsNetworkingInstalled,S_BUILDNUMBER,pGetBuildNumber)
  144. //
  145. // [Identification]
  146. //
  147. #define IDENTIFICATION_SECTION_SETTINGS \
  148. FUNDATA(pIsNetworkingInstalled,S_JOINDOMAIN,pGetUpgradeDomainName) \
  149. FUNDATA(pIsNetworkingInstalled,S_JOINWORKGROUP,pGetUpgradeWorkgroupName)
  150. //
  151. // [NetProtocols]
  152. //
  153. #define NETPROTOCOLS_SECTION_SETTINGS \
  154. STRDATA(pIsNwIpxInstalled,S_MS_NWIPX,S_MS_NWIPX) \
  155. STRDATA(pIsTcpIpInstalled,S_MS_TCPIP,S_MS_TCPIP) \
  156. //
  157. // These protocols were removed from Whistler, don't migrate settings for them
  158. //
  159. // STRDATA(pIsNetBeuiInstalled,S_MS_NETBEUI,S_MS_NETBEUI) \
  160. // STRDATA(pIsMsDlcInstalled,S_MS_DLC,S_MS_DLC) \
  161. //
  162. // [Adapter<x>.ipx]
  163. //
  164. #define IPX_ADAPTER_SECTION_SETTINGS \
  165. FUNDATA(NULL,S_SPECIFICTO,pSpecificTo) \
  166. FUNDATA(NULL,S_PKTTYPE,pGetIpxPacketType) \
  167. FUNDATA(NULL,S_NETWORKNUMBER,pGetIpxNetworkNumber) \
  168. //
  169. // [MS_TCPIP]
  170. //
  171. #define TCPIP_SECTION_SETTINGS \
  172. FUNDATA(pIsTcpIpInstalled,S_ADAPTERSECTIONS,pGetAdaptersWithTcpBindings) \
  173. FUNDATA(pIsTcpIpInstalled,S_DNS,pGetDnsStatus) \
  174. REGDATA(pIsDnsEnabled,S_DNSHOST,S_MSTCP_KEY,S_HOSTNAMEVAL) \
  175. FUNDATA(pIsDnsEnabled,S_DNSSUFFIXSEARCHORDER,pGetDnsSuffixSearchOrder) \
  176. REGDATA(pIsTcpIpInstalled,S_SCOPEID,S_MSTCP_KEY,S_SCOPEID) \
  177. REGDATA(pIsTcpIpInstalled,S_IMPORTLMHOSTSFILE,S_MSTCP_KEY,S_LMHOSTS) \
  178. //
  179. // [Adapter<x>.tcpip]
  180. //
  181. #define TCP_ADAPTER_SECTION_SETTINGS \
  182. FUNDATA(NULL,S_SPECIFICTO,pSpecificTo) \
  183. FUNDATA(NULL,S_DHCP,pGetDhcpStatus) \
  184. STRDATA(NULL,S_NETBIOSOPTION,S_ONE) \
  185. FUNDATA(pHasStaticIpAddress,S_IPADDRESS,pGetIpAddress) \
  186. FUNDATA(pHasStaticIpAddress,S_SUBNETMASK,pGetSubnetMask) \
  187. FUNDATA(NULL,S_DEFAULTGATEWAY,pGetGateway) \
  188. FUNDATA(pIsDnsEnabled,S_DNSSERVERSEARCHORDER,pGetDnsServerSearchOrder) \
  189. REGDATA(pIsDnsEnabled,S_DNSDOMAIN,S_MSTCP_KEY,S_DOMAINVAL) \
  190. FUNDATA(NULL,S_WINS,pGetWinsStatus) \
  191. FUNDATA(NULL,S_WINSSERVERLIST,pGetWinsServers)
  192. #define HOMENET_SECTION_SETTINGS \
  193. FUNDATA(pExternalIsAdapter,S_EXTERNAL_ADAPTER, pIcsExternalAdapter) \
  194. FUNDATA(pExternalIsRasConn,S_EXTERNAL_CONNECTION_NAME, pIcsExternalConnectionName) \
  195. FUNDATA(NULL, S_INTERNAL_IS_BRIDGE, pInternalIsBridge) \
  196. FUNDATA(pHasInternalAdapter, S_INTERNAL_ADAPTER, pInternalAdapter) \
  197. FUNDATA(pHasBridge, S_BRIDGE, pBridge) \
  198. FUNDATA(NULL, S_DIAL_ON_DEMAND, pDialOnDemand) \
  199. REGDATA(NULL, S_ENABLEICS, S_ICS_KEY, S_ENABLED) \
  200. REGDATA(NULL, S_SHOW_TRAY_ICON, S_ICS_KEY, S_SHOW_TRAY_ICON) \
  201. STRDATA(NULL, S_ISW9XUPGRADE, S_YES)
  202. //
  203. // [NetClients]
  204. //
  205. #define NETCLIENTS_SECTION_SETTINGS \
  206. STRDATA(pIsWkstaInstalled,S_MS_NETCLIENT,S_MS_NETCLIENT) \
  207. STRDATA(pIsNwClientInstalled,S_MS_NWCLIENT,S_MS_NWCLIENT) \
  208. //
  209. // [ServiceStartTypes]
  210. //
  211. #define SERVICESTARTTYPES_SECTION_SETTINGS \
  212. STRDATA(pDisableBrowserService,S_BROWSER,TEXT("3")) \
  213. //
  214. // [NetServices]
  215. //
  216. #define NETSERVICES_SECTION_SETTINGS \
  217. STRDATA(pInstallMsServer,S_MS_SERVER,S_MS_SERVER) \
  218. STRDATA(pIsRasInstalled,S_MSRASCLI,S_MSRASCLI)
  219. //
  220. // [NetOptionalComponents]
  221. //
  222. #define NETOPTIONALCOMPONENTS_SECTION_SETTINGS \
  223. STRDATA(pIsSnmpInstalled,S_SNMP,S_ONE) \
  224. STRDATA(pIsUpnpInstalled,S_UPNP,S_ONE)
  225. //
  226. // [params.rascli]
  227. //
  228. #define PARAMSRASCLI_SECTION_SETTINGS \
  229. STRDATA(pIsRasInstalled,S_DIALOUTPROTOCOLS,S_ALL) \
  230. FUNDATA(pIsRasInstalled,S_PORTSECTIONS,pGetRasPorts)
  231. //
  232. // [com<x>]
  233. //
  234. #define RASPORT_SECTION_SETTINGS \
  235. FUNDATA(NULL,S_PORTNAME,pRasPortName) \
  236. STRDATA(NULL,S_PORTUSAGE,S_CLIENT)
  237. //
  238. // [NwClient]
  239. //
  240. #define NWCLIENT_SECTION_SETTINGS \
  241. REGDATA(pIsNwClientInstalled,S_PREFERREDSERVER,S_AUTHAGENTREG,S_AUTHENTICATINGAGENT) \
  242. REGDATA(pIsNwClientInstalled,S_DEFAULTCONTEXT,S_NWREDIRREG,S_DEFAULTNAMECONTEXT) \
  243. REGDATA(pIsNwClientInstalled,S_DEFAULTTREE,S_NWREDIRREG,S_PREFERREDNDSTREE) \
  244. FUNDATA(pIsNwClientInstalled,S_LOGONSCRIPT,pGetScriptProcessingStatus) \
  245. #define REGIONALSETTINGS_SECTION_SETTINGS \
  246. FUNDATA(NULL,S_LANGUAGEGROUP,pGetLanguageGroups) \
  247. REGDATA(NULL,S_LANGUAGE,S_SYSTEMLOCALEREG,TEXT("")) \
  248. //
  249. // typedefs for the various functions prototypes used by the winntsif code.
  250. //
  251. typedef BOOL (* CREATION_FUNCTION) (VOID);
  252. typedef PCTSTR (* DATA_FUNCTION) (VOID);
  253. typedef PCTSTR (* SECTION_FUNCTION) (VOID);
  254. //
  255. // The SETTING_TYPE enum contains all of the possible Types of settings which
  256. // may occur in the macro expansion list above.
  257. //
  258. typedef enum {
  259. FUNCTION_SETTING = 1,
  260. STRING_SETTING,
  261. REGISTRY_SETTING,
  262. LAST_SETTING
  263. } SETTING_TYPE;
  264. //
  265. // This structure wraps a key and a value inside a single structure. It is accessed
  266. // within the union below.
  267. //
  268. typedef struct {
  269. PCTSTR Key;
  270. PCTSTR Value;
  271. } REGKEYANDVALUE, *PREGKEYANDVALUE;
  272. //
  273. // SETTING contains the information to create a single setting within
  274. // a winntsif file.
  275. //
  276. typedef struct {
  277. SETTING_TYPE SettingType;
  278. CREATION_FUNCTION CreationFunction;
  279. PCTSTR KeyName;
  280. //
  281. // The data depends on the SETTING_TYPE above.
  282. //
  283. union {
  284. REGKEYANDVALUE Registry;
  285. DATA_FUNCTION Function;
  286. PCTSTR String;
  287. } Data;
  288. } SETTING, *PSETTING;
  289. //
  290. // Section is the toplevel hierarchy used for the winntsif file.
  291. // Each section contains a list of settings that will be processed and
  292. // possibly written for that section.
  293. //
  294. #define MAX_SETTINGS 16
  295. typedef struct {
  296. PTSTR SectionString;
  297. SECTION_FUNCTION SectionFunction;
  298. SETTING SettingList[MAX_SETTINGS];
  299. } SECTION, *PSECTION;
  300. #define FUNDATA(create,key,datafunction) {FUNCTION_SETTING, (create), (key), {(PTSTR) (datafunction), NULL}},
  301. #define STRDATA(create,key,datastring) {STRING_SETTING, (create), (key), {(PTSTR) (datastring), NULL}},
  302. #define REGDATA(create,key,regkey,regvalue) {REGISTRY_SETTING, (create), (key), {(regkey), (regvalue)}},
  303. #define STRSECTION(section,list) {(section),NULL,{list /*,*/ {LAST_SETTING,NULL,NULL,{NULL,NULL}}}},
  304. #define FUNSECTION(function,list) {NULL,(function),{list /*,*/ {LAST_SETTING,NULL,NULL,{NULL,NULL}}}},
  305. typedef struct {
  306. PCTSTR Text;
  307. BOOL Installed;
  308. } BINDINGPART, *PBINDINGPART;
  309. #define NUM_PROTOCOLS 4
  310. #define NUM_CLIENTS 2
  311. typedef struct {
  312. BINDINGPART Clients[NUM_CLIENTS];
  313. BINDINGPART Protocols[NUM_PROTOCOLS];
  314. } BINDINGINFO, *PBINDINGINFO;
  315. BINDINGINFO g_BindingInfo =
  316. {{{S_MS_NETCLIENT, FALSE},{S_MS_NWCLIENT, FALSE}},{{S_MS_TCPIP, FALSE},{S_MS_NWIPX, FALSE},{S_MS_NETBEUI, FALSE}, {S_MS_DLC, FALSE}}};
  317. TCHAR g_CurrentAdapter[MEMDB_MAX]; // During adapter/section enumeration, contains current adapter name.
  318. TCHAR g_CurrentSection[MEMDB_MAX]; // During some section enums, contains current section name.
  319. TCHAR g_TempBuffer[MEMDB_MAX]; // Contains the current value returned from pGetRegistryValue
  320. MEMDB_ENUM g_TempEnum; // A global enumerator that may be used by various section functions.
  321. HINF g_IntlInf;
  322. INFSTRUCT g_InfStruct = INITINFSTRUCT_POOLHANDLE;
  323. POOLHANDLE g_LocalePool;
  324. HASHTABLE g_LocaleTable;
  325. BOOL g_fIcsAdapterInPlace = FALSE;
  326. BOOL g_fHasIcsExternalAdapter = FALSE;
  327. TCHAR g_IcsAdapter[MEMDB_MAX] = {0};
  328. TCHAR g_IcsExternalAdapter[MEMDB_MAX] = {0};
  329. BOOL g_fIcsInternalIsBridge = FALSE;
  330. #define S_REGIONALSETTINGS TEXT("RegionalSettings")
  331. #define CLEARBUFFER() ZeroMemory(g_TempBuffer,MEMDB_MAX * sizeof (TCHAR));
  332. //
  333. // Helper and Miscellaneous functions..
  334. //
  335. /*++
  336. Routine Description:
  337. pGetRegistryValue is a utility wrapper used for getting data out of the
  338. registry. Because winntsif processing requires frequent and very similar
  339. reads from the registry, this wrapper is modified to be a little friendlier
  340. to this type of processing than the normal functions in reg.h. This
  341. function reads the data from the registry, and packs it into a multisz. It
  342. is capable of handling REG_DWORD, REG_MULTI_SZ, and REG_SZ style registry
  343. data. The data is stored in g_TempBuffer as well as being passed back
  344. through the return value. If the specified Key/Value does not exist in the
  345. registry, or the function is unable to retrieve a value, NULL is returned.
  346. Arguments:
  347. KeyString - Contains the Key to be read from the registry.
  348. ValueString - Contains the Value to be read from the registry.
  349. Return Value:
  350. A pointer to a multisz containing the data if it could be read from the
  351. registry, NULL otherwise.
  352. --*/
  353. PCTSTR
  354. pGetRegistryValue (
  355. IN PCTSTR KeyString,
  356. IN PCTSTR ValueString
  357. )
  358. {
  359. PCTSTR rString = NULL;
  360. HKEY key = NULL;
  361. PBYTE data = NULL;
  362. DWORD type = REG_NONE;
  363. LONG rc = ERROR_SUCCESS;
  364. PTSTR end;
  365. MYASSERT(KeyString && ValueString);
  366. //
  367. // Open registry key.
  368. //
  369. key = OpenRegKeyStr(KeyString);
  370. if (!key) {
  371. DEBUGMSG((DBG_WINNTSIF, "Key %s does not exist.",KeyString));
  372. return NULL;
  373. }
  374. __try {
  375. //
  376. // Get type of data
  377. //
  378. rc = RegQueryValueExA (key, ValueString, NULL, &type, NULL, NULL);
  379. if (rc != ERROR_SUCCESS) {
  380. DEBUGMSG((DBG_WINNTSIF,"RegQueryValueEx failed for %s[%s]. Value may not exist.",KeyString,ValueString));
  381. SetLastError (rc);
  382. return NULL;
  383. }
  384. MYASSERT(type == REG_DWORD || type == REG_MULTI_SZ || type == REG_SZ);
  385. //
  386. // Get data and move it to a multistring
  387. //
  388. data = GetRegValueData (key, ValueString);
  389. if (!data) {
  390. DEBUGMSG((DBG_WHOOPS,"pGetRegistryValue: RegQueryValueEx succeeded, but GetRegValueData failed...Could be a problem."));
  391. return NULL;
  392. }
  393. CLEARBUFFER();
  394. switch (type) {
  395. case REG_DWORD:
  396. wsprintf(g_TempBuffer,"%u", *(DWORD*) data);
  397. break;
  398. case REG_SZ:
  399. StringCopy(g_TempBuffer,(PCTSTR) data);
  400. //
  401. // some data is stored as REG_SZ, but is actually a comma separated multisz
  402. // append one more NULL to the end
  403. //
  404. end = GetEndOfString (g_TempBuffer) + 1;
  405. *end = 0;
  406. break;
  407. case REG_MULTI_SZ:
  408. end = (PTSTR) data;
  409. while (*end) {
  410. end = GetEndOfString (end) + 1;
  411. }
  412. memcpy(g_TempBuffer,data,(LONG)end - (LONG)data);
  413. break;
  414. default:
  415. LOG ((LOG_ERROR,"Unexpected registry type found while creating Setup answer file."));
  416. break;
  417. };
  418. } __finally {
  419. //
  420. // Clean up resources.
  421. //
  422. CloseRegKey(key);
  423. if (data) {
  424. MemFree(g_hHeap, 0, data);
  425. }
  426. }
  427. return g_TempBuffer;
  428. }
  429. BOOL
  430. CALLBACK
  431. pEnumLocalesFunc (
  432. IN PTSTR Locale
  433. )
  434. {
  435. PTSTR group = NULL;
  436. PTSTR directory = NULL;
  437. //
  438. // Get the language group.
  439. //
  440. if (InfFindFirstLine (g_IntlInf, S_LOCALES, Locale, &g_InfStruct)) {
  441. group = InfGetStringField (&g_InfStruct, 3);
  442. if (group) {
  443. group = PoolMemDuplicateString (g_LocalePool, group);
  444. }
  445. ELSE_DEBUGMSG ((DBG_WARNING, "Unable to retrieve group data for locale %s.", Locale));
  446. }
  447. //
  448. // Get the language directory.
  449. //
  450. if (group && InfFindFirstLine (g_IntlInf, S_LANGUAGEGROUPS, group, &g_InfStruct)) {
  451. directory = InfGetStringField (&g_InfStruct, 2);
  452. if (directory) {
  453. directory = PoolMemDuplicateString (g_LocalePool, directory);
  454. }
  455. }
  456. //
  457. // Save the information into the locale hash table.
  458. //
  459. if (group) {
  460. HtAddStringAndData (g_LocaleTable, group, &directory);
  461. }
  462. return TRUE;
  463. }
  464. VOID
  465. pBuildLanguageData (
  466. VOID
  467. )
  468. {
  469. //
  470. // Allocate needed resources.
  471. //
  472. g_LocaleTable = HtAllocWithData (sizeof (PTSTR));
  473. g_LocalePool = PoolMemInitNamedPool (TEXT("Locale Pool"));
  474. //
  475. // Read data in from intl.inf. This is used to gather
  476. // the necessary information we need for each installed
  477. // locale.
  478. //
  479. g_IntlInf = InfOpenInfInAllSources (S_INTLINF);
  480. if (g_IntlInf != INVALID_HANDLE_VALUE) {
  481. EnumSystemLocales (pEnumLocalesFunc, LCID_INSTALLED);
  482. InfCloseInfFile (g_IntlInf);
  483. }
  484. InfCleanUpInfStruct (&g_InfStruct);
  485. }
  486. PTSTR
  487. GetNeededLangDirs (
  488. VOID
  489. )
  490. {
  491. UINT bytes = 0;
  492. PTSTR rDirs = NULL;
  493. HASHTABLE_ENUM e;
  494. GROWBUFFER buf = GROWBUF_INIT;
  495. PTSTR dir;
  496. //
  497. // Gather language data.
  498. //
  499. pBuildLanguageData ();
  500. if (EnumFirstHashTableString (&e, g_LocaleTable)) {
  501. do {
  502. if (e.ExtraData) {
  503. dir = *((PTSTR *) e.ExtraData);
  504. }
  505. else {
  506. dir = NULL;
  507. }
  508. //
  509. // Some language groups do not require an optional dir.
  510. //
  511. if (dir && *dir) {
  512. MultiSzAppend (&buf, dir);
  513. }
  514. } while (EnumNextHashTableString (&e));
  515. }
  516. if (buf.Buf) {
  517. bytes = SizeOfMultiSz (buf.Buf);
  518. }
  519. if (bytes) {
  520. rDirs = PoolMemGetMemory (g_LocalePool, bytes);
  521. CopyMemory (rDirs, buf.Buf, bytes);
  522. }
  523. FreeGrowBuffer (&buf);
  524. return rDirs;
  525. }
  526. /*++
  527. Routine Description:
  528. This simple helper function determines wether a specific net component has
  529. bindings or not.
  530. Arguments:
  531. NetComponent - Contains the Networking component to enumerate.
  532. Return Value:
  533. TRUE if the specified Networking Component has bindings, FALSE
  534. otherwise.
  535. --*/
  536. BOOL
  537. pDoesNetComponentHaveBindings (
  538. IN PCTSTR NetComponent
  539. )
  540. {
  541. PTSTR keyString = NULL;
  542. REGKEY_ENUM e;
  543. keyString = JoinPaths(S_ENUM_NETWORK_KEY,NetComponent);
  544. if (!EnumFirstRegKeyStr (&e, keyString)) {
  545. FreePathString(keyString);
  546. return FALSE;
  547. }
  548. FreePathString(keyString);
  549. AbortRegKeyEnum (&e);
  550. return TRUE;
  551. }
  552. /*++
  553. Routine Description:
  554. pGatherNetAdapterInfo is responsible for preprocessing the NetAdapter
  555. information in the registry in order to build up a tree of information
  556. about these adapters in memdb. This tree contains information about each
  557. adapter, including its pnpid, its network bindings, and the nettrans keys
  558. for each of those bindings.
  559. Arguments:
  560. None.
  561. Return Value:
  562. None.
  563. --*/
  564. VOID
  565. pGatherNetAdapterInfo (
  566. VOID
  567. )
  568. {
  569. NETCARD_ENUM eNetCard;
  570. REGVALUE_ENUM eRegVal;
  571. UINT curAdapter = 1;
  572. UINT offset = 0;
  573. TCHAR adapterString[30];
  574. PCTSTR bindingsKey = NULL;
  575. PCTSTR networkKey = NULL;
  576. PCTSTR netTransKey = NULL;
  577. PTSTR p = NULL;
  578. HKEY hKey;
  579. BOOL fBoundToTCP = FALSE;
  580. ZeroMemory(g_IcsAdapter, sizeof(g_IcsAdapter));
  581. //
  582. // Enumerate all net cards, we'll create
  583. // entries for all of the non-dialup PNP adapters
  584. // with the following proviso: If more than one net card is specified,
  585. //
  586. if (EnumFirstNetCard(&eNetCard)) {
  587. __try {
  588. do {
  589. fBoundToTCP = FALSE;
  590. //
  591. // Skip the Dial-Up Adapter.
  592. //
  593. if (StringIMatch(eNetCard.Description,S_DIALUP_ADAPTER_DESC)) {
  594. continue;
  595. }
  596. //
  597. // Create the adapter section name for this adapter.
  598. //
  599. wsprintf(adapterString,TEXT("Adapter%u"),curAdapter);
  600. //
  601. // Next, we need to enumerate all of the bindings for this adapter
  602. // and create nettrans keys for each.
  603. //
  604. bindingsKey = JoinPaths(eNetCard.CurrentKey,S_BINDINGS);
  605. //
  606. // Open this key and enumerate the bindings underneath it.
  607. //
  608. if ((hKey = OpenRegKeyStr(bindingsKey)) != NULL) {
  609. if (EnumFirstRegValue(&eRegVal,hKey)) {
  610. do {
  611. //
  612. // For each protocol entry, build up the nettrans key.
  613. //
  614. networkKey = JoinPaths(S_NETWORK_BRANCH,eRegVal.ValueName);
  615. netTransKey = JoinPaths(S_SERVICECLASS,pGetRegistryValue(networkKey,S_DRIVERVAL));
  616. //
  617. // Save this key into memdb.
  618. //
  619. MemDbSetValueEx(
  620. MEMDB_CATEGORY_NETTRANSKEYS,
  621. adapterString,
  622. netTransKey,
  623. NULL,
  624. 0,
  625. &offset
  626. );
  627. //
  628. // link it into the adapters section.
  629. //
  630. p = _tcschr(eRegVal.ValueName,TEXT('\\'));
  631. if (p) {
  632. *p = 0;
  633. }
  634. MemDbSetValueEx(
  635. MEMDB_CATEGORY_NETADAPTERS,
  636. adapterString,
  637. S_BINDINGS,
  638. eRegVal.ValueName,
  639. offset,
  640. NULL
  641. );
  642. if ((!fBoundToTCP) && 0 == lstrcmpi(eRegVal.ValueName, S_MSTCP))
  643. {
  644. fBoundToTCP = TRUE;
  645. }
  646. FreePathString(networkKey);
  647. FreePathString(netTransKey);
  648. } while (EnumNextRegValue(&eRegVal));
  649. }
  650. CloseRegKey(hKey);
  651. }
  652. //
  653. // Finally, store the pnpid for this card into memdb.
  654. //
  655. MemDbSetValueEx(
  656. MEMDB_CATEGORY_NETADAPTERS,
  657. adapterString,
  658. MEMDB_FIELD_PNPID,
  659. eNetCard.HardwareId && *eNetCard.HardwareId ? eNetCard.HardwareId : eNetCard.CompatibleIDs,
  660. 0,
  661. NULL
  662. );
  663. //store the driver key for this card into memdb
  664. MemDbSetValueEx(
  665. MEMDB_CATEGORY_NETADAPTERS,
  666. adapterString,
  667. MEMDB_FIELD_DRIVER,
  668. eNetCard.HardwareEnum.Driver,
  669. 0,
  670. NULL
  671. );
  672. if (fBoundToTCP && 0 == lstrcmp(eNetCard.CompatibleIDs, S_ICSHARE))
  673. {
  674. //Save the ICSHARE adapter name for further use
  675. lstrcpyn(g_IcsAdapter, adapterString, sizeof(g_IcsAdapter)/sizeof(g_IcsAdapter[0]));
  676. }
  677. FreePathString(bindingsKey);
  678. curAdapter++;
  679. } while (EnumNextNetCard(&eNetCard));
  680. } __except (EXCEPTION_EXECUTE_HANDLER) {
  681. EnumNetCardAbort(&eNetCard);
  682. LOG ((LOG_ERROR,"Caught exception while gathering data about network adapters."));
  683. return;
  684. }
  685. }
  686. }
  687. /*++
  688. Routine Description:
  689. pEnumFirstAdapterByBinding and pEnumNextAdapterByBinding are memdb enumeration wrapperz
  690. that are used by several functions to enumerate based upon a certain protocol. This is
  691. necessary in order to build the per-adapter portions of the winnt.sif file.
  692. Arguments:
  693. Enum - A pointer to a valid MEMDB_ENUM structure.
  694. Binding - Contains the binding to enumerate upon.
  695. Return Value:
  696. TRUE if an adapter was found with the specified binding, FALSE otherwise.
  697. --*/
  698. BOOL
  699. pEnumFirstAdapterByBinding (
  700. IN PMEMDB_ENUM Enum,
  701. IN PCTSTR Binding
  702. )
  703. {
  704. BOOL rBindingFound = FALSE;
  705. TCHAR key[MEMDB_MAX];
  706. UINT unused;
  707. if (MemDbEnumItems(Enum,MEMDB_CATEGORY_NETADAPTERS)) {
  708. do {
  709. MemDbBuildKey(key,MEMDB_CATEGORY_NETADAPTERS,Enum -> szName,S_BINDINGS,Binding);
  710. rBindingFound = MemDbGetValue(key,&unused);
  711. } while(!rBindingFound && MemDbEnumNextValue(Enum));
  712. }
  713. return rBindingFound;
  714. }
  715. BOOL
  716. pEnumNextAdapterByBinding (
  717. IN OUT PMEMDB_ENUM Enum,
  718. IN PCTSTR Binding
  719. )
  720. {
  721. BOOL rBindingFound = FALSE;
  722. TCHAR key[MEMDB_MAX];
  723. UINT unused;
  724. while(!rBindingFound && MemDbEnumNextValue(Enum)) {
  725. MemDbBuildKey(key,MEMDB_CATEGORY_NETADAPTERS,Enum -> szName,S_BINDINGS,Binding);
  726. rBindingFound = MemDbGetValue(key,&unused);
  727. }
  728. return rBindingFound;
  729. }
  730. /*++
  731. Routine Description:
  732. pGetNetTransBinding returns the registry key to the Network Transport
  733. settings for a specified Adapter and Protocol.
  734. Arguments:
  735. Adapter - Contains the adapter to use to retrieve nettrans key information.
  736. Protocol - Contains the protocol to use to retrieve NetTrans Key
  737. information.
  738. Return Value:
  739. The NetTrans Key if successful, NULL otherwise.
  740. --*/
  741. PCTSTR
  742. pGetNetTransBinding(
  743. IN PCTSTR Adapter,
  744. IN PCTSTR Protocol
  745. )
  746. {
  747. TCHAR key[MEMDB_MAX];
  748. UINT netTransOffset;
  749. MemDbBuildKey(key,MEMDB_CATEGORY_NETADAPTERS,Adapter,S_BINDINGS,Protocol);
  750. if (!MemDbGetValue(key,&netTransOffset)) {
  751. LOG ((LOG_ERROR,"Adapter %s does not have a binding to %s.",Adapter,Protocol));
  752. return NULL;
  753. }
  754. if (!MemDbBuildKeyFromOffset(netTransOffset,g_TempBuffer,2,NULL)) {
  755. DEBUGMSG((DBG_ERROR,"Error building net trans key..Adapter: %s Protocol: %s",Adapter,Protocol));
  756. return NULL;
  757. }
  758. return g_TempBuffer;
  759. }
  760. /*++
  761. Routine Description:
  762. pListAdaptersWithBinding is used to create a multisz of adapter section
  763. names for adapters that have bindings to a specific networking component.
  764. Several winntsif sections require data in this form.
  765. Arguments:
  766. Binding - The Binding to use as a filter in listing the adapter sections.
  767. Suffix - an optional suffix which is attached to each adapter section
  768. name. This is useful for building sections such as: adapter1.ipx
  769. adapter2.ipx, etc etc.
  770. Return Value:
  771. The list of adapters with the specified network component binding if any,
  772. NULL otherwise.
  773. --*/
  774. PCTSTR
  775. pListAdaptersWithBinding (
  776. IN PCTSTR Binding,
  777. IN PCTSTR Suffix OPTIONAL
  778. )
  779. {
  780. PCTSTR rAdapterSections = NULL;
  781. PTSTR string = g_TempBuffer;
  782. MEMDB_ENUM e;
  783. *string = 0;
  784. //
  785. // Enumerate all adapters, and create an entry for each adapter that has
  786. // IPX bindings.
  787. //
  788. if (pEnumFirstAdapterByBinding(&e,Binding)) {
  789. rAdapterSections = g_TempBuffer;
  790. do {
  791. //
  792. // Add this adapter into the multistring.
  793. //
  794. StringCopy(string,e.szName);
  795. if (Suffix) {
  796. StringCat(string,Suffix);
  797. }
  798. string = GetEndOfString(string) + 1;
  799. } while (pEnumNextAdapterByBinding(&e,Binding));
  800. ++string;
  801. *string = 0;
  802. }
  803. return rAdapterSections;
  804. }
  805. //
  806. // Section Functions
  807. //
  808. /*++
  809. Routine Description:
  810. Each Section Function is used to build n number of sections within the
  811. winntsif file. This is necessary for information which has multiple
  812. sections based upon some criteria. As an example, pNetAdapterSections
  813. returns a valid section for each adapter found on the system. When there
  814. are no more sections needed, these functions return NULL.
  815. Arguments:
  816. None.
  817. Return Value:
  818. A valid section name if one is necessary or NULL otherwise.
  819. --*/
  820. PCTSTR
  821. pNetAdapterSections (
  822. VOID
  823. )
  824. {
  825. static BOOL firstTime = TRUE;
  826. PCTSTR rSection = NULL;
  827. BOOL moreNetAdapterInfo = FALSE;
  828. //
  829. // The first time this function is called it causes all net adapter information
  830. // to be prescanned into memdb and starts an enumeration. Afterwards,
  831. // the function simply continues the enumeration.
  832. //
  833. if (firstTime) {
  834. firstTime = FALSE;
  835. //
  836. // The first thing we need to do is gather all of the necessary net card
  837. // information that will be needed during winntsif processing and store
  838. // it in a reasonable manner.
  839. //
  840. pGatherNetAdapterInfo();
  841. //
  842. // After pre-scanning all of the network adapter information into
  843. // memdb, we simply enumerate the adapters and return the section
  844. // names.
  845. //
  846. moreNetAdapterInfo = MemDbEnumItems(&g_TempEnum,MEMDB_CATEGORY_NETADAPTERS);
  847. }
  848. else {
  849. moreNetAdapterInfo = MemDbEnumNextValue(&g_TempEnum);
  850. }
  851. if (moreNetAdapterInfo) {
  852. StringCopy(g_CurrentAdapter,g_TempEnum.szName);
  853. rSection = g_CurrentAdapter;
  854. //
  855. // We have a minor hack here. The [NetAdapters] Section is a little unique
  856. // and doesn't fit our overall scheme. We secretly fill it in inside this
  857. // function.
  858. //
  859. WriteInfKey(S_PAGE_NETADAPTERS,g_TempEnum.szName,g_TempEnum.szName);
  860. }
  861. return rSection;
  862. }
  863. PCTSTR
  864. pIpxAdapterSections (
  865. VOID
  866. )
  867. {
  868. static firstTime = TRUE;
  869. PCTSTR rSectionName = NULL;
  870. BOOL moreIpxAdapterSections;
  871. if (firstTime) {
  872. firstTime = FALSE;
  873. moreIpxAdapterSections = pEnumFirstAdapterByBinding(&g_TempEnum,S_NWLINK);
  874. }
  875. else {
  876. moreIpxAdapterSections = pEnumNextAdapterByBinding(&g_TempEnum,S_NWLINK);
  877. }
  878. if (moreIpxAdapterSections) {
  879. StringCopy(g_CurrentAdapter,g_TempEnum.szName);
  880. StringCopy(g_CurrentSection,g_TempEnum.szName);
  881. StringCat(g_CurrentSection,S_IPX_SUFFIX);
  882. rSectionName = g_CurrentSection;
  883. }
  884. return rSectionName;
  885. }
  886. PCTSTR
  887. pTcpAdapterSections (
  888. VOID
  889. )
  890. {
  891. static firstTime = TRUE;
  892. PCTSTR rSectionName = NULL;
  893. BOOL moreTcpAdapterSections;
  894. g_fIcsAdapterInPlace = FALSE;
  895. if (firstTime) {
  896. firstTime = FALSE;
  897. moreTcpAdapterSections = pEnumFirstAdapterByBinding(&g_TempEnum,S_MSTCP);
  898. }
  899. else {
  900. moreTcpAdapterSections = pEnumNextAdapterByBinding(&g_TempEnum,S_MSTCP);
  901. }
  902. if (moreTcpAdapterSections) {
  903. StringCopy(g_CurrentAdapter,g_TempEnum.szName);
  904. StringCopy(g_CurrentSection,g_TempEnum.szName);
  905. StringCat(g_CurrentSection,S_TCPIP_SUFFIX);
  906. rSectionName = g_CurrentSection;
  907. //if ICS is installed, in Win9x, the external LAN adapter uses the TCP settings of
  908. //the virtual adapter -- ICSHARE. So when we save the TCP settings of this LAN
  909. //adapter, we should save the settings of ICSHARE adapter. That's why
  910. //we replace the g_CurrentAdapter with g_IcsAdapter
  911. if (g_fHasIcsExternalAdapter &&
  912. lstrcmp(g_CurrentAdapter, g_IcsExternalAdapter) == 0)
  913. {
  914. StringCopy(g_CurrentAdapter, g_IcsAdapter);
  915. g_fIcsAdapterInPlace = TRUE;
  916. }
  917. }
  918. return rSectionName;
  919. }
  920. PCTSTR
  921. pRasPortSections (
  922. VOID
  923. )
  924. {
  925. static BOOL firstTime = TRUE;
  926. static REGKEY_ENUM e;
  927. static UINT modemNum = 1;
  928. BOOL moreRasPortSections;
  929. PCTSTR rSectionName = NULL;
  930. if (firstTime) {
  931. firstTime = FALSE;
  932. moreRasPortSections = HwComp_DialUpAdapterFound() && EnumFirstRegKeyStr(&e,S_MODEMS);
  933. }
  934. else {
  935. moreRasPortSections = EnumNextRegKey(&e);
  936. }
  937. if (moreRasPortSections) {
  938. wsprintf(g_CurrentSection,TEXT("COM%u"),modemNum);
  939. modemNum++;
  940. rSectionName = g_CurrentSection;
  941. }
  942. return rSectionName;
  943. }
  944. VOID
  945. pInitializeBindingInfo (
  946. HASHTABLE Table
  947. )
  948. {
  949. MEMDB_ENUM e;
  950. UINT i;
  951. UINT j;
  952. TCHAR buffer[MEMDB_MAX];
  953. BOOL enabled=FALSE;
  954. //
  955. // This function will enumerate all possible binding paths on the machine and add them to
  956. // the provided string table. Later on, specifically enabled bindings will be removed.
  957. //
  958. if (MemDbEnumItems (&e, MEMDB_CATEGORY_NETADAPTERS)) {
  959. do {
  960. for (i = 0; i < NUM_CLIENTS; i++) {
  961. if (!g_BindingInfo.Clients[i].Installed) {
  962. continue;
  963. }
  964. for (j = 0; j < NUM_PROTOCOLS; j++) {
  965. if (g_BindingInfo.Protocols[j].Installed) {
  966. //
  967. // Add this client/protocl/adapter possibility to
  968. // the hash table.
  969. //
  970. wsprintf (
  971. buffer,
  972. TEXT("%s,%s,%s"),
  973. g_BindingInfo.Clients[i].Text,
  974. g_BindingInfo.Protocols[j].Text,
  975. e.szName
  976. );
  977. HtAddStringAndData (Table, buffer, &enabled);
  978. DEBUGMSG ((DBG_VERBOSE, "DISABLED BINDING: %s", buffer));
  979. }
  980. }
  981. }
  982. for (j = 0; j < NUM_PROTOCOLS; j++) {
  983. //
  984. // Add the protocol adapter mapping into the table.
  985. //
  986. if (g_BindingInfo.Protocols[j].Installed) {
  987. wsprintf (buffer, TEXT("%s,%s"), g_BindingInfo.Protocols[j].Text, e.szName);
  988. HtAddStringAndData (Table, buffer, &enabled);
  989. DEBUGMSG ((DBG_VERBOSE, "DISABLED BINDING: %s", buffer));
  990. }
  991. }
  992. } while(MemDbEnumNextValue (&e));
  993. }
  994. }
  995. VOID
  996. pResolveEnabledBindings (
  997. HASHTABLE Table
  998. )
  999. {
  1000. //
  1001. // This function removes enabled binding paths from the hash table provided
  1002. // (previously initialized with all of the binding possibilities that could
  1003. // exist on the machine..)
  1004. //
  1005. NETCARD_ENUM eCard;
  1006. REGVALUE_ENUM eValues;
  1007. REGVALUE_ENUM eProtocolValues;
  1008. UINT curAdapter = 1;
  1009. TCHAR adapterString[30];
  1010. PTSTR bindingsPath = NULL;
  1011. PTSTR protocolBindingsPath = NULL;
  1012. PTSTR protocol = NULL;
  1013. PTSTR client = NULL;
  1014. HKEY key;
  1015. HKEY protocolsKey;
  1016. TCHAR buffer[MEMDB_MAX];
  1017. HASHITEM index;
  1018. BOOL enabled=TRUE;
  1019. if (EnumFirstNetCard (&eCard)) {
  1020. __try {
  1021. do {
  1022. //
  1023. // Skip the Dial-Up Adapter.
  1024. //
  1025. if (StringIMatch (eCard.Description, S_DIALUP_ADAPTER_DESC)) {
  1026. continue;
  1027. }
  1028. //
  1029. // Create the adapter section name for this adapter.
  1030. //
  1031. wsprintf (adapterString, TEXT("Adapter%u"), curAdapter);
  1032. curAdapter++;
  1033. bindingsPath = JoinPaths(eCard.CurrentKey,S_BINDINGS);
  1034. key = OpenRegKeyStr (bindingsPath);
  1035. FreePathString (bindingsPath);
  1036. if (!key) {
  1037. continue;
  1038. }
  1039. if (EnumFirstRegValue (&eValues, key)) {
  1040. do {
  1041. protocol = NULL;
  1042. /*
  1043. if (IsPatternMatch (TEXT("NETBEUI*"), eValues.ValueName)) {
  1044. protocol = S_MS_NETBEUI;
  1045. } else if (IsPatternMatch (TEXT("MSDLC*"), eValues.ValueName)) {
  1046. protocol = S_MS_DLC;
  1047. }
  1048. */
  1049. if (IsPatternMatch (TEXT("NWLINK*"), eValues.ValueName)) {
  1050. protocol = S_MS_NWIPX;
  1051. }
  1052. else if (IsPatternMatch (TEXT("MSTCP*"), eValues.ValueName)) {
  1053. protocol = S_MS_TCPIP;
  1054. }
  1055. if (!protocol) {
  1056. continue;
  1057. }
  1058. //
  1059. // Enable protocol <-> adapter binding.
  1060. //
  1061. wsprintf (buffer, TEXT("%s,%s"), protocol, adapterString);
  1062. index = HtFindString (Table, buffer);
  1063. if (index) {
  1064. HtSetStringData (Table, index, (PBYTE) &enabled);
  1065. }
  1066. DEBUGMSG ((DBG_VERBOSE, "ENABLED BINDING: %s", buffer));
  1067. //
  1068. // Search the bindings and enable protocol <-> client bindings
  1069. //
  1070. protocolBindingsPath = JoinPaths (S_NETWORK_BRANCH, eValues.ValueName);
  1071. bindingsPath = JoinPaths (protocolBindingsPath, S_BINDINGS);
  1072. FreePathString(protocolBindingsPath);
  1073. protocolsKey = OpenRegKeyStr (bindingsPath);
  1074. FreePathString (bindingsPath);
  1075. if (!protocolsKey) {
  1076. continue;
  1077. }
  1078. if (EnumFirstRegValue (&eProtocolValues, protocolsKey)) {
  1079. do {
  1080. client = NULL;
  1081. if (IsPatternMatch (TEXT("NWREDIR*"), eProtocolValues.ValueName) ||
  1082. IsPatternMatch (TEXT("NWLINK*"), eProtocolValues.ValueName) ||
  1083. IsPatternMatch (TEXT("NOVELLIPX32*"), eProtocolValues.ValueName) ||
  1084. IsPatternMatch (TEXT("IPXODI*"), eProtocolValues.ValueName) ||
  1085. IsPatternMatch (TEXT("NOVELL32*"), eProtocolValues.ValueName)) {
  1086. client = S_MS_NWCLIENT;
  1087. }
  1088. else if (IsPatternMatch (TEXT("VREDIR*"), eProtocolValues.ValueName)) {
  1089. client = S_MS_NETCLIENT;
  1090. }
  1091. if (client) {
  1092. //
  1093. // We can now remove a path from the bindings table -- we've got an
  1094. // enabled one.
  1095. //
  1096. wsprintf (buffer, TEXT("%s,%s,%s"), client, protocol, adapterString);
  1097. index = HtFindString (Table, buffer);
  1098. if (index) {
  1099. HtSetStringData (Table, index, (PBYTE) &enabled);
  1100. }
  1101. DEBUGMSG ((DBG_VERBOSE, "ENABLED BINDING: %s", buffer));
  1102. }
  1103. } while (EnumNextRegValue (&eProtocolValues));
  1104. }
  1105. CloseRegKey (protocolsKey);
  1106. } while (EnumNextRegValue (&eValues));
  1107. }
  1108. CloseRegKey (key);
  1109. } while (EnumNextNetCard (&eCard));
  1110. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1111. EnumNetCardAbort(&eCard);
  1112. LOG ((LOG_ERROR,"Caught exception while gathering data about network adapters."));
  1113. return;
  1114. }
  1115. }
  1116. }
  1117. BOOL
  1118. pSplitBindingPathIntoComponents (
  1119. IN OUT PTSTR BindingPath,
  1120. OUT PCTSTR * Client,
  1121. OUT PCTSTR * Protocol,
  1122. OUT PCTSTR * Adapter
  1123. )
  1124. {
  1125. PTSTR p;
  1126. p = BindingPath;
  1127. *Client = p;
  1128. p = _tcschr (p, TEXT(','));
  1129. MYASSERT (p);
  1130. if (!p) {
  1131. return FALSE;
  1132. }
  1133. *p = 0;
  1134. p = _tcsinc (p);
  1135. *Protocol = p;
  1136. p = _tcschr (p, TEXT(','));
  1137. if (!p) {
  1138. //
  1139. // Only Adapter and Protocol specified.
  1140. //
  1141. *Adapter = *Protocol;
  1142. *Protocol = *Client;
  1143. *Client = NULL;
  1144. }
  1145. else {
  1146. //
  1147. // Adapter/Protocol/Client specified.
  1148. //
  1149. *p = 0;
  1150. p = _tcsinc (p);
  1151. *Adapter = p;
  1152. }
  1153. return TRUE;
  1154. }
  1155. PCTSTR
  1156. pBindingSections (
  1157. VOID
  1158. )
  1159. {
  1160. HASHTABLE disabledBindings;
  1161. HASHTABLE_ENUM e;
  1162. TCHAR bindingString[MEMDB_MAX];
  1163. PTSTR client = NULL;
  1164. PTSTR protocol = NULL;
  1165. PTSTR adapter = NULL;
  1166. DWORD keyVal = 0;
  1167. disabledBindings = HtAllocWithData (sizeof(BOOL));
  1168. if (!disabledBindings) {
  1169. return NULL;
  1170. }
  1171. pInitializeBindingInfo (disabledBindings);
  1172. pResolveEnabledBindings (disabledBindings);
  1173. //
  1174. // Simply enumerate the table and blast each disabled setting
  1175. // to winnt.sif.
  1176. //
  1177. if (EnumFirstHashTableString (&e, disabledBindings)) {
  1178. do {
  1179. if (!*((PBOOL) e.ExtraData)) {
  1180. StringCopy (bindingString, e.String);
  1181. if (!pSplitBindingPathIntoComponents (bindingString, &client, &protocol, &adapter)) {
  1182. continue;
  1183. }
  1184. MYASSERT (protocol && adapter);
  1185. //
  1186. // Write full path..
  1187. //
  1188. keyVal = 0;
  1189. if (client) {
  1190. keyVal = WriteInfKeyEx (S_NETBINDINGS, S_DISABLED, client, keyVal, TRUE);
  1191. }
  1192. keyVal = WriteInfKeyEx (S_NETBINDINGS, S_DISABLED, protocol, keyVal, TRUE);
  1193. keyVal = WriteInfKeyEx (S_NETBINDINGS, S_DISABLED, adapter, keyVal, TRUE);
  1194. DEBUGMSG ((DBG_VERBOSE, "DISABLED BINDING: %s", e.String));
  1195. }
  1196. } while (EnumNextHashTableString (&e));
  1197. }
  1198. HtFree (disabledBindings);
  1199. //
  1200. // All of the binding information is handled outside the normal winntsif proceessing. Therefore, we always return
  1201. // NULL here (winntsif processing continues on...)
  1202. //
  1203. return NULL;
  1204. }
  1205. //
  1206. // Creation Functions
  1207. //
  1208. /*++
  1209. Routine Description:
  1210. Each Creation function is responsible for determining wether a specific
  1211. winntsif setting should be processed or
  1212. not. The purpose of most of these functions is obvious.
  1213. pIsNetworkingInstalled -
  1214. returns TRUE if the machine has networking installed.
  1215. pIsNetBeuiInstalled -
  1216. TRUE if NETBEUI is installed on the machine.
  1217. pIsMsDlcInstalled -
  1218. TRUE if MSDLC or MSDLC32 is installed on the machine.
  1219. pIsNwIpxInstalled -
  1220. TRUE if the machine is running the IPX protocol.
  1221. pIsTcpIpInstalled -
  1222. TRUE if the machine is running the TCPIP protocol.
  1223. pIsDnsEnabled -
  1224. TRUE DNS support is enabled.
  1225. pIsRasInstalled
  1226. TRUE if the machine uses Remote Access.
  1227. pIsWkstaInstalled
  1228. TRUE if the Workstation Service is installed.
  1229. pIsNwClientInstalled
  1230. TRUE if the NWLINK is installed.
  1231. pHasStaticIpAddress
  1232. TRUE if the machine has a static IP address.
  1233. Arguments:
  1234. None.
  1235. Return Value:
  1236. TRUE if the winntsif engine should process the setting, FALSE otherwise.
  1237. --*/
  1238. BOOL
  1239. pIsNetworkingInstalled (
  1240. VOID
  1241. )
  1242. {
  1243. static BOOL firstTime = TRUE;
  1244. static BOOL rCreate = FALSE;
  1245. if (firstTime) {
  1246. firstTime = FALSE;
  1247. rCreate =
  1248. HwComp_DialUpAdapterFound() ||
  1249. MemDbGetEndpointValueEx(
  1250. MEMDB_CATEGORY_NETADAPTERS,
  1251. TEXT("Adapter1"),
  1252. MEMDB_FIELD_PNPID,
  1253. g_TempBuffer
  1254. );
  1255. }
  1256. return rCreate;
  1257. }
  1258. BOOL
  1259. pInstallMsServer (
  1260. VOID
  1261. )
  1262. {
  1263. if (MemDbGetEndpointValueEx(
  1264. MEMDB_CATEGORY_NETADAPTERS,
  1265. TEXT("Adapter1"),
  1266. MEMDB_FIELD_PNPID,
  1267. g_TempBuffer
  1268. )) {
  1269. return TRUE;
  1270. }
  1271. return FALSE;
  1272. }
  1273. BOOL
  1274. pIsNetBeuiInstalled (
  1275. VOID
  1276. )
  1277. {
  1278. static BOOL rCreate = FALSE;
  1279. static BOOL firstTime = TRUE;
  1280. UINT i;
  1281. if (firstTime) {
  1282. rCreate = pIsNetworkingInstalled() && pDoesNetComponentHaveBindings(S_NETBEUI);
  1283. if (rCreate) {
  1284. //
  1285. // Need to make sure tcp/ip is taken care of when processing bindings.
  1286. //
  1287. for (i=0;i<NUM_PROTOCOLS;i++) {
  1288. if (StringIMatch (g_BindingInfo.Protocols[i].Text, S_MS_NETBEUI)) {
  1289. g_BindingInfo.Protocols[i].Installed = TRUE;
  1290. break;
  1291. }
  1292. }
  1293. }
  1294. firstTime = FALSE;
  1295. }
  1296. return rCreate;
  1297. }
  1298. #define S_IBMDLC TEXT("IBMDLC")
  1299. #define S_IBMDLC_REG TEXT("HKLM\\Enum\\Network\\IBMDLC")
  1300. BOOL
  1301. pIsMsDlcInstalled (
  1302. VOID
  1303. )
  1304. {
  1305. static BOOL rCreate = FALSE;
  1306. static BOOL firstTime = TRUE;
  1307. UINT i;
  1308. if (firstTime) {
  1309. firstTime = FALSE;
  1310. if (!pIsNetworkingInstalled()) {
  1311. return FALSE;
  1312. }
  1313. //
  1314. // Check to se if MS client is installed.
  1315. //
  1316. if (pDoesNetComponentHaveBindings(S_MSDLC) || pDoesNetComponentHaveBindings(S_MSDLC32)) {
  1317. rCreate = TRUE;
  1318. }
  1319. //
  1320. // Check to see if IBM DLC client is installed (and hasn't been handled by a migration dll..)
  1321. // If so, we'll install the MS DLC client. IBM needs to write a migration dll to handle the
  1322. // migration of their client. In the migration dll, they can handle this registry key, and
  1323. // we will not install the protocol.
  1324. //
  1325. if (!rCreate && pDoesNetComponentHaveBindings(S_IBMDLC) && !Is95RegKeySuppressed (S_IBMDLC_REG)) {
  1326. rCreate = TRUE;
  1327. }
  1328. if (rCreate) {
  1329. for (i=0;i<NUM_PROTOCOLS;i++) {
  1330. if (StringIMatch (g_BindingInfo.Protocols[i].Text, S_MS_DLC)) {
  1331. g_BindingInfo.Protocols[i].Installed = TRUE;
  1332. break;
  1333. }
  1334. }
  1335. }
  1336. }
  1337. return rCreate;
  1338. }
  1339. BOOL
  1340. pIsNwIpxInstalled (
  1341. VOID
  1342. )
  1343. {
  1344. static BOOL firstTime = TRUE;
  1345. static BOOL rCreate = FALSE;
  1346. UINT i;
  1347. if (firstTime) {
  1348. rCreate = pIsNetworkingInstalled() && pDoesNetComponentHaveBindings(S_NWLINK);
  1349. if (rCreate) {
  1350. //
  1351. // Need to make sure tcp/ip is taken care of when processing bindings.
  1352. //
  1353. for (i=0;i<NUM_PROTOCOLS;i++) {
  1354. if (StringIMatch (g_BindingInfo.Protocols[i].Text,S_MS_NWIPX)) {
  1355. g_BindingInfo.Protocols[i].Installed = TRUE;
  1356. break;
  1357. }
  1358. }
  1359. }
  1360. firstTime = FALSE;
  1361. }
  1362. return rCreate;
  1363. }
  1364. BOOL
  1365. pIsTcpIpInstalled (
  1366. VOID
  1367. )
  1368. {
  1369. static BOOL firstTime = TRUE;
  1370. static BOOL rCreate = FALSE;
  1371. UINT i;
  1372. if (firstTime) {
  1373. firstTime = FALSE;
  1374. rCreate = pIsNetworkingInstalled() && pDoesNetComponentHaveBindings(S_MSTCP);
  1375. //
  1376. // Need to make sure tcp/ip is taken care of when processing bindings.
  1377. //
  1378. for (i=0;i<NUM_PROTOCOLS;i++) {
  1379. if (StringIMatch (g_BindingInfo.Protocols[i].Text, S_MS_TCPIP)) {
  1380. g_BindingInfo.Protocols[i].Installed = TRUE;
  1381. break;
  1382. }
  1383. }
  1384. }
  1385. return rCreate;
  1386. }
  1387. BOOL
  1388. pIsDnsEnabled (
  1389. VOID
  1390. )
  1391. {
  1392. return pGetRegistryValue (S_MSTCP_KEY, S_ENABLEDNS) && *g_TempBuffer == TEXT('1');
  1393. }
  1394. BOOL
  1395. pIsRasInstalled (
  1396. VOID
  1397. )
  1398. {
  1399. return HwComp_DialUpAdapterFound();
  1400. }
  1401. BOOL
  1402. pIsSnmpInstalled (
  1403. VOID
  1404. )
  1405. {
  1406. return pDoesNetComponentHaveBindings (S_SNMP);
  1407. }
  1408. BOOL
  1409. pIsUpnpInstalled (
  1410. VOID
  1411. )
  1412. {
  1413. HKEY key;
  1414. BOOL b = FALSE;
  1415. key = OpenRegKey (HKEY_LOCAL_MACHINE, S_REGKEY_UPNP);
  1416. if (key) {
  1417. b = TRUE;
  1418. CloseRegKey (key);
  1419. }
  1420. return b;
  1421. }
  1422. BOOL
  1423. pIsWkstaInstalled (
  1424. VOID
  1425. )
  1426. {
  1427. static BOOL firstTime = TRUE;
  1428. static BOOL rCreate = FALSE;
  1429. UINT i;
  1430. if (firstTime) {
  1431. firstTime = FALSE;
  1432. rCreate = pDoesNetComponentHaveBindings(S_VREDIR);
  1433. if (rCreate) {
  1434. //
  1435. // Need to make sure tcp/ip is taken care of when processing bindings.
  1436. //
  1437. for (i=0;i<NUM_CLIENTS;i++) {
  1438. if (StringIMatch (g_BindingInfo.Clients[i].Text, S_MS_NETCLIENT)) {
  1439. g_BindingInfo.Clients[i].Installed = TRUE;
  1440. break;
  1441. }
  1442. }
  1443. }
  1444. }
  1445. return rCreate;
  1446. }
  1447. BOOL
  1448. pDisableBrowserService (
  1449. VOID
  1450. )
  1451. {
  1452. if (pIsWkstaInstalled () && !pDoesNetComponentHaveBindings (S_VSERVER)) {
  1453. return TRUE;
  1454. }
  1455. return FALSE;
  1456. }
  1457. #define S_IPXODI TEXT("IPXODI")
  1458. #define S_IPXODI_REG TEXT("HKLM\\Enum\\Network\\IPXODI")
  1459. #define S_NOVELLIPX32 TEXT("NOVELLIPX32")
  1460. #define S_NOVELL32 TEXT("NOVELL32")
  1461. BOOL
  1462. pIsNwClientInstalled (
  1463. VOID
  1464. )
  1465. {
  1466. static BOOL firstTime = TRUE;
  1467. static BOOL rCreate = FALSE;
  1468. UINT i;
  1469. if (firstTime) {
  1470. firstTime = FALSE;
  1471. rCreate = pDoesNetComponentHaveBindings(S_NWREDIR) ||
  1472. pDoesNetComponentHaveBindings(S_NOVELLIPX32) ||
  1473. pDoesNetComponentHaveBindings(S_NOVELL32) ||
  1474. (pDoesNetComponentHaveBindings(S_IPXODI) && !Is95RegKeySuppressed (S_IPXODI_REG));
  1475. if (rCreate) {
  1476. //
  1477. // Need to make sure tcp/ip is taken care of when processing bindings.
  1478. //
  1479. for (i=0;i<NUM_CLIENTS;i++) {
  1480. if (StringIMatch (g_BindingInfo.Clients[i].Text, S_MS_NWCLIENT)) {
  1481. g_BindingInfo.Clients[i].Installed = TRUE;
  1482. break;
  1483. }
  1484. }
  1485. }
  1486. }
  1487. return rCreate;
  1488. }
  1489. BOOL
  1490. pHasStaticIpAddress (
  1491. VOID
  1492. )
  1493. {
  1494. PCTSTR netTrans = NULL;
  1495. netTrans = pGetNetTransBinding (g_CurrentAdapter, S_MSTCP);
  1496. return netTrans != NULL &&
  1497. pGetRegistryValue (netTrans, S_IPADDRVAL) != NULL &&
  1498. !StringMatch (g_TempBuffer, TEXT("0.0.0.0"));
  1499. }
  1500. //
  1501. // Data Functions
  1502. //
  1503. /*++
  1504. Routine Description:
  1505. pGetTempDir returns the temporary directory used by the win9xupg code.
  1506. Arguments:
  1507. None.
  1508. Return Value:
  1509. a multisz contaiining the win9xupg directory, or NULL if it could not be
  1510. retrieved.
  1511. --*/
  1512. PCTSTR
  1513. pGetTempDir (
  1514. VOID
  1515. )
  1516. {
  1517. //
  1518. // Necessary for winntsif.exe tool.
  1519. //
  1520. if (!g_TempDir) {
  1521. return NULL;
  1522. }
  1523. CLEARBUFFER();
  1524. StringCopy(g_TempBuffer,g_TempDir);
  1525. return g_TempBuffer;
  1526. }
  1527. /*++
  1528. Routine Description:
  1529. pGetWin9xBootDrive returns the win9x boot drive letter used by the win9xupg code.
  1530. Arguments:
  1531. None.
  1532. Return Value:
  1533. a multisz contaiining the win9x boot drive letter, or NULL if it could not be
  1534. retrieved.
  1535. --*/
  1536. PCTSTR
  1537. pGetWin9xBootDrive (
  1538. VOID
  1539. )
  1540. {
  1541. CLEARBUFFER();
  1542. wsprintf(g_TempBuffer,TEXT("%c:"),g_BootDriveLetter);
  1543. return g_TempBuffer;
  1544. }
  1545. /*++
  1546. Routine Description:
  1547. pGetGuiCodePage adds the code page override data for GUI mode to run in.
  1548. Arguments:
  1549. None.
  1550. Return Value:
  1551. a multisz contaiining the code page GUI mode should run in or NULL if it could not be
  1552. retrieved or isn't needed.
  1553. --*/
  1554. PCTSTR
  1555. pGetGuiCodePage (
  1556. VOID
  1557. )
  1558. {
  1559. HKEY key;
  1560. PCTSTR systemCodePage;
  1561. PCTSTR winntCodePage;
  1562. INFSTRUCT is = INITINFSTRUCT_POOLHANDLE;
  1563. PCTSTR rCodePage = NULL;
  1564. TCHAR nlsFile[MAX_TCHAR_PATH];
  1565. TCHAR nlsFileCompressed[MAX_TCHAR_PATH];
  1566. PTSTR p;
  1567. UINT i;
  1568. BOOL cpExists = FALSE;
  1569. key = OpenRegKeyStr (TEXT("HKLM\\System\\CurrentControlSet\\Control\\Nls\\CodePage"));
  1570. if (!key) {
  1571. return NULL;
  1572. }
  1573. __try {
  1574. //
  1575. // Get the ACP of the currently running system.
  1576. //
  1577. systemCodePage = GetRegValueString (key, TEXT("ACP"));
  1578. if (!systemCodePage || InfFindFirstLine (g_Win95UpgInf, S_CODEPAGESTOIGNORE, systemCodePage, &is)) {
  1579. //
  1580. // Either the code page doesn't exist, or we intentionally skip it.
  1581. //
  1582. __leave;
  1583. }
  1584. //
  1585. // Get the code page of our infs.
  1586. //
  1587. if (InfFindFirstLine (g_Win95UpgInf, S_VERSION, TEXT("LANGUAGE"), &is)) {
  1588. winntCodePage = InfGetStringField (&is,1);
  1589. if (!winntCodePage) {
  1590. __leave;
  1591. }
  1592. }
  1593. if (StringIMatch (winntCodePage, systemCodePage)) {
  1594. //
  1595. // Nothing to do if they are the same.
  1596. //
  1597. __leave;
  1598. }
  1599. if (!InfFindFirstLine (g_Win95UpgInf, S_ALLOWEDCODEPAGEOVERRIDES, winntCodePage, &is)) {
  1600. //
  1601. // We don't allow code page overrides from this winnt code page.
  1602. //
  1603. __leave;
  1604. }
  1605. //
  1606. // See if this nls file exists in the source directories.
  1607. //
  1608. wsprintf(nlsFileCompressed, TEXT("c_%s.nl_"), systemCodePage);
  1609. wsprintf(nlsFile, TEXT("c_%s.nls"), systemCodePage);
  1610. for (i = 0; i < SOURCEDIRECTORYCOUNT(); i++) {
  1611. p = JoinPaths (SOURCEDIRECTORY(i), nlsFileCompressed);
  1612. if (DoesFileExist (p)) {
  1613. cpExists = TRUE;
  1614. }
  1615. else {
  1616. FreePathString (p);
  1617. p = JoinPaths (SOURCEDIRECTORY(i), nlsFile);
  1618. if (DoesFileExist (p)) {
  1619. cpExists = TRUE;
  1620. }
  1621. }
  1622. FreePathString (p);
  1623. }
  1624. if (!cpExists) {
  1625. wsprintf(nlsFile, TEXT("c_%s.nls"), systemCodePage);
  1626. for (i = 0; i < SOURCEDIRECTORYCOUNT(); i++) {
  1627. p = JoinPaths (SOURCEDIRECTORY(i), nlsFile);
  1628. if (DoesFileExist (p)) {
  1629. cpExists = TRUE;
  1630. }
  1631. FreePathString (p);
  1632. }
  1633. }
  1634. //
  1635. // Codepage exists. We can and should override this for GUI mode.
  1636. //
  1637. if (cpExists) {
  1638. CLEARBUFFER();
  1639. StringCopy (g_TempBuffer, systemCodePage);
  1640. rCodePage = g_TempBuffer;
  1641. DEBUGMSG ((DBG_VERBOSE, "Overriding code page %s with %s during GUI mode.", winntCodePage, systemCodePage));
  1642. }
  1643. }
  1644. __finally {
  1645. if (systemCodePage) {
  1646. MemFree (g_hHeap, 0, systemCodePage);
  1647. }
  1648. InfCleanUpInfStruct (&is);
  1649. CloseRegKey (key);
  1650. }
  1651. return rCodePage;
  1652. }
  1653. /*++
  1654. Routine Description:
  1655. pBackupImageList writes a path to winnt.sif listing the files to backup.
  1656. Arguments:
  1657. None.
  1658. Return Value:
  1659. a multisz containing the backup path, or NULL if it isn't needed.
  1660. --*/
  1661. PCTSTR
  1662. pBackupFileList (
  1663. VOID
  1664. )
  1665. {
  1666. if (TRISTATE_NO == g_ConfigOptions.EnableBackup) {
  1667. return NULL;
  1668. }
  1669. CLEARBUFFER();
  1670. StringCopy (g_TempBuffer, g_TempDir);
  1671. StringCopy (AppendWack (g_TempBuffer), TEXT("backup.txt"));
  1672. return g_TempBuffer;
  1673. }
  1674. PCTSTR
  1675. pUninstallMoveFileList (
  1676. VOID
  1677. )
  1678. {
  1679. if (!g_ConfigOptions.EnableBackup) {
  1680. return NULL;
  1681. }
  1682. CLEARBUFFER();
  1683. StringCopy (g_TempBuffer, g_TempDir);
  1684. StringCopy (AppendWack (g_TempBuffer), S_UNINSTALL_TEMP_DIR TEXT("\\") S_ROLLBACK_MOVED_TXT);
  1685. return g_TempBuffer;
  1686. }
  1687. PCTSTR
  1688. pUninstallDelDirList (
  1689. VOID
  1690. )
  1691. {
  1692. if (!g_ConfigOptions.EnableBackup) {
  1693. return NULL;
  1694. }
  1695. CLEARBUFFER();
  1696. StringCopy (g_TempBuffer, g_TempDir);
  1697. StringCopy (AppendWack (g_TempBuffer), S_UNINSTALL_TEMP_DIR TEXT("\\") S_ROLLBACK_DELDIRS_TXT);
  1698. return g_TempBuffer;
  1699. }
  1700. PCTSTR
  1701. pUninstallDelFileList (
  1702. VOID
  1703. )
  1704. {
  1705. if (!g_ConfigOptions.EnableBackup) {
  1706. return NULL;
  1707. }
  1708. CLEARBUFFER();
  1709. StringCopy (g_TempBuffer, g_TempDir);
  1710. StringCopy (AppendWack (g_TempBuffer), S_UNINSTALL_TEMP_DIR TEXT("\\") S_ROLLBACK_DELFILES_TXT);
  1711. return g_TempBuffer;
  1712. }
  1713. PCTSTR
  1714. pUninstallMkDirList (
  1715. VOID
  1716. )
  1717. {
  1718. if (!g_ConfigOptions.EnableBackup) {
  1719. return NULL;
  1720. }
  1721. CLEARBUFFER();
  1722. StringCopy (g_TempBuffer, g_TempDir);
  1723. StringCopy (AppendWack (g_TempBuffer), S_UNINSTALL_TEMP_DIR TEXT("\\") S_ROLLBACK_MKDIRS_TXT);
  1724. return g_TempBuffer;
  1725. }
  1726. /*++
  1727. Routine Description:
  1728. pGetWin9xSifDir returns the directory containing the filemove and filedel
  1729. files.
  1730. Arguments:
  1731. None.
  1732. Return Value:
  1733. a multisz contaiining the win9xsifdir directory, or NULL if it could not be
  1734. retrieved.
  1735. --*/
  1736. PCTSTR
  1737. pGetWin9xSifDir (
  1738. VOID
  1739. )
  1740. {
  1741. //
  1742. // Necessary for winntsif.exe tool.
  1743. //
  1744. if (!g_Win9xSifDir) {
  1745. return NULL;
  1746. }
  1747. CLEARBUFFER();
  1748. StringCopy(g_TempBuffer,g_Win9xSifDir);
  1749. return g_TempBuffer;
  1750. }
  1751. /*++
  1752. Routine Description:
  1753. pGetWinDir returns the windows directory of the machine being upgraded.
  1754. Arguments:
  1755. None.
  1756. Return Value:
  1757. a multisz contaiining the windows directory, or NULL if it could not be
  1758. retrieved.
  1759. --*/
  1760. PCTSTR
  1761. pGetWinDir (
  1762. VOID
  1763. )
  1764. {
  1765. //
  1766. // Necessary for winntsif.exe tool.
  1767. //
  1768. if (!g_WinDir) {
  1769. return NULL;
  1770. }
  1771. CLEARBUFFER();
  1772. StringCopy(g_TempBuffer,g_WinDir);
  1773. return g_TempBuffer;
  1774. }
  1775. #if 0
  1776. /*++
  1777. Routine Description:
  1778. If the upgrade is running in unattended mode, this function returns "1",
  1779. otherwise it returns "0". This is used to control wether GUI mode setup pauses
  1780. at the final wizard screen or reboots automatically.
  1781. Arguments:
  1782. None.
  1783. Return Value:
  1784. a multisz contaiining the GUI mode pause state.
  1785. --*/
  1786. PCTSTR
  1787. pNoWaitAfterGuiMode (
  1788. VOID
  1789. )
  1790. {
  1791. CLEARBUFFER();
  1792. StringCopy(g_TempBuffer,UNATTENDED() ? S_ONE : S_ZERO);
  1793. return g_TempBuffer;
  1794. }
  1795. #endif
  1796. /*++
  1797. Routine Description:
  1798. pGetKeyboardLayout retrieves the keyboard layout to write to the winntsif file.
  1799. This is done by retrieving the name of the layout being used by win9x and matching it
  1800. against the keyboard layouts in txtsetup.sif.
  1801. Arguments:
  1802. None.
  1803. Return Value:
  1804. a multisz containing the keyboard layout, or NULL if it could not be
  1805. retrieved.
  1806. --*/
  1807. PCTSTR
  1808. pGetKeyboardLayout (
  1809. VOID
  1810. )
  1811. {
  1812. TCHAR buffer[MAX_KEYBOARDLAYOUT];
  1813. INFCONTEXT ic;
  1814. GetKeyboardLayoutName(buffer);
  1815. //
  1816. // Because some brilliant developer added ["Keyboard Layout"] instead of
  1817. // just [Keyboard Layout], we cannot use GetPrivateProfileString.
  1818. // We must use setup APIs.
  1819. //
  1820. if (SetupFindFirstLine (g_TxtSetupSif, S_QUOTEDKEYBOARDLAYOUT, buffer, &ic)) {
  1821. if (SetupGetOemStringField (&ic, 1, g_TempBuffer, sizeof (g_TempBuffer), NULL)) {
  1822. return g_TempBuffer;
  1823. }
  1824. }
  1825. DEBUGMSG((DBG_WINNTSIF,"Keyboard layout %s not found in txtsetup.sif.",buffer));
  1826. return NULL;
  1827. }
  1828. /*++
  1829. Routine Description:
  1830. pGetKeyboardHardware retrives the keyboard hardware id of the machine running
  1831. the upgrade.
  1832. Arguments:
  1833. None.
  1834. Return Value:
  1835. a multisz contaiining the win9xupg directory, or NULL if it could not be
  1836. retrieved.
  1837. --*/
  1838. PCTSTR
  1839. pGetKeyboardHardware (
  1840. VOID
  1841. )
  1842. {
  1843. CLEARBUFFER();
  1844. if (GetLegacyKeyboardId (g_TempBuffer,sizeof(g_TempBuffer))) {
  1845. return g_TempBuffer;
  1846. }
  1847. return NULL;
  1848. }
  1849. /*++
  1850. Routine Description:
  1851. This rather laborious function retrieves the correct index to write to
  1852. the winntsif file for the timezone being used on the machine. To do this,
  1853. it is necessary to munge through several parts of the registry in order
  1854. to find the correct string to match with and then match that string against
  1855. the timezone mappings contained in win95upg.inf to come up with the actual
  1856. index.
  1857. Arguments:
  1858. None.
  1859. Return Value:
  1860. a multisz containing the index to write to the winntsif file, or NULL if it
  1861. could not be retrieved.
  1862. --*/
  1863. PCTSTR
  1864. pGetTimeZone (
  1865. VOID
  1866. )
  1867. {
  1868. TIMEZONE_ENUM e;
  1869. PCTSTR component = NULL;
  1870. PCTSTR warning = NULL;
  1871. PCTSTR args[1];
  1872. if (EnumFirstTimeZone (&e, TZFLAG_USE_FORCED_MAPPINGS) || EnumFirstTimeZone(&e, TZFLAG_ENUM_ALL)) {
  1873. if (e.MapCount != 1) {
  1874. //
  1875. // Ambigous timezone situation. Add an incompatibility message.
  1876. //
  1877. args[0] = e.CurTimeZone;
  1878. component = GetStringResource (MSG_TIMEZONE_COMPONENT);
  1879. if (*e.CurTimeZone) {
  1880. warning = ParseMessageID (MSG_TIMEZONE_WARNING, args);
  1881. }
  1882. else {
  1883. warning = GetStringResource (MSG_TIMEZONE_WARNING_UNKNOWN);
  1884. }
  1885. MYASSERT (component);
  1886. MYASSERT (warning);
  1887. MsgMgr_ObjectMsg_Add (TEXT("*TIMEZONE"), component, warning);
  1888. FreeStringResource (component);
  1889. FreeStringResource (warning);
  1890. }
  1891. CLEARBUFFER();
  1892. StringCopy (g_TempBuffer, e.MapIndex);
  1893. return g_TempBuffer;
  1894. }
  1895. else {
  1896. LOG ((LOG_ERROR, "Unable to get timezone. User will have to enter timezone in GUI mode."));
  1897. }
  1898. return NULL;
  1899. }
  1900. /*++
  1901. Routine Description:
  1902. pGetFullName returns the full name of the owner of the machine running
  1903. the upgrade. This function first searches the registry and then, if that
  1904. does not provide the needed information, calls GetUserName.
  1905. Arguments:
  1906. None.
  1907. Return Value:
  1908. a multisz containing the required data, or NULL if it could not be
  1909. retrieved.
  1910. --*/
  1911. PCTSTR
  1912. pGetFullName (
  1913. VOID
  1914. )
  1915. {
  1916. UINT size;
  1917. INVALID_NAME_ENUM e;
  1918. if (!pGetRegistryValue(S_WINDOWS_CURRENTVERSION,S_REGISTEREDOWNER)) {
  1919. size = MEMDB_MAX;
  1920. if (GetUserName (g_TempBuffer,&size)) {
  1921. MYASSERT (g_TempBuffer[size - 1] == 0);
  1922. g_TempBuffer[size] = 0;
  1923. }
  1924. }
  1925. //
  1926. // check if this name is:
  1927. // 1. Empty - what do we do in this case?
  1928. // 2. A reserved NT name: then we'll use the new name (user was informed about this)
  1929. //
  1930. if (*g_TempBuffer) {
  1931. if (EnumFirstInvalidName (&e)) {
  1932. do {
  1933. if (StringIMatch (e.OriginalName, g_TempBuffer)) {
  1934. //
  1935. // the buffer is actually interpreted as a MULTISZ, so make sure
  1936. // it's terminated with 2 zeroes
  1937. //
  1938. if (SizeOfString (e.NewName) + sizeof (TCHAR) <= sizeof (g_TempBuffer)) {
  1939. //
  1940. // we surely have space for an extra 0
  1941. //
  1942. StringCopy (g_TempBuffer, e.NewName);
  1943. *(GetEndOfString (g_TempBuffer) + 1) = 0;
  1944. break;
  1945. }
  1946. }
  1947. } while (EnumNextInvalidName (&e));
  1948. }
  1949. }
  1950. return g_TempBuffer;
  1951. }
  1952. /*++
  1953. Routine Description:
  1954. pGetFullName returns the computer name of the machine running the
  1955. upgrade.
  1956. Arguments:
  1957. None.
  1958. Return Value:
  1959. a multisz containing the required data, or NULL if it could not be
  1960. retrieved.
  1961. --*/
  1962. PCTSTR
  1963. pGetComputerName (
  1964. VOID
  1965. )
  1966. {
  1967. CLEARBUFFER();
  1968. if (!GetUpgradeComputerName(g_TempBuffer)) {
  1969. return NULL;
  1970. }
  1971. return g_TempBuffer;
  1972. }
  1973. /*++
  1974. Routine Description:
  1975. pGetXResolution and pGetYResolution return the x and y resolution for
  1976. the machine running the upgrade.
  1977. Arguments:
  1978. None.
  1979. Return Value:
  1980. a multisz containing the required data, or NULL if it could not be
  1981. retrieved.
  1982. --*/
  1983. PCTSTR
  1984. pGetXResolution (
  1985. VOID
  1986. )
  1987. {
  1988. /*
  1989. PTSTR s = NULL;
  1990. if (!pGetRegistryValue(S_DISPLAYSETTINGS,S_RESOLUTION)) {
  1991. LOG ((LOG_ERROR, "No Resolution settings."));
  1992. return NULL;
  1993. }
  1994. s = _tcschr(g_TempBuffer,TEXT(','));
  1995. if (s) {
  1996. *s = 0;
  1997. s++;
  1998. *s = 0;
  1999. }
  2000. */
  2001. wsprintf (g_TempBuffer, TEXT("%u%c"), GetSystemMetrics (SM_CXSCREEN), 0);
  2002. return g_TempBuffer;
  2003. }
  2004. PCTSTR
  2005. pGetYResolution (
  2006. VOID
  2007. )
  2008. {
  2009. /*
  2010. PTSTR s = NULL;
  2011. if (!pGetRegistryValue(S_DISPLAYSETTINGS,S_RESOLUTION)) {
  2012. LOG ((LOG_ERROR, "WinntSif: No Resolution settings."));
  2013. return NULL;
  2014. }
  2015. s = _tcschr(g_TempBuffer,TEXT(','));
  2016. if (s) {
  2017. s++;
  2018. }
  2019. return s;
  2020. */
  2021. wsprintf (g_TempBuffer, TEXT("%u%c"), GetSystemMetrics (SM_CYSCREEN), 0);
  2022. return g_TempBuffer;
  2023. }
  2024. PCTSTR
  2025. pGetBitsPerPixel (
  2026. VOID
  2027. )
  2028. {
  2029. DEVMODE dm;
  2030. if (!EnumDisplaySettings (NULL, ENUM_CURRENT_SETTINGS, &dm) ||
  2031. !dm.dmBitsPerPel
  2032. ) {
  2033. return NULL;
  2034. }
  2035. wsprintf (g_TempBuffer, TEXT("%lu%c"), dm.dmBitsPerPel, 0);
  2036. return g_TempBuffer;
  2037. }
  2038. PCTSTR
  2039. pGetVerticalRefreshRate (
  2040. VOID
  2041. )
  2042. {
  2043. DEVMODE dm;
  2044. if (!EnumDisplaySettings (NULL, ENUM_CURRENT_SETTINGS, &dm) ||
  2045. !dm.dmDisplayFrequency
  2046. ) {
  2047. return NULL;
  2048. }
  2049. wsprintf (g_TempBuffer, TEXT("%lu%c"), dm.dmDisplayFrequency, 0);
  2050. return g_TempBuffer;
  2051. }
  2052. /*++
  2053. Routine Description:
  2054. Returns the PNP id for the current adapter being worked with.
  2055. Arguments:
  2056. None.
  2057. Return Value:
  2058. a multisz containing the required data, or NULL if it could not be
  2059. retrieved.
  2060. --*/
  2061. PCTSTR
  2062. pGetNetAdapterPnpId (
  2063. VOID
  2064. )
  2065. {
  2066. PCTSTR rPnpId = NULL;
  2067. PTSTR p = NULL;
  2068. INFSTRUCT is = INITINFSTRUCT_POOLHANDLE;
  2069. CLEARBUFFER();
  2070. rPnpId = g_TempBuffer;
  2071. if (!MemDbGetEndpointValueEx(
  2072. MEMDB_CATEGORY_NETADAPTERS,
  2073. g_CurrentAdapter,
  2074. MEMDB_FIELD_PNPID,
  2075. g_TempBuffer
  2076. )) {
  2077. *g_TempBuffer = TEXT('*');
  2078. }
  2079. else {
  2080. p = _tcschr(g_TempBuffer,TEXT(','));
  2081. if (p) {
  2082. *p = 0;
  2083. p++;
  2084. *p = 0;
  2085. }
  2086. //
  2087. // We may need to map this id.
  2088. //
  2089. if (InfFindFirstLine (g_Win95UpgInf, S_NICIDMAP, g_TempBuffer, &is)) {
  2090. //
  2091. // This pnp id needs to be mapped.
  2092. //
  2093. p = InfGetStringField (&is, 1);
  2094. if (p) {
  2095. CLEARBUFFER();
  2096. StringCopy (g_TempBuffer, p);
  2097. }
  2098. }
  2099. }
  2100. return rPnpId;
  2101. }
  2102. /*++
  2103. Routine Description:
  2104. pSpecificTo simply copies the current adapter into the the temporary
  2105. buffer and returns it. This is necessary for the various adapter sections.
  2106. Arguments:
  2107. None.
  2108. Return Value:
  2109. a multisz containing the required data, or NULL if it could not be
  2110. retrieved.
  2111. --*/
  2112. PCTSTR
  2113. pSpecificTo (
  2114. VOID
  2115. )
  2116. {
  2117. CLEARBUFFER();
  2118. //if this is ICS external adapter and we are saving tcpip settings, then the g_CurrentAdapter
  2119. //actually contains name of the ICSHARE adapter intead of the real LAN adapter.
  2120. //However, "SpecificTo" still needs to point to the real LAN adapter
  2121. StringCopy(g_TempBuffer, (g_fIcsAdapterInPlace) ? g_IcsExternalAdapter : g_CurrentAdapter);
  2122. return g_TempBuffer;
  2123. }
  2124. /*++
  2125. Routine Description:
  2126. pGetBuildNumber simply packs the buildnumber into a string and passes
  2127. it back.
  2128. Arguments:
  2129. None.
  2130. Return Value:
  2131. a multisz containing the required data, or NULL if it could not be
  2132. retrieved.
  2133. --*/
  2134. PCTSTR
  2135. pGetBuildNumber (
  2136. VOID
  2137. )
  2138. {
  2139. CLEARBUFFER();
  2140. wsprintf(g_TempBuffer,"%u",BUILDNUMBER());
  2141. return g_TempBuffer;
  2142. }
  2143. /*++
  2144. Routine Description:
  2145. pGetUpgradeDomainName returns the upgrade domain name.
  2146. Arguments:
  2147. None.
  2148. Return Value:
  2149. a multisz containing the required data, or NULL if it could not be
  2150. retrieved.
  2151. --*/
  2152. PCTSTR
  2153. pGetUpgradeDomainName (
  2154. VOID
  2155. )
  2156. {
  2157. PCTSTR rDomainName = NULL;
  2158. CLEARBUFFER();
  2159. if (GetUpgradeDomainName(g_TempBuffer)) {
  2160. rDomainName = g_TempBuffer;
  2161. //
  2162. // Need to save some state information for use in GUI mode.
  2163. //
  2164. MemDbSetValueEx (
  2165. MEMDB_CATEGORY_STATE,
  2166. MEMDB_ITEM_MSNP32,
  2167. NULL,
  2168. NULL,
  2169. 0,
  2170. NULL
  2171. );
  2172. }
  2173. //
  2174. // If /#u:ForceWorkgroup is specified, force to workgroup
  2175. //
  2176. if (g_ConfigOptions.ForceWorkgroup) {
  2177. return NULL;
  2178. }
  2179. return rDomainName;
  2180. }
  2181. /*++
  2182. Routine Description:
  2183. pGetUpgradeWorkgroupName returns the upgrade domain name.
  2184. Arguments:
  2185. None.
  2186. Return Value:
  2187. a multisz containing the required data, or NULL if it could not be
  2188. retrieved.
  2189. --*/
  2190. PCTSTR
  2191. pGetUpgradeWorkgroupName (
  2192. VOID
  2193. )
  2194. {
  2195. PCTSTR rWorkGroupName = NULL;
  2196. //
  2197. // Don't write workgroup settings if domain settings already exist.
  2198. //
  2199. if (pGetUpgradeDomainName()) {
  2200. return NULL;
  2201. }
  2202. CLEARBUFFER();
  2203. #ifdef PRERELEASE
  2204. //
  2205. // If /#U:STRESS was specified, hardcode ntdev.
  2206. //
  2207. if (g_Stress) {
  2208. StringCopy(g_TempBuffer,TEXT("ntdev"));
  2209. rWorkGroupName = g_TempBuffer;
  2210. } else
  2211. #endif
  2212. //
  2213. // If /#u:ForceWorkgroup is specified, force to workgroup
  2214. //
  2215. if (!GetUpgradeWorkgroupName(g_TempBuffer) && !GetUpgradeDomainName(g_TempBuffer)) {
  2216. PCTSTR Buf = GetStringResource (MSG_DEFAULT_WORKGROUP);
  2217. MYASSERT(Buf);
  2218. StringCopy (g_TempBuffer, Buf);
  2219. FreeStringResource (Buf);
  2220. }
  2221. rWorkGroupName = g_TempBuffer;
  2222. return rWorkGroupName;
  2223. }
  2224. /*++
  2225. Routine Description:
  2226. pGetAdaptersWithIpxBindings and pGetAdaptersWithTcpBindings simply return a
  2227. multisz list of adapter sections names for per-adapter sections of winnt.sif
  2228. data for IPX and TCP settings respectively.
  2229. Arguments:
  2230. None.
  2231. Return Value:
  2232. a multisz containing the required data, or NULL if it could not be
  2233. retrieved.
  2234. --*/
  2235. PCTSTR
  2236. pGetAdaptersWithIpxBindings (
  2237. VOID
  2238. )
  2239. {
  2240. return pListAdaptersWithBinding(S_NWLINK,S_IPX_SUFFIX);
  2241. }
  2242. PCTSTR
  2243. pGetAdaptersWithTcpBindings (
  2244. VOID
  2245. )
  2246. {
  2247. return pListAdaptersWithBinding(S_MSTCP,S_TCPIP_SUFFIX);
  2248. }
  2249. /*++
  2250. Routine Description:
  2251. pGetIpxPacketType maps the frame type found in the win9x registry to the
  2252. packet types that are possible in the winnt.sif file.
  2253. Arguments:
  2254. None.
  2255. Return Value:
  2256. a multisz containing the required data, or NULL if it could not be
  2257. retrieved.
  2258. --*/
  2259. PCTSTR
  2260. pGetIpxPacketType (
  2261. VOID
  2262. )
  2263. {
  2264. PCTSTR frameType = NULL;
  2265. PCTSTR netTrans = NULL;
  2266. CLEARBUFFER();
  2267. netTrans = pGetNetTransBinding (g_CurrentAdapter, S_NWLINK);
  2268. if (netTrans) {
  2269. frameType = pGetRegistryValue(netTrans, S_FRAME_TYPE);
  2270. }
  2271. //
  2272. // We must map the win9x frame type onto the compatible NT frame type.
  2273. //
  2274. if (frameType) {
  2275. g_TempBuffer[1] = 0;
  2276. switch(*frameType) {
  2277. case TEXT('0'):
  2278. *g_TempBuffer = TEXT('1'); // 802.3
  2279. break;
  2280. case TEXT('1'):
  2281. *g_TempBuffer = TEXT('2'); // 802.2
  2282. break;
  2283. case TEXT('2'):
  2284. *g_TempBuffer = TEXT('0'); // ETHERNET II
  2285. break;
  2286. case TEXT('3'):
  2287. *g_TempBuffer = TEXT('3'); // ETHERNET SNAP
  2288. break;
  2289. default:
  2290. //
  2291. // If we find anything else, we'll just set it to AUTODETECT.
  2292. //
  2293. StringCopy(g_TempBuffer,TEXT("FF"));
  2294. //
  2295. // Lets log this to setupact.log.
  2296. //
  2297. LOG ((LOG_WARNING, (PCTSTR) MSG_AUTODETECT_FRAMETYPE));
  2298. }
  2299. }
  2300. else {
  2301. return NULL;
  2302. }
  2303. return g_TempBuffer;
  2304. }
  2305. PCTSTR
  2306. pGetIpxNetworkNumber (
  2307. VOID
  2308. )
  2309. {
  2310. PCTSTR netTrans = NULL;
  2311. CLEARBUFFER();
  2312. netTrans = pGetNetTransBinding (g_CurrentAdapter, S_NWLINK);
  2313. if (netTrans) {
  2314. return pGetRegistryValue (netTrans, S_NETWORK_ID);
  2315. }
  2316. return NULL;
  2317. }
  2318. /*++
  2319. Routine Description:
  2320. pGetDNSStatus returns "Yes" If DNS is enabled on the win9xupg machine,
  2321. "No" otherwise.
  2322. Arguments:
  2323. None.
  2324. Return Value:
  2325. a multisz containing the required data, or NULL if it could not be
  2326. retrieved.
  2327. --*/
  2328. PCTSTR
  2329. pGetDnsStatus (
  2330. VOID
  2331. )
  2332. {
  2333. CLEARBUFFER();
  2334. StringCopy(g_TempBuffer,pIsDnsEnabled() ? S_YES : S_NO);
  2335. return g_TempBuffer;
  2336. }
  2337. /*++
  2338. Routine Description:
  2339. pGetScriptProcessingStatus returns "Yes" if logon script processing is enabled,
  2340. "No" otherwise.
  2341. Arguments:
  2342. None.
  2343. Return Value:
  2344. a multisz containing the required data, or NULL if it could not be
  2345. retrieved.
  2346. --*/
  2347. PCTSTR
  2348. pGetScriptProcessingStatus (
  2349. VOID
  2350. )
  2351. {
  2352. PBYTE p = NULL;
  2353. HKEY key;
  2354. CLEARBUFFER();
  2355. key = OpenRegKeyStr(S_NETWORKLOGON);
  2356. if (key && key != INVALID_HANDLE_VALUE) {
  2357. p = GetRegValueBinary(key,S_PROCESSLOGINSCRIPT);
  2358. StringCopy(g_TempBuffer,p && *p == 0x01 ? S_YES : S_NO);
  2359. CloseRegKey(key);
  2360. }
  2361. else {
  2362. DEBUGMSG((DBG_WARNING,"pGetScriptProcessingStatus could not open key %s.",S_NETWORKLOGON));
  2363. StringCopy(g_TempBuffer,S_NO);
  2364. }
  2365. if (p) {
  2366. MemFree(g_hHeap,0,p);
  2367. }
  2368. return g_TempBuffer;
  2369. }
  2370. /*++
  2371. Routine Description:
  2372. pGetIpAddress returns the IP Address of the win9xupg machine being upgraded,
  2373. if it exists.
  2374. Arguments:
  2375. None.
  2376. Return Value:
  2377. a multisz containing the required data, or NULL if it could not be
  2378. retrieved.
  2379. --*/
  2380. PCTSTR
  2381. pGetIpAddress (
  2382. VOID
  2383. )
  2384. {
  2385. PTSTR p;
  2386. PCTSTR netTrans;
  2387. CLEARBUFFER();
  2388. netTrans = pGetNetTransBinding (g_CurrentAdapter, S_MSTCP);
  2389. if (!netTrans || !pGetRegistryValue(netTrans, S_IPADDRVAL)) {
  2390. return NULL;
  2391. }
  2392. else {
  2393. p = g_TempBuffer;
  2394. while (p && *p) {
  2395. p = _tcschr(p,TEXT(','));
  2396. if (p) {
  2397. *p = 0;
  2398. p = _tcsinc(p);
  2399. }
  2400. }
  2401. }
  2402. return g_TempBuffer;
  2403. }
  2404. /*++
  2405. Routine Description:
  2406. pGetDHCPStatus returns "Yes" if DHCP is enabled, "No" otherwise.
  2407. Arguments:
  2408. None.
  2409. Return Value:
  2410. a multisz containing the required data, or NULL if it could not be
  2411. retrieved.
  2412. --*/
  2413. PCTSTR
  2414. pGetDhcpStatus (
  2415. VOID
  2416. )
  2417. {
  2418. BOOL rStatus = !pHasStaticIpAddress();
  2419. CLEARBUFFER();
  2420. StringCopy(g_TempBuffer,rStatus ? S_YES : S_NO);
  2421. return g_TempBuffer;
  2422. }
  2423. /*++
  2424. Routine Description:
  2425. pGetSubnetMask returns the subnet mask in dotted decimal notation for the
  2426. machine being upgraded.
  2427. Arguments:
  2428. None.
  2429. Return Value:
  2430. a multisz containing the required data, or NULL if it could not be
  2431. retrieved.
  2432. --*/
  2433. PCTSTR
  2434. pGetSubnetMask (
  2435. VOID
  2436. )
  2437. {
  2438. PTSTR p;
  2439. PCTSTR netTrans = NULL;
  2440. CLEARBUFFER();
  2441. netTrans = pGetNetTransBinding (g_CurrentAdapter, S_MSTCP);
  2442. if (!netTrans || !pGetRegistryValue (netTrans, S_SUBNETVAL)) {
  2443. return NULL;
  2444. }
  2445. else {
  2446. p = g_TempBuffer;
  2447. while (p && *p) {
  2448. p = _tcschr(p,TEXT(','));
  2449. if (p) {
  2450. *p = 0;
  2451. p = _tcsinc(p);
  2452. }
  2453. }
  2454. }
  2455. return g_TempBuffer;
  2456. }
  2457. /*++
  2458. Routine Description:
  2459. pGetGateway returns the gateway(s) in dotted decimal notation for the
  2460. machine being upgraded. If the machine doesn't have a static IP address,
  2461. the Gateway settings are NOT migrated.
  2462. Arguments:
  2463. None.
  2464. Return Value:
  2465. a multisz containing the required data, or NULL if it could not be
  2466. retrieved.
  2467. --*/
  2468. PCTSTR
  2469. pGetGateway (
  2470. VOID
  2471. )
  2472. {
  2473. PTSTR p;
  2474. PCTSTR netTrans = NULL;
  2475. CLEARBUFFER();
  2476. if (!pHasStaticIpAddress()) {
  2477. return NULL;
  2478. }
  2479. netTrans = pGetNetTransBinding (g_CurrentAdapter, S_MSTCP);
  2480. if (!netTrans || !pGetRegistryValue (netTrans, S_DEFGATEWAYVAL)) {
  2481. return NULL;
  2482. }
  2483. else {
  2484. p = g_TempBuffer;
  2485. while (p && *p) {
  2486. p = _tcschr(p,TEXT(','));
  2487. if (p) {
  2488. *p = 0;
  2489. p = _tcsinc(p);
  2490. }
  2491. }
  2492. }
  2493. return g_TempBuffer;
  2494. }
  2495. PCTSTR
  2496. pGetDnsSuffixSearchOrder (
  2497. VOID
  2498. )
  2499. {
  2500. PTSTR p;
  2501. CLEARBUFFER();
  2502. if (!pGetRegistryValue(S_MSTCP_KEY,S_SEARCHLIST)) {
  2503. return NULL;
  2504. }
  2505. else {
  2506. p = g_TempBuffer;
  2507. while (p && *p) {
  2508. p = _tcschr(p,TEXT(','));
  2509. if (p) {
  2510. *p = 0;
  2511. p = _tcsinc(p);
  2512. }
  2513. }
  2514. }
  2515. return g_TempBuffer;
  2516. }
  2517. PCTSTR
  2518. pGetDnsServerSearchOrder (
  2519. VOID
  2520. )
  2521. {
  2522. PTSTR p;
  2523. CLEARBUFFER();
  2524. if (!pGetRegistryValue(S_MSTCP_KEY,S_NAMESERVERVAL)) {
  2525. return NULL;
  2526. }
  2527. else {
  2528. p = g_TempBuffer;
  2529. while (p && *p) {
  2530. p = _tcschr(p,TEXT(','));
  2531. if (p) {
  2532. *p = 0;
  2533. p = _tcsinc(p);
  2534. }
  2535. }
  2536. }
  2537. return g_TempBuffer;
  2538. }
  2539. /*++
  2540. Routine Description:
  2541. pGetWinsStatus returns "Yes" if WINS servers are enabled, "No" otehrwise.
  2542. Arguments:
  2543. None.
  2544. Return Value:
  2545. a multisz containing the required data, or NULL if it could not be
  2546. retrieved.
  2547. --*/
  2548. PCTSTR
  2549. pGetWinsStatus (
  2550. VOID
  2551. )
  2552. {
  2553. PCTSTR status;
  2554. PCTSTR netTrans = NULL;
  2555. netTrans = pGetNetTransBinding (g_CurrentAdapter, S_MSTCP);
  2556. if (!netTrans) {
  2557. status = S_NO;
  2558. }
  2559. else {
  2560. status =
  2561. (!pGetRegistryValue (netTrans, S_NODEVAL) &&
  2562. !pGetRegistryValue (S_MSTCP_KEY, S_NODEVAL))
  2563. ? S_NO : S_YES;
  2564. }
  2565. CLEARBUFFER();
  2566. StringCopy(g_TempBuffer,status);
  2567. return g_TempBuffer;
  2568. }
  2569. /*++
  2570. Routine Description:
  2571. pGetWinsServers returns the primary and secondary wins servers in dotted decimal
  2572. notation for the machine being upgraded.
  2573. Arguments:
  2574. None.
  2575. Return Value:
  2576. a multisz containing the required data, or NULL if it could not be
  2577. retrieved.
  2578. --*/
  2579. PCTSTR
  2580. pGetWinsServers (
  2581. VOID
  2582. )
  2583. {
  2584. TCHAR winsServer2[MEMDB_MAX] = {""};
  2585. TCHAR netTrans[MAX_PATH];
  2586. PTSTR p;
  2587. PCTSTR q;
  2588. CLEARBUFFER ();
  2589. q = pGetNetTransBinding (g_CurrentAdapter, S_MSTCP);
  2590. if (!q) {
  2591. return NULL;
  2592. }
  2593. StringCopy (netTrans, q);
  2594. if (pGetRegistryValue (netTrans, S_NAMESERVER2VAL)) {
  2595. StringCopy (winsServer2, g_TempBuffer);
  2596. } else if (pGetRegistryValue (S_MSTCP_KEY, S_NAMESERVER2VAL)) {
  2597. StringCopy (winsServer2, g_TempBuffer);
  2598. }
  2599. if (pGetRegistryValue (netTrans, S_NAMESERVER1VAL) ||
  2600. pGetRegistryValue(S_MSTCP_KEY, S_NAMESERVER1VAL)) {
  2601. p = GetEndOfString (g_TempBuffer) + 1;
  2602. StringCopy (p, winsServer2);
  2603. return g_TempBuffer;
  2604. }
  2605. return NULL;
  2606. }
  2607. /*++
  2608. Routine Description:
  2609. pGetRasPorts returns a multisz containing all of the ras ports for the
  2610. machine being upgraded.
  2611. Arguments:
  2612. None.
  2613. Return Value:
  2614. a multisz containing the required data, or NULL if it could not be
  2615. retrieved.
  2616. --*/
  2617. PCTSTR
  2618. pGetRasPorts (
  2619. VOID
  2620. )
  2621. {
  2622. REGKEY_ENUM e;
  2623. PTSTR p;
  2624. UINT modemNum = 1;
  2625. CLEARBUFFER();
  2626. if (EnumFirstRegKeyStr(&e,S_MODEMS)) {
  2627. p = g_TempBuffer;
  2628. do {
  2629. wsprintf(p,TEXT("COM%u"),modemNum);
  2630. modemNum++;
  2631. p = GetEndOfString (p) + 1;
  2632. } while (EnumNextRegKey(&e));
  2633. }
  2634. else {
  2635. //
  2636. // Apparently no modems.. Just return NULL.
  2637. //
  2638. return NULL;
  2639. }
  2640. return g_TempBuffer;
  2641. }
  2642. /*++
  2643. Routine Description:
  2644. pRasPortName returns the current ras port name for the ras section
  2645. currently being processed.
  2646. Arguments:
  2647. None.
  2648. Return Value:
  2649. a multisz containing the required data, or NULL if it could not be
  2650. retrieved.
  2651. --*/
  2652. PCTSTR
  2653. pRasPortName (
  2654. VOID
  2655. )
  2656. {
  2657. CLEARBUFFER();
  2658. StringCopy(g_TempBuffer,g_CurrentSection);
  2659. return g_TempBuffer;
  2660. }
  2661. /*++
  2662. Routine Description:
  2663. pGetLanguageGroups returns the list of language groups to be installed
  2664. during GUI mode setup. Note that any additional directories will have
  2665. been communicated to Setup as optional directories earlier.
  2666. Arguments:
  2667. None.
  2668. Return Value:
  2669. a multisz containing the required data, or NULL if it could not be
  2670. retrieved.
  2671. --*/
  2672. PCTSTR
  2673. pGetLanguageGroups (
  2674. VOID
  2675. )
  2676. {
  2677. HASHTABLE_ENUM e;
  2678. PTSTR p;
  2679. if (!g_LocaleTable) {
  2680. DEBUGMSG ((DBG_WARNING, "No information in Locale Hash Table."));
  2681. return NULL;
  2682. }
  2683. CLEARBUFFER();
  2684. p = g_TempBuffer;
  2685. if (EnumFirstHashTableString (&e, g_LocaleTable)) {
  2686. do {
  2687. StringCopy (p, e.String);
  2688. p = GetEndOfString (p) + 1;
  2689. } while (EnumNextHashTableString (&e));
  2690. }
  2691. return g_TempBuffer;
  2692. }
  2693. #if 0
  2694. BOOL
  2695. pFileVersionLesser (
  2696. IN PCTSTR FileName,
  2697. IN DWORD FileVerMS,
  2698. IN DWORD FileVerLS
  2699. )
  2700. {
  2701. DWORD dwLength, dwTemp;
  2702. UINT DataLength;
  2703. PVOID lpData;
  2704. VS_FIXEDFILEINFO *VsInfo;
  2705. BOOL b = TRUE;
  2706. if(dwLength = GetFileVersionInfoSize ((PTSTR)FileName, &dwTemp)) {
  2707. lpData = PoolMemGetMemory (g_GlobalPool, dwLength);
  2708. if(GetFileVersionInfo((PTSTR)FileName, 0, dwLength, lpData)) {
  2709. if (VerQueryValue(lpData, TEXT("\\"), &VsInfo, &DataLength)) {
  2710. b = VsInfo->dwFileVersionMS < FileVerMS ||
  2711. (VsInfo->dwFileVersionMS == FileVerMS &&
  2712. VsInfo->dwFileVersionLS <= FileVerLS);
  2713. }
  2714. }
  2715. PoolMemReleaseMemory (g_GlobalPool, lpData);
  2716. }
  2717. return b;
  2718. }
  2719. BOOL
  2720. pNewerW95upgntOnCD (
  2721. IN PCTSTR ReplacementDll
  2722. )
  2723. {
  2724. DWORD dwLength, dwTemp;
  2725. PVOID lpData = NULL;
  2726. VS_FIXEDFILEINFO *VsInfo;
  2727. UINT DataLength;
  2728. DWORD result;
  2729. UINT u;
  2730. PCTSTR pathCDdllSource = NULL;
  2731. PCTSTR pathCDdllTarget = NULL;
  2732. DWORD FileVerMS;
  2733. DWORD FileVerLS;
  2734. BOOL b = TRUE;
  2735. __try {
  2736. for (u = 0; u < SOURCEDIRECTORYCOUNT(); u++) {
  2737. pathCDdllSource = JoinPaths (SOURCEDIRECTORY(u), WINNT_WIN95UPG_NTKEY);
  2738. if (DoesFileExist (pathCDdllSource)) {
  2739. break;
  2740. }
  2741. FreePathString (pathCDdllSource);
  2742. pathCDdllSource = NULL;
  2743. }
  2744. if (!pathCDdllSource) {
  2745. __leave;
  2746. }
  2747. pathCDdllTarget = JoinPaths (g_TempDir, WINNT_WIN95UPG_NTKEY);
  2748. SetFileAttributes (pathCDdllTarget, FILE_ATTRIBUTE_NORMAL);
  2749. DeleteFile (pathCDdllTarget);
  2750. result = SetupDecompressOrCopyFile (pathCDdllSource, pathCDdllTarget, 0);
  2751. if (result != ERROR_SUCCESS) {
  2752. LOG ((
  2753. LOG_ERROR,
  2754. "pGetW95UpgNTCDFileVersion: Unable to decompress %s",
  2755. pathCDdllSource
  2756. ));
  2757. __leave;
  2758. }
  2759. if (dwLength = GetFileVersionInfoSize ((PTSTR)pathCDdllTarget, &dwTemp)) {
  2760. lpData = PoolMemGetMemory (g_GlobalPool, dwLength);
  2761. if (GetFileVersionInfo ((PTSTR)pathCDdllTarget, 0, dwLength, lpData)) {
  2762. if (VerQueryValue (lpData, TEXT("\\"), &VsInfo, &DataLength)) {
  2763. b = pFileVersionLesser (
  2764. ReplacementDll,
  2765. VsInfo->dwFileVersionMS,
  2766. VsInfo->dwFileVersionLS
  2767. );
  2768. }
  2769. }
  2770. }
  2771. }
  2772. __finally {
  2773. if (lpData) {
  2774. PoolMemReleaseMemory (g_GlobalPool, lpData);
  2775. }
  2776. if (pathCDdllSource) {
  2777. FreePathString (pathCDdllSource);
  2778. }
  2779. if (pathCDdllTarget) {
  2780. SetFileAttributes (pathCDdllTarget, FILE_ATTRIBUTE_NORMAL);
  2781. DeleteFile (pathCDdllTarget);
  2782. FreePathString (pathCDdllTarget);
  2783. }
  2784. }
  2785. return b;
  2786. }
  2787. /*++
  2788. Routine Description:
  2789. pGetReplacementDll is responsible for scanning the registry for an NT side
  2790. win9x replacement dll and putting it into the answer file if found.
  2791. Arguments:
  2792. None.
  2793. Return Value:
  2794. a multisz containing the required data, or NULL if it could not be
  2795. found.
  2796. --*/
  2797. PCTSTR
  2798. pGetReplacementDll (
  2799. VOID
  2800. )
  2801. {
  2802. HKEY key = NULL;
  2803. PTSTR val = NULL;
  2804. BOOL b = FALSE;
  2805. key = OpenRegKey (HKEY_LOCAL_MACHINE, WINNT_WIN95UPG_REPLACEMENT);
  2806. if (!key) {
  2807. return NULL;
  2808. }
  2809. __try {
  2810. val = GetRegValueString (key, WINNT_WIN95UPG_NTKEY);
  2811. if (!val) {
  2812. __leave;
  2813. }
  2814. if (pNewerW95upgntOnCD (val)) {
  2815. __leave;
  2816. }
  2817. CLEARBUFFER();
  2818. StringCopy (g_TempBuffer, val);
  2819. b = TRUE;
  2820. } __finally {
  2821. CloseRegKey (key);
  2822. if (val) {
  2823. MemFree (g_hHeap, 0, val);
  2824. }
  2825. }
  2826. return b ? g_TempBuffer : NULL;
  2827. }
  2828. #endif
  2829. VOID
  2830. pGenerateRandomPassword (
  2831. OUT PTSTR Password
  2832. )
  2833. /*++
  2834. Routine Description:
  2835. pGenerateRandomPassword creates a password of upper-case, lower-case and
  2836. numeric letters. The password has a length between 8 and 14
  2837. characters.
  2838. Arguments:
  2839. Password - Receives the generated password
  2840. Return Value:
  2841. none
  2842. --*/
  2843. {
  2844. INT Length;
  2845. TCHAR Offset;
  2846. INT Limit;
  2847. PTSTR p;
  2848. //
  2849. // Generate a random length based on the tick count
  2850. //
  2851. srand (GetTickCount());
  2852. Length = (rand() % 6) + 8;
  2853. p = Password;
  2854. while (Length) {
  2855. Limit = rand() % 3;
  2856. Offset = TEXT(' ');
  2857. if (Limit == 0) {
  2858. Limit = 10;
  2859. Offset = TEXT('0');
  2860. } else if (Limit == 1) {
  2861. Limit = 26;
  2862. Offset = TEXT('a');
  2863. } else if (Limit == 2) {
  2864. Limit = 26;
  2865. Offset = TEXT('A');
  2866. }
  2867. *p = Offset + (rand() % Limit);
  2868. p++;
  2869. Length--;
  2870. }
  2871. *p = 0;
  2872. DEBUGMSG ((DBG_WINNTSIF, "Generated password: %s", Password));
  2873. }
  2874. PCTSTR
  2875. pSetAdminPassword (
  2876. VOID
  2877. )
  2878. /*++
  2879. Routine Description:
  2880. pSetAdminPassword retrieves the AdminPassword as specified in the unattend file, if present.
  2881. Otherwise it generates a random one.
  2882. This information is stored in memdb to be available later.
  2883. Arguments:
  2884. None.
  2885. Return Value:
  2886. A pointer to the admin password.
  2887. --*/
  2888. {
  2889. BOOL attribs = 0;
  2890. TCHAR node[MEMDB_MAX];
  2891. BOOL blank = FALSE;
  2892. if (!g_UnattendScriptFile ||
  2893. !*g_UnattendScriptFile ||
  2894. !GetPrivateProfileString (
  2895. S_GUIUNATTENDED,
  2896. WINNT_US_ADMINPASS,
  2897. TEXT(""),
  2898. g_TempBuffer,
  2899. MEMDB_MAX,
  2900. *g_UnattendScriptFile
  2901. )
  2902. ) {
  2903. if (g_PersonalSKU) {
  2904. //
  2905. // for Personal set an empty admin password
  2906. //
  2907. StringCopy (g_TempBuffer, TEXT("*"));
  2908. } else {
  2909. pGenerateRandomPassword (g_TempBuffer);
  2910. attribs = PASSWORD_ATTR_RANDOM;
  2911. }
  2912. } else {
  2913. if (GetPrivateProfileString (
  2914. S_GUIUNATTENDED,
  2915. WINNT_US_ENCRYPTEDADMINPASS,
  2916. TEXT(""),
  2917. node,
  2918. MEMDB_MAX,
  2919. *g_UnattendScriptFile
  2920. )) {
  2921. if (StringIMatch (node, S_YES) || StringIMatch (node, TEXT("1"))) {
  2922. attribs = PASSWORD_ATTR_ENCRYPTED;
  2923. }
  2924. }
  2925. }
  2926. if (StringMatch (g_TempBuffer, TEXT("*"))) {
  2927. blank = TRUE;
  2928. *g_TempBuffer = 0;
  2929. }
  2930. MemDbBuildKey (node, MEMDB_CATEGORY_STATE, MEMDB_ITEM_ADMIN_PASSWORD, g_TempBuffer, NULL);
  2931. MemDbSetValue (node, attribs);
  2932. if (blank) {
  2933. wsprintf (g_TempBuffer, TEXT("*%c"), 0);
  2934. }
  2935. return g_TempBuffer;
  2936. }
  2937. //ICS upgrade functions
  2938. /*++
  2939. Routine Description:
  2940. pGetNetAdapterSectionNameBasedOnDriverID retrieves the net adapter name (for example, "Adapter1") based on the ID of
  2941. the driver of this adapter. For example, "0001" is the ID for the driver under
  2942. HKLM\System\CurrentControlSet\Services\Class\Net\0001.
  2943. Arguments:
  2944. String of the driver ID
  2945. Return Value:
  2946. A pointer to the adapter name
  2947. --*/
  2948. PCTSTR
  2949. pGetNetAdapterSectionNameBasedOnDriverID(
  2950. PCTSTR pszDriverID
  2951. )
  2952. {
  2953. TCHAR szID[256];
  2954. PCTSTR rAdapterSections = NULL;
  2955. PTSTR string = g_TempBuffer;
  2956. PCSTR pReturn = NULL;
  2957. MEMDB_ENUM e;
  2958. //first cache the string for the driver ID
  2959. lstrcpyn(szID, pszDriverID, sizeof(szID)/sizeof(szID[0]));
  2960. *string = 0;
  2961. //
  2962. // Enumerate all adapters, and create an entry for each adapter that has
  2963. // TCP bindings.
  2964. //
  2965. if (pEnumFirstAdapterByBinding(&e, S_MSTCP)) {
  2966. do {
  2967. //
  2968. // check whether the driver ID of the card
  2969. //
  2970. MemDbGetEndpointValueEx(
  2971. MEMDB_CATEGORY_NETADAPTERS,
  2972. e.szName,
  2973. MEMDB_FIELD_DRIVER,
  2974. g_TempBuffer
  2975. );
  2976. string = _tcsstr(g_TempBuffer, S_NET_PREFIX);
  2977. if (string)
  2978. {
  2979. string += TcharCount(S_NET_PREFIX);
  2980. if (0 == StringICompare(string, szID))
  2981. {
  2982. pReturn = e.szName;
  2983. break;
  2984. }
  2985. }
  2986. } while (pEnumNextAdapterByBinding(&e,S_MSTCP));
  2987. }
  2988. return pReturn;
  2989. }
  2990. /*++
  2991. Routine Description:
  2992. pHomenetSection is used to control whether the "ICSharing" section should show up in the
  2993. answer file or not.
  2994. If the ICS (Internet Connection Sharing) is installed, then we return "ICSharing" string for
  2995. the first time of this call, otherwise always return NULL. In such way, we can ensure the
  2996. "ICSharing" section will show up in the answer file ONLY when ICS is installed.
  2997. Arguments:
  2998. None
  2999. Return Value:
  3000. A pointer to "ICSharing" string if ICS is installed.
  3001. Otherwise, return NULL.
  3002. --*/
  3003. PCTSTR
  3004. pHomenetSection(
  3005. VOID
  3006. )
  3007. {
  3008. static BOOL firstTime = TRUE;
  3009. PCTSTR pReturn = NULL;
  3010. if (firstTime && NULL != pGetRegistryValue (S_ICS_KEY, S_EXTERNAL_ADAPTER))
  3011. {
  3012. firstTime = FALSE;
  3013. StringCopy(g_CurrentSection, S_HOMENET);
  3014. pReturn = g_CurrentSection;
  3015. }
  3016. return pReturn;
  3017. }
  3018. /*++
  3019. Routine Description:
  3020. pExternalIsAdapter detects whether the External connection of ICS is a LAN connection
  3021. --*/
  3022. BOOL
  3023. pExternalIsAdapter(
  3024. void
  3025. )
  3026. {
  3027. BOOL fRet = FALSE;
  3028. if (NULL == pGetRegistryValue (S_ICS_KEY, S_EXTERNAL_ADAPTER))
  3029. {
  3030. return FALSE;
  3031. }
  3032. return (NULL != pGetNetAdapterSectionNameBasedOnDriverID(g_TempBuffer));
  3033. return fRet;
  3034. }
  3035. /*++
  3036. Routine Description:
  3037. pExternalIsRasConn detects whether the External connection of ICS is a RAS connection
  3038. --*/
  3039. BOOL
  3040. pExternalIsRasConn(
  3041. void
  3042. )
  3043. {
  3044. if (NULL == pGetRegistryValue (S_ICS_KEY, S_EXTERNAL_ADAPTER))
  3045. {
  3046. return FALSE;
  3047. }
  3048. return NULL == pGetNetAdapterSectionNameBasedOnDriverID(g_TempBuffer);
  3049. }
  3050. /*++
  3051. Routine Description:
  3052. pHasInternalAdapter detects whether the first Internal Adapter is specified for ICS
  3053. --*/
  3054. BOOL
  3055. pHasInternalAdapter(
  3056. void
  3057. )
  3058. {
  3059. //To have the "InternalAdapter" key, two conditions have to be statisfy:
  3060. //(1) there is "InternalAdapter" AND
  3061. //(2) this is the only internal adapter, i.e. internal is NOT bridge
  3062. return (NULL != pGetRegistryValue (S_ICS_KEY, S_INTERNAL_ADAPTER) &&
  3063. (!g_fIcsInternalIsBridge));
  3064. }
  3065. /*++
  3066. Routine Description:
  3067. pHasBridge detects whether there are two ICS Internal Adapters. If so, we
  3068. need to bridge those two adapter together
  3069. --*/
  3070. pHasBridge(
  3071. void
  3072. )
  3073. {
  3074. return g_fIcsInternalIsBridge;
  3075. }
  3076. /*++
  3077. Routine Description:
  3078. pIcsExternalAdapter retrieves the adapter name (for example, "Adapter1")
  3079. for external ICS connection
  3080. --*/
  3081. PCTSTR
  3082. pIcsExternalAdapter (
  3083. VOID
  3084. )
  3085. {
  3086. PCSTR pszAdapter;
  3087. if (NULL == pGetRegistryValue(S_ICS_KEY, S_EXTERNAL_ADAPTER))
  3088. return NULL;
  3089. pszAdapter = pGetNetAdapterSectionNameBasedOnDriverID(g_TempBuffer);
  3090. if (NULL == pszAdapter)
  3091. {
  3092. return NULL;
  3093. }
  3094. //ICSHARE adapter's TCP setting overwrite the TCP setting of the external adapter
  3095. //We remember all the info here and will use it when saving the TCP setting of this adapter
  3096. if (0 != lstrlen(g_IcsAdapter))
  3097. {
  3098. //this flag will be used to upgrade the TCP/IP settings of the ICSHARE adapter
  3099. g_fHasIcsExternalAdapter = TRUE;
  3100. lstrcpyn(g_IcsExternalAdapter,
  3101. pszAdapter,
  3102. sizeof(g_IcsExternalAdapter)/sizeof(g_IcsExternalAdapter[0]));
  3103. }
  3104. CLEARBUFFER();
  3105. StringCopy(g_TempBuffer, pszAdapter);
  3106. return g_TempBuffer;
  3107. }
  3108. /*++
  3109. Routine Description:
  3110. pIcsExternalConnectionName retrieves the name (for example, "My Dial-up Connection")
  3111. for external ICS RAS connection
  3112. --*/
  3113. PCSTR
  3114. pIcsExternalConnectionName (
  3115. VOID
  3116. )
  3117. {
  3118. TCHAR szKey[MEMDB_MAX * 2]; // Contains the current value returned from pGetRegistryValue
  3119. PCSTR pReturn = NULL;
  3120. if (NULL == pGetRegistryValue(S_ICS_KEY, S_EXTERNAL_ADAPTER))
  3121. {
  3122. return NULL;
  3123. }
  3124. StringCopy(szKey, S_NET_DRIVER_KEY);
  3125. StringCat(szKey, _T("\\"));
  3126. StringCat(szKey, g_TempBuffer);
  3127. //The "DriverDesc" value has to be "Dial-Up Adapter"
  3128. if (NULL == pGetRegistryValue(szKey, S_DRIVERDESC) && 0 != StringCompare(g_TempBuffer, S_DIALUP_ADAPTER_DESC))
  3129. {
  3130. return NULL;
  3131. }
  3132. //the default ras connection should be the external one. The reg location of the connection name is at
  3133. //HKCU\RemoteAccess\Default
  3134. return pGetRegistryValue(S_REMOTEACCESS_KEY, S_RAS_DEFAULT);
  3135. }
  3136. /*++
  3137. Routine Description:
  3138. pInternalIsBridge detects whether there are two ICS Internal Adapters. If so, we
  3139. need to bridge those two adapter together
  3140. --*/
  3141. PCSTR
  3142. pInternalIsBridge(
  3143. VOID
  3144. )
  3145. {
  3146. g_fIcsInternalIsBridge = (NULL != pGetRegistryValue (S_ICS_KEY, S_INTERNAL_ADAPTER) &&
  3147. NULL != pGetRegistryValue (S_ICS_KEY, S_INTERNAL_ADAPTER2));
  3148. CLEARBUFFER();
  3149. StringCopy(g_TempBuffer, (g_fIcsInternalIsBridge) ? S_YES : S_NO);
  3150. return g_TempBuffer;
  3151. }
  3152. /*++
  3153. Routine Description:
  3154. pInternalAdapter retrieves the adapter name (for example, "Adapter1") for first internal ICS connection
  3155. NOTE: internal connections has to be LAN conncections
  3156. --*/
  3157. PCSTR
  3158. pInternalAdapter(
  3159. VOID
  3160. )
  3161. {
  3162. PCSTR pszAdapter;
  3163. if (NULL == pGetRegistryValue(S_ICS_KEY, S_INTERNAL_ADAPTER))
  3164. {
  3165. return NULL;
  3166. }
  3167. pszAdapter = pGetNetAdapterSectionNameBasedOnDriverID(g_TempBuffer);
  3168. if (NULL == pszAdapter)
  3169. {
  3170. return NULL;
  3171. }
  3172. CLEARBUFFER();
  3173. StringCopy(g_TempBuffer, pszAdapter);
  3174. return g_TempBuffer;
  3175. }
  3176. /*++
  3177. Routine Description:
  3178. pBridge retrieves name the two internal adapter names (for example, "Adapter2")
  3179. --*/
  3180. PCSTR
  3181. pBridge(
  3182. VOID
  3183. )
  3184. {
  3185. TCHAR szBuff[MEMDB_MAX] = {0};
  3186. TCHAR * psz = szBuff;
  3187. PCSTR pszAdapter;
  3188. if (NULL == pGetRegistryValue(S_ICS_KEY, S_INTERNAL_ADAPTER))
  3189. {
  3190. return NULL;
  3191. }
  3192. pszAdapter = pGetNetAdapterSectionNameBasedOnDriverID(g_TempBuffer);
  3193. if (NULL == pszAdapter)
  3194. {
  3195. return NULL;
  3196. }
  3197. StringCopy(psz, pszAdapter);
  3198. psz = GetEndOfString(szBuff) + 1;
  3199. if (NULL == pGetRegistryValue(S_ICS_KEY, S_INTERNAL_ADAPTER2))
  3200. {
  3201. return NULL;
  3202. }
  3203. pszAdapter = pGetNetAdapterSectionNameBasedOnDriverID(g_TempBuffer);
  3204. if (NULL == pszAdapter)
  3205. {
  3206. return NULL;
  3207. }
  3208. StringCopy(psz, pszAdapter);
  3209. psz = GetEndOfString(psz) + 1;
  3210. *psz = 0;
  3211. CLEARBUFFER();
  3212. memcpy(g_TempBuffer, szBuff,
  3213. sizeof(szBuff) < sizeof(g_TempBuffer) ? sizeof(szBuff) : sizeof(g_TempBuffer));
  3214. return g_TempBuffer;
  3215. }
  3216. /*++
  3217. Routine Description:
  3218. pDialOnDemand retrieves the dial-on-demand feature
  3219. for ICS connection
  3220. --*/
  3221. PCSTR
  3222. pDialOnDemand(
  3223. VOID
  3224. )
  3225. {
  3226. PCTSTR KeyString = S_INET_SETTINGS;
  3227. PCTSTR ValueString = S_ENABLE_AUTODIAL;
  3228. PCTSTR rString = NULL;
  3229. HKEY key = NULL;
  3230. PBYTE data = NULL;
  3231. DWORD type = REG_NONE;
  3232. DWORD BufferSize = 0;
  3233. LONG rc = ERROR_SUCCESS;
  3234. PCTSTR end;
  3235. //
  3236. //
  3237. // Open registry key.
  3238. //
  3239. key = OpenRegKeyStr(KeyString);
  3240. if (!key) {
  3241. DEBUGMSG((DBG_WINNTSIF, "Key %s does not exist.",KeyString));
  3242. return NULL;
  3243. }
  3244. //
  3245. // Get type of data
  3246. //
  3247. rc = RegQueryValueExA (key, ValueString, NULL, &type, NULL, &BufferSize);
  3248. if (rc != ERROR_SUCCESS) {
  3249. DEBUGMSG((DBG_WINNTSIF,"RegQueryValueEx failed for %s[%s]. Value may not exist.",KeyString,ValueString));
  3250. CloseRegKey(key);
  3251. SetLastError (rc);
  3252. return NULL;
  3253. }
  3254. if (0 == BufferSize ||
  3255. (REG_DWORD != type && REG_BINARY != type))
  3256. {
  3257. DEBUGMSG((DBG_WINNTSIF,"EnableAutoDial is not a DWORD, nor a Binary."));
  3258. CloseRegKey(key);
  3259. return NULL;
  3260. }
  3261. if (REG_BINARY == type && sizeof(DWORD) != BufferSize)
  3262. {
  3263. DEBUGMSG((DBG_WINNTSIF,"EnableAutoDial is a binary, but the buffer size is not 4."));
  3264. CloseRegKey(key);
  3265. return NULL;
  3266. }
  3267. data = (PBYTE) MemAlloc (g_hHeap, 0, BufferSize);
  3268. if (NULL == data)
  3269. {
  3270. DEBUGMSG((DBG_WINNTSIF,"Alloc failed. Out of memory."));
  3271. CloseRegKey(key);
  3272. return NULL;
  3273. }
  3274. rc = RegQueryValueExA (key, ValueString, NULL, NULL, data, &BufferSize);
  3275. if (rc != ERROR_SUCCESS) {
  3276. DEBUGMSG((DBG_WINNTSIF,"RegQueryValueEx failed for %s[%s]. Value may not exist.",KeyString,ValueString));
  3277. MemFree(g_hHeap, 0, data);
  3278. data = NULL;
  3279. CloseRegKey(key);
  3280. SetLastError (rc);
  3281. return NULL;
  3282. }
  3283. CLEARBUFFER();
  3284. wsprintf(g_TempBuffer,"%u",*((DWORD*) data));
  3285. //
  3286. // Clean up resources.
  3287. //
  3288. CloseRegKey(key);
  3289. if (data) {
  3290. MemFree(g_hHeap, 0, data);
  3291. data = NULL;
  3292. }
  3293. return g_TempBuffer;
  3294. }
  3295. //
  3296. // Processing functions
  3297. //
  3298. //
  3299. // g_SectionList contains the list of all winntsif sections that will be enumerated and processed by BuildWinntSifFile.
  3300. //
  3301. SECTION g_SectionList[] = {WINNTSIF_SECTIONS /*,*/ {NULL,NULL,{{LAST_SETTING,NULL,NULL,{NULL,NULL}}}}};
  3302. /*++
  3303. Routine Description:
  3304. pProcessSectionSettings is responsible for processing a single section
  3305. worth of data. For this section, it will process all of the settings in the
  3306. settinglist passed in.
  3307. Arguments:
  3308. SectionName - The name of the section being processed.
  3309. SettingsList - a list of settings to be processed for this sections.
  3310. Return Value:
  3311. --*/
  3312. BOOL
  3313. pProcessSectionSettings (
  3314. IN PCTSTR SectionName,
  3315. IN PSETTING SettingsList
  3316. )
  3317. {
  3318. PSETTING curSetting = SettingsList;
  3319. PTSTR data = NULL;
  3320. PTSTR p;
  3321. MULTISZ_ENUM e;
  3322. UINT index = 0;
  3323. TCHAR key[MEMDB_MAX];
  3324. MYASSERT(curSetting);
  3325. MYASSERT(SectionName);
  3326. DEBUGMSG((DBG_WINNTSIF,"pProcessSectionSettings: Processing [%s] Section...",SectionName));
  3327. //
  3328. // The last setting in the list is a null setting with the type LAST_SETTING. We use this as the
  3329. // break condition of our loop.
  3330. //
  3331. while (curSetting -> SettingType != LAST_SETTING) {
  3332. if (!curSetting -> CreationFunction || curSetting -> CreationFunction()) {
  3333. //
  3334. // Any setting that gets to this point MUST have a key name.
  3335. // Since this data is static, we just assert this.
  3336. //
  3337. MYASSERT(curSetting -> KeyName);
  3338. //
  3339. // We must still get the data for this particular setting. How we get that data is determined by
  3340. // the SettingType of the current setting. If at the end, data is NULL, we will write nothing.
  3341. //
  3342. switch (curSetting -> SettingType) {
  3343. case FUNCTION_SETTING:
  3344. data = (PTSTR) curSetting -> Data.Function();
  3345. break;
  3346. case STRING_SETTING:
  3347. StringCopy(g_TempBuffer,curSetting -> Data.String);
  3348. p = GetEndOfString (g_TempBuffer) + 1;
  3349. *p = 0;
  3350. data = g_TempBuffer;
  3351. break;
  3352. case REGISTRY_SETTING:
  3353. data = (PTSTR) pGetRegistryValue(curSetting -> Data.Registry.Key, curSetting -> Data.Registry.Value);
  3354. break;
  3355. default:
  3356. DEBUGMSG((
  3357. DBG_WHOOPS,
  3358. "pProcessSectionSettings: Unexpected Setting Type for Section %s, Key %s. (Type: %u)",
  3359. SectionName,
  3360. curSetting -> KeyName,
  3361. curSetting -> SettingType
  3362. ));
  3363. break;
  3364. }
  3365. //
  3366. // If we found data, go ahead and create the setting. All data is stored in multi strings, typically only one string long.
  3367. //
  3368. if (data) {
  3369. //
  3370. // Make sure this isn't suppressed.
  3371. //
  3372. MemDbBuildKey (
  3373. key,
  3374. MEMDB_CATEGORY_SUPPRESS_ANSWER_FILE_SETTINGS,
  3375. SectionName,
  3376. curSetting->KeyName,
  3377. NULL
  3378. );
  3379. if (MemDbGetPatternValue (key, NULL)) {
  3380. DEBUGMSG ((DBG_WINNTSIF, "Answer File Section is suppressed: [%s] %s", SectionName, curSetting->KeyName));
  3381. }
  3382. else {
  3383. DEBUGMSG((DBG_WINNTSIF,"Creating WinntSif Entry: Section: %s, Key: %s.",SectionName, curSetting -> KeyName));
  3384. if (EnumFirstMultiSz(&e,data)) {
  3385. index = 0;
  3386. do {
  3387. index = WriteInfKeyEx(SectionName, curSetting -> KeyName, e.CurrentString, index, FALSE);
  3388. DEBUGMSG_IF((
  3389. !index,
  3390. DBG_ERROR,
  3391. "pProcessSectionSettings: WriteInfKeyEx Failed. Section: %s Key: %s Value: %s",
  3392. SectionName,
  3393. curSetting -> KeyName,
  3394. e.CurrentString
  3395. ));
  3396. DEBUGMSG_IF((index,DBG_WINNTSIF,"Value: %s",e.CurrentString));
  3397. } while (EnumNextMultiSz(&e));
  3398. }
  3399. }
  3400. }
  3401. ELSE_DEBUGMSG((DBG_WARNING,"pProcessSectionSettings: No data for Section %s, Key %s.",SectionName, curSetting -> KeyName));
  3402. }
  3403. curSetting++;
  3404. }
  3405. return TRUE;
  3406. }
  3407. /*++
  3408. Routine Description:
  3409. BuildWinntSifFile is responsible for writing all of the necessary unattend
  3410. settings to the winnt.sif file. The Win9xUpg code uses these unattended
  3411. settings to control the behavior of text mode and GUI mode setup so that
  3412. the settings gathered from win9x are incorporated into the new NT
  3413. system.
  3414. The settings to be written are kept in the global list g_SettingL
  3415. ist which is itself built from macro expansion lists. This function cycles
  3416. through these settings, calculating wether each setting should be written
  3417. and if so, with what data.
  3418. Arguments:
  3419. None.
  3420. Return Value:
  3421. TRUE if the function returned successfully, FALSE otherwise.
  3422. --*/
  3423. BOOL
  3424. pBuildWinntSifFile (
  3425. VOID
  3426. )
  3427. {
  3428. BOOL rSuccess = TRUE;
  3429. PSECTION curSection = g_SectionList;
  3430. PCTSTR sectionName = NULL;
  3431. while (curSection -> SectionString || curSection -> SectionFunction) {
  3432. sectionName = curSection -> SectionString ? curSection -> SectionString : curSection -> SectionFunction();
  3433. while (sectionName) {
  3434. if (!pProcessSectionSettings (sectionName,curSection -> SettingList)) {
  3435. LOG ((LOG_ERROR,"Unable to process answer file settings for %s Section.",sectionName));
  3436. rSuccess = FALSE;
  3437. }
  3438. //
  3439. // If the section name was from a static string, we set the sectionName to NULL, exiting this loop.
  3440. // If the section name was from a function, we call the function again. If there is another
  3441. // section to build, it will return a new name, otherwise, it will return NULL.
  3442. //
  3443. sectionName = curSection -> SectionString ? NULL : curSection -> SectionFunction();
  3444. }
  3445. //
  3446. // Go to the next setting.
  3447. //
  3448. curSection++;
  3449. }
  3450. return rSuccess;
  3451. }
  3452. DWORD
  3453. BuildWinntSifFile (
  3454. DWORD Request
  3455. )
  3456. {
  3457. switch (Request) {
  3458. case REQUEST_QUERYTICKS:
  3459. return TICKS_BUILD_UNATTEND;
  3460. case REQUEST_RUN:
  3461. if (!pBuildWinntSifFile ()) {
  3462. return GetLastError ();
  3463. }
  3464. else {
  3465. return ERROR_SUCCESS;
  3466. }
  3467. default:
  3468. DEBUGMSG ((DBG_ERROR, "Bad parameter in BuildWinntSif"));
  3469. }
  3470. return 0;
  3471. }
  3472. VOID
  3473. TerminateWinntSifBuilder (
  3474. VOID
  3475. )
  3476. {
  3477. if (g_LocalePool) {
  3478. HtFree (g_LocaleTable);
  3479. PoolMemDestroyPool (g_LocalePool);
  3480. g_LocaleTable = NULL;
  3481. g_LocalePool = NULL;
  3482. }
  3483. }