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

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