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.

482 lines
12 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Copyright (c) 1997-1999 Microsoft Corporation
  4. // All rights reserved.
  5. //
  6. // File Name:
  7. // hsload.c
  8. //
  9. // Description:
  10. //
  11. // The functions in this file are a workaround. Ideally they should be
  12. // merged in with non-Hal/SCSI equivalents of these functions. The
  13. // decision was made to fix a HAL/SCSI bug and we are close to RTM so
  14. // these extra functions were created to not jeopardize the standard
  15. // answerfile write out. Sometime post-RTM these functions should be
  16. // merged back into the core write out and queueing routines.
  17. //
  18. //----------------------------------------------------------------------------
  19. #include "pch.h"
  20. #include "settypes.h"
  21. LINKED_LIST *SelectSettingQueue(QUEUENUM dwWhichQueue);
  22. BOOL DoesSectionHaveKeys( SECTION_NODE *pSection );
  23. BOOL SettingQueueHalScsi_Flush(LPTSTR lpFileName,
  24. QUEUENUM dwWhichQueue);
  25. BOOL SettingQueueHalScsi_AddSetting(LPTSTR lpSection,
  26. LPTSTR lpKey,
  27. LPTSTR lpValue,
  28. QUEUENUM dwWhichQueue);
  29. SECTION_NODE * SettingQueue_AddSection(LPTSTR lpSection, QUEUENUM dwWhichQueue);
  30. KEY_NODE* FindKey(LINKED_LIST *ListHead,
  31. LPTSTR lpKeyName);
  32. VOID InsertNode(LINKED_LIST *pList, PVOID pNode);
  33. //----------------------------------------------------------------------------
  34. //
  35. // Function: IsBlankLine
  36. //
  37. // Purpose:
  38. //
  39. //----------------------------------------------------------------------------
  40. BOOL
  41. IsBlankLine( TCHAR * pszBuffer )
  42. {
  43. TCHAR * p = pszBuffer;
  44. while( *p != _T('\0') )
  45. {
  46. if( ! _istspace( *p ) )
  47. {
  48. return( FALSE );
  49. }
  50. p++;
  51. }
  52. return( TRUE );
  53. }
  54. //----------------------------------------------------------------------------
  55. //
  56. // Function: LoadOriginalSettingsLowHalScsi
  57. //
  58. // Purpose:
  59. //
  60. //----------------------------------------------------------------------------
  61. VOID
  62. LoadOriginalSettingsLowHalScsi(HWND hwnd,
  63. LPTSTR lpFileName,
  64. QUEUENUM dwWhichQueue)
  65. {
  66. TCHAR Buffer[MAX_INILINE_LEN];
  67. FILE *fp;
  68. TCHAR SectionName[MAX_ININAME_LEN + 1] = _T("");
  69. TCHAR KeyName[MAX_ININAME_LEN + 1] = _T("");
  70. TCHAR *pValue;
  71. //
  72. // Open the answer file for reading
  73. //
  74. if ( (fp = My_fopen( lpFileName, _T("r") )) == NULL )
  75. return;
  76. //
  77. // Read each line
  78. //
  79. while ( My_fgets(Buffer, MAX_INILINE_LEN - 1, fp) != NULL ) {
  80. BOOL bSectionLine = FALSE;
  81. BOOL bCreatedPriorSection = FALSE;
  82. TCHAR *p;
  83. TCHAR *pEqual;
  84. //
  85. // A semicolon(;) denotes that the rest of the line is a comment.
  86. // Thus, if a semicolon(;) exists in the Buffer, place a null char
  87. // there and send the Buffer on for further processing.
  88. //
  89. //
  90. // Look for [SectionName]
  91. //
  92. if ( Buffer[0] == _T('[') ) {
  93. for ( p=Buffer+1; *p && *p != _T(']'); p++ )
  94. ;
  95. if ( p ) {
  96. *p = _T('\0');
  97. bSectionLine = TRUE;
  98. }
  99. }
  100. //
  101. // If this line has [SectionName], be sure we made a section node
  102. // on the setting queue before overwriting SectionName buffer. This
  103. // is the only way to get the SettingQueueFlush routine to write
  104. // out an empty section. The user had an empty section originally,
  105. // so we'll preserve it.
  106. //
  107. if( bSectionLine )
  108. {
  109. lstrcpyn(SectionName, Buffer+1, AS(SectionName));
  110. }
  111. else {
  112. //
  113. // if its not a Section line or a blank line then just add the full line to the
  114. // queue under its appropriate section
  115. //
  116. if( ! IsBlankLine( Buffer ) )
  117. {
  118. //
  119. // Don't add the key unless it has a section to go under. This has the side
  120. // effect of striping comments from the top of txtsetup.oem.
  121. //
  122. if( SectionName[0] != _T('\0') )
  123. {
  124. SettingQueueHalScsi_AddSetting(SectionName,
  125. L"",
  126. Buffer,
  127. dwWhichQueue);
  128. bCreatedPriorSection = TRUE;
  129. }
  130. }
  131. }
  132. }
  133. My_fclose(fp);
  134. return;
  135. }
  136. //----------------------------------------------------------------------------
  137. //
  138. // Function: SettingQueueHalScsi_Flush
  139. //
  140. // Purpose: This function is called (by the wizard) once all the settings
  141. // have been queued for Hal and SCSI.
  142. //
  143. // Arguments:
  144. // LPTSTR lpFileName - name of file to create/edit
  145. // DWORD dwWhichQueue - which queue, answers file, .udf, ...
  146. //
  147. // Returns:
  148. // BOOL - success
  149. //
  150. //----------------------------------------------------------------------------
  151. BOOL
  152. SettingQueueHalScsi_Flush(LPTSTR lpFileName,
  153. QUEUENUM dwWhichQueue)
  154. {
  155. LINKED_LIST *pList;
  156. SECTION_NODE *pSection;
  157. KEY_NODE *pKey;
  158. TCHAR Buffer[MAX_INILINE_LEN];
  159. FILE *fp;
  160. INT BufferSize = sizeof(Buffer) / sizeof(TCHAR);
  161. HRESULT hrPrintf;
  162. //
  163. // Point to the proper queue to flush
  164. //
  165. pList = SelectSettingQueue(dwWhichQueue);
  166. if (pList == NULL)
  167. return FALSE;
  168. pSection = (SECTION_NODE *) pList->Head;
  169. //
  170. // Start writing the file
  171. //
  172. if( ( fp = My_fopen( lpFileName, _T("w") ) ) == NULL ) {
  173. return( FALSE );
  174. }
  175. if( My_fputs( _T(";SetupMgrTag\n"), fp ) == _TEOF ) {
  176. My_fclose( fp );
  177. return( FALSE );
  178. }
  179. //
  180. // For each section ...
  181. //
  182. for ( pSection = (SECTION_NODE *) pList->Head;
  183. pSection;
  184. pSection = (SECTION_NODE *) pSection->Header.next ) {
  185. Buffer[0] = _T('\0');
  186. //
  187. // We don't write out sections that are still marked volatile.
  188. //
  189. if ( pSection->bVolatile )
  190. continue;
  191. //
  192. // Write the section name only if we will write keys below it
  193. //
  194. // ISSUE-2002/02/28-stelo- this causes problems because we want to write out
  195. // some sections without keys, like:
  196. //
  197. //[NetServices]
  198. // MS_SERVER=params.MS_SERVER
  199. //
  200. //[params.MS_SERVER]
  201. //
  202. // How can we get around this?
  203. //
  204. if( DoesSectionHaveKeys( pSection ) ) {
  205. hrPrintf=StringCchPrintf(Buffer,
  206. AS(Buffer),
  207. _T("[%s]\n"),
  208. pSection->lpSection);
  209. }
  210. else {
  211. continue;
  212. }
  213. if( My_fputs( Buffer, fp ) == _TEOF ) {
  214. My_fclose( fp );
  215. return( FALSE );
  216. }
  217. //
  218. // Write out the value
  219. //
  220. for ( pKey = (KEY_NODE *) pSection->key_list.Head;
  221. pKey;
  222. pKey = (KEY_NODE *) pKey->Header.next ) {
  223. TCHAR *p;
  224. Buffer[0] = _T('\0');
  225. //
  226. // An empty value means to not write it
  227. //
  228. if ( pKey->lpValue[0] == _T('\0') )
  229. continue;
  230. //
  231. // Put the key we want into Buffer
  232. //
  233. lstrcatn( Buffer, pKey->lpValue, BufferSize );
  234. if( My_fputs( Buffer, fp ) == _TEOF ) {
  235. My_fclose( fp );
  236. return( FALSE );
  237. }
  238. }
  239. //
  240. // Write a blank line at the end of the section
  241. //
  242. hrPrintf=StringCchPrintf(Buffer, AS(Buffer), _T("\n"));
  243. if( My_fputs( Buffer, fp ) == _TEOF ) {
  244. My_fclose( fp );
  245. return( FALSE );
  246. }
  247. }
  248. My_fclose( fp );
  249. return( TRUE );
  250. }
  251. //----------------------------------------------------------------------------
  252. //
  253. // Function: FindValue
  254. //
  255. // Purpose: Searches the given list of keynodes and finds one with the
  256. // given name.
  257. //
  258. // Arguments:
  259. // LPTSTR lpSection - name of section in .ini
  260. //
  261. // Returns:
  262. // SECTION_NODE * or NULL if it does not exist
  263. //
  264. // Notes:
  265. // - Searches are case insensitive
  266. //
  267. //----------------------------------------------------------------------------
  268. KEY_NODE* FindValue(LINKED_LIST *ListHead,
  269. LPTSTR lpValue)
  270. {
  271. KEY_NODE *p = (KEY_NODE *) ListHead->Head;
  272. if ( p == NULL )
  273. return NULL;
  274. do {
  275. if ( _tcsicmp(p->lpValue, lpValue) == 0 )
  276. break;
  277. p = (KEY_NODE *) p->Header.next;
  278. } while ( p );
  279. return p;
  280. }
  281. //----------------------------------------------------------------------------
  282. //
  283. // Function: SettingQueueHalScsi_AddSetting
  284. //
  285. // Purpose: Same as SettingQueue_AddSetting except with HAL and SCSI all of
  286. // the enties under a section are values, there are no keys. So don't add a
  287. // setting if the value is already there.
  288. //
  289. // Arguments:
  290. //
  291. // Returns:
  292. //
  293. //----------------------------------------------------------------------------
  294. BOOL SettingQueueHalScsi_AddSetting(LPTSTR lpSection,
  295. LPTSTR lpKey,
  296. LPTSTR lpValue,
  297. QUEUENUM dwWhichQueue)
  298. {
  299. SECTION_NODE *pSectionNode;
  300. KEY_NODE *pKeyNode;
  301. //
  302. // You have to pass a section key and value. Section name cannot
  303. // be empty.
  304. //
  305. Assert(lpSection != NULL);
  306. Assert(lpKey != NULL);
  307. Assert(lpValue != NULL);
  308. Assert(lpSection[0]);
  309. //
  310. // See if a node for this section already exists. If not, create one.
  311. //
  312. pSectionNode = SettingQueue_AddSection(lpSection, dwWhichQueue);
  313. if ( pSectionNode == NULL )
  314. return FALSE;
  315. //
  316. // See if this key has already been set. If not, alloc a node and
  317. // set all of its fields except for the lpValue.
  318. //
  319. // If the node already exist, free the lpValue to make room for
  320. // the new value.
  321. //
  322. pKeyNode = FindValue( &pSectionNode->key_list, lpValue );
  323. if( pKeyNode == NULL ) {
  324. if ( (pKeyNode=malloc(sizeof(KEY_NODE))) == NULL )
  325. return FALSE;
  326. if ( (pKeyNode->lpKey = lstrdup(lpKey)) == NULL )
  327. {
  328. free(pKeyNode);
  329. return FALSE;
  330. }
  331. InsertNode(&pSectionNode->key_list, pKeyNode);
  332. } else {
  333. #if DBG
  334. //
  335. // If the wizard has already set this key once, assert.
  336. //
  337. if ( pKeyNode->bSetOnce ) {
  338. AssertMsg2(FALSE,
  339. "Section \"%S\" Key \"%S\" has already been set",
  340. lpSection, lpKey);
  341. }
  342. #endif
  343. free(pKeyNode->lpValue);
  344. }
  345. #if DBG
  346. //
  347. // If this is going to an output queue, mark this setting as
  348. // having already been set by the wizard.
  349. //
  350. // Note that when the input queue is copied to the output queue,
  351. // the copy function preserves this setting.
  352. //
  353. pKeyNode->bSetOnce = ( (dwWhichQueue == SETTING_QUEUE_ANSWERS) |
  354. (dwWhichQueue == SETTING_QUEUE_UDF) );
  355. #endif
  356. //
  357. // Put the (possibly new) value in
  358. //
  359. if ( (pKeyNode->lpValue = lstrdup(lpValue)) == NULL )
  360. return FALSE;
  361. return TRUE;
  362. }