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
3148 lines
89 KiB
/*++
|
|
|
|
Copyright (c) 1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
wowlist.c
|
|
|
|
Abstract:
|
|
|
|
This module implements a program that determines which files in an NT
|
|
product INF should be installed as wow files. It then builds a list
|
|
of these files that can be appended to other sections in a master inf.
|
|
|
|
The input to the program consists of a filtered NT product INF (for example
|
|
the layout.inf for i386, all products), and a control INF that specifies
|
|
mappings and rules about how to migrate files.
|
|
|
|
Author:
|
|
|
|
Andrew Ritz (andrewr) 24-Nov-1999 Created It.
|
|
|
|
Revision History:
|
|
ATM Shafiqul Khalid(askhalid) 27-April-2001
|
|
Make changes in HandleSetupapiQuotingForString() to add double
|
|
quote if the string contains ','.
|
|
|
|
|
|
--*/
|
|
|
|
#include <windows.h>
|
|
#include <tchar.h>
|
|
#include <stdio.h>
|
|
#include <setupapi.h>
|
|
#include <sputils.h>
|
|
#include <shlwapi.h>
|
|
|
|
#if DBG
|
|
|
|
VOID
|
|
AssertFail(
|
|
IN PSTR FileName,
|
|
IN UINT LineNumber,
|
|
IN PSTR Condition
|
|
)
|
|
{
|
|
int i;
|
|
CHAR Name[MAX_PATH];
|
|
PCHAR p;
|
|
CHAR Msg[MAX_INF_STRING_LENGTH];
|
|
|
|
//
|
|
// Use dll name as caption
|
|
//
|
|
GetModuleFileNameA(NULL,Name,MAX_PATH);
|
|
if(p = strrchr(Name,'\\')) {
|
|
p++;
|
|
} else {
|
|
p = Name;
|
|
}
|
|
|
|
wsprintfA(
|
|
Msg,
|
|
"Assertion failure at line %u in file %s: %s\n\nCall DebugBreak()?",
|
|
LineNumber,
|
|
FileName,
|
|
Condition
|
|
);
|
|
|
|
OutputDebugStringA(Msg);
|
|
|
|
i = MessageBoxA(
|
|
NULL,
|
|
Msg,
|
|
p,
|
|
MB_YESNO | MB_TASKMODAL | MB_ICONSTOP | MB_SETFOREGROUND
|
|
);
|
|
|
|
if(i == IDYES) {
|
|
DebugBreak();
|
|
}
|
|
}
|
|
|
|
#define MYASSERT(x) if(!(x)) { AssertFail(__FILE__,__LINE__,#x); }
|
|
|
|
#else
|
|
|
|
#define MYASSERT( exp )
|
|
|
|
#endif // DBG
|
|
|
|
//
|
|
// String Macros
|
|
//
|
|
#define AS(x) ( sizeof(x) / sizeof(x[0]) )
|
|
#define LSTRCPY(x,y) ( lstrcpyn(x, y, AS(x)) )
|
|
#define LSTRCAT(x,y) ( lstrcpyn(x + lstrlen(x), y, AS(x) - lstrlen(x)) )
|
|
|
|
//
|
|
// backward-compatible depreciated export from setupapi.dll
|
|
//
|
|
|
|
BOOL
|
|
SetupGetInfSections (
|
|
IN HINF InfHandle,
|
|
OUT PTSTR Buffer, OPTIONAL
|
|
IN UINT Size, OPTIONAL
|
|
OUT UINT *SizeNeeded OPTIONAL
|
|
);
|
|
|
|
//
|
|
// Define program result codes (returned from main()).
|
|
//
|
|
#define SUCCESS 0
|
|
#define FAILURE 1
|
|
|
|
typedef enum _WOWLISTACTION {
|
|
BuildCopyList,
|
|
BuildOLEList,
|
|
BuildSetupINF,
|
|
WowListMax
|
|
} WOWLISTACTION;
|
|
|
|
#define KEYWORD_COPYFILES 0x00000001
|
|
#define KEYWORD_DELFILES 0x00000002
|
|
#define KEYWORD_RENFILES 0x00000004
|
|
#define KEYWORD_REGISTERDLLS 0x00000008
|
|
#define KEYWORD_UNREGISTERDLLS 0x00000010
|
|
#define KEYWORD_ADDREG 0x00000020
|
|
#define KEYWORD_DELREG 0x00000040
|
|
|
|
#define KEYWORD_NEEDDESTDIRS (KEYWORD_COPYFILES | KEYWORD_DELFILES | KEYWORD_RENFILES)
|
|
#define KEYWORD_NEEDLAYOUTDATA (KEYWORD_COPYFILES)
|
|
#define KEYWORD_NEEDFILENAME (KEYWORD_COPYFILES)
|
|
|
|
|
|
PCTSTR KeywordArray[] = {
|
|
TEXT("CopyFiles"),
|
|
TEXT("DelFiles"),
|
|
TEXT("RenFiles"),
|
|
TEXT("RegisterDlls"),
|
|
TEXT("UnRegisterDlls"),
|
|
TEXT("AddReg"),
|
|
TEXT("DelReg")
|
|
} ;
|
|
|
|
#define INDEX_COPYFILES 0
|
|
#define INDEX_DELFILES 1
|
|
#define INDEX_RENFILES 2
|
|
#define INDEX_REGISTERDLLS 3
|
|
#define INDEX_UNREGISTERDLLS 4
|
|
#define INDEX_ADDREG 5
|
|
#define INDEX_DELREG 6
|
|
|
|
typedef struct _PERSECTION_CONTEXT {
|
|
//
|
|
// remember the destinationdir that we're outputting to
|
|
//
|
|
DWORD DestinationDir;
|
|
|
|
//
|
|
// remember the keywords we're processing
|
|
//
|
|
DWORD KeywordVector;
|
|
} PERSECTION_CONTEXT, *PPERSECTION_CONTEXT;
|
|
|
|
|
|
typedef struct _SETUPINF_CONTEXT {
|
|
FILE * OutFile;
|
|
FILE * OutLayoutFile;
|
|
FILE * OutInfLayoutFile;
|
|
HINF hControlInf;
|
|
HINF hInputInf;
|
|
BOOL AlreadyOutputKeyword;
|
|
} SETUPINF_CONTEXT, *PSETUPINF_CONTEXT;
|
|
|
|
typedef struct _SUBST_STRING {
|
|
PTSTR InputString;
|
|
PTSTR SourceInputString;
|
|
PTSTR OutputString;
|
|
} SUBST_STRING,*PSUBST_STRING;
|
|
|
|
//
|
|
// note that WOW64 does file system redirection of system32, but it does NOT do
|
|
// redirection of program files, etc. So we must substitute in the 32 bit
|
|
// environment variables in those cases where WOW64 does not do it for us
|
|
// automatically
|
|
//
|
|
SUBST_STRING StringArray[] = {
|
|
//
|
|
// order of these 2 is important!
|
|
//
|
|
{ NULL, TEXT("%SystemRoot%\\system32"), TEXT("%16425%") },
|
|
{ NULL, TEXT("%SystemRoot%"), TEXT("%10%") },
|
|
//
|
|
// order of these 2 is important!
|
|
//
|
|
{ NULL, TEXT("%CommonProgramFiles%"), TEXT("%16428%") },
|
|
{ NULL, TEXT("%ProgramFiles%"), TEXT("%16426%") },
|
|
{ NULL, TEXT("%SystemDrive%"), TEXT("%30%") }
|
|
} ;
|
|
|
|
PSUBST_STRING StringList;
|
|
|
|
//
|
|
// Keep statistics...
|
|
//
|
|
INT ProcessedLines = 0;
|
|
|
|
TCHAR InputInf[MAX_PATH];
|
|
TCHAR ControlInf[MAX_PATH];
|
|
TCHAR OLEInputInf[MAX_PATH];
|
|
PCTSTR OutputFile;
|
|
PCTSTR OutputLayoutFile = NULL;
|
|
PCTSTR HeaderText;
|
|
PCTSTR OLESection;
|
|
PCTSTR FilePrefix;
|
|
PCTSTR SectionDecoration;
|
|
PCTSTR ThisProgramName;
|
|
WOWLISTACTION Action = WowListMax;
|
|
BOOL fDoAnsiOutput = TRUE;
|
|
BOOL fDoVerboseDebugOutput = FALSE;
|
|
BOOL g_PostBuild = FALSE;
|
|
PCTSTR OutputInfLayoutFile = NULL;
|
|
|
|
//
|
|
// a global scratch buffer for getting a decorated sectionname
|
|
//
|
|
TCHAR DecoratedSectionName[MAX_PATH];
|
|
|
|
//
|
|
// global scratch buffer for line data
|
|
//
|
|
TCHAR LineText[MAX_INF_STRING_LENGTH];
|
|
TCHAR ScratchText[MAX_INF_STRING_LENGTH];
|
|
TCHAR ScratchTextEnv[MAX_INF_STRING_LENGTH];
|
|
|
|
PSUBST_STRING InitializeStringList(
|
|
VOID
|
|
)
|
|
{
|
|
DWORD SizeNeeded,i;
|
|
PSUBST_STRING StringList;
|
|
|
|
SizeNeeded = (sizeof(StringArray)/sizeof(SUBST_STRING)) *
|
|
(sizeof(SUBST_STRING)+(MAX_PATH*sizeof(TCHAR)));
|
|
|
|
StringList = pSetupMalloc( SizeNeeded );
|
|
|
|
if (!StringList) {
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return(NULL);
|
|
}
|
|
|
|
RtlCopyMemory( StringList, &StringArray, sizeof(StringArray) );
|
|
|
|
for (i = 0; i < sizeof(StringArray)/sizeof(SUBST_STRING); i++) {
|
|
StringList[i].InputString = (PTSTR) ((PBYTE)StringList + (ULONG_PTR)sizeof(StringArray)+(i*sizeof(TCHAR)*MAX_PATH));
|
|
|
|
ExpandEnvironmentStrings( StringList[i].SourceInputString, StringList[i].InputString, MAX_PATH );
|
|
}
|
|
|
|
return StringList;
|
|
|
|
}
|
|
|
|
PTSTR
|
|
MyGetDecoratedSectionName(
|
|
HINF ControlInfHandle,
|
|
PCTSTR String
|
|
)
|
|
{
|
|
INFCONTEXT Context;
|
|
|
|
_tcscpy(DecoratedSectionName,String);
|
|
|
|
if (SectionDecoration){
|
|
_tcscat(DecoratedSectionName,TEXT("."));
|
|
_tcscat(DecoratedSectionName,SectionDecoration);
|
|
|
|
if( !SetupFindFirstLine(
|
|
ControlInfHandle,
|
|
DecoratedSectionName,
|
|
NULL,
|
|
&Context)){
|
|
_tcscpy(DecoratedSectionName,String);
|
|
}
|
|
|
|
}
|
|
|
|
return DecoratedSectionName;
|
|
|
|
|
|
}
|
|
|
|
void
|
|
FixupSetupapiPercents(
|
|
IN OUT PTSTR String
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine doubles up the '%' char if present in the input string.
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
String - input string to be searched. We edit this string
|
|
in-place if we find a match.
|
|
|
|
Return Value:
|
|
|
|
Boolean indicating outcome.
|
|
|
|
--*/
|
|
{
|
|
|
|
PTCHAR p,q;
|
|
|
|
if( !String || !String[0] )
|
|
return;
|
|
|
|
p = String;
|
|
q = ScratchTextEnv;
|
|
|
|
ZeroMemory(ScratchTextEnv,sizeof(ScratchTextEnv));
|
|
|
|
while( *p && (q < (ScratchTextEnv+MAX_INF_STRING_LENGTH-1)) ){
|
|
|
|
if (*p == TEXT('%')) {
|
|
*(q++) = TEXT('%');
|
|
}
|
|
*q = *p;
|
|
|
|
p++;
|
|
q++;
|
|
}
|
|
*q = 0;
|
|
|
|
lstrcpy( String, ScratchTextEnv );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
BOOL
|
|
pSubstituteEnvVarsForActualPaths(
|
|
IN OUT PTSTR String
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine filters and outputs the input line. It looks for a string
|
|
pattern that matches one of a known list of strings, and replaces the
|
|
known string with a substitution string.
|
|
|
|
Arguments:
|
|
|
|
String - input string to be searched. We edit this string
|
|
in-place if we find a match.
|
|
|
|
Return Value:
|
|
|
|
Boolean indicating outcome.
|
|
|
|
--*/
|
|
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
|
|
if (!StringList) {
|
|
StringList = InitializeStringList();
|
|
if (!StringList) {
|
|
RetVal = FALSE;
|
|
}
|
|
}
|
|
|
|
if (RetVal) {
|
|
DWORD i;
|
|
PTSTR p,q;
|
|
TCHAR c;
|
|
|
|
MYASSERT( StringList != NULL );
|
|
|
|
for (i = 0; i< sizeof(StringArray)/sizeof(SUBST_STRING); i++) {
|
|
if (p = StrStrI(String,StringList[i].InputString)) {
|
|
//
|
|
// if we found a hit, then find the end of the string
|
|
// and concatenate that to our source string, which gives
|
|
// the resultant string with substitutions.
|
|
//
|
|
q = p + _tcslen(StringList[i].InputString);
|
|
c = *p;
|
|
*p = TEXT('\0');
|
|
_tcscpy(ScratchTextEnv,String);
|
|
*p = c;
|
|
_tcscat(ScratchTextEnv,StringList[i].OutputString);
|
|
_tcscat(ScratchTextEnv,q);
|
|
_tcscpy(String,ScratchTextEnv);
|
|
//
|
|
// recursively call in case there are more strings.
|
|
//
|
|
pSubstituteEnvVarsForActualPaths(String);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return(RetVal);
|
|
}
|
|
|
|
BOOL
|
|
MyGetFilePrefix(
|
|
HINF ControlInfHandle,
|
|
PCTSTR Filename,
|
|
PTSTR Prefix
|
|
)
|
|
{
|
|
|
|
TCHAR Entry[MAX_PATH];
|
|
INFCONTEXT ControlContext;
|
|
|
|
if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("MyGetFilePrefix: Called for %s\n"), Filename);
|
|
|
|
if( !Filename || !Prefix ) {
|
|
_ftprintf(stderr, TEXT("MyGetFilePrefix: Filename or prefix bad - Filename - %s\n"), Filename);
|
|
return FALSE;
|
|
}
|
|
|
|
if( !FilePrefix ){
|
|
Prefix[0] = (TCHAR)NULL;
|
|
}else{
|
|
lstrcpy( Prefix, FilePrefix );
|
|
}
|
|
|
|
|
|
|
|
|
|
if (SetupFindFirstLine(
|
|
ControlInfHandle,
|
|
TEXT("NativeDataToWowData.FilePrefixList"),
|
|
Filename,
|
|
&ControlContext)) {
|
|
|
|
if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("MyGetFilePrefix: SetupFindFirstLine succeeded for %s\n"), Filename);
|
|
|
|
if (!SetupGetStringField(&ControlContext,1,Entry,sizeof(Entry)/sizeof(TCHAR),NULL)) {
|
|
_ftprintf(stderr, TEXT("MyGetFilePrefix():SetupGetStringField [%s] failed, ec = 0x%08x\n"),Filename,GetLastError());
|
|
}else{
|
|
lstrcpy( Prefix, Entry );
|
|
}
|
|
}else{
|
|
if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("MyGetFilePrefix: SetupFindFirstLine failed for %s - ec = 0x%08x\n"), Filename,GetLastError());
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
BOOL
|
|
ParseArgs(
|
|
IN int argc,
|
|
IN TCHAR *argv[]
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function reads the cmdline, translating arguments into the appropriate
|
|
global variable.
|
|
|
|
Arguments:
|
|
|
|
argc - number of arguments from main().
|
|
argv - argument array.
|
|
|
|
Return Value:
|
|
|
|
Boolean value, true indicates that the cmdline arguments are valid.
|
|
|
|
--*/
|
|
|
|
{
|
|
int i;
|
|
PTSTR p;
|
|
ThisProgramName = argv[0];
|
|
|
|
|
|
if(argc < 4) {
|
|
return(FALSE);
|
|
}
|
|
|
|
for (i = 0; i < argc; i++) {
|
|
if (argv[i][0] == TEXT('-')) {
|
|
switch (tolower(argv[i][1])) {
|
|
case TEXT('a'):
|
|
switch(tolower(argv[i][2])) {
|
|
case TEXT('c'):
|
|
Action = BuildCopyList;
|
|
break;
|
|
case TEXT('o'):
|
|
Action = BuildOLEList;
|
|
break;
|
|
case TEXT('s'):
|
|
Action = BuildSetupINF;
|
|
break;
|
|
default:
|
|
_ftprintf(stderr, TEXT("unknown arg %s\n"),argv[i]);
|
|
return(FALSE);
|
|
}
|
|
break;
|
|
case TEXT('c'):
|
|
GetFullPathName(argv[i+1],sizeof(ControlInf)/sizeof(TCHAR),ControlInf,&p);
|
|
break;
|
|
case TEXT('d'):
|
|
OutputLayoutFile = argv[i+1];
|
|
break;
|
|
case TEXT('f'):
|
|
FilePrefix = argv[i+1];
|
|
break;
|
|
case TEXT('g'):
|
|
SectionDecoration = argv[i+1];
|
|
break;
|
|
case TEXT('h'):
|
|
HeaderText = argv[i+1];
|
|
break;
|
|
case TEXT('i'):
|
|
GetFullPathName(argv[i+1],sizeof(InputInf)/sizeof(TCHAR),InputInf,&p);
|
|
break;
|
|
case TEXT('l'):
|
|
GetFullPathName(argv[i+1],sizeof(OLEInputInf)/sizeof(TCHAR),OLEInputInf,&p);
|
|
break;
|
|
case TEXT('n'):
|
|
OutputInfLayoutFile = argv[i+1];
|
|
break;
|
|
case TEXT('o'):
|
|
OutputFile = argv[i+1];
|
|
break;
|
|
case TEXT('p'):
|
|
g_PostBuild = TRUE;
|
|
break;
|
|
case TEXT('s'):
|
|
OLESection = argv[i+1];
|
|
break;
|
|
case TEXT('u'):
|
|
fDoAnsiOutput = FALSE;
|
|
break;
|
|
case TEXT('v'):
|
|
fDoVerboseDebugOutput = TRUE;
|
|
break;
|
|
default:
|
|
_ftprintf(stderr, TEXT("unknown arg %s\n"),argv[i]);
|
|
return(FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
_ftprintf(stderr, TEXT("%s\n"),InputInf);
|
|
if (Action == WowListMax) {
|
|
return(FALSE);
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
int
|
|
myftprintf(
|
|
FILE * FileHandle,
|
|
BOOL AnsiOutput,
|
|
PCTSTR FormatString,
|
|
...
|
|
)
|
|
{
|
|
va_list arglist;
|
|
TCHAR text[MAX_INF_STRING_LENGTH];
|
|
DWORD d;
|
|
int retval;
|
|
|
|
|
|
|
|
va_start(arglist,FormatString);
|
|
|
|
_vstprintf(text,FormatString,arglist);
|
|
|
|
|
|
#ifdef UNICODE
|
|
|
|
if (AnsiOutput) {
|
|
PCSTR TextA = pSetupUnicodeToAnsi(text);
|
|
retval = fputs(TextA,FileHandle);
|
|
pSetupFree(TextA);
|
|
} else {
|
|
PWSTR p,q;
|
|
// Assume we opened the file in binary mode for Unicode stream I/O
|
|
p = text;
|
|
while(1){
|
|
if( q = wcschr( p, L'\n' )){
|
|
*q=L'\0';
|
|
retval = fputws(p,FileHandle);
|
|
retval = fputws(L"\r\n", FileHandle);
|
|
if( *(q+1) )
|
|
p = q+1;
|
|
else
|
|
break;
|
|
}else{
|
|
retval = fputws(p,FileHandle);
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
if (AnsiOutput) {
|
|
retval = fputs(text,FileHandle);
|
|
} else{
|
|
PCWSTR TextW = pSetupAnsiToUnicode(text);
|
|
retval = fputws(TextW,FileHandle);
|
|
pSetupFree(TextW);
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
return(retval);
|
|
}
|
|
|
|
BOOL
|
|
AppendWowFileToCopyList(
|
|
IN HINF hControlInf,
|
|
IN PINFCONTEXT LineContext,
|
|
IN FILE *OutFile
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine appends the file specified by LineContext to the output file,
|
|
writing the data in a form required by textmode setup. see layout.inx for
|
|
a detailed description of this syntax.
|
|
|
|
Arguments:
|
|
|
|
hControlInf - inf handle that contains control directives.
|
|
LineContext - inf context from layout.inf for the file we want to output.
|
|
OutFile - file handle to write the data into
|
|
|
|
Return Value:
|
|
|
|
Boolean value, true indicates the file was properly written.
|
|
|
|
--*/
|
|
{
|
|
TCHAR LineText[MAX_INF_STRING_LENGTH];
|
|
TCHAR TempFileName[MAX_PATH], FileName[MAX_PATH], Prefix[40];
|
|
BOOL RetVal;
|
|
|
|
DWORD EntryCount,i;
|
|
|
|
|
|
ZeroMemory(LineText,sizeof(LineText));
|
|
ZeroMemory(Prefix,sizeof(Prefix));
|
|
|
|
|
|
|
|
//
|
|
// get the filename
|
|
//
|
|
if (!SetupGetStringField(
|
|
LineContext,
|
|
0,
|
|
TempFileName,
|
|
sizeof(TempFileName)/sizeof(TCHAR),
|
|
NULL)) {
|
|
_ftprintf(stderr, TEXT("SetupGetStringField failed, ec = 0x%08x\n"),GetLastError());
|
|
RetVal = FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("Current File - %s\n"),TempFileName);
|
|
|
|
MyGetFilePrefix( hControlInf, TempFileName, Prefix );
|
|
_tcscpy(FileName, Prefix);
|
|
_tcscat(FileName, TempFileName );
|
|
|
|
|
|
|
|
EntryCount = SetupGetFieldCount(LineContext);
|
|
|
|
for (i = 1; i<=EntryCount; i++) {
|
|
TCHAR Entry[40];
|
|
INFCONTEXT ControlContext;
|
|
|
|
//
|
|
// get the current text to be appended
|
|
//
|
|
if (!SetupGetStringField(LineContext,i,Entry,sizeof(Entry)/sizeof(TCHAR),NULL)) {
|
|
_ftprintf(stderr, TEXT("SetupGetStringField [%s] failed, ec = 0x%08x\n"),FileName,GetLastError());
|
|
RetVal = FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// now do any necessary substitutions
|
|
//
|
|
|
|
//
|
|
// SourceDisksNames substitution
|
|
//
|
|
if (i == 1) {
|
|
//
|
|
// look in the appropriate control inf section for the data
|
|
//
|
|
if (!SetupFindFirstLine(
|
|
hControlInf,
|
|
TEXT("NativeDataToWowData.SourceInfo"),
|
|
Entry,
|
|
&ControlContext)) {
|
|
_ftprintf(stderr, TEXT("SetupFindFirstLine [%s] failed, ec = 0x%08x\n"),FileName,GetLastError());
|
|
RetVal = FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
if (!SetupGetStringField(&ControlContext,1,Entry,sizeof(Entry)/sizeof(TCHAR),NULL)) {
|
|
_ftprintf(stderr, TEXT("SetupGetStringField [%s] failed, ec = 0x%08x\n"),FileName,GetLastError());
|
|
RetVal = FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Directory Id substitution
|
|
//
|
|
if (i == 8) {
|
|
//
|
|
// look in the appropriate control inf section for the data
|
|
//
|
|
if (!SetupFindFirstLine(
|
|
hControlInf,
|
|
TEXT("NativeDataToWowData.DirectoryInformation.Textmode"),
|
|
Entry,
|
|
&ControlContext)) {
|
|
_ftprintf(stderr, TEXT("SetupFindFirstLine [%s] failed, ec = 0x%08x\n"),FileName,GetLastError());
|
|
RetVal = FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
if (!SetupGetStringField(&ControlContext,1,Entry,sizeof(Entry)/sizeof(TCHAR),NULL)) {
|
|
_ftprintf(stderr, TEXT("SetupGetStringField [%s] failed, ec = 0x%08x\n"),FileName,GetLastError());
|
|
RetVal = FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// filename rename
|
|
//
|
|
if (i == 11) {
|
|
//
|
|
// if there was already a renaming to be done, then just use that.
|
|
// otherwise we may have to add a rename entry if there was a
|
|
// filename prefix
|
|
//
|
|
if (Entry[0] == (TCHAR)NULL) {
|
|
if (Prefix[0]) {
|
|
_tcsncpy(Entry, TempFileName, AS(Entry));
|
|
}
|
|
}
|
|
}
|
|
|
|
_tcscat(LineText, Entry);
|
|
|
|
//
|
|
// now append a comma if necessary
|
|
//
|
|
if (i !=EntryCount) {
|
|
_tcscat(LineText, TEXT(","));
|
|
}
|
|
|
|
//
|
|
// filename rename
|
|
//
|
|
if (EntryCount < 11 && i == EntryCount) {
|
|
//
|
|
// if there is no renaming to be done, we may have to add a rename
|
|
// entry if there was a filename prefix
|
|
//
|
|
if (Prefix[0]) {
|
|
DWORD j;
|
|
for (j=i;j<11;j++) {
|
|
_tcscat(LineText, TEXT(","));
|
|
}
|
|
_tcscat(LineText, TempFileName);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
if( g_PostBuild ){
|
|
myftprintf(OutFile, fDoAnsiOutput, TEXT("%s:%s=%s\n"),TempFileName,FileName,LineText);
|
|
}else{
|
|
myftprintf(OutFile, fDoAnsiOutput, TEXT("%s=%s\n"),FileName,LineText);
|
|
}
|
|
|
|
RetVal = TRUE;
|
|
|
|
exit:
|
|
return(RetVal);
|
|
}
|
|
|
|
BOOL
|
|
AppendWowFileToOLEList(
|
|
IN HINF hControlInf,
|
|
IN HINF hOLEInputInf,
|
|
IN PINFCONTEXT LineContext,
|
|
IN FILE *OutFile
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine appends the file specified by LineContext to the output file,
|
|
writing the data in OLE Registration form.
|
|
|
|
OLE Registration form is as follows:
|
|
|
|
<DIRID>,<subdir>,filename,[flags]
|
|
|
|
where <DIRID> is a standard setupapi DIRID; <subdir> is optional and
|
|
represents a subdir of the given directory; filename is the name
|
|
of the dll.
|
|
|
|
|
|
Arguments:
|
|
|
|
hControlInf - inf handle that contains control directives.
|
|
hOLEInputInf - inf handle that contains OLE list information.
|
|
LineContext - inf context from layout.inf for the file we want to output.
|
|
OutFile - file handle to write the data into
|
|
|
|
Return Value:
|
|
|
|
Boolean value, true indicates the file was properly written.
|
|
|
|
--*/
|
|
{
|
|
TCHAR LineText[MAX_INF_STRING_LENGTH];
|
|
BOOL RetVal;
|
|
INFCONTEXT OLEContext;
|
|
|
|
DWORD EntryCount,i;
|
|
|
|
|
|
ZeroMemory(LineText,sizeof(LineText));
|
|
|
|
EntryCount = SetupGetFieldCount(LineContext);
|
|
|
|
for (i = 1; i<=EntryCount; i++) {
|
|
TCHAR Entry[MAX_INF_STRING_LENGTH];
|
|
INFCONTEXT ControlContext;
|
|
|
|
//
|
|
// get the current text to be appended
|
|
//
|
|
if (!SetupGetStringField(LineContext,i,Entry,sizeof(Entry)/sizeof(TCHAR),NULL)) {
|
|
_ftprintf(stderr, TEXT("SetupGetStringField failed, ec = 0x%08x\n"),GetLastError());
|
|
RetVal = FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("Entry (1)- %s\n"),Entry);
|
|
FixupSetupapiPercents(Entry);
|
|
if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("Entry (2)- %s\n"),Entry);
|
|
pSubstituteEnvVarsForActualPaths(Entry);
|
|
|
|
if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("Entry (3)- %s\n"),Entry);
|
|
|
|
//
|
|
// now do any necessary substitutions
|
|
//
|
|
|
|
//
|
|
// DIRID substitution
|
|
//
|
|
if (i == 1) {
|
|
//
|
|
// look in the appropriate control inf section for the data
|
|
//
|
|
if (!SetupFindFirstLine(
|
|
hControlInf,
|
|
TEXT("NativeDataToWowData.DirectoryInformation.SetupAPI"),
|
|
Entry,
|
|
&ControlContext)) {
|
|
_ftprintf(stderr, TEXT("SetupFindFirstLine failed, ec = 0x%08x\n"),GetLastError());
|
|
RetVal = FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
if (!SetupGetStringField(&ControlContext,1,Entry,sizeof(Entry)/sizeof(TCHAR),NULL)) {
|
|
_ftprintf(stderr, TEXT("SetupGetStringField failed, ec = 0x%08x\n"),GetLastError());
|
|
RetVal = FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
}
|
|
|
|
_tcscat(LineText, Entry);
|
|
|
|
//
|
|
// now append a comma if necessary
|
|
//
|
|
if (i !=EntryCount) {
|
|
_tcscat(LineText, TEXT(","));
|
|
}
|
|
|
|
}
|
|
|
|
myftprintf(OutFile, TRUE, TEXT("%s\n"),LineText);
|
|
|
|
RetVal = TRUE;
|
|
|
|
exit:
|
|
return(RetVal);
|
|
}
|
|
|
|
|
|
BOOL
|
|
IsWowFile(
|
|
IN HINF hControlInf,
|
|
IN PINFCONTEXT LineContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine determines if the specified file is to be installed for
|
|
as a wow file.
|
|
|
|
This is determined by comparing directives in the control inf with
|
|
the installation information in file inf context.
|
|
|
|
|
|
Arguments:
|
|
|
|
hControlInf - inf handle that contains control directives.
|
|
LineContext - inf context from layout.inf for the file we want to examine.
|
|
|
|
Return Value:
|
|
|
|
Boolean value, true indicates the file is a wow file.
|
|
|
|
--*/
|
|
{
|
|
BOOL RetVal = FALSE;
|
|
TCHAR FileName[40];
|
|
DWORD Disposition,DirectoryId;
|
|
PTSTR p;
|
|
|
|
INFCONTEXT ControlContext;
|
|
TCHAR Extension[8];
|
|
DWORD ExtensionCount,i;
|
|
DWORD ControlDirId;
|
|
|
|
//
|
|
// get the filename
|
|
//
|
|
if (!SetupGetStringField(LineContext,0,FileName,sizeof(FileName)/sizeof(TCHAR),NULL)) {
|
|
_ftprintf(stderr, TEXT("SetupGetStringField failed, ec = 0x%08x\n"),GetLastError());
|
|
RetVal = FALSE;
|
|
goto e0;
|
|
}
|
|
|
|
//
|
|
// see if the file is in our "exclusion list"
|
|
//
|
|
if(SetupFindFirstLine(
|
|
hControlInf,
|
|
TEXT("WowData.Files.Exclude"),
|
|
FileName,
|
|
&ControlContext)) {
|
|
_ftprintf(stderr,
|
|
TEXT("filtering %ws because it's in our exclusion list\n"),
|
|
FileName);
|
|
RetVal = FALSE;
|
|
SetLastError(ERROR_SUCCESS);
|
|
goto e0;
|
|
}
|
|
|
|
//
|
|
// see if the file is in our "inclusion list"
|
|
//
|
|
if(SetupFindFirstLine(
|
|
hControlInf,
|
|
TEXT("WowData.Files.Include"),
|
|
FileName,
|
|
&ControlContext)) {
|
|
_ftprintf(stderr,
|
|
TEXT("force inclusion of [%ws] because it's in our inclusion list\n"),
|
|
FileName);
|
|
RetVal = TRUE;
|
|
SetLastError(ERROR_SUCCESS);
|
|
goto e0;
|
|
}
|
|
|
|
//
|
|
// see if the file is installed by textmode setup
|
|
//
|
|
if (!SetupGetIntField(LineContext,9,&Disposition)) {
|
|
_ftprintf(stderr, TEXT("SetupGetIntField (%ws) failed, ec = 0x%08x\n"),FileName,GetLastError());
|
|
RetVal = FALSE;
|
|
goto e0;
|
|
}
|
|
|
|
if (Disposition == 3) {
|
|
_ftprintf(stderr, TEXT("[%ws] is not an installed file\n"),FileName);
|
|
SetLastError(ERROR_SUCCESS);
|
|
RetVal = FALSE;
|
|
goto e0;
|
|
}
|
|
|
|
//
|
|
// get the extension of the file and compare it to the list of extensions
|
|
// we're trolling for
|
|
//
|
|
p = _tcsrchr( FileName, TEXT('.') );
|
|
if (p) {
|
|
p+=1;
|
|
} else {
|
|
_ftprintf(stderr, TEXT("[%ws] does not have a file extension\n"),FileName);
|
|
p = TEXT("");
|
|
}
|
|
|
|
|
|
|
|
if(!SetupFindFirstLine(
|
|
hControlInf,
|
|
TEXT("WowData.Filter"),
|
|
TEXT("FileExtensions"),
|
|
&ControlContext
|
|
)) {
|
|
_ftprintf(stderr, TEXT("SetupFindFirstLine (ControlInf) failed\n"));
|
|
RetVal = FALSE;
|
|
goto e0;
|
|
}
|
|
|
|
RetVal = FALSE;
|
|
|
|
|
|
do{
|
|
|
|
ExtensionCount = SetupGetFieldCount(&ControlContext);
|
|
//
|
|
// this is a 1-based index
|
|
//
|
|
for (i = 1; i <= ExtensionCount ; i++) {
|
|
if (SetupGetStringField(&ControlContext,i,Extension,sizeof(Extension)/sizeof(TCHAR),NULL)) {
|
|
if (_tcsicmp(Extension,p)==0) {
|
|
RetVal = TRUE;
|
|
break;
|
|
}
|
|
}else{
|
|
_ftprintf(stderr, TEXT("SetupGetStringField failed, ec = 0x%08x\n"),GetLastError());
|
|
RetVal = FALSE;
|
|
goto e0;
|
|
|
|
}
|
|
}
|
|
|
|
}while(SetupFindNextMatchLine(&ControlContext, TEXT("FileExtensions"), &ControlContext));
|
|
|
|
if (!RetVal) {
|
|
_ftprintf(stderr, TEXT("%ws does not match extension list\n"),FileName);
|
|
SetLastError(ERROR_SUCCESS);
|
|
goto e0;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// get the directory the file is installed into and see if it's in our list
|
|
// of directories we're trolling for.
|
|
//
|
|
if (!SetupGetIntField(LineContext,8,&DirectoryId)) {
|
|
_ftprintf(stderr, TEXT("SetupGetIntField (%ws) failed, ec = 0x%08x\n"),FileName,GetLastError());
|
|
RetVal = FALSE;
|
|
goto e0;
|
|
}
|
|
|
|
RetVal = FALSE;
|
|
if(!SetupFindFirstLine(
|
|
hControlInf,
|
|
TEXT("WowData.Filter"),
|
|
TEXT("DirectoryToMap"),
|
|
&ControlContext
|
|
)) {
|
|
_ftprintf(stderr, TEXT("SetupFindFirstLine failed, ec = 0x%08x\n"),GetLastError());
|
|
RetVal = FALSE;
|
|
goto e0;
|
|
}
|
|
|
|
do {
|
|
|
|
if (!SetupGetIntField(&ControlContext,1,&ControlDirId)) {
|
|
_ftprintf(stderr, TEXT("SetupGetIntField (\"DirectoryToMap\") (%ws) failed, ec = 0x%08x\n"),FileName,GetLastError());
|
|
RetVal = FALSE;
|
|
goto e0;
|
|
}
|
|
|
|
if (ControlDirId == DirectoryId) {
|
|
RetVal = TRUE;
|
|
break;
|
|
}
|
|
|
|
} while ( SetupFindNextMatchLine(&ControlContext,TEXT("DirectoryToMap"),&ControlContext ));
|
|
|
|
if (!RetVal) {
|
|
_ftprintf(stderr, TEXT("directory id %d for [%ws] is not in list\n"),DirectoryId,FileName);
|
|
SetLastError(ERROR_SUCCESS);
|
|
goto e0;
|
|
}
|
|
|
|
e0:
|
|
return(RetVal);
|
|
}
|
|
|
|
BOOL
|
|
IsWowOLEFile(
|
|
IN HINF hControlInf,
|
|
IN HINF hInputInf,
|
|
IN PINFCONTEXT LineContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine determines if the specified file requires OLE self
|
|
registration.
|
|
|
|
This is determined by comparing directives in the control inf with
|
|
the installation information in file inf context.
|
|
|
|
|
|
Arguments:
|
|
|
|
hControlInf - inf handle that contains control directives.
|
|
hInputInf - inf handle that contains layout information.
|
|
LineContext - inf context from syssetup.inf for the file we want to examine.
|
|
|
|
Return Value:
|
|
|
|
Boolean value, true indicates the file is a wow file.
|
|
|
|
--*/
|
|
{
|
|
BOOL RetVal = FALSE;
|
|
TCHAR FileName[40];
|
|
PTSTR p;
|
|
TCHAR SourceArchitecture[10];
|
|
TCHAR SourceDiskFiles[80];
|
|
BOOL FirstTime;
|
|
|
|
INFCONTEXT ControlContext,InfContext;
|
|
INFCONTEXT InputContext;
|
|
|
|
|
|
//
|
|
// get the filename
|
|
//
|
|
FileName[0] = L'\0';
|
|
if (!SetupGetStringField(LineContext,3,FileName,sizeof(FileName)/sizeof(TCHAR),NULL)) {
|
|
_ftprintf(stderr, TEXT("SetupGetStringField [%s] failed, ec = 0x%08x\n"),FileName,GetLastError());
|
|
RetVal = FALSE;
|
|
goto e0;
|
|
}
|
|
|
|
|
|
MYASSERT(FileName[0] != (TCHAR)NULL);
|
|
|
|
//
|
|
// see if the file is in our "exclusion list"
|
|
//
|
|
if(SetupFindFirstLine(
|
|
hControlInf,
|
|
TEXT("WowData.OLEList.Exclude"),
|
|
FileName,
|
|
&ControlContext)) {
|
|
_ftprintf(stderr,
|
|
TEXT("filtering %ws because it's in our exclusion list\n"),
|
|
FileName);
|
|
SetLastError(ERROR_SUCCESS);
|
|
RetVal = FALSE;
|
|
goto e0;
|
|
}
|
|
|
|
//
|
|
// see if the file is in our "inclusion list"
|
|
//
|
|
if(SetupFindFirstLine(
|
|
hControlInf,
|
|
TEXT("WowData.OLELIst.Include"),
|
|
FileName,
|
|
&ControlContext)) {
|
|
_ftprintf(stderr,
|
|
TEXT("force inclusion of [%ws] because it's in our inclusion list\n"),
|
|
FileName);
|
|
SetLastError(ERROR_SUCCESS);
|
|
RetVal = TRUE;
|
|
goto e0;
|
|
}
|
|
|
|
//
|
|
// see if the file is in the layout file and if it is,
|
|
// we have success
|
|
//
|
|
//
|
|
// get the required architecture decoration
|
|
//
|
|
if (!SetupFindFirstLine(
|
|
hControlInf,
|
|
TEXT("WowData.Filter"),
|
|
TEXT("SourceArchitecture"),
|
|
&InfContext) ||
|
|
!SetupGetStringField(
|
|
&InfContext,
|
|
1,
|
|
SourceArchitecture,
|
|
sizeof(SourceArchitecture)/sizeof(TCHAR),
|
|
NULL)) {
|
|
_ftprintf(stderr,TEXT("Unable to get SourceArchitecture\n"));
|
|
goto e0;
|
|
}
|
|
|
|
FirstTime = TRUE;
|
|
_tcscpy(SourceDiskFiles, TEXT("SourceDisksFiles"));
|
|
|
|
while (TRUE) {
|
|
DWORD FileCount;
|
|
|
|
if (!FirstTime) {
|
|
_tcscat(SourceDiskFiles,TEXT("."));
|
|
_tcscat(SourceDiskFiles,SourceArchitecture);
|
|
}
|
|
|
|
if(SetupFindFirstLine(
|
|
hInputInf,
|
|
SourceDiskFiles,
|
|
FileName,
|
|
&InputContext) &&
|
|
IsWowFile(hControlInf,&InputContext)) {
|
|
RetVal = TRUE;
|
|
break;
|
|
}
|
|
|
|
if (!FirstTime) {
|
|
RetVal = FALSE;
|
|
break;
|
|
}
|
|
|
|
FirstTime = FALSE;
|
|
|
|
}
|
|
|
|
e0:
|
|
SetLastError(ERROR_SUCCESS);
|
|
return(RetVal);
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
DoCopyListSection(
|
|
IN PCTSTR InputSectionName,
|
|
IN HINF hInputInf,
|
|
IN HINF hControlInf,
|
|
IN FILE *OutFile
|
|
)
|
|
{
|
|
DWORD SectionCount, i;
|
|
INFCONTEXT InputContext;
|
|
UCHAR line[MAX_INF_STRING_LENGTH];
|
|
TCHAR SourceFileName[MAX_PATH];
|
|
|
|
if(!SetupFindFirstLine(
|
|
hInputInf,
|
|
InputSectionName,
|
|
NULL,
|
|
&InputContext)){
|
|
_ftprintf(stderr, TEXT("%s: Warning - Section %s not present: Ignoring Section\n"), ThisProgramName, InputSectionName);
|
|
return(TRUE);
|
|
|
|
}
|
|
|
|
SectionCount = SetupGetLineCount(hInputInf,InputSectionName);
|
|
|
|
|
|
for (i = 0; i < SectionCount; i++) {
|
|
if (SetupGetLineByIndex(hInputInf, InputSectionName, i, &InputContext)) {
|
|
if (IsWowFile(hControlInf,&InputContext)) {
|
|
|
|
AppendWowFileToCopyList(hControlInf,&InputContext, OutFile);
|
|
|
|
} else if (GetLastError() != NO_ERROR) {
|
|
_ftprintf(stderr, TEXT("IsWowFile failed\n"));
|
|
return(FALSE);
|
|
}
|
|
} else {
|
|
_ftprintf(stderr, TEXT("SetupGetLineByIndex failed, ec = %d\n"), GetLastError());
|
|
return(FALSE);
|
|
}
|
|
|
|
ProcessedLines += 1;
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
BOOL
|
|
DoCopyList(
|
|
IN PCTSTR InputInfA,
|
|
IN PCTSTR ControlInfA,
|
|
IN FILE *OutFile
|
|
)
|
|
{
|
|
PCWSTR InputInf;
|
|
PCWSTR ControlInf;
|
|
HINF hInputInf;
|
|
HINF hControlInf;
|
|
INFCONTEXT InfContext;
|
|
FILE *HeaderFile;
|
|
|
|
TCHAR SourceArchitecture[10];
|
|
TCHAR SourceDiskFiles[80];
|
|
BOOL FirstTime;
|
|
|
|
|
|
BOOL b;
|
|
|
|
b = TRUE;
|
|
|
|
|
|
//
|
|
// initialize and open the infs
|
|
//
|
|
#ifdef UNICODE
|
|
InputInf = InputInfA;
|
|
#else
|
|
InputInf = pSetupAnsiToUnicode(InputInfA);
|
|
#endif
|
|
if (!InputInf) {
|
|
_ftprintf(stderr,TEXT("Unable to convert %s to Unicode %d\n"),InputInfA, GetLastError());
|
|
goto e0;
|
|
}
|
|
|
|
#ifdef UNICODE
|
|
ControlInf = ControlInfA;
|
|
#else
|
|
ControlInf = pSetupAnsiToUnicode(ControlInfA);
|
|
#endif
|
|
|
|
if (!ControlInf) {
|
|
_ftprintf(stderr,TEXT("Unable to convert %s to Unicode %d\n"),ControlInfA, GetLastError());
|
|
goto e1;
|
|
}
|
|
|
|
hInputInf = SetupOpenInfFileW(InputInf,NULL,INF_STYLE_WIN4,NULL);
|
|
if(hInputInf == INVALID_HANDLE_VALUE) {
|
|
_ftprintf(stderr,TEXT("Unable to open Inf %ws, ec=0x%08x\n"),InputInf, GetLastError());
|
|
goto e2;
|
|
}
|
|
|
|
hControlInf = SetupOpenInfFileW(ControlInf,NULL,INF_STYLE_WIN4,NULL);
|
|
if(hControlInf == INVALID_HANDLE_VALUE) {
|
|
_ftprintf(stderr,TEXT("Unable to open Inf %ws, ec=0x%08x\n"),ControlInf, GetLastError());
|
|
goto e3;
|
|
}
|
|
|
|
myftprintf(OutFile, fDoAnsiOutput, TEXT("\n\n"));
|
|
|
|
//
|
|
// write the output file header
|
|
//
|
|
HeaderFile = _tfopen(HeaderText,TEXT("rt"));
|
|
if (HeaderFile) {
|
|
while (!feof(HeaderFile)) {
|
|
TCHAR Buffer[100];
|
|
DWORD CharsRead;
|
|
|
|
CharsRead = fread(Buffer,sizeof(TCHAR),sizeof(Buffer)/sizeof(TCHAR),HeaderFile);
|
|
|
|
if (CharsRead) {
|
|
fwrite(Buffer,sizeof(TCHAR),CharsRead,OutFile);
|
|
}
|
|
}
|
|
fclose(HeaderFile);
|
|
}
|
|
myftprintf(OutFile, fDoAnsiOutput, TEXT("\n"));
|
|
|
|
//
|
|
// get the required architecture decoration
|
|
//
|
|
if (!SetupFindFirstLine(
|
|
hControlInf,
|
|
TEXT("WowData.Filter"),
|
|
TEXT("SourceArchitecture"),
|
|
&InfContext) ||
|
|
!SetupGetStringField(
|
|
&InfContext,
|
|
1,
|
|
SourceArchitecture,
|
|
sizeof(SourceArchitecture)/sizeof(TCHAR),
|
|
NULL)) {
|
|
_ftprintf(stderr,TEXT("Unable to get SourceArchitecture\n"));
|
|
goto e4;
|
|
}
|
|
|
|
FirstTime = TRUE;
|
|
_tcscpy(SourceDiskFiles, TEXT("SourceDisksFiles"));
|
|
|
|
while (TRUE) {
|
|
DWORD FileCount;
|
|
|
|
if (!FirstTime) {
|
|
_tcscat(SourceDiskFiles,TEXT("."));
|
|
_tcscat(SourceDiskFiles,SourceArchitecture);
|
|
}
|
|
|
|
DoCopyListSection(
|
|
SourceDiskFiles,
|
|
hInputInf,
|
|
hControlInf,
|
|
OutFile
|
|
);
|
|
|
|
if (FirstTime) {
|
|
FirstTime = FALSE;
|
|
} else {
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
e4:
|
|
SetupCloseInfFile( hControlInf );
|
|
e3:
|
|
SetupCloseInfFile( hInputInf );
|
|
e2:
|
|
#ifndef UNICODE
|
|
pSetupFree(ControlInf);
|
|
#endif
|
|
e1:
|
|
#ifndef UNICODE
|
|
pSetupFree(InputInf);
|
|
#endif
|
|
e0:
|
|
return(b);
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
DoOLEListSection(
|
|
IN HINF hInputInf,
|
|
IN HINF hOLEInputInf,
|
|
IN HINF hControlInf,
|
|
IN FILE *OutFile
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine iterates through all files in the input inf specified by the
|
|
section name. If the specified file is a WOW file, then we check if it
|
|
is in the ole registration list. If it is, then we do the appropriate
|
|
transform on the data and output the data to our data file.
|
|
|
|
Arguments:
|
|
|
|
hInputInf - inf handle with file list in it.
|
|
hOLEInputInf - inf handle with ole lists in it.
|
|
hControlInf - inf handle for control inf that drives our filters
|
|
OutFile - file handle where the output data gets placed into
|
|
|
|
Return Value:
|
|
|
|
Boolean value, true indicates the file is a wow file.
|
|
|
|
--*/
|
|
{
|
|
DWORD SectionCount, i;
|
|
INFCONTEXT InputContext;
|
|
UCHAR line[MAX_INF_STRING_LENGTH];
|
|
TCHAR SourceFileName[MAX_PATH];
|
|
|
|
SetupFindFirstLine(
|
|
hOLEInputInf,
|
|
OLESection,
|
|
NULL,
|
|
&InputContext);
|
|
|
|
SectionCount = SetupGetLineCount(hOLEInputInf,OLESection);
|
|
|
|
for (i = 0; i < SectionCount; i++) {
|
|
if (SetupGetLineByIndex(hOLEInputInf, OLESection, i, &InputContext)) {
|
|
if (IsWowOLEFile(hControlInf,hInputInf, &InputContext)) {
|
|
|
|
AppendWowFileToOLEList(hControlInf,hOLEInputInf,&InputContext, OutFile);
|
|
|
|
} else if (GetLastError() != NO_ERROR) {
|
|
_ftprintf(stderr, TEXT("IsWowOLEFile failed\n"));
|
|
return(FALSE);
|
|
}
|
|
} else {
|
|
_ftprintf(stderr, TEXT("SetupGetLineByIndex failed, ec = %d\n"), GetLastError());
|
|
return(FALSE);
|
|
}
|
|
|
|
ProcessedLines += 1;
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
BOOL
|
|
DoOLEList(
|
|
IN PCTSTR InputInfA,
|
|
IN PCTSTR OLEInputInfA,
|
|
IN PCTSTR ControlInfA,
|
|
IN FILE *OutFile
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine runs through the list of specified files in the input inf
|
|
and feeds them into a worker routine which will build the list of OLE
|
|
Control dlls.
|
|
|
|
Arguments:
|
|
|
|
InputInfA - name of input inf containing the files to be run through
|
|
our "filter"
|
|
OLEInputInfA - name of input inf containing the ole directives to be
|
|
processed
|
|
ControlInfA - name of the control inf that tells us how to parse the
|
|
input infs
|
|
OutFile - file pointer for the file to be written
|
|
|
|
Return Value:
|
|
|
|
Boolean value, true indicates the file is a wow file.
|
|
|
|
--*/
|
|
{
|
|
PCWSTR InputInf;
|
|
PCWSTR OLEInputInf;
|
|
PCWSTR ControlInf;
|
|
HINF hInputInf;
|
|
HINF hControlInf;
|
|
HINF hOLEInputInf;
|
|
INFCONTEXT InfContext;
|
|
FILE *HeaderFile;
|
|
|
|
BOOL b = FALSE;
|
|
|
|
//
|
|
// initialize and open the infs
|
|
//
|
|
#ifdef UNICODE
|
|
InputInf = InputInfA;
|
|
#else
|
|
InputInf = pSetupAnsiToUnicode(InputInfA);
|
|
#endif
|
|
if (!InputInf) {
|
|
_ftprintf(stderr,TEXT("Unable to convert %s to Unicode %d\n"),InputInfA, GetLastError());
|
|
goto e0;
|
|
}
|
|
#ifdef UNICODE
|
|
ControlInf = ControlInfA;
|
|
#else
|
|
ControlInf = pSetupAnsiToUnicode(ControlInfA);
|
|
#endif
|
|
if (!ControlInf) {
|
|
_ftprintf(stderr,TEXT("Unable to convert %s to Unicode %d\n"),ControlInf, GetLastError());
|
|
goto e1;
|
|
}
|
|
|
|
#ifdef UNICODE
|
|
OLEInputInf = OLEInputInfA;
|
|
#else
|
|
OLEInputInf = pSetupAnsiToUnicode(OLEInputInfA);
|
|
#endif
|
|
|
|
if (!OLEInputInf) {
|
|
_ftprintf(stderr,TEXT("Unable to convert %s to Unicode %d\n"),OLEInputInfA, GetLastError());
|
|
goto e2;
|
|
}
|
|
|
|
hInputInf = SetupOpenInfFileW(InputInf,NULL,INF_STYLE_WIN4,NULL);
|
|
if(hInputInf == INVALID_HANDLE_VALUE) {
|
|
_ftprintf(stderr,TEXT("Unable to open Inf %ws, ec=0x%08x\n"),InputInf, GetLastError());
|
|
goto e3;
|
|
}
|
|
|
|
hOLEInputInf = SetupOpenInfFileW(OLEInputInf,NULL,INF_STYLE_WIN4,NULL);
|
|
if(hOLEInputInf == INVALID_HANDLE_VALUE) {
|
|
_ftprintf(stderr,TEXT("Unable to open Inf %ws, ec=0x%08x\n"),OLEInputInf, GetLastError());
|
|
goto e4;
|
|
}
|
|
|
|
hControlInf = SetupOpenInfFileW(ControlInf,NULL,INF_STYLE_WIN4,NULL);
|
|
if(hControlInf == INVALID_HANDLE_VALUE) {
|
|
_ftprintf(stderr,TEXT("Unable to open Inf %ws, ec=0x%08x\n"),ControlInf, GetLastError());
|
|
goto e5;
|
|
}
|
|
|
|
myftprintf(OutFile, TRUE, TEXT("\n\n"));
|
|
|
|
//
|
|
// write the output file header
|
|
//
|
|
HeaderFile = _tfopen(HeaderText,TEXT("rt"));
|
|
if (HeaderFile) {
|
|
while (!feof(HeaderFile)) {
|
|
TCHAR Buffer[100];
|
|
DWORD CharsRead;
|
|
|
|
CharsRead = fread(Buffer,sizeof(TCHAR),sizeof(Buffer)/sizeof(TCHAR),HeaderFile);
|
|
|
|
if (CharsRead) {
|
|
fwrite(Buffer,sizeof(TCHAR),CharsRead,OutFile);
|
|
}
|
|
}
|
|
}
|
|
|
|
myftprintf(OutFile, TRUE, TEXT("\n"));
|
|
|
|
|
|
b = DoOLEListSection(
|
|
hInputInf,
|
|
hOLEInputInf,
|
|
hControlInf,
|
|
OutFile
|
|
);
|
|
|
|
SetupCloseInfFile( hControlInf );
|
|
e5:
|
|
SetupCloseInfFile( hOLEInputInf );
|
|
e4:
|
|
SetupCloseInfFile( hInputInf );
|
|
e3:
|
|
#ifndef UNICODE
|
|
pSetupFree(OLEInputInf);
|
|
#endif
|
|
e2:
|
|
#ifndef UNICODE
|
|
pSetupFree(ControlInf);
|
|
#endif
|
|
e1:
|
|
#ifndef UNICODE
|
|
pSetupFree(InputInf);
|
|
#endif
|
|
e0:
|
|
return(b);
|
|
}
|
|
|
|
BOOL
|
|
pFilterSetupInfSection(
|
|
PVOID FilteredSectionsStringTable,
|
|
PCTSTR SectionName,
|
|
PSETUPINF_CONTEXT Context
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine determines if a given section should be filtered by
|
|
looking in the control inf for the directives that we're interested
|
|
in.
|
|
|
|
Arguments:
|
|
|
|
FilteredSectionsStringTable - pointer to a string table which we'll
|
|
add our filtered section name to if we find a hit
|
|
|
|
SectionName - name of the section in the INF we're interested in
|
|
|
|
Context - contains context information for this function, like
|
|
input infs name, etc.
|
|
|
|
Return Value:
|
|
|
|
Boolean value, true indicates the file is a wow file.
|
|
|
|
--*/
|
|
{
|
|
BOOL RetVal;
|
|
TCHAR KeywordList[MAX_PATH];
|
|
PCTSTR CurrentKeyword;
|
|
DWORD KeywordBitmap;
|
|
INFCONTEXT ControlInfContext;
|
|
DWORD i;
|
|
BOOL AlreadyOutputSectionName,AlreadyOutputKeyword;
|
|
|
|
//
|
|
// get the keywords that we're supposed to map.
|
|
//
|
|
// bugbug look at having a per-inf extension to this
|
|
//
|
|
if (!SetupFindFirstLine(
|
|
Context->hControlInf,
|
|
MyGetDecoratedSectionName(Context->hControlInf, TEXT("NativeDataToWowData.SetupINF.Keyword")),
|
|
TEXT("Keywords"),
|
|
&ControlInfContext)) {
|
|
_ftprintf(stderr, TEXT("Could not get Keywords line in [NativeDataToWowData.SetupINF.Keyword]: SetupFindFirstLine failed, ec = 0x%08x\n"),GetLastError());
|
|
RetVal = FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// now look for each keyword
|
|
//
|
|
SetupGetIntField(&ControlInfContext,1,&KeywordBitmap);
|
|
|
|
AlreadyOutputSectionName = FALSE;
|
|
AlreadyOutputKeyword = FALSE;
|
|
CurrentKeyword = NULL;
|
|
for (i = 0; i < 32;i++) {
|
|
INFCONTEXT InputInfContext;
|
|
INFCONTEXT ContextDirId;
|
|
BOOL LookatDirIds;
|
|
DWORD FieldCount,Field;
|
|
TCHAR ActualSectionName[LINE_LEN];
|
|
|
|
if (KeywordBitmap & (1<<i)) {
|
|
CurrentKeyword = KeywordArray[i];
|
|
MYASSERT( CurrentKeyword != NULL);
|
|
}
|
|
|
|
if (!CurrentKeyword) {
|
|
continue;
|
|
}
|
|
|
|
if (!SetupFindFirstLine(
|
|
Context->hControlInf,
|
|
MyGetDecoratedSectionName(Context->hControlInf, TEXT("NativeDataToWowData.SetupINF.Keyword")),
|
|
CurrentKeyword,
|
|
&ContextDirId)) {
|
|
_ftprintf(stderr, TEXT("Could not get %s line in [NativeDataToWowData.SetupINF.Keyword]: SetupFindFirstLine failed, ec = 0x%08x\n"), CurrentKeyword, GetLastError());
|
|
RetVal = FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// field 2 is "MapDirId". If it's specified, then we
|
|
// need to look at the destinationdirs keyword
|
|
//
|
|
LookatDirIds = (SetupGetFieldCount(&ContextDirId)>=2) ? TRUE : FALSE;
|
|
|
|
//
|
|
// look for specified keyword in our section
|
|
//
|
|
if (SetupFindFirstLine(
|
|
Context->hInputInf,
|
|
SectionName,
|
|
CurrentKeyword,
|
|
&InputInfContext
|
|
)) {
|
|
//
|
|
// we found a hit. see if we need to map this keyword
|
|
//
|
|
do {
|
|
|
|
//
|
|
// each field is a section name.
|
|
//
|
|
FieldCount = SetupGetFieldCount(&InputInfContext);
|
|
for(Field=1; Field<=FieldCount; Field++) {
|
|
BOOL MapThisSection = FALSE;
|
|
TCHAR DirId[LINE_LEN];
|
|
DWORD MappedDirId = 0;
|
|
INFCONTEXT InputDirId,ControlDirId;
|
|
|
|
SetupGetStringField(&InputInfContext,Field,ActualSectionName,LINE_LEN,NULL);
|
|
|
|
//
|
|
// if we need to look at the destination dirs keyword,
|
|
// then look it up and compare it against the control inf
|
|
// mapper
|
|
//
|
|
if (LookatDirIds) {
|
|
if(!SetupFindFirstLine(
|
|
Context->hInputInf,
|
|
TEXT("DestinationDirs"),
|
|
ActualSectionName,
|
|
&InputDirId)) {
|
|
if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("SetupFindFirstLine failed, ec = 0x%08x finding %s in %s \n"),GetLastError(), ActualSectionName, TEXT("DestinationDirs"));
|
|
|
|
if(!SetupFindFirstLine(
|
|
Context->hInputInf,
|
|
TEXT("DestinationDirs"),
|
|
TEXT("DefaultDestDir"),
|
|
&InputDirId)) {
|
|
_ftprintf(stderr, TEXT("SetupFindFirstLine failed, ec = 0x%08x finding %s in %s\n"),GetLastError(), TEXT("DefaultDestDir"), TEXT("DestinationDirs"));
|
|
RetVal = FALSE;
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
if(SetupGetStringField(&InputDirId,1,DirId,LINE_LEN,NULL) &&
|
|
SetupFindFirstLine(
|
|
Context->hControlInf,
|
|
MyGetDecoratedSectionName(Context->hControlInf, TEXT("NativeDataToWowData.SetupINF.DestinationDirsToMap")),
|
|
DirId,
|
|
&ControlDirId)) {
|
|
//
|
|
// we found a hit, thus we should map this section
|
|
//
|
|
MapThisSection = TRUE;
|
|
SetupGetIntField(&ControlDirId,1,&MappedDirId);
|
|
if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("Mapping %s to %lu\n"), DirId, MappedDirId);
|
|
|
|
}
|
|
} else {
|
|
MapThisSection = TRUE;
|
|
}
|
|
|
|
if (MapThisSection) {
|
|
DWORD StringId;
|
|
PERSECTION_CONTEXT SectionContext;
|
|
BOOL AddNewEntry;
|
|
//
|
|
// output the toplevel section name if we haven't done
|
|
// so already. this section name is not decorated
|
|
//
|
|
if (!AlreadyOutputSectionName) {
|
|
myftprintf(Context->OutFile, fDoAnsiOutput, TEXT("\n[%s]\n"),SectionName);
|
|
AlreadyOutputSectionName = TRUE;
|
|
}
|
|
|
|
//
|
|
// output the keyword and decorated section name
|
|
// note that we need to separate the section names
|
|
// by a comma
|
|
//
|
|
if (!AlreadyOutputKeyword) {
|
|
myftprintf(Context->OutFile, fDoAnsiOutput, TEXT("%s="), CurrentKeyword);
|
|
myftprintf(Context->OutFile, fDoAnsiOutput, TEXT("%s%s"),FilePrefix,ActualSectionName);
|
|
AlreadyOutputKeyword = TRUE;
|
|
} else {
|
|
myftprintf(Context->OutFile, fDoAnsiOutput, TEXT(",%s%s"),FilePrefix,ActualSectionName);
|
|
}
|
|
|
|
//
|
|
// now append the section to the string table
|
|
//
|
|
StringId = pSetupStringTableLookUpString(
|
|
FilteredSectionsStringTable,
|
|
(PTSTR)ActualSectionName,
|
|
STRTAB_CASE_INSENSITIVE);
|
|
|
|
if (StringId != -1) {
|
|
pSetupStringTableGetExtraData(
|
|
FilteredSectionsStringTable,
|
|
StringId,
|
|
&SectionContext,
|
|
sizeof(SectionContext));
|
|
AddNewEntry = FALSE;
|
|
} else {
|
|
RtlZeroMemory(&SectionContext,sizeof(SectionContext));
|
|
AddNewEntry = TRUE;
|
|
}
|
|
|
|
SectionContext.DestinationDir = MappedDirId;
|
|
SectionContext.KeywordVector |= (1<<i);
|
|
|
|
if (AddNewEntry) {
|
|
|
|
if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("Adding %s to string table\n"), ActualSectionName);
|
|
|
|
if ( -1 == pSetupStringTableAddStringEx(
|
|
FilteredSectionsStringTable,
|
|
(PTSTR)ActualSectionName,
|
|
STRTAB_CASE_SENSITIVE | STRTAB_NEW_EXTRADATA,
|
|
&SectionContext,
|
|
sizeof(SectionContext))){
|
|
|
|
_ftprintf(stderr, TEXT("Could not add %s to string table\n"), ActualSectionName);
|
|
|
|
|
|
}
|
|
} else {
|
|
|
|
if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("Adding %s to string table\n"), ActualSectionName);
|
|
|
|
if ( !pSetupStringTableSetExtraData(
|
|
FilteredSectionsStringTable,
|
|
StringId,
|
|
&SectionContext,
|
|
sizeof(SectionContext))){
|
|
|
|
_ftprintf(stderr, TEXT("Could not add %s to string table\n"), ActualSectionName);}
|
|
}
|
|
}
|
|
}
|
|
|
|
} while ( SetupFindNextMatchLine(&InputInfContext,
|
|
CurrentKeyword,
|
|
&InputInfContext ));
|
|
|
|
}
|
|
|
|
if (AlreadyOutputKeyword) {
|
|
myftprintf(Context->OutFile, fDoAnsiOutput, TEXT("\n"));
|
|
}
|
|
//
|
|
// reset this for the next keyword
|
|
//
|
|
AlreadyOutputKeyword = FALSE;
|
|
CurrentKeyword = NULL;
|
|
|
|
}
|
|
|
|
exit:
|
|
return(RetVal);
|
|
}
|
|
|
|
BOOL
|
|
AppendSetupInfDataToLayoutFile(
|
|
IN FILE *OutFile,
|
|
IN FILE *OutInfFile,
|
|
IN HINF hControlInf,
|
|
IN HINF hInputInf,
|
|
IN PINFCONTEXT LineContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine filters and outputs a layout line.
|
|
|
|
We only need to filter "Copyfiles" sections, and since the files are
|
|
not installed by textmode setup, the line which we output is largely
|
|
hardcoded.
|
|
|
|
|
|
Arguments:
|
|
|
|
OutFile - output file handle
|
|
|
|
OutInfFile - output file handle for layout information within INF
|
|
|
|
hControlInf - inf handle to the inf with the control directives
|
|
|
|
LineContext - inf context to the input line we want to filter.
|
|
|
|
Return Value:
|
|
|
|
Boolean indicating outcome.
|
|
|
|
--*/
|
|
{
|
|
TCHAR FileName[MAX_PATH],InfField[MAX_PATH],Entry[50], Prefix[40];
|
|
INFCONTEXT ControlContext;
|
|
BOOL RetVal;
|
|
INT SourceID = 1;
|
|
TCHAR SourceIDStr[6], DefaultIDStr[6];
|
|
BOOL LayoutWithinInf = FALSE;
|
|
|
|
DWORD EntryCount,i;
|
|
|
|
|
|
ZeroMemory(Entry,sizeof(Entry));
|
|
ZeroMemory(Prefix,sizeof(Prefix));
|
|
|
|
|
|
//
|
|
// get the source filename
|
|
//
|
|
EntryCount = SetupGetFieldCount(LineContext);
|
|
if ((((EntryCount <= 1)
|
|
|| !SetupGetStringField(LineContext,2,InfField,MAX_PATH,NULL)
|
|
|| !InfField[0]))
|
|
&& (!SetupGetStringField(LineContext,1,InfField,MAX_PATH,NULL)
|
|
|| !InfField[0])) {
|
|
//
|
|
// bad line?
|
|
//
|
|
MYASSERT(0);
|
|
_ftprintf(stderr, TEXT("AppendSetupInfDataToLayoutFile: Could not get source filename - ec = 0x%08x\n"), GetLastError());
|
|
}
|
|
|
|
MyGetFilePrefix( hControlInf, InfField, Prefix );
|
|
_tcscpy(FileName, Prefix);
|
|
_tcscat(FileName, InfField );
|
|
|
|
|
|
|
|
//
|
|
// see if the file is in our "SetupInf exclusion list"
|
|
//
|
|
if(SetupFindFirstLine(
|
|
hControlInf,
|
|
MyGetDecoratedSectionName(hControlInf, TEXT("WowData.SetupInfLayout.Exclude")),
|
|
InfField,
|
|
&ControlContext) ||
|
|
SetupFindFirstLine(
|
|
hControlInf,
|
|
MyGetDecoratedSectionName(hControlInf, TEXT("NativeDataToWowData.SetupINF.FilesToExclude")),
|
|
InfField,
|
|
&ControlContext)) {
|
|
_ftprintf(stderr,
|
|
TEXT("filtering %ws because it's in our SetupInf exclusion list\n"),
|
|
InfField);
|
|
RetVal = FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// Get Default Source ID
|
|
// By default this means the Source ID that is processed for dosnet.inf, txtsetup.sif etc.
|
|
// i.e layout.inf today only has = 1,,,,,,, type of entries that translate to = 55,,,,,
|
|
// Currently we can support only one such mapping as the default translation
|
|
// That means that we will take SourceDisksFiles entries pertaining to the default and always output it into the layout.inf stub
|
|
// so that dosnet.inf gets it.
|
|
//
|
|
|
|
|
|
if (!SetupFindFirstLine(
|
|
hControlInf,
|
|
TEXT("NativeDataToWowData.SourceInfo"),
|
|
TEXT("Default"), //bugbug need a way to get this for other source disks
|
|
&ControlContext) ||
|
|
|
|
!SetupGetStringField(&ControlContext,1,DefaultIDStr,sizeof(DefaultIDStr)/sizeof(TCHAR),NULL)) {
|
|
_ftprintf(stderr, TEXT("SetupFindFirstLine to get default SourceID for file %s failed - Using %s, ec = 0x%08x\n"),FileName,DefaultIDStr,GetLastError());
|
|
// As last resort use 1
|
|
lstrcpy( DefaultIDStr, TEXT("1"));
|
|
}
|
|
|
|
|
|
if( !SetupGetSourceFileLocation(hInputInf,
|
|
LineContext,
|
|
NULL,
|
|
&SourceID,
|
|
NULL,
|
|
0,
|
|
NULL)){
|
|
|
|
|
|
_ftprintf(stderr, TEXT("SetupGetSourceFileLocation [%s] failed - Using SourceID 1, ec = 0x%08x\n"),FileName,GetLastError());
|
|
//Assume Default
|
|
lstrcpy( SourceIDStr, DefaultIDStr);
|
|
LayoutWithinInf = FALSE;
|
|
}else{
|
|
LayoutWithinInf = TRUE;;
|
|
_itot( SourceID, SourceIDStr, 10);
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// look in the appropriate control inf section for the data
|
|
//
|
|
if (!SetupFindFirstLine(
|
|
hControlInf,
|
|
TEXT("NativeDataToWowData.SourceInfo"),
|
|
SourceIDStr,
|
|
&ControlContext)) {
|
|
_ftprintf(stderr, TEXT("SetupFindFirstLine [%s] failed, ec = 0x%08x finding %s key in [NativeDataToWowData.SourceInfo]\n"),FileName,GetLastError(), SourceIDStr);
|
|
RetVal = FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
if (!SetupGetStringField(&ControlContext,1,Entry,sizeof(Entry)/sizeof(TCHAR),NULL)) {
|
|
_ftprintf(stderr, TEXT("SetupGetStringField [%s] failed, ec = 0x%08x\n"),FileName,GetLastError());
|
|
RetVal = FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
if( LayoutWithinInf && OutInfFile){
|
|
//If we found SourceFileInfo within this file and we were
|
|
//asked to add the WOW equivalent to the same INF then do so.
|
|
myftprintf(OutInfFile, fDoAnsiOutput, TEXT("%s:%s=%s,,,,,,,,3,3\n"),InfField,FileName,Entry);
|
|
|
|
//Also if the SourceID matches the default we want to output to the layout.inf stub as well so
|
|
//that it makes it into dosnet.inf. See earlier comments about the DefaultIDStr
|
|
//InfField is the filename without the prefix - useful for postbuild. Has to be stripped out before appending the layout.inf stub.
|
|
|
|
if( !lstrcmpi( SourceIDStr, DefaultIDStr )){
|
|
myftprintf(OutFile, TRUE, TEXT("%s:%s=%s,,,,,,,,3,3\n"),InfField,FileName,Entry);
|
|
}
|
|
|
|
}else{
|
|
myftprintf(OutFile, TRUE, TEXT("%s:%s=%s,,,,,,,,3,3\n"),InfField,FileName,Entry);
|
|
}
|
|
|
|
RetVal = TRUE;
|
|
|
|
exit:
|
|
return(RetVal);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
HandleSetupapiQuotingForString(
|
|
IN OUT PTSTR String
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine looks at the passed in line and does the right quoting and handling of
|
|
the string to handle characters that may have been stripped off by setupapi.
|
|
|
|
It first scans through the string looking for characters <= 0x20, '\"','%','\\'
|
|
If it finds any of these then it places a " at the beginning and end of the string. Additionally it doubles
|
|
every quote within.
|
|
|
|
|
|
Arguments:
|
|
|
|
String - input string to be searched. We edit this string
|
|
in-place if we find a match.
|
|
|
|
Return Value:
|
|
|
|
Boolean indicating outcome.
|
|
|
|
--*/
|
|
{
|
|
PTCHAR p,q;
|
|
BOOL Pass2Needed = FALSE;
|
|
|
|
|
|
|
|
if( !String || !String[0] )
|
|
return;
|
|
|
|
p = String;
|
|
|
|
//
|
|
// [askhalid] ',' Need to be considered as well
|
|
//
|
|
while( *p ){
|
|
if( (*p <= 0x20) || (*p == TEXT('\"')) || (*p == TEXT(',')) || (*p == TEXT(';')) ||(*p == TEXT('%')) || (*p == TEXT('\\')))
|
|
Pass2Needed = TRUE;
|
|
p++;
|
|
}// while
|
|
|
|
if( Pass2Needed ){
|
|
// Quote the start
|
|
p = String;
|
|
q = ScratchTextEnv+1;
|
|
|
|
ZeroMemory(ScratchTextEnv,sizeof(ScratchTextEnv));
|
|
|
|
ScratchTextEnv[0] = TEXT('\"');
|
|
|
|
while( *p && (q < (ScratchTextEnv+MAX_INF_STRING_LENGTH-3)) ){
|
|
|
|
// If we have a quote in the string double it
|
|
|
|
if (*p == TEXT('\"')) {
|
|
*(q++) = TEXT('\"');
|
|
}
|
|
*q = *p;
|
|
|
|
p++;q++;
|
|
|
|
}// while
|
|
|
|
// Quote the end
|
|
*(q++) = TEXT('\"');
|
|
*q = 0;
|
|
|
|
lstrcpy( String, ScratchTextEnv );
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
AppendSetupInfDataToSection(
|
|
IN FILE *OutFile,
|
|
IN HINF hControlInf,
|
|
IN PINFCONTEXT InputContext,
|
|
IN PCTSTR KeywordName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine filters and outputs an input line. The control inf
|
|
lists the syntax for the specified keyword. We filter the keywords
|
|
we know about and let the other ones just fall through.
|
|
|
|
Arguments:
|
|
|
|
OutFile - output file handle
|
|
|
|
hControlInf - inf handle to the inf with the control directives
|
|
|
|
InputContext - inf context to the input line we want to filter.
|
|
|
|
KeywordName - string indicating the keyword associated with the section
|
|
we are filtering.
|
|
|
|
Return Value:
|
|
|
|
Boolean indicating outcome.
|
|
|
|
--*/
|
|
{
|
|
TCHAR FileName[40], Prefix[40];
|
|
TCHAR KeyName[LINE_LEN];
|
|
TCHAR Cmd[LINE_LEN];
|
|
BOOL RetVal;
|
|
DWORD EntryCount,i;
|
|
INFCONTEXT ControlContext,KeywordContext;
|
|
|
|
//
|
|
// ISSUE-2000/06/27-JamieHun Appears to be no error checking here, someone should fix this
|
|
//
|
|
SetupFindFirstLine(
|
|
hControlInf,
|
|
MyGetDecoratedSectionName(hControlInf, TEXT("NativeDataToWowData.SetupINF.Keyword")),
|
|
KeywordName,
|
|
&ControlContext);
|
|
|
|
if(SetupGetStringField(&ControlContext,1,KeyName,LINE_LEN,NULL)) {
|
|
SetupFindFirstLine(
|
|
hControlInf,
|
|
MyGetDecoratedSectionName(hControlInf, TEXT("NativeDataToWowData.SetupINF.Syntax")),
|
|
KeyName,
|
|
&KeywordContext);
|
|
}
|
|
|
|
ZeroMemory(LineText,sizeof(LineText));
|
|
FileName[0] = TEXT('\0');
|
|
|
|
if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("KeywordName - %s\n"),KeywordName);
|
|
|
|
EntryCount = SetupGetFieldCount(InputContext);
|
|
|
|
for (i = 1; i<=EntryCount; i++) {
|
|
TCHAR ScratchEntry[MAX_PATH];
|
|
|
|
//
|
|
// get the current text to be appended
|
|
//
|
|
if (!SetupGetStringField(InputContext,i,ScratchText,sizeof(ScratchText)/sizeof(TCHAR),NULL)) {
|
|
_ftprintf(stderr, TEXT("SetupGetStringField [%s] failed, ec = 0x%08x\n"),FileName,GetLastError());
|
|
RetVal = FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
|
|
if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("ScratchText (1)- %s\n"),ScratchText);
|
|
FixupSetupapiPercents(ScratchText);
|
|
if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("ScratchText (2)- %s\n"),ScratchText);
|
|
pSubstituteEnvVarsForActualPaths(ScratchText);
|
|
|
|
if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("ScratchText (3)- %s\n"),ScratchText);
|
|
|
|
//
|
|
// now do any necessary substitutions
|
|
//
|
|
if(SetupGetStringField(&KeywordContext,i,Cmd,LINE_LEN,NULL)
|
|
&& Cmd[0]) {
|
|
|
|
//
|
|
// dirid substitution
|
|
//
|
|
if (!_tcsicmp(Cmd,TEXT("MapDirId"))) {
|
|
//
|
|
// look in the appropriate control inf section for the data
|
|
//
|
|
if (!SetupFindFirstLine(
|
|
hControlInf,
|
|
MyGetDecoratedSectionName(hControlInf, TEXT("NativeDataToWowData.SetupINF.DestinationDirsToMap")),
|
|
ScratchText,
|
|
&ControlContext)) {
|
|
_ftprintf(stderr, TEXT("SetupFindFirstLine [%s] failed, ec = 0x%08x\n"),FileName,GetLastError());
|
|
RetVal = FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
if (!SetupGetStringField(&ControlContext,1,ScratchText,sizeof(ScratchText)/sizeof(TCHAR),NULL)) {
|
|
_ftprintf(stderr, TEXT("SetupGetStringField [%s] failed, ec = 0x%08x\n"),FileName,GetLastError());
|
|
RetVal = FALSE;
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
//
|
|
// source name substitution
|
|
//
|
|
if (!_tcsicmp(Cmd,TEXT("srcname"))) {
|
|
|
|
MyGetFilePrefix( hControlInf, FileName, Prefix );
|
|
LSTRCPY(ScratchEntry,Prefix);
|
|
if (ScratchText[0]) {
|
|
LSTRCAT(ScratchEntry,ScratchText);
|
|
} else {
|
|
LSTRCAT(ScratchEntry,FileName);
|
|
}
|
|
|
|
LSTRCPY(ScratchText,ScratchEntry);
|
|
}
|
|
|
|
//_ftprintf(stderr, TEXT("ScratchText(2) - %s\n"),ScratchText);
|
|
|
|
|
|
if (!_tcsicmp(Cmd,TEXT("RegistryFlags"))) {
|
|
DWORD RegVal,CurrentRegVal;
|
|
//
|
|
// look in the appropriate control inf section for the data
|
|
//
|
|
if (!SetupFindFirstLine(
|
|
hControlInf,
|
|
MyGetDecoratedSectionName(hControlInf, TEXT("NativeDataToWowData.SetupINF.RegistryInformation")),
|
|
TEXT("RegistryFlags"),
|
|
&ControlContext)) {
|
|
_ftprintf(stderr, TEXT("SetupFindFirstLine [%s] failed, ec = 0x%08x\n"),FileName,GetLastError());
|
|
RetVal = FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
CurrentRegVal = 0;
|
|
RegVal = 0;
|
|
SetupGetIntField(&ControlContext,1,&RegVal);
|
|
SetupGetIntField(InputContext,i,&CurrentRegVal);
|
|
|
|
CurrentRegVal |= RegVal;
|
|
|
|
_stprintf(ScratchText, TEXT("0x%08x"), CurrentRegVal);
|
|
|
|
}
|
|
|
|
|
|
if (!_tcsicmp(Cmd,TEXT("dstname"))) {
|
|
LSTRCPY(FileName,ScratchText);
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
HandleSetupapiQuotingForString(ScratchText);
|
|
|
|
_tcscat(LineText, ScratchText);
|
|
|
|
|
|
//
|
|
// now append a comma if necessary
|
|
//
|
|
if (i !=EntryCount) {
|
|
_tcscat(LineText, TEXT(","));
|
|
}
|
|
|
|
|
|
}
|
|
|
|
if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("LineText - %s\n"),LineText);
|
|
|
|
|
|
//
|
|
// Check if we need to exclude the DLL
|
|
//
|
|
|
|
if (KeywordName == KeywordArray[INDEX_COPYFILES] ||
|
|
KeywordName == KeywordArray[INDEX_DELFILES] ||
|
|
KeywordName == KeywordArray[INDEX_RENFILES] ||
|
|
KeywordName == KeywordArray[INDEX_REGISTERDLLS]){
|
|
|
|
|
|
// Check if we need to exclude this file from processing
|
|
|
|
if( SetupFindFirstLine(
|
|
hControlInf,
|
|
MyGetDecoratedSectionName(hControlInf, TEXT("NativeDataToWowData.SetupINF.FilesToExclude")),
|
|
FileName,
|
|
&ControlContext)){
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
if (KeywordName == KeywordArray[INDEX_COPYFILES]) {
|
|
|
|
//
|
|
// if we didn't have a file rename in copyfiles, we add it now.
|
|
//
|
|
|
|
if ((--i) < SetupGetFieldCount(&KeywordContext)) {
|
|
_tcscat(LineText, TEXT(","));
|
|
if( MyGetFilePrefix( hControlInf, FileName, Prefix )){
|
|
_tcscat(LineText, Prefix);
|
|
}
|
|
_tcscat(LineText, FileName);
|
|
}
|
|
if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("LineText(2) - %s\n"),LineText);
|
|
|
|
} else if (KeywordName == KeywordArray[INDEX_ADDREG] ||
|
|
KeywordName == KeywordArray[INDEX_DELREG]) {
|
|
//
|
|
// we need to pad out AddReg or DelReg if necessary.
|
|
//
|
|
DWORD count;
|
|
TCHAR Entry[MAX_PATH];
|
|
count = SetupGetFieldCount(&KeywordContext);
|
|
if (count > i ) {
|
|
while (i <= count) {
|
|
if(SetupGetStringField(&KeywordContext,i,Cmd,LINE_LEN,NULL)
|
|
&& Cmd[0]) {
|
|
if (!_tcsicmp(Cmd,TEXT("RegistryFlags"))) {
|
|
//
|
|
// look in the appropriate control inf section for the data
|
|
//
|
|
if (!SetupFindFirstLine(
|
|
hControlInf,
|
|
MyGetDecoratedSectionName(hControlInf, TEXT("NativeDataToWowData.SetupINF.RegistryInformation")),
|
|
TEXT("RegistryFlags"),
|
|
&ControlContext)) {
|
|
_ftprintf(stderr, TEXT("SetupFindFirstLine [%s] failed, ec = 0x%08x\n"),FileName,GetLastError());
|
|
RetVal = FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
if (!SetupGetStringField(&ControlContext,1,Entry,sizeof(Entry)/sizeof(TCHAR),NULL)) {
|
|
_ftprintf(stderr, TEXT("SetupGetStringField [%s] failed, ec = 0x%08x\n"),FileName,GetLastError());
|
|
RetVal = FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
_tcscat(LineText, TEXT(","));
|
|
_tcscat(LineText, Entry);
|
|
|
|
}
|
|
}
|
|
|
|
if (i != count) {
|
|
_tcscat(LineText, TEXT(","));
|
|
}
|
|
|
|
i +=1;
|
|
|
|
}
|
|
|
|
}
|
|
}else if (KeywordName == KeywordArray[INDEX_REGISTERDLLS]) {
|
|
|
|
// Check if we need to exclude this file from RegisterDlls
|
|
if( SetupFindFirstLine(
|
|
hControlInf,
|
|
MyGetDecoratedSectionName(hControlInf, TEXT("NativeDataToWowData.SetupINF.FilesToExcludeFromRegistration")),
|
|
FileName,
|
|
&ControlContext)){
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
myftprintf(OutFile, fDoAnsiOutput, TEXT("%s\n"),LineText);
|
|
|
|
RetVal = TRUE;
|
|
|
|
exit:
|
|
return(RetVal);
|
|
|
|
}
|
|
|
|
|
|
BOOL
|
|
pOutputSectionData(
|
|
IN PVOID StringTable,
|
|
IN LONG StringId,
|
|
IN PCTSTR String,
|
|
IN PPERSECTION_CONTEXT SectionContext,
|
|
IN UINT SectionContextSize,
|
|
IN LPARAM cntxt
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
String table callback.
|
|
|
|
This routine outputs the contents of the specified section to both the
|
|
system layout file and the output file.
|
|
|
|
Arguments:
|
|
|
|
Standard string table callback args.
|
|
|
|
Return Value:
|
|
|
|
Boolean indicating outcome. If FALSE, an error will have been logged.
|
|
FALSE also stops the string table enumeration and causes pSetupStringTableEnum()
|
|
to return FALSE. There is a bug in setupapi where we will jump into
|
|
the next hash_bucket and may process few more entries.
|
|
|
|
--*/
|
|
{
|
|
TCHAR LineText[MAX_INF_STRING_LENGTH];
|
|
BOOL RetVal;
|
|
INFCONTEXT LineContext;
|
|
|
|
DWORD EntryCount,i,SectionCount;
|
|
INFCONTEXT InputContext;
|
|
UCHAR line[MAX_INF_STRING_LENGTH];
|
|
PSETUPINF_CONTEXT Context = (PSETUPINF_CONTEXT)cntxt;
|
|
|
|
|
|
if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("Enumerating Section %s\n"), String);
|
|
|
|
|
|
//
|
|
// output the decorated section header
|
|
//
|
|
myftprintf(Context->OutFile, fDoAnsiOutput, TEXT("[%s%s]\n"),FilePrefix,String);
|
|
|
|
//
|
|
// get the section context
|
|
//
|
|
if(! SetupFindFirstLine(
|
|
Context->hInputInf,
|
|
String,
|
|
NULL,
|
|
&InputContext)){
|
|
|
|
_ftprintf(stderr, TEXT("Could not find lines in Section %s\n"), String);
|
|
|
|
//continue with next section
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("Output Section %s\n"), String);
|
|
|
|
do {
|
|
|
|
SectionCount = SetupGetLineCount(Context->hInputInf,String);
|
|
|
|
for (i = 0; i < SectionCount; i++) {
|
|
if (SetupGetLineByIndex(
|
|
Context->hInputInf,
|
|
String,
|
|
i,&InputContext)) {
|
|
//
|
|
// get the keyword for the section we're mapping
|
|
//
|
|
PCTSTR KeywordName = NULL;
|
|
DWORD j=0;
|
|
MYASSERT(SectionContext->KeywordVector != 0);
|
|
while (!KeywordName) {
|
|
if (SectionContext->KeywordVector & (1<<j)) {
|
|
KeywordName = KeywordArray[j];
|
|
break;
|
|
}
|
|
|
|
j += 1;
|
|
}
|
|
|
|
MYASSERT(KeywordName != NULL);
|
|
|
|
//
|
|
// filter and output the data
|
|
//
|
|
AppendSetupInfDataToSection(
|
|
Context->OutFile,
|
|
Context->hControlInf,
|
|
&InputContext,
|
|
KeywordName );
|
|
|
|
if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("Got back from AppendSetupInfDataToSection\n"));
|
|
|
|
|
|
//
|
|
// output the data to the layout file if we need to
|
|
//
|
|
if ((SectionContext->KeywordVector & KEYWORD_NEEDLAYOUTDATA) && Context->OutLayoutFile) {
|
|
|
|
if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("Calling AppendSetupInfDataToLayoutFile\n"));
|
|
|
|
AppendSetupInfDataToLayoutFile(
|
|
Context->OutLayoutFile,
|
|
Context->OutInfLayoutFile,
|
|
Context->hControlInf,
|
|
Context->hInputInf,
|
|
&InputContext );
|
|
|
|
if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("Got back from AppendSetupInfDataToLayoutFile\n"));
|
|
|
|
}
|
|
|
|
} else {
|
|
_ftprintf(stderr, TEXT("SetupGetLineByIndex failed, ec = %d\n"), GetLastError());
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
} while (SetupFindNextLine( &InputContext,
|
|
&InputContext)); // bugbug is this really
|
|
// necessary ??
|
|
|
|
myftprintf(Context->OutFile, fDoAnsiOutput, TEXT("\n"));
|
|
RetVal = TRUE;
|
|
return(RetVal);
|
|
}
|
|
|
|
|
|
BOOL
|
|
pOutputDestinationDirs(
|
|
IN PVOID StringTable,
|
|
IN LONG StringId,
|
|
IN PCTSTR String,
|
|
IN PPERSECTION_CONTEXT SectionContext,
|
|
IN UINT SectionContextSize,
|
|
IN LPARAM cntxt
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
String table callback.
|
|
|
|
This routine outputs the destination dirs keyword
|
|
followed by the decorated section name and dirid mapping.
|
|
|
|
Arguments:
|
|
|
|
Standard string table callback args.
|
|
|
|
Return Value:
|
|
|
|
Boolean indicating outcome. If FALSE, an error will have been logged.
|
|
FALSE also stops the string table enumeration and causes pSetupStringTableEnum()
|
|
to return FALSE.
|
|
|
|
--*/
|
|
{
|
|
TCHAR LineText[MAX_INF_STRING_LENGTH];
|
|
BOOL RetVal;
|
|
INFCONTEXT LineContext;
|
|
|
|
DWORD EntryCount,i,cch;
|
|
PSETUPINF_CONTEXT Context = (PSETUPINF_CONTEXT)cntxt;
|
|
|
|
//
|
|
// only process this entry if it need destination dirs
|
|
//
|
|
|
|
if (0 == (SectionContext->KeywordVector & (KEYWORD_NEEDDESTDIRS))) {
|
|
RetVal = TRUE;
|
|
goto exit;
|
|
}
|
|
|
|
|
|
//
|
|
// first output "destinationdirs" if we haven't done so already
|
|
//
|
|
if (!Context->AlreadyOutputKeyword) {
|
|
myftprintf(Context->OutFile, fDoAnsiOutput, TEXT("[DestinationDirs]\n"));
|
|
Context->AlreadyOutputKeyword = TRUE;
|
|
}
|
|
|
|
//
|
|
// now get the unfiltered data so that we can filter it
|
|
//
|
|
if( !SetupFindFirstLine(
|
|
Context->hInputInf,
|
|
TEXT("DestinationDirs"),
|
|
String,
|
|
&LineContext)){
|
|
|
|
SetupFindFirstLine(
|
|
Context->hInputInf,
|
|
TEXT("DestinationDirs"),
|
|
TEXT("DefaultDestDir"),
|
|
&LineContext);
|
|
|
|
}
|
|
|
|
|
|
ZeroMemory(LineText,sizeof(LineText));
|
|
cch = sizeof(LineText)/sizeof(LineText[0]);
|
|
|
|
EntryCount = SetupGetFieldCount(&LineContext);
|
|
|
|
for (i = 1; i<=EntryCount; i++) {
|
|
TCHAR Entry[MAX_PATH+1]; // The extra character is for the possible comma at the end.
|
|
INFCONTEXT ControlContext;
|
|
DWORD cchEntry;
|
|
|
|
//
|
|
// get the current text to be appended
|
|
//
|
|
if (!SetupGetStringField(&LineContext,i,Entry,MAX_PATH,NULL)) {
|
|
_ftprintf(stderr, TEXT("SetupGetStringField failed, ec = 0x%08x\n"),GetLastError());
|
|
RetVal = FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// now do any necessary substitutions
|
|
//
|
|
if (i == 1) {
|
|
_stprintf(Entry, TEXT("%d"), SectionContext->DestinationDir);
|
|
}
|
|
|
|
//
|
|
// now append a comma if necessary
|
|
//
|
|
if (i !=EntryCount) {
|
|
_tcscat(Entry, TEXT(","));
|
|
}
|
|
|
|
//
|
|
// check for buffer overruns
|
|
//
|
|
cchEntry = _tcslen(Entry);
|
|
if (cchEntry >= cch) {
|
|
_ftprintf(stderr, TEXT("pOutputDestinationDirs: line too long, File = %s\n"), String);
|
|
RetVal = FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
_tcscat(LineText, Entry);
|
|
cch -= cchEntry;
|
|
|
|
if (fDoVerboseDebugOutput) _ftprintf(stderr, TEXT("LineText = %s\n"), LineText, SectionContext->DestinationDir);
|
|
|
|
}
|
|
|
|
//
|
|
// output the filtered data
|
|
//
|
|
myftprintf(Context->OutFile, fDoAnsiOutput, TEXT("%s%s=%s\n"),FilePrefix,String,LineText);
|
|
|
|
RetVal = TRUE;
|
|
|
|
exit:
|
|
return(RetVal);
|
|
}
|
|
|
|
|
|
BOOL
|
|
DoSetupINF(
|
|
IN PCTSTR InputInfA,
|
|
IN PCTSTR ControlInfA,
|
|
IN FILE *OutFile,
|
|
IN FILE *OutLayoutFile,
|
|
IN FILE *OutInfLayoutFile
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Filters a setupapi-based INF.
|
|
|
|
Arguments:
|
|
|
|
InputInfA - name of the inf to be filtered.
|
|
ControlInfA - name of the control directive inf
|
|
OutFile - output file handle
|
|
OutLayoutFile - output file handle for layout information
|
|
OutInfLayoutFile - output file handle for layout information contained in this INF
|
|
|
|
Return Value:
|
|
|
|
NONE.
|
|
|
|
--*/
|
|
{
|
|
PCWSTR InputInf;
|
|
PCWSTR ControlInf;
|
|
HINF hInputInf;
|
|
HINF hControlInf;
|
|
INFCONTEXT InfContext;
|
|
SETUPINF_CONTEXT Context;
|
|
PERSECTION_CONTEXT SectionContext;
|
|
FILE *HeaderFile;
|
|
|
|
TCHAR SourceArchitecture[10];
|
|
TCHAR SourceDiskFiles[80];
|
|
BOOL FirstTime;
|
|
PTSTR Sections,Current;
|
|
DWORD SizeNeeded;
|
|
PVOID FilteredSectionsStringTable;
|
|
|
|
BOOL b;
|
|
|
|
b = FALSE;
|
|
|
|
//
|
|
// initialize and open the infs
|
|
//
|
|
#ifdef UNICODE
|
|
InputInf = InputInfA;
|
|
#else
|
|
InputInf = pSetupAnsiToUnicode(InputInfA);
|
|
#endif
|
|
if (!InputInf) {
|
|
_ftprintf(stderr,TEXT("Unable to convert %s to Unicode %d\n"),InputInfA, GetLastError());
|
|
goto e0;
|
|
}
|
|
#ifdef UNICODE
|
|
ControlInf = ControlInfA;
|
|
#else
|
|
ControlInf = pSetupAnsiToUnicode(ControlInfA);
|
|
#endif
|
|
if (!ControlInf) {
|
|
_ftprintf(stderr,TEXT("Unable to convert %s to Unicode %d\n"),ControlInfA, GetLastError());
|
|
goto e1;
|
|
}
|
|
|
|
hInputInf = SetupOpenInfFileW(InputInf,NULL,INF_STYLE_WIN4,NULL);
|
|
if(hInputInf == INVALID_HANDLE_VALUE) {
|
|
_ftprintf(stderr,TEXT("Unable to open Inf %ws, ec=0x%08x\n"),InputInf, GetLastError());
|
|
goto e2;
|
|
}
|
|
|
|
hControlInf = SetupOpenInfFileW(ControlInf,NULL,INF_STYLE_WIN4,NULL);
|
|
if(hControlInf == INVALID_HANDLE_VALUE) {
|
|
_ftprintf(stderr,TEXT("Unable to open Inf %ws, ec=0x%08x\n"),ControlInf, GetLastError());
|
|
goto e3;
|
|
}
|
|
|
|
|
|
myftprintf(OutFile, fDoAnsiOutput, TEXT("\n\n"));
|
|
|
|
//
|
|
// write the output file header
|
|
//
|
|
HeaderFile = _tfopen(HeaderText,TEXT("rt"));
|
|
if (HeaderFile) {
|
|
while (!feof(HeaderFile)) {
|
|
TCHAR Buffer[100];
|
|
DWORD CharsRead;
|
|
|
|
CharsRead = fread(Buffer,sizeof(TCHAR),sizeof(Buffer)/sizeof(TCHAR),HeaderFile);
|
|
|
|
if (CharsRead) {
|
|
fwrite(Buffer,sizeof(TCHAR),CharsRead,OutFile);
|
|
}
|
|
}
|
|
fclose(HeaderFile);
|
|
}
|
|
|
|
myftprintf(OutFile, fDoAnsiOutput, TEXT("\n"));
|
|
|
|
//
|
|
// get all of the section names
|
|
//
|
|
if (!SetupGetInfSections(hInputInf, NULL, 0, &SizeNeeded)) {
|
|
_ftprintf(stderr,TEXT("Unable to get section names, ec=0x%08x\n"), GetLastError());
|
|
goto e4;
|
|
}
|
|
if (SizeNeeded == 0) {
|
|
b= TRUE;
|
|
goto e4;
|
|
}
|
|
|
|
Sections = pSetupMalloc (SizeNeeded + 1);
|
|
if (!Sections) {
|
|
_ftprintf(stderr,TEXT("Unable to allocate memory, ec=0x%08x\n"), GetLastError());
|
|
goto e4;
|
|
}
|
|
|
|
if (!SetupGetInfSections(hInputInf, Sections, SizeNeeded, NULL)) {
|
|
_ftprintf(stderr,TEXT("Unable to allocate memory, ec=0x%08x\n"), GetLastError());
|
|
goto e5;
|
|
}
|
|
|
|
FilteredSectionsStringTable = pSetupStringTableInitializeEx( sizeof(PERSECTION_CONTEXT),0);
|
|
if (!FilteredSectionsStringTable) {
|
|
_ftprintf(stderr,TEXT("Unable to create string table, ec=0x%08x\n"), GetLastError());
|
|
goto e5;
|
|
}
|
|
|
|
Current = Sections;
|
|
Context.OutFile = OutFile;
|
|
Context.OutLayoutFile = OutLayoutFile;
|
|
Context.OutInfLayoutFile = OutInfLayoutFile;
|
|
Context.hControlInf = hControlInf;
|
|
Context.hInputInf = hInputInf;
|
|
Context.AlreadyOutputKeyword = FALSE;
|
|
|
|
//
|
|
// process each section, which will output the
|
|
// sections names and keywords that we want to filter
|
|
//
|
|
while (*Current) {
|
|
|
|
if (SetupFindFirstLine(
|
|
hControlInf,
|
|
MyGetDecoratedSectionName(hControlInf, TEXT("NativeDataToWowData.SetupINF.ExcludeSection")),
|
|
Current,
|
|
&InfContext)) {
|
|
_ftprintf(stderr, TEXT("Skipping section %s as per [NativeDataToWowData.SetupINF.ExcludeSection]: ec = 0x%08x\n"), Current, GetLastError());
|
|
Current += lstrlen(Current)+1;
|
|
continue;
|
|
}
|
|
|
|
|
|
if (fDoVerboseDebugOutput) _ftprintf(stderr,TEXT("Processing section %s\n"), Current );
|
|
|
|
pFilterSetupInfSection(
|
|
FilteredSectionsStringTable,
|
|
Current,
|
|
&Context);
|
|
|
|
Current += lstrlen(Current)+1;
|
|
}
|
|
|
|
myftprintf(Context.OutFile, fDoAnsiOutput, TEXT("\n"));
|
|
|
|
//
|
|
// for each section that we decided to filter, we now need to output the
|
|
// actual section
|
|
//
|
|
pSetupStringTableEnum(
|
|
FilteredSectionsStringTable,
|
|
&SectionContext,
|
|
sizeof(PERSECTION_CONTEXT),
|
|
pOutputSectionData,
|
|
(LPARAM)&Context
|
|
);
|
|
|
|
|
|
//
|
|
// now we need to output the destination dirs section
|
|
//
|
|
pSetupStringTableEnum(
|
|
FilteredSectionsStringTable,
|
|
&SectionContext,
|
|
sizeof(PERSECTION_CONTEXT),
|
|
pOutputDestinationDirs,
|
|
(LPARAM)&Context
|
|
);
|
|
|
|
b = TRUE;
|
|
|
|
pSetupStringTableDestroy(FilteredSectionsStringTable);
|
|
e5:
|
|
pSetupFree(Sections);
|
|
e4:
|
|
SetupCloseInfFile( hControlInf );
|
|
e3:
|
|
SetupCloseInfFile( hInputInf );
|
|
e2:
|
|
#ifndef UNICODE
|
|
pSetupFree(ControlInf);
|
|
#endif
|
|
e1:
|
|
#ifndef UNICODE
|
|
pSetupFree(InputInf);
|
|
#endif
|
|
e0:
|
|
return(b);
|
|
}
|
|
|
|
|
|
void
|
|
Usage(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Prints the usage to stderr.
|
|
|
|
Arguments:
|
|
|
|
NONE.
|
|
|
|
Return Value:
|
|
|
|
NONE.
|
|
|
|
--*/
|
|
{
|
|
_fputts( TEXT("generate list of wow files. Usage:\n")
|
|
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")
|
|
TEXT("\n")
|
|
TEXT(" -i <inf file> - input inf containing list of dependencies\n")
|
|
TEXT(" -c <control inf> - contains directives for creating list.\n")
|
|
TEXT(" -l <OLE inf> - contains ole registration directives.\n")
|
|
TEXT(" -o <output file> - output list\n")
|
|
TEXT(" -g <section> - SetupAPI INF filtering decoration for per-inf filtering\n")
|
|
TEXT(" -h <header file> - append this to top of the output list\n")
|
|
TEXT(" -s <section name> - specifies section in OLE Inf to process\n")
|
|
TEXT(" -d <output layout> - output layout.inf information for SetupAPI INF filtering\n")
|
|
TEXT(" -f <file prefix> - specifies the decoration to be prepended to filtered files.\n")
|
|
TEXT(" -a <c|o|s> - specifies filter action\n")
|
|
TEXT(" -u - create UNICODE output list (only with /o)\n")
|
|
TEXT(" -n <file> - create layout file for SourceDisksFiles within the INF (to be appended to INF itself)\n")
|
|
TEXT("\tc - Create copy list.\n")
|
|
TEXT("\to - Create OLE list.\n")
|
|
TEXT("\ts - Create SetupINF list.\n")
|
|
TEXT("\n")
|
|
TEXT("\n"),
|
|
stderr );
|
|
}
|
|
|
|
int
|
|
__cdecl
|
|
_tmain(
|
|
IN int argc,
|
|
IN TCHAR *argv[]
|
|
)
|
|
{
|
|
FILE *hFileOut,*hFileLayoutOut = NULL, *hFileInfLayoutOut=NULL;
|
|
BOOL b;
|
|
|
|
|
|
//
|
|
// Assume failure.
|
|
//
|
|
b = FALSE;
|
|
|
|
if(!pSetupInitializeUtils()) {
|
|
return FAILURE;
|
|
}
|
|
|
|
if(!ParseArgs(argc,argv)) {
|
|
Usage();
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// Open the output file.
|
|
//
|
|
if( fDoAnsiOutput )
|
|
hFileOut = _tfopen(OutputFile,TEXT("wt"));
|
|
else
|
|
hFileOut = _tfopen(OutputFile,TEXT("wb"));
|
|
if(hFileOut) {
|
|
|
|
if (Action == BuildCopyList) {
|
|
|
|
_ftprintf(stdout,TEXT("%s: creating copy list %s from %s and %s\n"),
|
|
ThisProgramName,
|
|
OutputFile,
|
|
InputInf,
|
|
ControlInf);
|
|
b = DoCopyList(
|
|
InputInf,
|
|
ControlInf,
|
|
hFileOut );
|
|
|
|
} else if (Action == BuildOLEList) {
|
|
|
|
_ftprintf(stdout,
|
|
TEXT("%s: creating OLE list %s from %s, %s, and %s\n"),
|
|
ThisProgramName,
|
|
OutputFile,
|
|
InputInf,
|
|
OLEInputInf,
|
|
ControlInf);
|
|
|
|
b = DoOLEList(
|
|
InputInf,
|
|
OLEInputInf,
|
|
ControlInf,
|
|
hFileOut );
|
|
|
|
} else if (Action == BuildSetupINF) {
|
|
|
|
if( OutputLayoutFile )
|
|
hFileLayoutOut = _tfopen(OutputLayoutFile,TEXT("wt"));
|
|
|
|
// Check if we want to process layout information that needs to be added
|
|
// to the INF itself. This is used for INFs that have their own layout information.
|
|
// This file will get the layout information for thunked files which had
|
|
// SourceDisksFiles entries within this INF.
|
|
|
|
if(OutputInfLayoutFile){
|
|
|
|
if( fDoAnsiOutput )
|
|
hFileInfLayoutOut = _tfopen(OutputInfLayoutFile,TEXT("wt"));
|
|
else
|
|
hFileInfLayoutOut = _tfopen(OutputInfLayoutFile,TEXT("wb"));
|
|
|
|
}
|
|
|
|
_ftprintf(stdout,
|
|
TEXT("%s: creating SetupINF list %s (layout %s) from %s and %s\n"),
|
|
ThisProgramName,
|
|
OutputFile,
|
|
OutputLayoutFile,
|
|
InputInf,
|
|
ControlInf);
|
|
|
|
b = DoSetupINF(
|
|
InputInf,
|
|
ControlInf,
|
|
hFileOut,
|
|
hFileLayoutOut,
|
|
hFileInfLayoutOut);
|
|
|
|
if( hFileLayoutOut )
|
|
fclose( hFileLayoutOut );
|
|
|
|
if( hFileInfLayoutOut )
|
|
fclose( hFileInfLayoutOut );
|
|
|
|
} else {
|
|
_ftprintf(stderr,TEXT("unknown action."));
|
|
MYASSERT(FALSE);
|
|
}
|
|
|
|
fclose(hFileOut);
|
|
|
|
} else {
|
|
_ftprintf(stderr,TEXT("%s: Unable to create output file %s\n"),ThisProgramName,OutputFile);
|
|
}
|
|
|
|
|
|
exit:
|
|
|
|
pSetupUninitializeUtils();
|
|
|
|
return(b ? SUCCESS : FAILURE);
|
|
}
|