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.

3148 lines
89 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. wowlist.c
  5. Abstract:
  6. This module implements a program that determines which files in an NT
  7. product INF should be installed as wow files. It then builds a list
  8. of these files that can be appended to other sections in a master inf.
  9. The input to the program consists of a filtered NT product INF (for example
  10. the layout.inf for i386, all products), and a control INF that specifies
  11. mappings and rules about how to migrate files.
  12. Author:
  13. Andrew Ritz (andrewr) 24-Nov-1999 Created It.
  14. Revision History:
  15. ATM Shafiqul Khalid(askhalid) 27-April-2001
  16. Make changes in HandleSetupapiQuotingForString() to add double
  17. quote if the string contains ','.
  18. --*/
  19. #include <windows.h>
  20. #include <tchar.h>
  21. #include <stdio.h>
  22. #include <setupapi.h>
  23. #include <sputils.h>
  24. #include <shlwapi.h>
  25. #if DBG
  26. VOID
  27. AssertFail(
  28. IN PSTR FileName,
  29. IN UINT LineNumber,
  30. IN PSTR Condition
  31. )
  32. {
  33. int i;
  34. CHAR Name[MAX_PATH];
  35. PCHAR p;
  36. CHAR Msg[MAX_INF_STRING_LENGTH];
  37. //
  38. // Use dll name as caption
  39. //
  40. GetModuleFileNameA(NULL,Name,MAX_PATH);
  41. if(p = strrchr(Name,'\\')) {
  42. p++;
  43. } else {
  44. p = Name;
  45. }
  46. wsprintfA(
  47. Msg,
  48. "Assertion failure at line %u in file %s: %s\n\nCall DebugBreak()?",
  49. LineNumber,
  50. FileName,
  51. Condition
  52. );
  53. OutputDebugStringA(Msg);
  54. i = MessageBoxA(
  55. NULL,
  56. Msg,
  57. p,
  58. MB_YESNO | MB_TASKMODAL | MB_ICONSTOP | MB_SETFOREGROUND
  59. );
  60. if(i == IDYES) {
  61. DebugBreak();
  62. }
  63. }
  64. #define MYASSERT(x) if(!(x)) { AssertFail(__FILE__,__LINE__,#x); }
  65. #else
  66. #define MYASSERT( exp )
  67. #endif // DBG
  68. //
  69. // String Macros
  70. //
  71. #define AS(x) ( sizeof(x) / sizeof(x[0]) )
  72. #define LSTRCPY(x,y) ( lstrcpyn(x, y, AS(x)) )
  73. #define LSTRCAT(x,y) ( lstrcpyn(x + lstrlen(x), y, AS(x) - lstrlen(x)) )
  74. //
  75. // backward-compatible depreciated export from setupapi.dll
  76. //
  77. BOOL
  78. SetupGetInfSections (
  79. IN HINF InfHandle,
  80. OUT PTSTR Buffer, OPTIONAL
  81. IN UINT Size, OPTIONAL
  82. OUT UINT *SizeNeeded OPTIONAL
  83. );
  84. //
  85. // Define program result codes (returned from main()).
  86. //
  87. #define SUCCESS 0
  88. #define FAILURE 1
  89. typedef enum _WOWLISTACTION {
  90. BuildCopyList,
  91. BuildOLEList,
  92. BuildSetupINF,
  93. WowListMax
  94. } WOWLISTACTION;
  95. #define KEYWORD_COPYFILES 0x00000001
  96. #define KEYWORD_DELFILES 0x00000002
  97. #define KEYWORD_RENFILES 0x00000004
  98. #define KEYWORD_REGISTERDLLS 0x00000008
  99. #define KEYWORD_UNREGISTERDLLS 0x00000010
  100. #define KEYWORD_ADDREG 0x00000020
  101. #define KEYWORD_DELREG 0x00000040
  102. #define KEYWORD_NEEDDESTDIRS (KEYWORD_COPYFILES | KEYWORD_DELFILES | KEYWORD_RENFILES)
  103. #define KEYWORD_NEEDLAYOUTDATA (KEYWORD_COPYFILES)
  104. #define KEYWORD_NEEDFILENAME (KEYWORD_COPYFILES)
  105. PCTSTR KeywordArray[] = {
  106. TEXT("CopyFiles"),
  107. TEXT("DelFiles"),
  108. TEXT("RenFiles"),
  109. TEXT("RegisterDlls"),
  110. TEXT("UnRegisterDlls"),
  111. TEXT("AddReg"),
  112. TEXT("DelReg")
  113. } ;
  114. #define INDEX_COPYFILES 0
  115. #define INDEX_DELFILES 1
  116. #define INDEX_RENFILES 2
  117. #define INDEX_REGISTERDLLS 3
  118. #define INDEX_UNREGISTERDLLS 4
  119. #define INDEX_ADDREG 5
  120. #define INDEX_DELREG 6
  121. typedef struct _PERSECTION_CONTEXT {
  122. //
  123. // remember the destinationdir that we're outputting to
  124. //
  125. DWORD DestinationDir;
  126. //
  127. // remember the keywords we're processing
  128. //
  129. DWORD KeywordVector;
  130. } PERSECTION_CONTEXT, *PPERSECTION_CONTEXT;
  131. typedef struct _SETUPINF_CONTEXT {
  132. FILE * OutFile;
  133. FILE * OutLayoutFile;
  134. FILE * OutInfLayoutFile;
  135. HINF hControlInf;
  136. HINF hInputInf;
  137. BOOL AlreadyOutputKeyword;
  138. } SETUPINF_CONTEXT, *PSETUPINF_CONTEXT;
  139. typedef struct _SUBST_STRING {
  140. PTSTR InputString;
  141. PTSTR SourceInputString;
  142. PTSTR OutputString;
  143. } SUBST_STRING,*PSUBST_STRING;
  144. //
  145. // note that WOW64 does file system redirection of system32, but it does NOT do
  146. // redirection of program files, etc. So we must substitute in the 32 bit
  147. // environment variables in those cases where WOW64 does not do it for us
  148. // automatically
  149. //
  150. SUBST_STRING StringArray[] = {
  151. //
  152. // order of these 2 is important!
  153. //
  154. { NULL, TEXT("%SystemRoot%\\system32"), TEXT("%16425%") },
  155. { NULL, TEXT("%SystemRoot%"), TEXT("%10%") },
  156. //
  157. // order of these 2 is important!
  158. //
  159. { NULL, TEXT("%CommonProgramFiles%"), TEXT("%16428%") },
  160. { NULL, TEXT("%ProgramFiles%"), TEXT("%16426%") },
  161. { NULL, TEXT("%SystemDrive%"), TEXT("%30%") }
  162. } ;
  163. PSUBST_STRING StringList;
  164. //
  165. // Keep statistics...
  166. //
  167. INT ProcessedLines = 0;
  168. TCHAR InputInf[MAX_PATH];
  169. TCHAR ControlInf[MAX_PATH];
  170. TCHAR OLEInputInf[MAX_PATH];
  171. PCTSTR OutputFile;
  172. PCTSTR OutputLayoutFile = NULL;
  173. PCTSTR HeaderText;
  174. PCTSTR OLESection;
  175. PCTSTR FilePrefix;
  176. PCTSTR SectionDecoration;
  177. PCTSTR ThisProgramName;
  178. WOWLISTACTION Action = WowListMax;
  179. BOOL fDoAnsiOutput = TRUE;
  180. BOOL fDoVerboseDebugOutput = FALSE;
  181. BOOL g_PostBuild = FALSE;
  182. PCTSTR OutputInfLayoutFile = NULL;
  183. //
  184. // a global scratch buffer for getting a decorated sectionname
  185. //
  186. TCHAR DecoratedSectionName[MAX_PATH];
  187. //
  188. // global scratch buffer for line data
  189. //
  190. TCHAR LineText[MAX_INF_STRING_LENGTH];
  191. TCHAR ScratchText[MAX_INF_STRING_LENGTH];
  192. TCHAR ScratchTextEnv[MAX_INF_STRING_LENGTH];
  193. PSUBST_STRING InitializeStringList(
  194. VOID
  195. )
  196. {
  197. DWORD SizeNeeded,i;
  198. PSUBST_STRING StringList;
  199. SizeNeeded = (sizeof(StringArray)/sizeof(SUBST_STRING)) *
  200. (sizeof(SUBST_STRING)+(MAX_PATH*sizeof(TCHAR)));
  201. StringList = pSetupMalloc( SizeNeeded );
  202. if (!StringList) {
  203. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  204. return(NULL);
  205. }
  206. RtlCopyMemory( StringList, &StringArray, sizeof(StringArray) );
  207. for (i = 0; i < sizeof(StringArray)/sizeof(SUBST_STRING); i++) {
  208. StringList[i].InputString = (PTSTR) ((PBYTE)StringList + (ULONG_PTR)sizeof(StringArray)+(i*sizeof(TCHAR)*MAX_PATH));
  209. ExpandEnvironmentStrings( StringList[i].SourceInputString, StringList[i].InputString, MAX_PATH );
  210. }
  211. return StringList;
  212. }
  213. PTSTR
  214. MyGetDecoratedSectionName(
  215. HINF ControlInfHandle,
  216. PCTSTR String
  217. )
  218. {
  219. INFCONTEXT Context;
  220. _tcscpy(DecoratedSectionName,String);
  221. if (SectionDecoration){
  222. _tcscat(DecoratedSectionName,TEXT("."));
  223. _tcscat(DecoratedSectionName,SectionDecoration);
  224. if( !SetupFindFirstLine(
  225. ControlInfHandle,
  226. DecoratedSectionName,
  227. NULL,
  228. &Context)){
  229. _tcscpy(DecoratedSectionName,String);
  230. }
  231. }
  232. return DecoratedSectionName;
  233. }
  234. void
  235. FixupSetupapiPercents(
  236. IN OUT PTSTR String
  237. )
  238. /*++
  239. Routine Description:
  240. This routine doubles up the '%' char if present in the input string.
  241. Arguments:
  242. String - input string to be searched. We edit this string
  243. in-place if we find a match.
  244. Return Value:
  245. Boolean indicating outcome.
  246. --*/
  247. {
  248. PTCHAR p,q;
  249. if( !String || !String[0] )
  250. return;
  251. p = String;
  252. q = ScratchTextEnv;
  253. ZeroMemory(ScratchTextEnv,sizeof(ScratchTextEnv));
  254. while( *p && (q < (ScratchTextEnv+MAX_INF_STRING_LENGTH-1)) ){
  255. if (*p == TEXT('%')) {
  256. *(q++) = TEXT('%');
  257. }
  258. *q = *p;
  259. p++;
  260. q++;
  261. }
  262. *q = 0;
  263. lstrcpy( String, ScratchTextEnv );
  264. return;
  265. }
  266. BOOL
  267. pSubstituteEnvVarsForActualPaths(
  268. IN OUT PTSTR String
  269. )
  270. /*++
  271. Routine Description:
  272. This routine filters and outputs the input line. It looks for a string
  273. pattern that matches one of a known list of strings, and replaces the
  274. known string with a substitution string.
  275. Arguments:
  276. String - input string to be searched. We edit this string
  277. in-place if we find a match.
  278. Return Value:
  279. Boolean indicating outcome.
  280. --*/
  281. {
  282. BOOL RetVal = TRUE;
  283. if (!StringList) {
  284. StringList = InitializeStringList();
  285. if (!StringList) {
  286. RetVal = FALSE;
  287. }
  288. }
  289. if (RetVal) {
  290. DWORD i;
  291. PTSTR p,q;
  292. TCHAR c;
  293. MYASSERT( StringList != NULL );
  294. for (i = 0; i< sizeof(StringArray)/sizeof(SUBST_STRING); i++) {
  295. if (p = StrStrI(String,StringList[i].InputString)) {
  296. //
  297. // if we found a hit, then find the end of the string
  298. // and concatenate that to our source string, which gives
  299. // the resultant string with substitutions.
  300. //
  301. q = p + _tcslen(StringList[i].InputString);
  302. c = *p;
  303. *p = TEXT('\0');
  304. _tcscpy(ScratchTextEnv,String);
  305. *p = c;
  306. _tcscat(ScratchTextEnv,StringList[i].OutputString);
  307. _tcscat(ScratchTextEnv,q);
  308. _tcscpy(String,ScratchTextEnv);
  309. //
  310. // recursively call in case there are more strings.
  311. //
  312. pSubstituteEnvVarsForActualPaths(String);
  313. break;
  314. }
  315. }
  316. }
  317. return(RetVal);
  318. }
  319. BOOL
  320. MyGetFilePrefix(
  321. HINF ControlInfHandle,
  322. PCTSTR Filename,
  323. PTSTR Prefix
  324. )
  325. {
  326. TCHAR Entry[MAX_PATH];
  327. INFCONTEXT ControlContext;
  328. if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("MyGetFilePrefix: Called for %s\n"), Filename);
  329. if( !Filename || !Prefix ) {
  330. _ftprintf(stderr, TEXT("MyGetFilePrefix: Filename or prefix bad - Filename - %s\n"), Filename);
  331. return FALSE;
  332. }
  333. if( !FilePrefix ){
  334. Prefix[0] = (TCHAR)NULL;
  335. }else{
  336. lstrcpy( Prefix, FilePrefix );
  337. }
  338. if (SetupFindFirstLine(
  339. ControlInfHandle,
  340. TEXT("NativeDataToWowData.FilePrefixList"),
  341. Filename,
  342. &ControlContext)) {
  343. if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("MyGetFilePrefix: SetupFindFirstLine succeeded for %s\n"), Filename);
  344. if (!SetupGetStringField(&ControlContext,1,Entry,sizeof(Entry)/sizeof(TCHAR),NULL)) {
  345. _ftprintf(stderr, TEXT("MyGetFilePrefix():SetupGetStringField [%s] failed, ec = 0x%08x\n"),Filename,GetLastError());
  346. }else{
  347. lstrcpy( Prefix, Entry );
  348. }
  349. }else{
  350. if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("MyGetFilePrefix: SetupFindFirstLine failed for %s - ec = 0x%08x\n"), Filename,GetLastError());
  351. }
  352. return TRUE;
  353. }
  354. BOOL
  355. ParseArgs(
  356. IN int argc,
  357. IN TCHAR *argv[]
  358. )
  359. /*++
  360. Routine Description:
  361. This function reads the cmdline, translating arguments into the appropriate
  362. global variable.
  363. Arguments:
  364. argc - number of arguments from main().
  365. argv - argument array.
  366. Return Value:
  367. Boolean value, true indicates that the cmdline arguments are valid.
  368. --*/
  369. {
  370. int i;
  371. PTSTR p;
  372. ThisProgramName = argv[0];
  373. if(argc < 4) {
  374. return(FALSE);
  375. }
  376. for (i = 0; i < argc; i++) {
  377. if (argv[i][0] == TEXT('-')) {
  378. switch (tolower(argv[i][1])) {
  379. case TEXT('a'):
  380. switch(tolower(argv[i][2])) {
  381. case TEXT('c'):
  382. Action = BuildCopyList;
  383. break;
  384. case TEXT('o'):
  385. Action = BuildOLEList;
  386. break;
  387. case TEXT('s'):
  388. Action = BuildSetupINF;
  389. break;
  390. default:
  391. _ftprintf(stderr, TEXT("unknown arg %s\n"),argv[i]);
  392. return(FALSE);
  393. }
  394. break;
  395. case TEXT('c'):
  396. GetFullPathName(argv[i+1],sizeof(ControlInf)/sizeof(TCHAR),ControlInf,&p);
  397. break;
  398. case TEXT('d'):
  399. OutputLayoutFile = argv[i+1];
  400. break;
  401. case TEXT('f'):
  402. FilePrefix = argv[i+1];
  403. break;
  404. case TEXT('g'):
  405. SectionDecoration = argv[i+1];
  406. break;
  407. case TEXT('h'):
  408. HeaderText = argv[i+1];
  409. break;
  410. case TEXT('i'):
  411. GetFullPathName(argv[i+1],sizeof(InputInf)/sizeof(TCHAR),InputInf,&p);
  412. break;
  413. case TEXT('l'):
  414. GetFullPathName(argv[i+1],sizeof(OLEInputInf)/sizeof(TCHAR),OLEInputInf,&p);
  415. break;
  416. case TEXT('n'):
  417. OutputInfLayoutFile = argv[i+1];
  418. break;
  419. case TEXT('o'):
  420. OutputFile = argv[i+1];
  421. break;
  422. case TEXT('p'):
  423. g_PostBuild = TRUE;
  424. break;
  425. case TEXT('s'):
  426. OLESection = argv[i+1];
  427. break;
  428. case TEXT('u'):
  429. fDoAnsiOutput = FALSE;
  430. break;
  431. case TEXT('v'):
  432. fDoVerboseDebugOutput = TRUE;
  433. break;
  434. default:
  435. _ftprintf(stderr, TEXT("unknown arg %s\n"),argv[i]);
  436. return(FALSE);
  437. }
  438. }
  439. }
  440. _ftprintf(stderr, TEXT("%s\n"),InputInf);
  441. if (Action == WowListMax) {
  442. return(FALSE);
  443. }
  444. return(TRUE);
  445. }
  446. int
  447. myftprintf(
  448. FILE * FileHandle,
  449. BOOL AnsiOutput,
  450. PCTSTR FormatString,
  451. ...
  452. )
  453. {
  454. va_list arglist;
  455. TCHAR text[MAX_INF_STRING_LENGTH];
  456. DWORD d;
  457. int retval;
  458. va_start(arglist,FormatString);
  459. _vstprintf(text,FormatString,arglist);
  460. #ifdef UNICODE
  461. if (AnsiOutput) {
  462. PCSTR TextA = pSetupUnicodeToAnsi(text);
  463. retval = fputs(TextA,FileHandle);
  464. pSetupFree(TextA);
  465. } else {
  466. PWSTR p,q;
  467. // Assume we opened the file in binary mode for Unicode stream I/O
  468. p = text;
  469. while(1){
  470. if( q = wcschr( p, L'\n' )){
  471. *q=L'\0';
  472. retval = fputws(p,FileHandle);
  473. retval = fputws(L"\r\n", FileHandle);
  474. if( *(q+1) )
  475. p = q+1;
  476. else
  477. break;
  478. }else{
  479. retval = fputws(p,FileHandle);
  480. break;
  481. }
  482. }
  483. }
  484. #else
  485. if (AnsiOutput) {
  486. retval = fputs(text,FileHandle);
  487. } else{
  488. PCWSTR TextW = pSetupAnsiToUnicode(text);
  489. retval = fputws(TextW,FileHandle);
  490. pSetupFree(TextW);
  491. }
  492. #endif
  493. return(retval);
  494. }
  495. BOOL
  496. AppendWowFileToCopyList(
  497. IN HINF hControlInf,
  498. IN PINFCONTEXT LineContext,
  499. IN FILE *OutFile
  500. )
  501. /*++
  502. Routine Description:
  503. This routine appends the file specified by LineContext to the output file,
  504. writing the data in a form required by textmode setup. see layout.inx for
  505. a detailed description of this syntax.
  506. Arguments:
  507. hControlInf - inf handle that contains control directives.
  508. LineContext - inf context from layout.inf for the file we want to output.
  509. OutFile - file handle to write the data into
  510. Return Value:
  511. Boolean value, true indicates the file was properly written.
  512. --*/
  513. {
  514. TCHAR LineText[MAX_INF_STRING_LENGTH];
  515. TCHAR TempFileName[MAX_PATH], FileName[MAX_PATH], Prefix[40];
  516. BOOL RetVal;
  517. DWORD EntryCount,i;
  518. ZeroMemory(LineText,sizeof(LineText));
  519. ZeroMemory(Prefix,sizeof(Prefix));
  520. //
  521. // get the filename
  522. //
  523. if (!SetupGetStringField(
  524. LineContext,
  525. 0,
  526. TempFileName,
  527. sizeof(TempFileName)/sizeof(TCHAR),
  528. NULL)) {
  529. _ftprintf(stderr, TEXT("SetupGetStringField failed, ec = 0x%08x\n"),GetLastError());
  530. RetVal = FALSE;
  531. goto exit;
  532. }
  533. if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("Current File - %s\n"),TempFileName);
  534. MyGetFilePrefix( hControlInf, TempFileName, Prefix );
  535. _tcscpy(FileName, Prefix);
  536. _tcscat(FileName, TempFileName );
  537. EntryCount = SetupGetFieldCount(LineContext);
  538. for (i = 1; i<=EntryCount; i++) {
  539. TCHAR Entry[40];
  540. INFCONTEXT ControlContext;
  541. //
  542. // get the current text to be appended
  543. //
  544. if (!SetupGetStringField(LineContext,i,Entry,sizeof(Entry)/sizeof(TCHAR),NULL)) {
  545. _ftprintf(stderr, TEXT("SetupGetStringField [%s] failed, ec = 0x%08x\n"),FileName,GetLastError());
  546. RetVal = FALSE;
  547. goto exit;
  548. }
  549. //
  550. // now do any necessary substitutions
  551. //
  552. //
  553. // SourceDisksNames substitution
  554. //
  555. if (i == 1) {
  556. //
  557. // look in the appropriate control inf section for the data
  558. //
  559. if (!SetupFindFirstLine(
  560. hControlInf,
  561. TEXT("NativeDataToWowData.SourceInfo"),
  562. Entry,
  563. &ControlContext)) {
  564. _ftprintf(stderr, TEXT("SetupFindFirstLine [%s] failed, ec = 0x%08x\n"),FileName,GetLastError());
  565. RetVal = FALSE;
  566. goto exit;
  567. }
  568. if (!SetupGetStringField(&ControlContext,1,Entry,sizeof(Entry)/sizeof(TCHAR),NULL)) {
  569. _ftprintf(stderr, TEXT("SetupGetStringField [%s] failed, ec = 0x%08x\n"),FileName,GetLastError());
  570. RetVal = FALSE;
  571. goto exit;
  572. }
  573. }
  574. //
  575. // Directory Id substitution
  576. //
  577. if (i == 8) {
  578. //
  579. // look in the appropriate control inf section for the data
  580. //
  581. if (!SetupFindFirstLine(
  582. hControlInf,
  583. TEXT("NativeDataToWowData.DirectoryInformation.Textmode"),
  584. Entry,
  585. &ControlContext)) {
  586. _ftprintf(stderr, TEXT("SetupFindFirstLine [%s] failed, ec = 0x%08x\n"),FileName,GetLastError());
  587. RetVal = FALSE;
  588. goto exit;
  589. }
  590. if (!SetupGetStringField(&ControlContext,1,Entry,sizeof(Entry)/sizeof(TCHAR),NULL)) {
  591. _ftprintf(stderr, TEXT("SetupGetStringField [%s] failed, ec = 0x%08x\n"),FileName,GetLastError());
  592. RetVal = FALSE;
  593. goto exit;
  594. }
  595. }
  596. //
  597. // filename rename
  598. //
  599. if (i == 11) {
  600. //
  601. // if there was already a renaming to be done, then just use that.
  602. // otherwise we may have to add a rename entry if there was a
  603. // filename prefix
  604. //
  605. if (Entry[0] == (TCHAR)NULL) {
  606. if (Prefix[0]) {
  607. _tcsncpy(Entry, TempFileName, AS(Entry));
  608. }
  609. }
  610. }
  611. _tcscat(LineText, Entry);
  612. //
  613. // now append a comma if necessary
  614. //
  615. if (i !=EntryCount) {
  616. _tcscat(LineText, TEXT(","));
  617. }
  618. //
  619. // filename rename
  620. //
  621. if (EntryCount < 11 && i == EntryCount) {
  622. //
  623. // if there is no renaming to be done, we may have to add a rename
  624. // entry if there was a filename prefix
  625. //
  626. if (Prefix[0]) {
  627. DWORD j;
  628. for (j=i;j<11;j++) {
  629. _tcscat(LineText, TEXT(","));
  630. }
  631. _tcscat(LineText, TempFileName);
  632. }
  633. }
  634. }
  635. if( g_PostBuild ){
  636. myftprintf(OutFile, fDoAnsiOutput, TEXT("%s:%s=%s\n"),TempFileName,FileName,LineText);
  637. }else{
  638. myftprintf(OutFile, fDoAnsiOutput, TEXT("%s=%s\n"),FileName,LineText);
  639. }
  640. RetVal = TRUE;
  641. exit:
  642. return(RetVal);
  643. }
  644. BOOL
  645. AppendWowFileToOLEList(
  646. IN HINF hControlInf,
  647. IN HINF hOLEInputInf,
  648. IN PINFCONTEXT LineContext,
  649. IN FILE *OutFile
  650. )
  651. /*++
  652. Routine Description:
  653. This routine appends the file specified by LineContext to the output file,
  654. writing the data in OLE Registration form.
  655. OLE Registration form is as follows:
  656. <DIRID>,<subdir>,filename,[flags]
  657. where <DIRID> is a standard setupapi DIRID; <subdir> is optional and
  658. represents a subdir of the given directory; filename is the name
  659. of the dll.
  660. Arguments:
  661. hControlInf - inf handle that contains control directives.
  662. hOLEInputInf - inf handle that contains OLE list information.
  663. LineContext - inf context from layout.inf for the file we want to output.
  664. OutFile - file handle to write the data into
  665. Return Value:
  666. Boolean value, true indicates the file was properly written.
  667. --*/
  668. {
  669. TCHAR LineText[MAX_INF_STRING_LENGTH];
  670. BOOL RetVal;
  671. INFCONTEXT OLEContext;
  672. DWORD EntryCount,i;
  673. ZeroMemory(LineText,sizeof(LineText));
  674. EntryCount = SetupGetFieldCount(LineContext);
  675. for (i = 1; i<=EntryCount; i++) {
  676. TCHAR Entry[MAX_INF_STRING_LENGTH];
  677. INFCONTEXT ControlContext;
  678. //
  679. // get the current text to be appended
  680. //
  681. if (!SetupGetStringField(LineContext,i,Entry,sizeof(Entry)/sizeof(TCHAR),NULL)) {
  682. _ftprintf(stderr, TEXT("SetupGetStringField failed, ec = 0x%08x\n"),GetLastError());
  683. RetVal = FALSE;
  684. goto exit;
  685. }
  686. if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("Entry (1)- %s\n"),Entry);
  687. FixupSetupapiPercents(Entry);
  688. if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("Entry (2)- %s\n"),Entry);
  689. pSubstituteEnvVarsForActualPaths(Entry);
  690. if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("Entry (3)- %s\n"),Entry);
  691. //
  692. // now do any necessary substitutions
  693. //
  694. //
  695. // DIRID substitution
  696. //
  697. if (i == 1) {
  698. //
  699. // look in the appropriate control inf section for the data
  700. //
  701. if (!SetupFindFirstLine(
  702. hControlInf,
  703. TEXT("NativeDataToWowData.DirectoryInformation.SetupAPI"),
  704. Entry,
  705. &ControlContext)) {
  706. _ftprintf(stderr, TEXT("SetupFindFirstLine failed, ec = 0x%08x\n"),GetLastError());
  707. RetVal = FALSE;
  708. goto exit;
  709. }
  710. if (!SetupGetStringField(&ControlContext,1,Entry,sizeof(Entry)/sizeof(TCHAR),NULL)) {
  711. _ftprintf(stderr, TEXT("SetupGetStringField failed, ec = 0x%08x\n"),GetLastError());
  712. RetVal = FALSE;
  713. goto exit;
  714. }
  715. }
  716. _tcscat(LineText, Entry);
  717. //
  718. // now append a comma if necessary
  719. //
  720. if (i !=EntryCount) {
  721. _tcscat(LineText, TEXT(","));
  722. }
  723. }
  724. myftprintf(OutFile, TRUE, TEXT("%s\n"),LineText);
  725. RetVal = TRUE;
  726. exit:
  727. return(RetVal);
  728. }
  729. BOOL
  730. IsWowFile(
  731. IN HINF hControlInf,
  732. IN PINFCONTEXT LineContext
  733. )
  734. /*++
  735. Routine Description:
  736. This routine determines if the specified file is to be installed for
  737. as a wow file.
  738. This is determined by comparing directives in the control inf with
  739. the installation information in file inf context.
  740. Arguments:
  741. hControlInf - inf handle that contains control directives.
  742. LineContext - inf context from layout.inf for the file we want to examine.
  743. Return Value:
  744. Boolean value, true indicates the file is a wow file.
  745. --*/
  746. {
  747. BOOL RetVal = FALSE;
  748. TCHAR FileName[40];
  749. DWORD Disposition,DirectoryId;
  750. PTSTR p;
  751. INFCONTEXT ControlContext;
  752. TCHAR Extension[8];
  753. DWORD ExtensionCount,i;
  754. DWORD ControlDirId;
  755. //
  756. // get the filename
  757. //
  758. if (!SetupGetStringField(LineContext,0,FileName,sizeof(FileName)/sizeof(TCHAR),NULL)) {
  759. _ftprintf(stderr, TEXT("SetupGetStringField failed, ec = 0x%08x\n"),GetLastError());
  760. RetVal = FALSE;
  761. goto e0;
  762. }
  763. //
  764. // see if the file is in our "exclusion list"
  765. //
  766. if(SetupFindFirstLine(
  767. hControlInf,
  768. TEXT("WowData.Files.Exclude"),
  769. FileName,
  770. &ControlContext)) {
  771. _ftprintf(stderr,
  772. TEXT("filtering %ws because it's in our exclusion list\n"),
  773. FileName);
  774. RetVal = FALSE;
  775. SetLastError(ERROR_SUCCESS);
  776. goto e0;
  777. }
  778. //
  779. // see if the file is in our "inclusion list"
  780. //
  781. if(SetupFindFirstLine(
  782. hControlInf,
  783. TEXT("WowData.Files.Include"),
  784. FileName,
  785. &ControlContext)) {
  786. _ftprintf(stderr,
  787. TEXT("force inclusion of [%ws] because it's in our inclusion list\n"),
  788. FileName);
  789. RetVal = TRUE;
  790. SetLastError(ERROR_SUCCESS);
  791. goto e0;
  792. }
  793. //
  794. // see if the file is installed by textmode setup
  795. //
  796. if (!SetupGetIntField(LineContext,9,&Disposition)) {
  797. _ftprintf(stderr, TEXT("SetupGetIntField (%ws) failed, ec = 0x%08x\n"),FileName,GetLastError());
  798. RetVal = FALSE;
  799. goto e0;
  800. }
  801. if (Disposition == 3) {
  802. _ftprintf(stderr, TEXT("[%ws] is not an installed file\n"),FileName);
  803. SetLastError(ERROR_SUCCESS);
  804. RetVal = FALSE;
  805. goto e0;
  806. }
  807. //
  808. // get the extension of the file and compare it to the list of extensions
  809. // we're trolling for
  810. //
  811. p = _tcsrchr( FileName, TEXT('.') );
  812. if (p) {
  813. p+=1;
  814. } else {
  815. _ftprintf(stderr, TEXT("[%ws] does not have a file extension\n"),FileName);
  816. p = TEXT("");
  817. }
  818. if(!SetupFindFirstLine(
  819. hControlInf,
  820. TEXT("WowData.Filter"),
  821. TEXT("FileExtensions"),
  822. &ControlContext
  823. )) {
  824. _ftprintf(stderr, TEXT("SetupFindFirstLine (ControlInf) failed\n"));
  825. RetVal = FALSE;
  826. goto e0;
  827. }
  828. RetVal = FALSE;
  829. do{
  830. ExtensionCount = SetupGetFieldCount(&ControlContext);
  831. //
  832. // this is a 1-based index
  833. //
  834. for (i = 1; i <= ExtensionCount ; i++) {
  835. if (SetupGetStringField(&ControlContext,i,Extension,sizeof(Extension)/sizeof(TCHAR),NULL)) {
  836. if (_tcsicmp(Extension,p)==0) {
  837. RetVal = TRUE;
  838. break;
  839. }
  840. }else{
  841. _ftprintf(stderr, TEXT("SetupGetStringField failed, ec = 0x%08x\n"),GetLastError());
  842. RetVal = FALSE;
  843. goto e0;
  844. }
  845. }
  846. }while(SetupFindNextMatchLine(&ControlContext, TEXT("FileExtensions"), &ControlContext));
  847. if (!RetVal) {
  848. _ftprintf(stderr, TEXT("%ws does not match extension list\n"),FileName);
  849. SetLastError(ERROR_SUCCESS);
  850. goto e0;
  851. }
  852. //
  853. // get the directory the file is installed into and see if it's in our list
  854. // of directories we're trolling for.
  855. //
  856. if (!SetupGetIntField(LineContext,8,&DirectoryId)) {
  857. _ftprintf(stderr, TEXT("SetupGetIntField (%ws) failed, ec = 0x%08x\n"),FileName,GetLastError());
  858. RetVal = FALSE;
  859. goto e0;
  860. }
  861. RetVal = FALSE;
  862. if(!SetupFindFirstLine(
  863. hControlInf,
  864. TEXT("WowData.Filter"),
  865. TEXT("DirectoryToMap"),
  866. &ControlContext
  867. )) {
  868. _ftprintf(stderr, TEXT("SetupFindFirstLine failed, ec = 0x%08x\n"),GetLastError());
  869. RetVal = FALSE;
  870. goto e0;
  871. }
  872. do {
  873. if (!SetupGetIntField(&ControlContext,1,&ControlDirId)) {
  874. _ftprintf(stderr, TEXT("SetupGetIntField (\"DirectoryToMap\") (%ws) failed, ec = 0x%08x\n"),FileName,GetLastError());
  875. RetVal = FALSE;
  876. goto e0;
  877. }
  878. if (ControlDirId == DirectoryId) {
  879. RetVal = TRUE;
  880. break;
  881. }
  882. } while ( SetupFindNextMatchLine(&ControlContext,TEXT("DirectoryToMap"),&ControlContext ));
  883. if (!RetVal) {
  884. _ftprintf(stderr, TEXT("directory id %d for [%ws] is not in list\n"),DirectoryId,FileName);
  885. SetLastError(ERROR_SUCCESS);
  886. goto e0;
  887. }
  888. e0:
  889. return(RetVal);
  890. }
  891. BOOL
  892. IsWowOLEFile(
  893. IN HINF hControlInf,
  894. IN HINF hInputInf,
  895. IN PINFCONTEXT LineContext
  896. )
  897. /*++
  898. Routine Description:
  899. This routine determines if the specified file requires OLE self
  900. registration.
  901. This is determined by comparing directives in the control inf with
  902. the installation information in file inf context.
  903. Arguments:
  904. hControlInf - inf handle that contains control directives.
  905. hInputInf - inf handle that contains layout information.
  906. LineContext - inf context from syssetup.inf for the file we want to examine.
  907. Return Value:
  908. Boolean value, true indicates the file is a wow file.
  909. --*/
  910. {
  911. BOOL RetVal = FALSE;
  912. TCHAR FileName[40];
  913. PTSTR p;
  914. TCHAR SourceArchitecture[10];
  915. TCHAR SourceDiskFiles[80];
  916. BOOL FirstTime;
  917. INFCONTEXT ControlContext,InfContext;
  918. INFCONTEXT InputContext;
  919. //
  920. // get the filename
  921. //
  922. FileName[0] = L'\0';
  923. if (!SetupGetStringField(LineContext,3,FileName,sizeof(FileName)/sizeof(TCHAR),NULL)) {
  924. _ftprintf(stderr, TEXT("SetupGetStringField [%s] failed, ec = 0x%08x\n"),FileName,GetLastError());
  925. RetVal = FALSE;
  926. goto e0;
  927. }
  928. MYASSERT(FileName[0] != (TCHAR)NULL);
  929. //
  930. // see if the file is in our "exclusion list"
  931. //
  932. if(SetupFindFirstLine(
  933. hControlInf,
  934. TEXT("WowData.OLEList.Exclude"),
  935. FileName,
  936. &ControlContext)) {
  937. _ftprintf(stderr,
  938. TEXT("filtering %ws because it's in our exclusion list\n"),
  939. FileName);
  940. SetLastError(ERROR_SUCCESS);
  941. RetVal = FALSE;
  942. goto e0;
  943. }
  944. //
  945. // see if the file is in our "inclusion list"
  946. //
  947. if(SetupFindFirstLine(
  948. hControlInf,
  949. TEXT("WowData.OLELIst.Include"),
  950. FileName,
  951. &ControlContext)) {
  952. _ftprintf(stderr,
  953. TEXT("force inclusion of [%ws] because it's in our inclusion list\n"),
  954. FileName);
  955. SetLastError(ERROR_SUCCESS);
  956. RetVal = TRUE;
  957. goto e0;
  958. }
  959. //
  960. // see if the file is in the layout file and if it is,
  961. // we have success
  962. //
  963. //
  964. // get the required architecture decoration
  965. //
  966. if (!SetupFindFirstLine(
  967. hControlInf,
  968. TEXT("WowData.Filter"),
  969. TEXT("SourceArchitecture"),
  970. &InfContext) ||
  971. !SetupGetStringField(
  972. &InfContext,
  973. 1,
  974. SourceArchitecture,
  975. sizeof(SourceArchitecture)/sizeof(TCHAR),
  976. NULL)) {
  977. _ftprintf(stderr,TEXT("Unable to get SourceArchitecture\n"));
  978. goto e0;
  979. }
  980. FirstTime = TRUE;
  981. _tcscpy(SourceDiskFiles, TEXT("SourceDisksFiles"));
  982. while (TRUE) {
  983. DWORD FileCount;
  984. if (!FirstTime) {
  985. _tcscat(SourceDiskFiles,TEXT("."));
  986. _tcscat(SourceDiskFiles,SourceArchitecture);
  987. }
  988. if(SetupFindFirstLine(
  989. hInputInf,
  990. SourceDiskFiles,
  991. FileName,
  992. &InputContext) &&
  993. IsWowFile(hControlInf,&InputContext)) {
  994. RetVal = TRUE;
  995. break;
  996. }
  997. if (!FirstTime) {
  998. RetVal = FALSE;
  999. break;
  1000. }
  1001. FirstTime = FALSE;
  1002. }
  1003. e0:
  1004. SetLastError(ERROR_SUCCESS);
  1005. return(RetVal);
  1006. }
  1007. BOOL
  1008. DoCopyListSection(
  1009. IN PCTSTR InputSectionName,
  1010. IN HINF hInputInf,
  1011. IN HINF hControlInf,
  1012. IN FILE *OutFile
  1013. )
  1014. {
  1015. DWORD SectionCount, i;
  1016. INFCONTEXT InputContext;
  1017. UCHAR line[MAX_INF_STRING_LENGTH];
  1018. TCHAR SourceFileName[MAX_PATH];
  1019. if(!SetupFindFirstLine(
  1020. hInputInf,
  1021. InputSectionName,
  1022. NULL,
  1023. &InputContext)){
  1024. _ftprintf(stderr, TEXT("%s: Warning - Section %s not present: Ignoring Section\n"), ThisProgramName, InputSectionName);
  1025. return(TRUE);
  1026. }
  1027. SectionCount = SetupGetLineCount(hInputInf,InputSectionName);
  1028. for (i = 0; i < SectionCount; i++) {
  1029. if (SetupGetLineByIndex(hInputInf, InputSectionName, i, &InputContext)) {
  1030. if (IsWowFile(hControlInf,&InputContext)) {
  1031. AppendWowFileToCopyList(hControlInf,&InputContext, OutFile);
  1032. } else if (GetLastError() != NO_ERROR) {
  1033. _ftprintf(stderr, TEXT("IsWowFile failed\n"));
  1034. return(FALSE);
  1035. }
  1036. } else {
  1037. _ftprintf(stderr, TEXT("SetupGetLineByIndex failed, ec = %d\n"), GetLastError());
  1038. return(FALSE);
  1039. }
  1040. ProcessedLines += 1;
  1041. }
  1042. return(TRUE);
  1043. }
  1044. BOOL
  1045. DoCopyList(
  1046. IN PCTSTR InputInfA,
  1047. IN PCTSTR ControlInfA,
  1048. IN FILE *OutFile
  1049. )
  1050. {
  1051. PCWSTR InputInf;
  1052. PCWSTR ControlInf;
  1053. HINF hInputInf;
  1054. HINF hControlInf;
  1055. INFCONTEXT InfContext;
  1056. FILE *HeaderFile;
  1057. TCHAR SourceArchitecture[10];
  1058. TCHAR SourceDiskFiles[80];
  1059. BOOL FirstTime;
  1060. BOOL b;
  1061. b = TRUE;
  1062. //
  1063. // initialize and open the infs
  1064. //
  1065. #ifdef UNICODE
  1066. InputInf = InputInfA;
  1067. #else
  1068. InputInf = pSetupAnsiToUnicode(InputInfA);
  1069. #endif
  1070. if (!InputInf) {
  1071. _ftprintf(stderr,TEXT("Unable to convert %s to Unicode %d\n"),InputInfA, GetLastError());
  1072. goto e0;
  1073. }
  1074. #ifdef UNICODE
  1075. ControlInf = ControlInfA;
  1076. #else
  1077. ControlInf = pSetupAnsiToUnicode(ControlInfA);
  1078. #endif
  1079. if (!ControlInf) {
  1080. _ftprintf(stderr,TEXT("Unable to convert %s to Unicode %d\n"),ControlInfA, GetLastError());
  1081. goto e1;
  1082. }
  1083. hInputInf = SetupOpenInfFileW(InputInf,NULL,INF_STYLE_WIN4,NULL);
  1084. if(hInputInf == INVALID_HANDLE_VALUE) {
  1085. _ftprintf(stderr,TEXT("Unable to open Inf %ws, ec=0x%08x\n"),InputInf, GetLastError());
  1086. goto e2;
  1087. }
  1088. hControlInf = SetupOpenInfFileW(ControlInf,NULL,INF_STYLE_WIN4,NULL);
  1089. if(hControlInf == INVALID_HANDLE_VALUE) {
  1090. _ftprintf(stderr,TEXT("Unable to open Inf %ws, ec=0x%08x\n"),ControlInf, GetLastError());
  1091. goto e3;
  1092. }
  1093. myftprintf(OutFile, fDoAnsiOutput, TEXT("\n\n"));
  1094. //
  1095. // write the output file header
  1096. //
  1097. HeaderFile = _tfopen(HeaderText,TEXT("rt"));
  1098. if (HeaderFile) {
  1099. while (!feof(HeaderFile)) {
  1100. TCHAR Buffer[100];
  1101. DWORD CharsRead;
  1102. CharsRead = fread(Buffer,sizeof(TCHAR),sizeof(Buffer)/sizeof(TCHAR),HeaderFile);
  1103. if (CharsRead) {
  1104. fwrite(Buffer,sizeof(TCHAR),CharsRead,OutFile);
  1105. }
  1106. }
  1107. fclose(HeaderFile);
  1108. }
  1109. myftprintf(OutFile, fDoAnsiOutput, TEXT("\n"));
  1110. //
  1111. // get the required architecture decoration
  1112. //
  1113. if (!SetupFindFirstLine(
  1114. hControlInf,
  1115. TEXT("WowData.Filter"),
  1116. TEXT("SourceArchitecture"),
  1117. &InfContext) ||
  1118. !SetupGetStringField(
  1119. &InfContext,
  1120. 1,
  1121. SourceArchitecture,
  1122. sizeof(SourceArchitecture)/sizeof(TCHAR),
  1123. NULL)) {
  1124. _ftprintf(stderr,TEXT("Unable to get SourceArchitecture\n"));
  1125. goto e4;
  1126. }
  1127. FirstTime = TRUE;
  1128. _tcscpy(SourceDiskFiles, TEXT("SourceDisksFiles"));
  1129. while (TRUE) {
  1130. DWORD FileCount;
  1131. if (!FirstTime) {
  1132. _tcscat(SourceDiskFiles,TEXT("."));
  1133. _tcscat(SourceDiskFiles,SourceArchitecture);
  1134. }
  1135. DoCopyListSection(
  1136. SourceDiskFiles,
  1137. hInputInf,
  1138. hControlInf,
  1139. OutFile
  1140. );
  1141. if (FirstTime) {
  1142. FirstTime = FALSE;
  1143. } else {
  1144. break;
  1145. }
  1146. }
  1147. e4:
  1148. SetupCloseInfFile( hControlInf );
  1149. e3:
  1150. SetupCloseInfFile( hInputInf );
  1151. e2:
  1152. #ifndef UNICODE
  1153. pSetupFree(ControlInf);
  1154. #endif
  1155. e1:
  1156. #ifndef UNICODE
  1157. pSetupFree(InputInf);
  1158. #endif
  1159. e0:
  1160. return(b);
  1161. }
  1162. BOOL
  1163. DoOLEListSection(
  1164. IN HINF hInputInf,
  1165. IN HINF hOLEInputInf,
  1166. IN HINF hControlInf,
  1167. IN FILE *OutFile
  1168. )
  1169. /*++
  1170. Routine Description:
  1171. This routine iterates through all files in the input inf specified by the
  1172. section name. If the specified file is a WOW file, then we check if it
  1173. is in the ole registration list. If it is, then we do the appropriate
  1174. transform on the data and output the data to our data file.
  1175. Arguments:
  1176. hInputInf - inf handle with file list in it.
  1177. hOLEInputInf - inf handle with ole lists in it.
  1178. hControlInf - inf handle for control inf that drives our filters
  1179. OutFile - file handle where the output data gets placed into
  1180. Return Value:
  1181. Boolean value, true indicates the file is a wow file.
  1182. --*/
  1183. {
  1184. DWORD SectionCount, i;
  1185. INFCONTEXT InputContext;
  1186. UCHAR line[MAX_INF_STRING_LENGTH];
  1187. TCHAR SourceFileName[MAX_PATH];
  1188. SetupFindFirstLine(
  1189. hOLEInputInf,
  1190. OLESection,
  1191. NULL,
  1192. &InputContext);
  1193. SectionCount = SetupGetLineCount(hOLEInputInf,OLESection);
  1194. for (i = 0; i < SectionCount; i++) {
  1195. if (SetupGetLineByIndex(hOLEInputInf, OLESection, i, &InputContext)) {
  1196. if (IsWowOLEFile(hControlInf,hInputInf, &InputContext)) {
  1197. AppendWowFileToOLEList(hControlInf,hOLEInputInf,&InputContext, OutFile);
  1198. } else if (GetLastError() != NO_ERROR) {
  1199. _ftprintf(stderr, TEXT("IsWowOLEFile failed\n"));
  1200. return(FALSE);
  1201. }
  1202. } else {
  1203. _ftprintf(stderr, TEXT("SetupGetLineByIndex failed, ec = %d\n"), GetLastError());
  1204. return(FALSE);
  1205. }
  1206. ProcessedLines += 1;
  1207. }
  1208. return(TRUE);
  1209. }
  1210. BOOL
  1211. DoOLEList(
  1212. IN PCTSTR InputInfA,
  1213. IN PCTSTR OLEInputInfA,
  1214. IN PCTSTR ControlInfA,
  1215. IN FILE *OutFile
  1216. )
  1217. /*++
  1218. Routine Description:
  1219. This routine runs through the list of specified files in the input inf
  1220. and feeds them into a worker routine which will build the list of OLE
  1221. Control dlls.
  1222. Arguments:
  1223. InputInfA - name of input inf containing the files to be run through
  1224. our "filter"
  1225. OLEInputInfA - name of input inf containing the ole directives to be
  1226. processed
  1227. ControlInfA - name of the control inf that tells us how to parse the
  1228. input infs
  1229. OutFile - file pointer for the file to be written
  1230. Return Value:
  1231. Boolean value, true indicates the file is a wow file.
  1232. --*/
  1233. {
  1234. PCWSTR InputInf;
  1235. PCWSTR OLEInputInf;
  1236. PCWSTR ControlInf;
  1237. HINF hInputInf;
  1238. HINF hControlInf;
  1239. HINF hOLEInputInf;
  1240. INFCONTEXT InfContext;
  1241. FILE *HeaderFile;
  1242. BOOL b = FALSE;
  1243. //
  1244. // initialize and open the infs
  1245. //
  1246. #ifdef UNICODE
  1247. InputInf = InputInfA;
  1248. #else
  1249. InputInf = pSetupAnsiToUnicode(InputInfA);
  1250. #endif
  1251. if (!InputInf) {
  1252. _ftprintf(stderr,TEXT("Unable to convert %s to Unicode %d\n"),InputInfA, GetLastError());
  1253. goto e0;
  1254. }
  1255. #ifdef UNICODE
  1256. ControlInf = ControlInfA;
  1257. #else
  1258. ControlInf = pSetupAnsiToUnicode(ControlInfA);
  1259. #endif
  1260. if (!ControlInf) {
  1261. _ftprintf(stderr,TEXT("Unable to convert %s to Unicode %d\n"),ControlInf, GetLastError());
  1262. goto e1;
  1263. }
  1264. #ifdef UNICODE
  1265. OLEInputInf = OLEInputInfA;
  1266. #else
  1267. OLEInputInf = pSetupAnsiToUnicode(OLEInputInfA);
  1268. #endif
  1269. if (!OLEInputInf) {
  1270. _ftprintf(stderr,TEXT("Unable to convert %s to Unicode %d\n"),OLEInputInfA, GetLastError());
  1271. goto e2;
  1272. }
  1273. hInputInf = SetupOpenInfFileW(InputInf,NULL,INF_STYLE_WIN4,NULL);
  1274. if(hInputInf == INVALID_HANDLE_VALUE) {
  1275. _ftprintf(stderr,TEXT("Unable to open Inf %ws, ec=0x%08x\n"),InputInf, GetLastError());
  1276. goto e3;
  1277. }
  1278. hOLEInputInf = SetupOpenInfFileW(OLEInputInf,NULL,INF_STYLE_WIN4,NULL);
  1279. if(hOLEInputInf == INVALID_HANDLE_VALUE) {
  1280. _ftprintf(stderr,TEXT("Unable to open Inf %ws, ec=0x%08x\n"),OLEInputInf, GetLastError());
  1281. goto e4;
  1282. }
  1283. hControlInf = SetupOpenInfFileW(ControlInf,NULL,INF_STYLE_WIN4,NULL);
  1284. if(hControlInf == INVALID_HANDLE_VALUE) {
  1285. _ftprintf(stderr,TEXT("Unable to open Inf %ws, ec=0x%08x\n"),ControlInf, GetLastError());
  1286. goto e5;
  1287. }
  1288. myftprintf(OutFile, TRUE, TEXT("\n\n"));
  1289. //
  1290. // write the output file header
  1291. //
  1292. HeaderFile = _tfopen(HeaderText,TEXT("rt"));
  1293. if (HeaderFile) {
  1294. while (!feof(HeaderFile)) {
  1295. TCHAR Buffer[100];
  1296. DWORD CharsRead;
  1297. CharsRead = fread(Buffer,sizeof(TCHAR),sizeof(Buffer)/sizeof(TCHAR),HeaderFile);
  1298. if (CharsRead) {
  1299. fwrite(Buffer,sizeof(TCHAR),CharsRead,OutFile);
  1300. }
  1301. }
  1302. }
  1303. myftprintf(OutFile, TRUE, TEXT("\n"));
  1304. b = DoOLEListSection(
  1305. hInputInf,
  1306. hOLEInputInf,
  1307. hControlInf,
  1308. OutFile
  1309. );
  1310. SetupCloseInfFile( hControlInf );
  1311. e5:
  1312. SetupCloseInfFile( hOLEInputInf );
  1313. e4:
  1314. SetupCloseInfFile( hInputInf );
  1315. e3:
  1316. #ifndef UNICODE
  1317. pSetupFree(OLEInputInf);
  1318. #endif
  1319. e2:
  1320. #ifndef UNICODE
  1321. pSetupFree(ControlInf);
  1322. #endif
  1323. e1:
  1324. #ifndef UNICODE
  1325. pSetupFree(InputInf);
  1326. #endif
  1327. e0:
  1328. return(b);
  1329. }
  1330. BOOL
  1331. pFilterSetupInfSection(
  1332. PVOID FilteredSectionsStringTable,
  1333. PCTSTR SectionName,
  1334. PSETUPINF_CONTEXT Context
  1335. )
  1336. /*++
  1337. Routine Description:
  1338. This routine determines if a given section should be filtered by
  1339. looking in the control inf for the directives that we're interested
  1340. in.
  1341. Arguments:
  1342. FilteredSectionsStringTable - pointer to a string table which we'll
  1343. add our filtered section name to if we find a hit
  1344. SectionName - name of the section in the INF we're interested in
  1345. Context - contains context information for this function, like
  1346. input infs name, etc.
  1347. Return Value:
  1348. Boolean value, true indicates the file is a wow file.
  1349. --*/
  1350. {
  1351. BOOL RetVal;
  1352. TCHAR KeywordList[MAX_PATH];
  1353. PCTSTR CurrentKeyword;
  1354. DWORD KeywordBitmap;
  1355. INFCONTEXT ControlInfContext;
  1356. DWORD i;
  1357. BOOL AlreadyOutputSectionName,AlreadyOutputKeyword;
  1358. //
  1359. // get the keywords that we're supposed to map.
  1360. //
  1361. // bugbug look at having a per-inf extension to this
  1362. //
  1363. if (!SetupFindFirstLine(
  1364. Context->hControlInf,
  1365. MyGetDecoratedSectionName(Context->hControlInf, TEXT("NativeDataToWowData.SetupINF.Keyword")),
  1366. TEXT("Keywords"),
  1367. &ControlInfContext)) {
  1368. _ftprintf(stderr, TEXT("Could not get Keywords line in [NativeDataToWowData.SetupINF.Keyword]: SetupFindFirstLine failed, ec = 0x%08x\n"),GetLastError());
  1369. RetVal = FALSE;
  1370. goto exit;
  1371. }
  1372. //
  1373. // now look for each keyword
  1374. //
  1375. SetupGetIntField(&ControlInfContext,1,&KeywordBitmap);
  1376. AlreadyOutputSectionName = FALSE;
  1377. AlreadyOutputKeyword = FALSE;
  1378. CurrentKeyword = NULL;
  1379. for (i = 0; i < 32;i++) {
  1380. INFCONTEXT InputInfContext;
  1381. INFCONTEXT ContextDirId;
  1382. BOOL LookatDirIds;
  1383. DWORD FieldCount,Field;
  1384. TCHAR ActualSectionName[LINE_LEN];
  1385. if (KeywordBitmap & (1<<i)) {
  1386. CurrentKeyword = KeywordArray[i];
  1387. MYASSERT( CurrentKeyword != NULL);
  1388. }
  1389. if (!CurrentKeyword) {
  1390. continue;
  1391. }
  1392. if (!SetupFindFirstLine(
  1393. Context->hControlInf,
  1394. MyGetDecoratedSectionName(Context->hControlInf, TEXT("NativeDataToWowData.SetupINF.Keyword")),
  1395. CurrentKeyword,
  1396. &ContextDirId)) {
  1397. _ftprintf(stderr, TEXT("Could not get %s line in [NativeDataToWowData.SetupINF.Keyword]: SetupFindFirstLine failed, ec = 0x%08x\n"), CurrentKeyword, GetLastError());
  1398. RetVal = FALSE;
  1399. goto exit;
  1400. }
  1401. //
  1402. // field 2 is "MapDirId". If it's specified, then we
  1403. // need to look at the destinationdirs keyword
  1404. //
  1405. LookatDirIds = (SetupGetFieldCount(&ContextDirId)>=2) ? TRUE : FALSE;
  1406. //
  1407. // look for specified keyword in our section
  1408. //
  1409. if (SetupFindFirstLine(
  1410. Context->hInputInf,
  1411. SectionName,
  1412. CurrentKeyword,
  1413. &InputInfContext
  1414. )) {
  1415. //
  1416. // we found a hit. see if we need to map this keyword
  1417. //
  1418. do {
  1419. //
  1420. // each field is a section name.
  1421. //
  1422. FieldCount = SetupGetFieldCount(&InputInfContext);
  1423. for(Field=1; Field<=FieldCount; Field++) {
  1424. BOOL MapThisSection = FALSE;
  1425. TCHAR DirId[LINE_LEN];
  1426. DWORD MappedDirId = 0;
  1427. INFCONTEXT InputDirId,ControlDirId;
  1428. SetupGetStringField(&InputInfContext,Field,ActualSectionName,LINE_LEN,NULL);
  1429. //
  1430. // if we need to look at the destination dirs keyword,
  1431. // then look it up and compare it against the control inf
  1432. // mapper
  1433. //
  1434. if (LookatDirIds) {
  1435. if(!SetupFindFirstLine(
  1436. Context->hInputInf,
  1437. TEXT("DestinationDirs"),
  1438. ActualSectionName,
  1439. &InputDirId)) {
  1440. if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("SetupFindFirstLine failed, ec = 0x%08x finding %s in %s \n"),GetLastError(), ActualSectionName, TEXT("DestinationDirs"));
  1441. if(!SetupFindFirstLine(
  1442. Context->hInputInf,
  1443. TEXT("DestinationDirs"),
  1444. TEXT("DefaultDestDir"),
  1445. &InputDirId)) {
  1446. _ftprintf(stderr, TEXT("SetupFindFirstLine failed, ec = 0x%08x finding %s in %s\n"),GetLastError(), TEXT("DefaultDestDir"), TEXT("DestinationDirs"));
  1447. RetVal = FALSE;
  1448. goto exit;
  1449. }
  1450. }
  1451. if(SetupGetStringField(&InputDirId,1,DirId,LINE_LEN,NULL) &&
  1452. SetupFindFirstLine(
  1453. Context->hControlInf,
  1454. MyGetDecoratedSectionName(Context->hControlInf, TEXT("NativeDataToWowData.SetupINF.DestinationDirsToMap")),
  1455. DirId,
  1456. &ControlDirId)) {
  1457. //
  1458. // we found a hit, thus we should map this section
  1459. //
  1460. MapThisSection = TRUE;
  1461. SetupGetIntField(&ControlDirId,1,&MappedDirId);
  1462. if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("Mapping %s to %lu\n"), DirId, MappedDirId);
  1463. }
  1464. } else {
  1465. MapThisSection = TRUE;
  1466. }
  1467. if (MapThisSection) {
  1468. DWORD StringId;
  1469. PERSECTION_CONTEXT SectionContext;
  1470. BOOL AddNewEntry;
  1471. //
  1472. // output the toplevel section name if we haven't done
  1473. // so already. this section name is not decorated
  1474. //
  1475. if (!AlreadyOutputSectionName) {
  1476. myftprintf(Context->OutFile, fDoAnsiOutput, TEXT("\n[%s]\n"),SectionName);
  1477. AlreadyOutputSectionName = TRUE;
  1478. }
  1479. //
  1480. // output the keyword and decorated section name
  1481. // note that we need to separate the section names
  1482. // by a comma
  1483. //
  1484. if (!AlreadyOutputKeyword) {
  1485. myftprintf(Context->OutFile, fDoAnsiOutput, TEXT("%s="), CurrentKeyword);
  1486. myftprintf(Context->OutFile, fDoAnsiOutput, TEXT("%s%s"),FilePrefix,ActualSectionName);
  1487. AlreadyOutputKeyword = TRUE;
  1488. } else {
  1489. myftprintf(Context->OutFile, fDoAnsiOutput, TEXT(",%s%s"),FilePrefix,ActualSectionName);
  1490. }
  1491. //
  1492. // now append the section to the string table
  1493. //
  1494. StringId = pSetupStringTableLookUpString(
  1495. FilteredSectionsStringTable,
  1496. (PTSTR)ActualSectionName,
  1497. STRTAB_CASE_INSENSITIVE);
  1498. if (StringId != -1) {
  1499. pSetupStringTableGetExtraData(
  1500. FilteredSectionsStringTable,
  1501. StringId,
  1502. &SectionContext,
  1503. sizeof(SectionContext));
  1504. AddNewEntry = FALSE;
  1505. } else {
  1506. RtlZeroMemory(&SectionContext,sizeof(SectionContext));
  1507. AddNewEntry = TRUE;
  1508. }
  1509. SectionContext.DestinationDir = MappedDirId;
  1510. SectionContext.KeywordVector |= (1<<i);
  1511. if (AddNewEntry) {
  1512. if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("Adding %s to string table\n"), ActualSectionName);
  1513. if ( -1 == pSetupStringTableAddStringEx(
  1514. FilteredSectionsStringTable,
  1515. (PTSTR)ActualSectionName,
  1516. STRTAB_CASE_SENSITIVE | STRTAB_NEW_EXTRADATA,
  1517. &SectionContext,
  1518. sizeof(SectionContext))){
  1519. _ftprintf(stderr, TEXT("Could not add %s to string table\n"), ActualSectionName);
  1520. }
  1521. } else {
  1522. if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("Adding %s to string table\n"), ActualSectionName);
  1523. if ( !pSetupStringTableSetExtraData(
  1524. FilteredSectionsStringTable,
  1525. StringId,
  1526. &SectionContext,
  1527. sizeof(SectionContext))){
  1528. _ftprintf(stderr, TEXT("Could not add %s to string table\n"), ActualSectionName);}
  1529. }
  1530. }
  1531. }
  1532. } while ( SetupFindNextMatchLine(&InputInfContext,
  1533. CurrentKeyword,
  1534. &InputInfContext ));
  1535. }
  1536. if (AlreadyOutputKeyword) {
  1537. myftprintf(Context->OutFile, fDoAnsiOutput, TEXT("\n"));
  1538. }
  1539. //
  1540. // reset this for the next keyword
  1541. //
  1542. AlreadyOutputKeyword = FALSE;
  1543. CurrentKeyword = NULL;
  1544. }
  1545. exit:
  1546. return(RetVal);
  1547. }
  1548. BOOL
  1549. AppendSetupInfDataToLayoutFile(
  1550. IN FILE *OutFile,
  1551. IN FILE *OutInfFile,
  1552. IN HINF hControlInf,
  1553. IN HINF hInputInf,
  1554. IN PINFCONTEXT LineContext
  1555. )
  1556. /*++
  1557. Routine Description:
  1558. This routine filters and outputs a layout line.
  1559. We only need to filter "Copyfiles" sections, and since the files are
  1560. not installed by textmode setup, the line which we output is largely
  1561. hardcoded.
  1562. Arguments:
  1563. OutFile - output file handle
  1564. OutInfFile - output file handle for layout information within INF
  1565. hControlInf - inf handle to the inf with the control directives
  1566. LineContext - inf context to the input line we want to filter.
  1567. Return Value:
  1568. Boolean indicating outcome.
  1569. --*/
  1570. {
  1571. TCHAR FileName[MAX_PATH],InfField[MAX_PATH],Entry[50], Prefix[40];
  1572. INFCONTEXT ControlContext;
  1573. BOOL RetVal;
  1574. INT SourceID = 1;
  1575. TCHAR SourceIDStr[6], DefaultIDStr[6];
  1576. BOOL LayoutWithinInf = FALSE;
  1577. DWORD EntryCount,i;
  1578. ZeroMemory(Entry,sizeof(Entry));
  1579. ZeroMemory(Prefix,sizeof(Prefix));
  1580. //
  1581. // get the source filename
  1582. //
  1583. EntryCount = SetupGetFieldCount(LineContext);
  1584. if ((((EntryCount <= 1)
  1585. || !SetupGetStringField(LineContext,2,InfField,MAX_PATH,NULL)
  1586. || !InfField[0]))
  1587. && (!SetupGetStringField(LineContext,1,InfField,MAX_PATH,NULL)
  1588. || !InfField[0])) {
  1589. //
  1590. // bad line?
  1591. //
  1592. MYASSERT(0);
  1593. _ftprintf(stderr, TEXT("AppendSetupInfDataToLayoutFile: Could not get source filename - ec = 0x%08x\n"), GetLastError());
  1594. }
  1595. MyGetFilePrefix( hControlInf, InfField, Prefix );
  1596. _tcscpy(FileName, Prefix);
  1597. _tcscat(FileName, InfField );
  1598. //
  1599. // see if the file is in our "SetupInf exclusion list"
  1600. //
  1601. if(SetupFindFirstLine(
  1602. hControlInf,
  1603. MyGetDecoratedSectionName(hControlInf, TEXT("WowData.SetupInfLayout.Exclude")),
  1604. InfField,
  1605. &ControlContext) ||
  1606. SetupFindFirstLine(
  1607. hControlInf,
  1608. MyGetDecoratedSectionName(hControlInf, TEXT("NativeDataToWowData.SetupINF.FilesToExclude")),
  1609. InfField,
  1610. &ControlContext)) {
  1611. _ftprintf(stderr,
  1612. TEXT("filtering %ws because it's in our SetupInf exclusion list\n"),
  1613. InfField);
  1614. RetVal = FALSE;
  1615. goto exit;
  1616. }
  1617. //
  1618. // Get Default Source ID
  1619. // By default this means the Source ID that is processed for dosnet.inf, txtsetup.sif etc.
  1620. // i.e layout.inf today only has = 1,,,,,,, type of entries that translate to = 55,,,,,
  1621. // Currently we can support only one such mapping as the default translation
  1622. // That means that we will take SourceDisksFiles entries pertaining to the default and always output it into the layout.inf stub
  1623. // so that dosnet.inf gets it.
  1624. //
  1625. if (!SetupFindFirstLine(
  1626. hControlInf,
  1627. TEXT("NativeDataToWowData.SourceInfo"),
  1628. TEXT("Default"), //bugbug need a way to get this for other source disks
  1629. &ControlContext) ||
  1630. !SetupGetStringField(&ControlContext,1,DefaultIDStr,sizeof(DefaultIDStr)/sizeof(TCHAR),NULL)) {
  1631. _ftprintf(stderr, TEXT("SetupFindFirstLine to get default SourceID for file %s failed - Using %s, ec = 0x%08x\n"),FileName,DefaultIDStr,GetLastError());
  1632. // As last resort use 1
  1633. lstrcpy( DefaultIDStr, TEXT("1"));
  1634. }
  1635. if( !SetupGetSourceFileLocation(hInputInf,
  1636. LineContext,
  1637. NULL,
  1638. &SourceID,
  1639. NULL,
  1640. 0,
  1641. NULL)){
  1642. _ftprintf(stderr, TEXT("SetupGetSourceFileLocation [%s] failed - Using SourceID 1, ec = 0x%08x\n"),FileName,GetLastError());
  1643. //Assume Default
  1644. lstrcpy( SourceIDStr, DefaultIDStr);
  1645. LayoutWithinInf = FALSE;
  1646. }else{
  1647. LayoutWithinInf = TRUE;;
  1648. _itot( SourceID, SourceIDStr, 10);
  1649. }
  1650. //
  1651. // look in the appropriate control inf section for the data
  1652. //
  1653. if (!SetupFindFirstLine(
  1654. hControlInf,
  1655. TEXT("NativeDataToWowData.SourceInfo"),
  1656. SourceIDStr,
  1657. &ControlContext)) {
  1658. _ftprintf(stderr, TEXT("SetupFindFirstLine [%s] failed, ec = 0x%08x finding %s key in [NativeDataToWowData.SourceInfo]\n"),FileName,GetLastError(), SourceIDStr);
  1659. RetVal = FALSE;
  1660. goto exit;
  1661. }
  1662. if (!SetupGetStringField(&ControlContext,1,Entry,sizeof(Entry)/sizeof(TCHAR),NULL)) {
  1663. _ftprintf(stderr, TEXT("SetupGetStringField [%s] failed, ec = 0x%08x\n"),FileName,GetLastError());
  1664. RetVal = FALSE;
  1665. goto exit;
  1666. }
  1667. if( LayoutWithinInf && OutInfFile){
  1668. //If we found SourceFileInfo within this file and we were
  1669. //asked to add the WOW equivalent to the same INF then do so.
  1670. myftprintf(OutInfFile, fDoAnsiOutput, TEXT("%s:%s=%s,,,,,,,,3,3\n"),InfField,FileName,Entry);
  1671. //Also if the SourceID matches the default we want to output to the layout.inf stub as well so
  1672. //that it makes it into dosnet.inf. See earlier comments about the DefaultIDStr
  1673. //InfField is the filename without the prefix - useful for postbuild. Has to be stripped out before appending the layout.inf stub.
  1674. if( !lstrcmpi( SourceIDStr, DefaultIDStr )){
  1675. myftprintf(OutFile, TRUE, TEXT("%s:%s=%s,,,,,,,,3,3\n"),InfField,FileName,Entry);
  1676. }
  1677. }else{
  1678. myftprintf(OutFile, TRUE, TEXT("%s:%s=%s,,,,,,,,3,3\n"),InfField,FileName,Entry);
  1679. }
  1680. RetVal = TRUE;
  1681. exit:
  1682. return(RetVal);
  1683. }
  1684. void
  1685. HandleSetupapiQuotingForString(
  1686. IN OUT PTSTR String
  1687. )
  1688. /*++
  1689. Routine Description:
  1690. This routine looks at the passed in line and does the right quoting and handling of
  1691. the string to handle characters that may have been stripped off by setupapi.
  1692. It first scans through the string looking for characters <= 0x20, '\"','%','\\'
  1693. If it finds any of these then it places a " at the beginning and end of the string. Additionally it doubles
  1694. every quote within.
  1695. Arguments:
  1696. String - input string to be searched. We edit this string
  1697. in-place if we find a match.
  1698. Return Value:
  1699. Boolean indicating outcome.
  1700. --*/
  1701. {
  1702. PTCHAR p,q;
  1703. BOOL Pass2Needed = FALSE;
  1704. if( !String || !String[0] )
  1705. return;
  1706. p = String;
  1707. //
  1708. // [askhalid] ',' Need to be considered as well
  1709. //
  1710. while( *p ){
  1711. if( (*p <= 0x20) || (*p == TEXT('\"')) || (*p == TEXT(',')) || (*p == TEXT(';')) ||(*p == TEXT('%')) || (*p == TEXT('\\')))
  1712. Pass2Needed = TRUE;
  1713. p++;
  1714. }// while
  1715. if( Pass2Needed ){
  1716. // Quote the start
  1717. p = String;
  1718. q = ScratchTextEnv+1;
  1719. ZeroMemory(ScratchTextEnv,sizeof(ScratchTextEnv));
  1720. ScratchTextEnv[0] = TEXT('\"');
  1721. while( *p && (q < (ScratchTextEnv+MAX_INF_STRING_LENGTH-3)) ){
  1722. // If we have a quote in the string double it
  1723. if (*p == TEXT('\"')) {
  1724. *(q++) = TEXT('\"');
  1725. }
  1726. *q = *p;
  1727. p++;q++;
  1728. }// while
  1729. // Quote the end
  1730. *(q++) = TEXT('\"');
  1731. *q = 0;
  1732. lstrcpy( String, ScratchTextEnv );
  1733. }
  1734. return;
  1735. }
  1736. BOOL
  1737. AppendSetupInfDataToSection(
  1738. IN FILE *OutFile,
  1739. IN HINF hControlInf,
  1740. IN PINFCONTEXT InputContext,
  1741. IN PCTSTR KeywordName
  1742. )
  1743. /*++
  1744. Routine Description:
  1745. This routine filters and outputs an input line. The control inf
  1746. lists the syntax for the specified keyword. We filter the keywords
  1747. we know about and let the other ones just fall through.
  1748. Arguments:
  1749. OutFile - output file handle
  1750. hControlInf - inf handle to the inf with the control directives
  1751. InputContext - inf context to the input line we want to filter.
  1752. KeywordName - string indicating the keyword associated with the section
  1753. we are filtering.
  1754. Return Value:
  1755. Boolean indicating outcome.
  1756. --*/
  1757. {
  1758. TCHAR FileName[40], Prefix[40];
  1759. TCHAR KeyName[LINE_LEN];
  1760. TCHAR Cmd[LINE_LEN];
  1761. BOOL RetVal;
  1762. DWORD EntryCount,i;
  1763. INFCONTEXT ControlContext,KeywordContext;
  1764. //
  1765. // ISSUE-2000/06/27-JamieHun Appears to be no error checking here, someone should fix this
  1766. //
  1767. SetupFindFirstLine(
  1768. hControlInf,
  1769. MyGetDecoratedSectionName(hControlInf, TEXT("NativeDataToWowData.SetupINF.Keyword")),
  1770. KeywordName,
  1771. &ControlContext);
  1772. if(SetupGetStringField(&ControlContext,1,KeyName,LINE_LEN,NULL)) {
  1773. SetupFindFirstLine(
  1774. hControlInf,
  1775. MyGetDecoratedSectionName(hControlInf, TEXT("NativeDataToWowData.SetupINF.Syntax")),
  1776. KeyName,
  1777. &KeywordContext);
  1778. }
  1779. ZeroMemory(LineText,sizeof(LineText));
  1780. FileName[0] = TEXT('\0');
  1781. if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("KeywordName - %s\n"),KeywordName);
  1782. EntryCount = SetupGetFieldCount(InputContext);
  1783. for (i = 1; i<=EntryCount; i++) {
  1784. TCHAR ScratchEntry[MAX_PATH];
  1785. //
  1786. // get the current text to be appended
  1787. //
  1788. if (!SetupGetStringField(InputContext,i,ScratchText,sizeof(ScratchText)/sizeof(TCHAR),NULL)) {
  1789. _ftprintf(stderr, TEXT("SetupGetStringField [%s] failed, ec = 0x%08x\n"),FileName,GetLastError());
  1790. RetVal = FALSE;
  1791. goto exit;
  1792. }
  1793. if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("ScratchText (1)- %s\n"),ScratchText);
  1794. FixupSetupapiPercents(ScratchText);
  1795. if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("ScratchText (2)- %s\n"),ScratchText);
  1796. pSubstituteEnvVarsForActualPaths(ScratchText);
  1797. if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("ScratchText (3)- %s\n"),ScratchText);
  1798. //
  1799. // now do any necessary substitutions
  1800. //
  1801. if(SetupGetStringField(&KeywordContext,i,Cmd,LINE_LEN,NULL)
  1802. && Cmd[0]) {
  1803. //
  1804. // dirid substitution
  1805. //
  1806. if (!_tcsicmp(Cmd,TEXT("MapDirId"))) {
  1807. //
  1808. // look in the appropriate control inf section for the data
  1809. //
  1810. if (!SetupFindFirstLine(
  1811. hControlInf,
  1812. MyGetDecoratedSectionName(hControlInf, TEXT("NativeDataToWowData.SetupINF.DestinationDirsToMap")),
  1813. ScratchText,
  1814. &ControlContext)) {
  1815. _ftprintf(stderr, TEXT("SetupFindFirstLine [%s] failed, ec = 0x%08x\n"),FileName,GetLastError());
  1816. RetVal = FALSE;
  1817. goto exit;
  1818. }
  1819. if (!SetupGetStringField(&ControlContext,1,ScratchText,sizeof(ScratchText)/sizeof(TCHAR),NULL)) {
  1820. _ftprintf(stderr, TEXT("SetupGetStringField [%s] failed, ec = 0x%08x\n"),FileName,GetLastError());
  1821. RetVal = FALSE;
  1822. goto exit;
  1823. }
  1824. }
  1825. //
  1826. // source name substitution
  1827. //
  1828. if (!_tcsicmp(Cmd,TEXT("srcname"))) {
  1829. MyGetFilePrefix( hControlInf, FileName, Prefix );
  1830. LSTRCPY(ScratchEntry,Prefix);
  1831. if (ScratchText[0]) {
  1832. LSTRCAT(ScratchEntry,ScratchText);
  1833. } else {
  1834. LSTRCAT(ScratchEntry,FileName);
  1835. }
  1836. LSTRCPY(ScratchText,ScratchEntry);
  1837. }
  1838. //_ftprintf(stderr, TEXT("ScratchText(2) - %s\n"),ScratchText);
  1839. if (!_tcsicmp(Cmd,TEXT("RegistryFlags"))) {
  1840. DWORD RegVal,CurrentRegVal;
  1841. //
  1842. // look in the appropriate control inf section for the data
  1843. //
  1844. if (!SetupFindFirstLine(
  1845. hControlInf,
  1846. MyGetDecoratedSectionName(hControlInf, TEXT("NativeDataToWowData.SetupINF.RegistryInformation")),
  1847. TEXT("RegistryFlags"),
  1848. &ControlContext)) {
  1849. _ftprintf(stderr, TEXT("SetupFindFirstLine [%s] failed, ec = 0x%08x\n"),FileName,GetLastError());
  1850. RetVal = FALSE;
  1851. goto exit;
  1852. }
  1853. CurrentRegVal = 0;
  1854. RegVal = 0;
  1855. SetupGetIntField(&ControlContext,1,&RegVal);
  1856. SetupGetIntField(InputContext,i,&CurrentRegVal);
  1857. CurrentRegVal |= RegVal;
  1858. _stprintf(ScratchText, TEXT("0x%08x"), CurrentRegVal);
  1859. }
  1860. if (!_tcsicmp(Cmd,TEXT("dstname"))) {
  1861. LSTRCPY(FileName,ScratchText);
  1862. }
  1863. }
  1864. HandleSetupapiQuotingForString(ScratchText);
  1865. _tcscat(LineText, ScratchText);
  1866. //
  1867. // now append a comma if necessary
  1868. //
  1869. if (i !=EntryCount) {
  1870. _tcscat(LineText, TEXT(","));
  1871. }
  1872. }
  1873. if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("LineText - %s\n"),LineText);
  1874. //
  1875. // Check if we need to exclude the DLL
  1876. //
  1877. if (KeywordName == KeywordArray[INDEX_COPYFILES] ||
  1878. KeywordName == KeywordArray[INDEX_DELFILES] ||
  1879. KeywordName == KeywordArray[INDEX_RENFILES] ||
  1880. KeywordName == KeywordArray[INDEX_REGISTERDLLS]){
  1881. // Check if we need to exclude this file from processing
  1882. if( SetupFindFirstLine(
  1883. hControlInf,
  1884. MyGetDecoratedSectionName(hControlInf, TEXT("NativeDataToWowData.SetupINF.FilesToExclude")),
  1885. FileName,
  1886. &ControlContext)){
  1887. return TRUE;
  1888. }
  1889. }
  1890. if (KeywordName == KeywordArray[INDEX_COPYFILES]) {
  1891. //
  1892. // if we didn't have a file rename in copyfiles, we add it now.
  1893. //
  1894. if ((--i) < SetupGetFieldCount(&KeywordContext)) {
  1895. _tcscat(LineText, TEXT(","));
  1896. if( MyGetFilePrefix( hControlInf, FileName, Prefix )){
  1897. _tcscat(LineText, Prefix);
  1898. }
  1899. _tcscat(LineText, FileName);
  1900. }
  1901. if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("LineText(2) - %s\n"),LineText);
  1902. } else if (KeywordName == KeywordArray[INDEX_ADDREG] ||
  1903. KeywordName == KeywordArray[INDEX_DELREG]) {
  1904. //
  1905. // we need to pad out AddReg or DelReg if necessary.
  1906. //
  1907. DWORD count;
  1908. TCHAR Entry[MAX_PATH];
  1909. count = SetupGetFieldCount(&KeywordContext);
  1910. if (count > i ) {
  1911. while (i <= count) {
  1912. if(SetupGetStringField(&KeywordContext,i,Cmd,LINE_LEN,NULL)
  1913. && Cmd[0]) {
  1914. if (!_tcsicmp(Cmd,TEXT("RegistryFlags"))) {
  1915. //
  1916. // look in the appropriate control inf section for the data
  1917. //
  1918. if (!SetupFindFirstLine(
  1919. hControlInf,
  1920. MyGetDecoratedSectionName(hControlInf, TEXT("NativeDataToWowData.SetupINF.RegistryInformation")),
  1921. TEXT("RegistryFlags"),
  1922. &ControlContext)) {
  1923. _ftprintf(stderr, TEXT("SetupFindFirstLine [%s] failed, ec = 0x%08x\n"),FileName,GetLastError());
  1924. RetVal = FALSE;
  1925. goto exit;
  1926. }
  1927. if (!SetupGetStringField(&ControlContext,1,Entry,sizeof(Entry)/sizeof(TCHAR),NULL)) {
  1928. _ftprintf(stderr, TEXT("SetupGetStringField [%s] failed, ec = 0x%08x\n"),FileName,GetLastError());
  1929. RetVal = FALSE;
  1930. goto exit;
  1931. }
  1932. _tcscat(LineText, TEXT(","));
  1933. _tcscat(LineText, Entry);
  1934. }
  1935. }
  1936. if (i != count) {
  1937. _tcscat(LineText, TEXT(","));
  1938. }
  1939. i +=1;
  1940. }
  1941. }
  1942. }else if (KeywordName == KeywordArray[INDEX_REGISTERDLLS]) {
  1943. // Check if we need to exclude this file from RegisterDlls
  1944. if( SetupFindFirstLine(
  1945. hControlInf,
  1946. MyGetDecoratedSectionName(hControlInf, TEXT("NativeDataToWowData.SetupINF.FilesToExcludeFromRegistration")),
  1947. FileName,
  1948. &ControlContext)){
  1949. return TRUE;
  1950. }
  1951. }
  1952. myftprintf(OutFile, fDoAnsiOutput, TEXT("%s\n"),LineText);
  1953. RetVal = TRUE;
  1954. exit:
  1955. return(RetVal);
  1956. }
  1957. BOOL
  1958. pOutputSectionData(
  1959. IN PVOID StringTable,
  1960. IN LONG StringId,
  1961. IN PCTSTR String,
  1962. IN PPERSECTION_CONTEXT SectionContext,
  1963. IN UINT SectionContextSize,
  1964. IN LPARAM cntxt
  1965. )
  1966. /*++
  1967. Routine Description:
  1968. String table callback.
  1969. This routine outputs the contents of the specified section to both the
  1970. system layout file and the output file.
  1971. Arguments:
  1972. Standard string table callback args.
  1973. Return Value:
  1974. Boolean indicating outcome. If FALSE, an error will have been logged.
  1975. FALSE also stops the string table enumeration and causes pSetupStringTableEnum()
  1976. to return FALSE. There is a bug in setupapi where we will jump into
  1977. the next hash_bucket and may process few more entries.
  1978. --*/
  1979. {
  1980. TCHAR LineText[MAX_INF_STRING_LENGTH];
  1981. BOOL RetVal;
  1982. INFCONTEXT LineContext;
  1983. DWORD EntryCount,i,SectionCount;
  1984. INFCONTEXT InputContext;
  1985. UCHAR line[MAX_INF_STRING_LENGTH];
  1986. PSETUPINF_CONTEXT Context = (PSETUPINF_CONTEXT)cntxt;
  1987. if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("Enumerating Section %s\n"), String);
  1988. //
  1989. // output the decorated section header
  1990. //
  1991. myftprintf(Context->OutFile, fDoAnsiOutput, TEXT("[%s%s]\n"),FilePrefix,String);
  1992. //
  1993. // get the section context
  1994. //
  1995. if(! SetupFindFirstLine(
  1996. Context->hInputInf,
  1997. String,
  1998. NULL,
  1999. &InputContext)){
  2000. _ftprintf(stderr, TEXT("Could not find lines in Section %s\n"), String);
  2001. //continue with next section
  2002. return TRUE;
  2003. }
  2004. if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("Output Section %s\n"), String);
  2005. do {
  2006. SectionCount = SetupGetLineCount(Context->hInputInf,String);
  2007. for (i = 0; i < SectionCount; i++) {
  2008. if (SetupGetLineByIndex(
  2009. Context->hInputInf,
  2010. String,
  2011. i,&InputContext)) {
  2012. //
  2013. // get the keyword for the section we're mapping
  2014. //
  2015. PCTSTR KeywordName = NULL;
  2016. DWORD j=0;
  2017. MYASSERT(SectionContext->KeywordVector != 0);
  2018. while (!KeywordName) {
  2019. if (SectionContext->KeywordVector & (1<<j)) {
  2020. KeywordName = KeywordArray[j];
  2021. break;
  2022. }
  2023. j += 1;
  2024. }
  2025. MYASSERT(KeywordName != NULL);
  2026. //
  2027. // filter and output the data
  2028. //
  2029. AppendSetupInfDataToSection(
  2030. Context->OutFile,
  2031. Context->hControlInf,
  2032. &InputContext,
  2033. KeywordName );
  2034. if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("Got back from AppendSetupInfDataToSection\n"));
  2035. //
  2036. // output the data to the layout file if we need to
  2037. //
  2038. if ((SectionContext->KeywordVector & KEYWORD_NEEDLAYOUTDATA) && Context->OutLayoutFile) {
  2039. if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("Calling AppendSetupInfDataToLayoutFile\n"));
  2040. AppendSetupInfDataToLayoutFile(
  2041. Context->OutLayoutFile,
  2042. Context->OutInfLayoutFile,
  2043. Context->hControlInf,
  2044. Context->hInputInf,
  2045. &InputContext );
  2046. if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("Got back from AppendSetupInfDataToLayoutFile\n"));
  2047. }
  2048. } else {
  2049. _ftprintf(stderr, TEXT("SetupGetLineByIndex failed, ec = %d\n"), GetLastError());
  2050. return(FALSE);
  2051. }
  2052. }
  2053. } while (SetupFindNextLine( &InputContext,
  2054. &InputContext)); // bugbug is this really
  2055. // necessary ??
  2056. myftprintf(Context->OutFile, fDoAnsiOutput, TEXT("\n"));
  2057. RetVal = TRUE;
  2058. return(RetVal);
  2059. }
  2060. BOOL
  2061. pOutputDestinationDirs(
  2062. IN PVOID StringTable,
  2063. IN LONG StringId,
  2064. IN PCTSTR String,
  2065. IN PPERSECTION_CONTEXT SectionContext,
  2066. IN UINT SectionContextSize,
  2067. IN LPARAM cntxt
  2068. )
  2069. /*++
  2070. Routine Description:
  2071. String table callback.
  2072. This routine outputs the destination dirs keyword
  2073. followed by the decorated section name and dirid mapping.
  2074. Arguments:
  2075. Standard string table callback args.
  2076. Return Value:
  2077. Boolean indicating outcome. If FALSE, an error will have been logged.
  2078. FALSE also stops the string table enumeration and causes pSetupStringTableEnum()
  2079. to return FALSE.
  2080. --*/
  2081. {
  2082. TCHAR LineText[MAX_INF_STRING_LENGTH];
  2083. BOOL RetVal;
  2084. INFCONTEXT LineContext;
  2085. DWORD EntryCount,i,cch;
  2086. PSETUPINF_CONTEXT Context = (PSETUPINF_CONTEXT)cntxt;
  2087. //
  2088. // only process this entry if it need destination dirs
  2089. //
  2090. if (0 == (SectionContext->KeywordVector & (KEYWORD_NEEDDESTDIRS))) {
  2091. RetVal = TRUE;
  2092. goto exit;
  2093. }
  2094. //
  2095. // first output "destinationdirs" if we haven't done so already
  2096. //
  2097. if (!Context->AlreadyOutputKeyword) {
  2098. myftprintf(Context->OutFile, fDoAnsiOutput, TEXT("[DestinationDirs]\n"));
  2099. Context->AlreadyOutputKeyword = TRUE;
  2100. }
  2101. //
  2102. // now get the unfiltered data so that we can filter it
  2103. //
  2104. if( !SetupFindFirstLine(
  2105. Context->hInputInf,
  2106. TEXT("DestinationDirs"),
  2107. String,
  2108. &LineContext)){
  2109. SetupFindFirstLine(
  2110. Context->hInputInf,
  2111. TEXT("DestinationDirs"),
  2112. TEXT("DefaultDestDir"),
  2113. &LineContext);
  2114. }
  2115. ZeroMemory(LineText,sizeof(LineText));
  2116. cch = sizeof(LineText)/sizeof(LineText[0]);
  2117. EntryCount = SetupGetFieldCount(&LineContext);
  2118. for (i = 1; i<=EntryCount; i++) {
  2119. TCHAR Entry[MAX_PATH+1]; // The extra character is for the possible comma at the end.
  2120. INFCONTEXT ControlContext;
  2121. DWORD cchEntry;
  2122. //
  2123. // get the current text to be appended
  2124. //
  2125. if (!SetupGetStringField(&LineContext,i,Entry,MAX_PATH,NULL)) {
  2126. _ftprintf(stderr, TEXT("SetupGetStringField failed, ec = 0x%08x\n"),GetLastError());
  2127. RetVal = FALSE;
  2128. goto exit;
  2129. }
  2130. //
  2131. // now do any necessary substitutions
  2132. //
  2133. if (i == 1) {
  2134. _stprintf(Entry, TEXT("%d"), SectionContext->DestinationDir);
  2135. }
  2136. //
  2137. // now append a comma if necessary
  2138. //
  2139. if (i !=EntryCount) {
  2140. _tcscat(Entry, TEXT(","));
  2141. }
  2142. //
  2143. // check for buffer overruns
  2144. //
  2145. cchEntry = _tcslen(Entry);
  2146. if (cchEntry >= cch) {
  2147. _ftprintf(stderr, TEXT("pOutputDestinationDirs: line too long, File = %s\n"), String);
  2148. RetVal = FALSE;
  2149. goto exit;
  2150. }
  2151. _tcscat(LineText, Entry);
  2152. cch -= cchEntry;
  2153. if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("LineText = %s\n"), LineText, SectionContext->DestinationDir);
  2154. }
  2155. //
  2156. // output the filtered data
  2157. //
  2158. myftprintf(Context->OutFile, fDoAnsiOutput, TEXT("%s%s=%s\n"),FilePrefix,String,LineText);
  2159. RetVal = TRUE;
  2160. exit:
  2161. return(RetVal);
  2162. }
  2163. BOOL
  2164. DoSetupINF(
  2165. IN PCTSTR InputInfA,
  2166. IN PCTSTR ControlInfA,
  2167. IN FILE *OutFile,
  2168. IN FILE *OutLayoutFile,
  2169. IN FILE *OutInfLayoutFile
  2170. )
  2171. /*++
  2172. Routine Description:
  2173. Filters a setupapi-based INF.
  2174. Arguments:
  2175. InputInfA - name of the inf to be filtered.
  2176. ControlInfA - name of the control directive inf
  2177. OutFile - output file handle
  2178. OutLayoutFile - output file handle for layout information
  2179. OutInfLayoutFile - output file handle for layout information contained in this INF
  2180. Return Value:
  2181. NONE.
  2182. --*/
  2183. {
  2184. PCWSTR InputInf;
  2185. PCWSTR ControlInf;
  2186. HINF hInputInf;
  2187. HINF hControlInf;
  2188. INFCONTEXT InfContext;
  2189. SETUPINF_CONTEXT Context;
  2190. PERSECTION_CONTEXT SectionContext;
  2191. FILE *HeaderFile;
  2192. TCHAR SourceArchitecture[10];
  2193. TCHAR SourceDiskFiles[80];
  2194. BOOL FirstTime;
  2195. PTSTR Sections,Current;
  2196. DWORD SizeNeeded;
  2197. PVOID FilteredSectionsStringTable;
  2198. BOOL b;
  2199. b = FALSE;
  2200. //
  2201. // initialize and open the infs
  2202. //
  2203. #ifdef UNICODE
  2204. InputInf = InputInfA;
  2205. #else
  2206. InputInf = pSetupAnsiToUnicode(InputInfA);
  2207. #endif
  2208. if (!InputInf) {
  2209. _ftprintf(stderr,TEXT("Unable to convert %s to Unicode %d\n"),InputInfA, GetLastError());
  2210. goto e0;
  2211. }
  2212. #ifdef UNICODE
  2213. ControlInf = ControlInfA;
  2214. #else
  2215. ControlInf = pSetupAnsiToUnicode(ControlInfA);
  2216. #endif
  2217. if (!ControlInf) {
  2218. _ftprintf(stderr,TEXT("Unable to convert %s to Unicode %d\n"),ControlInfA, GetLastError());
  2219. goto e1;
  2220. }
  2221. hInputInf = SetupOpenInfFileW(InputInf,NULL,INF_STYLE_WIN4,NULL);
  2222. if(hInputInf == INVALID_HANDLE_VALUE) {
  2223. _ftprintf(stderr,TEXT("Unable to open Inf %ws, ec=0x%08x\n"),InputInf, GetLastError());
  2224. goto e2;
  2225. }
  2226. hControlInf = SetupOpenInfFileW(ControlInf,NULL,INF_STYLE_WIN4,NULL);
  2227. if(hControlInf == INVALID_HANDLE_VALUE) {
  2228. _ftprintf(stderr,TEXT("Unable to open Inf %ws, ec=0x%08x\n"),ControlInf, GetLastError());
  2229. goto e3;
  2230. }
  2231. myftprintf(OutFile, fDoAnsiOutput, TEXT("\n\n"));
  2232. //
  2233. // write the output file header
  2234. //
  2235. HeaderFile = _tfopen(HeaderText,TEXT("rt"));
  2236. if (HeaderFile) {
  2237. while (!feof(HeaderFile)) {
  2238. TCHAR Buffer[100];
  2239. DWORD CharsRead;
  2240. CharsRead = fread(Buffer,sizeof(TCHAR),sizeof(Buffer)/sizeof(TCHAR),HeaderFile);
  2241. if (CharsRead) {
  2242. fwrite(Buffer,sizeof(TCHAR),CharsRead,OutFile);
  2243. }
  2244. }
  2245. fclose(HeaderFile);
  2246. }
  2247. myftprintf(OutFile, fDoAnsiOutput, TEXT("\n"));
  2248. //
  2249. // get all of the section names
  2250. //
  2251. if (!SetupGetInfSections(hInputInf, NULL, 0, &SizeNeeded)) {
  2252. _ftprintf(stderr,TEXT("Unable to get section names, ec=0x%08x\n"), GetLastError());
  2253. goto e4;
  2254. }
  2255. if (SizeNeeded == 0) {
  2256. b= TRUE;
  2257. goto e4;
  2258. }
  2259. Sections = pSetupMalloc (SizeNeeded + 1);
  2260. if (!Sections) {
  2261. _ftprintf(stderr,TEXT("Unable to allocate memory, ec=0x%08x\n"), GetLastError());
  2262. goto e4;
  2263. }
  2264. if (!SetupGetInfSections(hInputInf, Sections, SizeNeeded, NULL)) {
  2265. _ftprintf(stderr,TEXT("Unable to allocate memory, ec=0x%08x\n"), GetLastError());
  2266. goto e5;
  2267. }
  2268. FilteredSectionsStringTable = pSetupStringTableInitializeEx( sizeof(PERSECTION_CONTEXT),0);
  2269. if (!FilteredSectionsStringTable) {
  2270. _ftprintf(stderr,TEXT("Unable to create string table, ec=0x%08x\n"), GetLastError());
  2271. goto e5;
  2272. }
  2273. Current = Sections;
  2274. Context.OutFile = OutFile;
  2275. Context.OutLayoutFile = OutLayoutFile;
  2276. Context.OutInfLayoutFile = OutInfLayoutFile;
  2277. Context.hControlInf = hControlInf;
  2278. Context.hInputInf = hInputInf;
  2279. Context.AlreadyOutputKeyword = FALSE;
  2280. //
  2281. // process each section, which will output the
  2282. // sections names and keywords that we want to filter
  2283. //
  2284. while (*Current) {
  2285. if (SetupFindFirstLine(
  2286. hControlInf,
  2287. MyGetDecoratedSectionName(hControlInf, TEXT("NativeDataToWowData.SetupINF.ExcludeSection")),
  2288. Current,
  2289. &InfContext)) {
  2290. _ftprintf(stderr, TEXT("Skipping section %s as per [NativeDataToWowData.SetupINF.ExcludeSection]: ec = 0x%08x\n"), Current, GetLastError());
  2291. Current += lstrlen(Current)+1;
  2292. continue;
  2293. }
  2294. if (fDoVerboseDebugOutput) _ftprintf(stderr,TEXT("Processing section %s\n"), Current );
  2295. pFilterSetupInfSection(
  2296. FilteredSectionsStringTable,
  2297. Current,
  2298. &Context);
  2299. Current += lstrlen(Current)+1;
  2300. }
  2301. myftprintf(Context.OutFile, fDoAnsiOutput, TEXT("\n"));
  2302. //
  2303. // for each section that we decided to filter, we now need to output the
  2304. // actual section
  2305. //
  2306. pSetupStringTableEnum(
  2307. FilteredSectionsStringTable,
  2308. &SectionContext,
  2309. sizeof(PERSECTION_CONTEXT),
  2310. pOutputSectionData,
  2311. (LPARAM)&Context
  2312. );
  2313. //
  2314. // now we need to output the destination dirs section
  2315. //
  2316. pSetupStringTableEnum(
  2317. FilteredSectionsStringTable,
  2318. &SectionContext,
  2319. sizeof(PERSECTION_CONTEXT),
  2320. pOutputDestinationDirs,
  2321. (LPARAM)&Context
  2322. );
  2323. b = TRUE;
  2324. pSetupStringTableDestroy(FilteredSectionsStringTable);
  2325. e5:
  2326. pSetupFree(Sections);
  2327. e4:
  2328. SetupCloseInfFile( hControlInf );
  2329. e3:
  2330. SetupCloseInfFile( hInputInf );
  2331. e2:
  2332. #ifndef UNICODE
  2333. pSetupFree(ControlInf);
  2334. #endif
  2335. e1:
  2336. #ifndef UNICODE
  2337. pSetupFree(InputInf);
  2338. #endif
  2339. e0:
  2340. return(b);
  2341. }
  2342. void
  2343. Usage(
  2344. VOID
  2345. )
  2346. /*++
  2347. Routine Description:
  2348. Prints the usage to stderr.
  2349. Arguments:
  2350. NONE.
  2351. Return Value:
  2352. NONE.
  2353. --*/
  2354. {
  2355. _fputts( TEXT("generate list of wow files. Usage:\n")
  2356. TEXT("wowlist <options> <inf file> -c <control inf> -l <ole inf> -o <output file> -a{cos} -h <header file> -g <section> -d <output layout> -f <file prefix>\n")
  2357. TEXT("\n")
  2358. TEXT(" -i <inf file> - input inf containing list of dependencies\n")
  2359. TEXT(" -c <control inf> - contains directives for creating list.\n")
  2360. TEXT(" -l <OLE inf> - contains ole registration directives.\n")
  2361. TEXT(" -o <output file> - output list\n")
  2362. TEXT(" -g <section> - SetupAPI INF filtering decoration for per-inf filtering\n")
  2363. TEXT(" -h <header file> - append this to top of the output list\n")
  2364. TEXT(" -s <section name> - specifies section in OLE Inf to process\n")
  2365. TEXT(" -d <output layout> - output layout.inf information for SetupAPI INF filtering\n")
  2366. TEXT(" -f <file prefix> - specifies the decoration to be prepended to filtered files.\n")
  2367. TEXT(" -a <c|o|s> - specifies filter action\n")
  2368. TEXT(" -u - create UNICODE output list (only with /o)\n")
  2369. TEXT(" -n <file> - create layout file for SourceDisksFiles within the INF (to be appended to INF itself)\n")
  2370. TEXT("\tc - Create copy list.\n")
  2371. TEXT("\to - Create OLE list.\n")
  2372. TEXT("\ts - Create SetupINF list.\n")
  2373. TEXT("\n")
  2374. TEXT("\n"),
  2375. stderr );
  2376. }
  2377. int
  2378. __cdecl
  2379. _tmain(
  2380. IN int argc,
  2381. IN TCHAR *argv[]
  2382. )
  2383. {
  2384. FILE *hFileOut,*hFileLayoutOut = NULL, *hFileInfLayoutOut=NULL;
  2385. BOOL b;
  2386. //
  2387. // Assume failure.
  2388. //
  2389. b = FALSE;
  2390. if(!pSetupInitializeUtils()) {
  2391. return FAILURE;
  2392. }
  2393. if(!ParseArgs(argc,argv)) {
  2394. Usage();
  2395. goto exit;
  2396. }
  2397. //
  2398. // Open the output file.
  2399. //
  2400. if( fDoAnsiOutput )
  2401. hFileOut = _tfopen(OutputFile,TEXT("wt"));
  2402. else
  2403. hFileOut = _tfopen(OutputFile,TEXT("wb"));
  2404. if(hFileOut) {
  2405. if (Action == BuildCopyList) {
  2406. _ftprintf(stdout,TEXT("%s: creating copy list %s from %s and %s\n"),
  2407. ThisProgramName,
  2408. OutputFile,
  2409. InputInf,
  2410. ControlInf);
  2411. b = DoCopyList(
  2412. InputInf,
  2413. ControlInf,
  2414. hFileOut );
  2415. } else if (Action == BuildOLEList) {
  2416. _ftprintf(stdout,
  2417. TEXT("%s: creating OLE list %s from %s, %s, and %s\n"),
  2418. ThisProgramName,
  2419. OutputFile,
  2420. InputInf,
  2421. OLEInputInf,
  2422. ControlInf);
  2423. b = DoOLEList(
  2424. InputInf,
  2425. OLEInputInf,
  2426. ControlInf,
  2427. hFileOut );
  2428. } else if (Action == BuildSetupINF) {
  2429. if( OutputLayoutFile )
  2430. hFileLayoutOut = _tfopen(OutputLayoutFile,TEXT("wt"));
  2431. // Check if we want to process layout information that needs to be added
  2432. // to the INF itself. This is used for INFs that have their own layout information.
  2433. // This file will get the layout information for thunked files which had
  2434. // SourceDisksFiles entries within this INF.
  2435. if(OutputInfLayoutFile){
  2436. if( fDoAnsiOutput )
  2437. hFileInfLayoutOut = _tfopen(OutputInfLayoutFile,TEXT("wt"));
  2438. else
  2439. hFileInfLayoutOut = _tfopen(OutputInfLayoutFile,TEXT("wb"));
  2440. }
  2441. _ftprintf(stdout,
  2442. TEXT("%s: creating SetupINF list %s (layout %s) from %s and %s\n"),
  2443. ThisProgramName,
  2444. OutputFile,
  2445. OutputLayoutFile,
  2446. InputInf,
  2447. ControlInf);
  2448. b = DoSetupINF(
  2449. InputInf,
  2450. ControlInf,
  2451. hFileOut,
  2452. hFileLayoutOut,
  2453. hFileInfLayoutOut);
  2454. if( hFileLayoutOut )
  2455. fclose( hFileLayoutOut );
  2456. if( hFileInfLayoutOut )
  2457. fclose( hFileInfLayoutOut );
  2458. } else {
  2459. _ftprintf(stderr,TEXT("unknown action."));
  2460. MYASSERT(FALSE);
  2461. }
  2462. fclose(hFileOut);
  2463. } else {
  2464. _ftprintf(stderr,TEXT("%s: Unable to create output file %s\n"),ThisProgramName,OutputFile);
  2465. }
  2466. exit:
  2467. pSetupUninitializeUtils();
  2468. return(b ? SUCCESS : FAILURE);
  2469. }