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.

817 lines
20 KiB

  1. #include "stdafx.h"
  2. #define MIGRATEINF ".\\migrate.inf"
  3. #define INITIALBUFFERSIZE 1024
  4. #define MIGINF_NOCREATE FALSE
  5. #define MIGINF_CREATE TRUE
  6. typedef struct tagMIGOBJECT MIGOBJECT, *PMIGOBJECT;
  7. struct tagMIGOBJECT {
  8. PSTR Key;
  9. PSTR Value;
  10. PMIGOBJECT Next;
  11. };
  12. typedef struct tagMIGSECTION MIGSECTION, * PMIGSECTION;
  13. struct tagMIGSECTION {
  14. PSTR Name;
  15. PMIGOBJECT Items;
  16. PMIGSECTION Next;
  17. };
  18. PMIGSECTION g_MigrationInf;
  19. POOLHANDLE g_Pool = NULL;
  20. static
  21. PCSTR
  22. pGetTypeAsString (
  23. IN MIGTYPE Type
  24. )
  25. {
  26. //
  27. // Note: Strings must be in the same order as the
  28. // corresponding types in the MIGTYPE enumeration above.
  29. //
  30. static PCHAR typeStrings[] = {
  31. "FIRST - Invalid",
  32. "File",
  33. "Path",
  34. "Registry",
  35. "Message - Invalid",
  36. "LAST - Invalid"
  37. };
  38. assert(Type > MIG_FIRSTTYPE && Type < MIG_LASTTYPE);
  39. return typeStrings[Type];
  40. }
  41. static
  42. PMIGSECTION
  43. pFindSection (
  44. IN PCSTR SectionString,
  45. IN BOOL CreateIfNotExist
  46. )
  47. {
  48. PMIGSECTION rSection;
  49. //
  50. // We assume that SectionString is not null.
  51. //
  52. assert(SectionString);
  53. rSection = g_MigrationInf;
  54. while (rSection && (_mbsicmp((const unsigned char *) rSection -> Name,(const unsigned char *) SectionString) != 0)) {
  55. //
  56. // Continue looking.
  57. //
  58. rSection = rSection -> Next;
  59. }
  60. if (!rSection && CreateIfNotExist) {
  61. //
  62. // No section was found matching this name. Make a new section and add it
  63. // to the list.
  64. //
  65. rSection = (PMIGSECTION) PoolMemGetMemory(g_Pool,sizeof(MIGSECTION));
  66. if (rSection) {
  67. ZeroMemory(rSection,sizeof(MIGSECTION));
  68. rSection -> Name = PoolMemDuplicateStringA(g_Pool,SectionString);
  69. rSection -> Next = g_MigrationInf;
  70. g_MigrationInf = rSection;
  71. if (!rSection -> Name) {
  72. //
  73. // Something went wrong when we tried to duplicate the SectionString.
  74. // NULL out the rSection so that the caller doesn't get back a
  75. // malformed section object.
  76. //
  77. rSection = NULL;
  78. }
  79. }
  80. }
  81. return rSection;
  82. }
  83. static
  84. BOOL
  85. pPathIsInPath(
  86. IN PCSTR SubPath,
  87. IN PCSTR ParentPath
  88. )
  89. {
  90. DWORD parentLength;
  91. BOOL rInPath;
  92. //
  93. // This function assumes both parameters are non-NULL.
  94. //
  95. assert(SubPath);
  96. assert(ParentPath);
  97. parentLength = _mbslen((const unsigned char *) ParentPath);
  98. //
  99. // A path is considered "in" another path if the path is in the ParentPath
  100. // or a subdirectory of it.
  101. //
  102. rInPath = !_mbsnicmp((const unsigned char *) SubPath,(const unsigned char *) ParentPath,parentLength);
  103. if (rInPath) {
  104. rInPath = SubPath[parentLength] == 0 || SubPath[parentLength] == '\\';
  105. }
  106. return rInPath;
  107. }
  108. static
  109. DWORD
  110. pGetMbsSize (
  111. IN LPCSTR String
  112. )
  113. {
  114. DWORD rLength;
  115. //rLength = (DWORD) _mbschr((const unsigned char *) String,0) - (DWORD) String + 1;
  116. rLength = strlen(String + 1);
  117. return rLength;
  118. }
  119. static
  120. LPSTR
  121. pEscapeString (
  122. IN MIGTYPE Type,
  123. OUT LPSTR EscapedString,
  124. IN LPCSTR String
  125. )
  126. {
  127. LPSTR stringStart;
  128. static CHAR exclusions[] = "[]~,;%\"";
  129. INT currentChar;
  130. //
  131. // We assume that all parameters are valid.
  132. //
  133. assert(EscapedString && String);
  134. stringStart = EscapedString;
  135. while (*String) {
  136. currentChar = _mbsnextc ((const unsigned char *) String);
  137. if (Type == MIG_REGKEY) {
  138. //
  139. // Registry keys require more complex escaping than do normal INF strings.
  140. //
  141. if (!_ismbcprint (currentChar) || _mbschr ((const unsigned char *) exclusions, currentChar)) {
  142. //
  143. // Escape unprintable or excluded character
  144. //
  145. wsprintfA (EscapedString, "~%X~", currentChar);
  146. EscapedString = (LPSTR) _mbschr ((const unsigned char *) EscapedString, 0);
  147. String = (LPCSTR) _mbsinc((const unsigned char *) String);
  148. }
  149. else {
  150. //
  151. // Copy multibyte character
  152. //
  153. if (isleadbyte (*String)) {
  154. *EscapedString = *String;
  155. EscapedString++;
  156. String++;
  157. }
  158. *EscapedString = *String;
  159. EscapedString++;
  160. String++;
  161. }
  162. }
  163. else {
  164. //
  165. // Escaping is pretty simple for non-registry keys. All we do is double up
  166. // quotes and percents.
  167. //
  168. if (*String == '\"' || *String == '%') {
  169. *EscapedString = *String;
  170. EscapedString++;
  171. }
  172. //
  173. // Copy multibyte character
  174. //
  175. if (isleadbyte (*String)) {
  176. *EscapedString = *String;
  177. EscapedString++;
  178. String++;
  179. }
  180. *EscapedString = *String;
  181. EscapedString++;
  182. String++;
  183. }
  184. }
  185. //
  186. // Ensure that returned string is NULL terminated.
  187. //
  188. *EscapedString = 0;
  189. return stringStart;
  190. }
  191. static
  192. PSTR
  193. pGetValueString (
  194. IN MIGTYPE ObjectType,
  195. IN LPCSTR StringOne,
  196. IN LPCSTR StringTwo
  197. )
  198. {
  199. static PSTR buffer;
  200. static DWORD bufferSize;
  201. DWORD maxLength;
  202. PSTR bufferEnd;
  203. //
  204. // This function assumes that StringOne exists.
  205. //
  206. assert(StringOne);
  207. if (ObjectType == MIG_REGKEY) {
  208. //
  209. // Size: size of both strings, plus the size of the quotes, plus the size of the brackets
  210. // for the value, * 6. This is the maximum size one of these could grow to, if every
  211. // character had to be escaped out.
  212. //
  213. maxLength = (pGetMbsSize(StringOne) + (StringTwo ? pGetMbsSize(StringTwo) + 2 : 0)) * 6 + 2;
  214. }
  215. else {
  216. //
  217. // Size: size of the string * 2 (The max size if every char was a '%' or '"' plus the quotes.
  218. //
  219. maxLength = pGetMbsSize(StringOne) * 2 + 2;
  220. }
  221. if (maxLength > bufferSize) {
  222. //
  223. // Initialize our buffer, or create a larger one.
  224. //
  225. bufferSize = (maxLength > INITIALBUFFERSIZE) ? maxLength : INITIALBUFFERSIZE;
  226. buffer = PoolMemCreateStringA(g_Pool,bufferSize);
  227. }
  228. if (buffer != NULL) {
  229. //
  230. // Insert initial quote.
  231. //
  232. *buffer = '"';
  233. //
  234. // Massage the string to ensure it is a valid INF file string.
  235. //
  236. pEscapeString(ObjectType,(char *) _mbsinc((const unsigned char *) buffer),StringOne);
  237. //
  238. // If this is a REGISTRY entry, then we also need to add the value part of the string,
  239. // if one was specified (In StringTwo)
  240. //
  241. if (ObjectType == MIG_REGKEY && StringTwo) {
  242. //
  243. // Add the opening bracket.
  244. //
  245. bufferEnd = (PSTR) _mbschr((const unsigned char *) buffer,0);
  246. if (bufferEnd)
  247. {
  248. *bufferEnd = '[';
  249. //
  250. // Add the value string in, again making sure the string is valid for an INF file.
  251. //
  252. pEscapeString(ObjectType,(char *) _mbsinc((const unsigned char *) bufferEnd),StringTwo);
  253. //
  254. // Now, add the closing braket.
  255. //
  256. bufferEnd = (PSTR) _mbschr((const unsigned char *) buffer,0);
  257. if (bufferEnd)
  258. {
  259. *bufferEnd = ']';
  260. //
  261. // Terminate the string.
  262. //
  263. bufferEnd = (PSTR) _mbsinc((const unsigned char *) bufferEnd);
  264. if (bufferEnd) {*bufferEnd = 0;}
  265. }
  266. }
  267. }
  268. //
  269. // Add the final quote.
  270. //
  271. bufferEnd = (PSTR) _mbschr((const unsigned char *) buffer,0);
  272. if (bufferEnd) {*bufferEnd = '"';}
  273. bufferEnd = (PSTR) _mbsinc((const unsigned char *) bufferEnd);
  274. if (bufferEnd) {*bufferEnd = 0;}
  275. }
  276. return buffer;
  277. }
  278. static
  279. BOOL
  280. pCreateMigObject (
  281. IN MIGTYPE ObjectType,
  282. IN PCSTR ParamOne,
  283. IN PCSTR ParamTwo,
  284. IN PMIGSECTION Section
  285. )
  286. {
  287. BOOL rSuccess = FALSE;
  288. PMIGOBJECT newObject = NULL;
  289. PSTR pTemp = NULL;
  290. //
  291. // pCreateMigObject uses a set of hueristics to correctly assemble an object.
  292. // These hueristics are based on the ObjectType and the contents of ParamTwo.
  293. //
  294. // ObjectType ParamTwo Key Value
  295. // -------------------------------------------------------------------------
  296. // MIG_REGKEY <any> ParamOne[ParamTwo] Registry
  297. // <other> NULL ParamOne <ObjectType As String>
  298. // <other> non-NULL ParamOne ParamTwo
  299. //
  300. //
  301. if (Section) {
  302. //
  303. // First, create an object...
  304. //
  305. newObject = (PMIGOBJECT) PoolMemGetMemory(g_Pool,sizeof(MIGOBJECT));
  306. if (newObject) {
  307. if (ObjectType == MIG_REGKEY) {
  308. pTemp = pGetValueString(ObjectType,ParamOne,ParamTwo);
  309. if (pTemp)
  310. {newObject -> Key = PoolMemDuplicateStringA(g_Pool,pTemp);}
  311. else
  312. {
  313. // out of memory
  314. goto pCreateMigObject_Exit;
  315. }
  316. newObject -> Value = PoolMemDuplicateStringA(g_Pool,pGetTypeAsString(ObjectType));
  317. }
  318. else {
  319. pTemp = pGetValueString(ObjectType,ParamOne,NULL);
  320. if (pTemp)
  321. {newObject -> Key = PoolMemDuplicateStringA(g_Pool,pTemp);}
  322. else
  323. {
  324. // out of memory
  325. goto pCreateMigObject_Exit;
  326. }
  327. if (ParamTwo) {
  328. pTemp = pGetValueString(ObjectType,ParamTwo,NULL);
  329. if (pTemp)
  330. {newObject -> Value = PoolMemDuplicateStringA(g_Pool,pTemp);}
  331. else
  332. {
  333. // out of memory
  334. goto pCreateMigObject_Exit;
  335. }
  336. }
  337. else {
  338. newObject -> Value = PoolMemDuplicateStringA(g_Pool,pGetTypeAsString(ObjectType));
  339. }
  340. }
  341. }
  342. }
  343. if (newObject)
  344. {
  345. if (newObject -> Key && newObject -> Value) {
  346. //
  347. // The object has been successfully created. Link it into the section.
  348. //
  349. newObject -> Next = Section -> Items;
  350. Section -> Items = newObject;
  351. rSuccess = TRUE;
  352. }
  353. else {
  354. rSuccess = FALSE;
  355. }
  356. }
  357. else {
  358. rSuccess = FALSE;
  359. }
  360. pCreateMigObject_Exit:
  361. return rSuccess;
  362. }
  363. static
  364. BOOL
  365. pWriteInfSectionToDisk (
  366. IN PMIGSECTION Section
  367. )
  368. {
  369. PMIGOBJECT curObject;
  370. BOOL rSuccess = TRUE;
  371. if (Section) {
  372. curObject = Section -> Items;
  373. while (curObject && rSuccess) {
  374. if (Section -> Name && curObject -> Key && curObject -> Value) {
  375. rSuccess = WritePrivateProfileString(
  376. Section -> Name,
  377. curObject -> Key,
  378. curObject -> Value,
  379. MIGRATEINF
  380. );
  381. }
  382. curObject = curObject -> Next;
  383. }
  384. }
  385. else {
  386. rSuccess = FALSE;
  387. }
  388. return rSuccess;
  389. }
  390. static
  391. BOOL
  392. pBuildListFromSection (
  393. IN PCSTR SectionString
  394. )
  395. {
  396. HINF infHandle;
  397. PMIGSECTION section;
  398. PMIGOBJECT currentObject;
  399. INFCONTEXT ic;
  400. DWORD size;
  401. BOOL rSuccess = TRUE;
  402. //
  403. // This function assumes that Section is non-NULL.
  404. //
  405. assert(SectionString);
  406. currentObject = NULL;
  407. //
  408. // First find the section specified.
  409. //
  410. section = pFindSection(SectionString,MIGINF_CREATE);
  411. if (section) {
  412. infHandle = SetupOpenInfFileA(MIGRATEINF,NULL,INF_STYLE_WIN4,NULL);
  413. if (infHandle != INVALID_HANDLE_VALUE) {
  414. if (SetupFindFirstLine(infHandle,SectionString,NULL,&ic)) {
  415. do {
  416. //
  417. // Create the object.
  418. //
  419. currentObject = (PMIGOBJECT) PoolMemGetMemory(g_Pool,sizeof(MIGOBJECT));
  420. if (!currentObject) {
  421. rSuccess = FALSE;
  422. break;
  423. }
  424. //
  425. // Get the size of the string.
  426. //
  427. if (!SetupGetLineTextA(&ic,NULL,NULL,NULL,NULL,0,&size)) {
  428. rSuccess = FALSE;
  429. break;
  430. }
  431. //
  432. // Create a string large enough.
  433. //
  434. currentObject -> Key = PoolMemCreateStringA(g_Pool,size);
  435. if (!currentObject -> Key) {
  436. rSuccess = FALSE;
  437. break;
  438. }
  439. //
  440. // Get the string.
  441. //
  442. if (!SetupGetLineTextA(&ic,NULL,NULL,NULL,currentObject -> Key,size,NULL)) {
  443. rSuccess = FALSE;
  444. break;
  445. }
  446. //
  447. // Successfully retrieved the line.
  448. //
  449. currentObject -> Value = (PSTR) pGetTypeAsString(MIG_FILE);
  450. currentObject -> Next = section -> Items;
  451. section -> Items = currentObject;
  452. } while(SetupFindNextLine(&ic,&ic));
  453. }
  454. SetupCloseInfFile(infHandle);
  455. }
  456. }
  457. else {
  458. rSuccess = FALSE;
  459. }
  460. return rSuccess;
  461. }
  462. BOOL
  463. WINAPI
  464. MigInf_Initialize(
  465. VOID
  466. )
  467. {
  468. //
  469. // First, initialize our pool and Zero out the structure.
  470. //
  471. g_Pool = PoolMemInitPool();
  472. if (g_Pool) {
  473. //
  474. // Now, read in the migration paths and excluded paths sections.
  475. //
  476. if (!pBuildListFromSection(SECTION_MIGRATIONPATHS) ||
  477. !pBuildListFromSection(SECTION_EXCLUDEDPATHS)) {
  478. //
  479. // Something went wrong (i.e. out of memory. Destroy and NULL our pool.
  480. //
  481. PoolMemDestroyPool(g_Pool);
  482. g_Pool = NULL;
  483. }
  484. }
  485. //
  486. // If our memory pool initialized successfully, return TRUE.
  487. //
  488. return (g_Pool != NULL);
  489. }
  490. VOID
  491. WINAPI
  492. MigInf_CleanUp (
  493. VOID
  494. )
  495. {
  496. //
  497. // Only thing we need to do is clean out pool mem. We'll NULL out the list header to make
  498. // sure it isn't usable.
  499. //
  500. if (g_Pool) {
  501. PoolMemDestroyPool(g_Pool);
  502. g_Pool = NULL;
  503. }
  504. g_MigrationInf = NULL;
  505. }
  506. BOOL
  507. WINAPI
  508. MigInf_AddObject (
  509. IN MIGTYPE ObjectType,
  510. IN PCSTR SectionString,
  511. IN PCSTR ParamOne,
  512. IN PCSTR ParamTwo
  513. )
  514. {
  515. return pCreateMigObject(
  516. ObjectType,
  517. ParamOne,
  518. ParamTwo,
  519. pFindSection(SectionString,MIGINF_CREATE)
  520. );
  521. }
  522. BOOL
  523. WINAPI
  524. MigInf_FirstInSection(
  525. IN PCSTR SectionName,
  526. OUT PMIGINFSECTIONENUM Enum
  527. )
  528. {
  529. PMIGSECTION section;
  530. //
  531. // We assume that Enum is valid.
  532. //
  533. assert(Enum);
  534. section = pFindSection(SectionName,MIGINF_NOCREATE);
  535. if (section) {
  536. Enum -> EnumKey = (PVOID) section -> Items;
  537. }
  538. return MigInf_NextInSection(Enum);
  539. }
  540. BOOL
  541. WINAPI
  542. MigInf_NextInSection(
  543. IN OUT PMIGINFSECTIONENUM Enum
  544. )
  545. {
  546. BOOL rSuccess = FALSE;
  547. //
  548. // We assume that the Enum is valid.
  549. //
  550. assert(Enum);
  551. if (Enum -> EnumKey) {
  552. Enum -> Key = ((PMIGOBJECT) (Enum -> EnumKey)) -> Key;
  553. Enum -> Value = ((PMIGOBJECT) (Enum -> EnumKey)) -> Value;
  554. Enum -> EnumKey = ((PVOID) ((PMIGOBJECT) (Enum -> EnumKey)) -> Next);
  555. rSuccess = TRUE;
  556. }
  557. return rSuccess;
  558. }
  559. BOOL
  560. WINAPI
  561. MigInf_WriteInfToDisk (
  562. VOID
  563. )
  564. {
  565. BOOL rSuccess = TRUE;
  566. PMIGSECTION curSection;
  567. //
  568. // Simply loop through all of the sections, writing each of them to disk.
  569. // As long as WriteSectionToDisk works, we work.
  570. //
  571. curSection = g_MigrationInf;
  572. while (curSection && rSuccess) {
  573. //
  574. // We skip the [Excluded Paths] and [Migration Paths] sections.
  575. //
  576. if (_mbsicmp((const unsigned char *) curSection -> Name,(const unsigned char *) SECTION_EXCLUDEDPATHS) &&
  577. _mbsicmp((const unsigned char *) curSection -> Name,(const unsigned char *) SECTION_MIGRATIONPATHS)) {
  578. rSuccess = pWriteInfSectionToDisk(curSection);
  579. }
  580. curSection = curSection -> Next;
  581. }
  582. return rSuccess;
  583. }
  584. BOOL
  585. WINAPI
  586. MigInf_PathIsExcluded (
  587. IN PCSTR Path
  588. )
  589. {
  590. PMIGOBJECT curExcluded;
  591. PMIGSECTION section;
  592. BOOL rIsExcluded = FALSE;
  593. //
  594. // We assume Path is valid.
  595. //
  596. assert(Path);
  597. section = pFindSection(SECTION_EXCLUDEDPATHS,MIGINF_NOCREATE);
  598. if (section) {
  599. curExcluded = section -> Items;
  600. while (curExcluded && !rIsExcluded) {
  601. rIsExcluded = pPathIsInPath(Path,curExcluded -> Key);
  602. curExcluded = curExcluded -> Next;
  603. }
  604. }
  605. return rIsExcluded;
  606. }
  607. PCSTR
  608. WINAPI
  609. MigInf_GetNewSectionName (
  610. VOID
  611. )
  612. {
  613. static CHAR sectionName[20];
  614. static DWORD seedNum=0;
  615. sprintf(sectionName,"msg%0.7u",seedNum++);
  616. return sectionName;
  617. }
  618. BOOL IsUpgradeTargetSupportIIS(LPCSTR szMyAnswerFile)
  619. {
  620. BOOL bReturn = TRUE;
  621. char szPlatformString[_MAX_PATH];
  622. if (GetPrivateProfileString("Version", "SetupSKU", _T(""), szPlatformString, _MAX_PATH, szMyAnswerFile))
  623. {
  624. if (*szPlatformString)
  625. {
  626. iisDebugOut(_T("[%s] [Version] SetupSKU=%s"), szMyAnswerFile,szPlatformString);
  627. if (0 == _mbsicmp((const unsigned char *) szPlatformString,(const unsigned char *) "Personal"))
  628. {
  629. bReturn = FALSE;
  630. }
  631. }
  632. }
  633. if (TRUE == bReturn)
  634. {
  635. // check a different key
  636. if (GetPrivateProfileString("Version", "SetupPlatform", _T(""), szPlatformString, _MAX_PATH, szMyAnswerFile))
  637. {
  638. if (*szPlatformString)
  639. {
  640. iisDebugOut(_T("[%s] [Version] SetupPlatform=%s"), szMyAnswerFile,szPlatformString);
  641. if (0 == _mbsicmp((const unsigned char *) szPlatformString,(const unsigned char *) "Personal"))
  642. {
  643. bReturn = FALSE;
  644. }
  645. }
  646. }
  647. }
  648. return bReturn;
  649. }