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.
 
 
 
 
 
 

506 lines
12 KiB

/*++
Copyright (c) Microsoft Corporation. All rights reserved.
For Internal use only!
Module Name:
INFSCAN
globals.cpp
Abstract:
Global functions (ie, not part of any class)
History:
Created July 2001 - JamieHun
--*/
#include "precomp.h"
#pragma hdrstop
#include <initguid.h>
#include <new.h>
int
__cdecl
my_new_handler(size_t)
{
throw std::bad_alloc();
return 0;
}
int
__cdecl
main(int argc,char *argv[])
/*++
Routine Description:
Main point of entry
Defer to GlobalScan::ParseArgs and GlobalScan::Scan
Arguments:
argc - # of arguments passed on command line
argv - arguments passed on command line
Return Value:
0 on success
1 no files
2 bad usage
3 fatal error (out of memory)
stdout -- scan errors
stderr -- trace/fatal errors
--*/
{
int res;
_PNH _old_new_handler = _set_new_handler(my_new_handler);
int _old_new_mode = _set_new_mode(1);
try {
GlobalScan scanner;
res = scanner.ParseArgs(argc,argv);
if(res != 0) {
return res;
}
res = scanner.Scan();
} catch(bad_alloc &) {
res = 3;
}
if(res == 3) {
fprintf(stderr,"Out of memory!\n");
}
_set_new_mode(_old_new_mode);
_set_new_handler(_old_new_handler);
return res;
}
void FormatToStream(FILE * stream,DWORD fmt,DWORD flags,...)
/*++
Routine Description:
Format text to stream using a particular msg-id fmt
Used for displaying localizable messages
Arguments:
stream - file stream to output to, stdout or stderr
fmt - message id
... - parameters %1...
Return Value:
none
--*/
{
va_list arglist;
LPTSTR locbuffer = NULL;
DWORD count;
va_start(arglist, flags);
count = FormatMessage(FORMAT_MESSAGE_FROM_HMODULE|FORMAT_MESSAGE_ALLOCATE_BUFFER|flags,
NULL,
fmt,
0, // LANGID
(LPTSTR) &locbuffer,
0, // minimum size of buffer
(flags & FORMAT_MESSAGE_ARGUMENT_ARRAY)
? reinterpret_cast<va_list*>(va_arg(arglist,DWORD_PTR*))
: &arglist);
if(locbuffer) {
if(count) {
int c;
int back = 0;
while(((c = *CharPrev(locbuffer,locbuffer+count)) == TEXT('\r')) ||
(c == TEXT('\n'))) {
count--;
back++;
}
if(back) {
locbuffer[count++] = TEXT('\n');
locbuffer[count] = TEXT('\0');
}
_fputts(locbuffer,stream);
}
LocalFree(locbuffer);
}
}
PTSTR CopyString(PCTSTR arg, int extra)
/*++
Routine Description:
Copy a string into a newly allocated buffer
Arguments:
arg - string to copy
extra - extra characters to allow for
Return Value:
TCHAR[] buffer, delete with "delete []"
--*/
{
int max = _tcslen(arg)+1;
PTSTR chr = new TCHAR[max+extra]; // may throw bad_alloc
memcpy(chr,arg,max*sizeof(TCHAR));
return chr;
}
#ifdef UNICODE
PTSTR CopyString(PCSTR arg, int extra)
/*++
Routine Description:
Copy a string into a newly allocated buffer
Converting from ANSI to UNICODE
Arguments:
arg - string to copy
extra - extra characters to allow for
Return Value:
TCHAR[] buffer, delete with "delete []"
--*/
{
int max = strlen(arg)+1;
PTSTR chr = new TCHAR[max+extra]; // may throw bad_alloc
if(!MultiByteToWideChar(CP_ACP,0,arg,max,chr,max)) {
delete [] chr;
return NULL;
}
return chr;
}
#else
PTSTR CopyString(PCWSTR arg, int extra)
/*++
Routine Description:
Copy a string into a newly allocated buffer
Converting from UNICODE to ANSI
Arguments:
arg - string to copy
extra - extra characters to allow for
Return Value:
TCHAR[] buffer, delete with "delete []"
--*/
{
#error CopyString(PCWSTR arg,int extra)
}
#endif
int GetFullPathName(const SafeString & given,SafeString & target)
/*++
Routine Description:
Obtain full pathname
Arguments:
given - path to convert
target - full pathname on success, same as given on error
Return Value:
0 on success, !=0 on failure
--*/
{
DWORD len = GetFullPathName(given.c_str(),0,NULL,NULL);
if(len == 0) {
if(&target != &given) {
target = given;
}
return -1;
}
PTSTR chr = new TCHAR[len];
if(!chr) {
if(&target != &given) {
target = given;
}
return -1;
}
DWORD alen = GetFullPathName(given.c_str(),len,chr,NULL);
if((alen == 0) || (alen>len)) {
if(&target != &given) {
target = given;
}
delete [] chr;
return -1;
}
target = chr;
delete [] chr;
return 0;
}
SafeString PathConcat(const SafeString & path,const SafeString & tail)
/*++
Routine Description:
Combine path and tail, returning newly combined string
inserts/removes path seperator if needed
Arguments:
path - first part
tail - last part
Return Value:
appended path
--*/
{
if(!path.length()) {
return tail;
}
if(!tail.length()) {
return path;
}
PCTSTR path_p = path.c_str();
int path_l = path.length();
int c = *CharPrev(path_p,path_p+path_l);
bool addslash = false;
bool takeslash = false;
if((c != TEXT('\\')) && (c != TEXT('/'))) {
addslash = true;
}
c = tail[0];
if((c == TEXT('\\')) || (c == TEXT('/'))) {
if(addslash) {
return path+tail;
} else {
return path+tail.substr(1);
}
} else {
if(addslash) {
return path+SafeString(TEXT("\\"))+tail;
} else {
return path+tail;
}
}
}
VOID
Usage(VOID)
/*++
Routine Description:
Help information
Arguments:
Return Value:
--*/
{
_tprintf(TEXT("Usage: INFSCAN [/B <textfile>] [/C <output>] [/D] [/E <output>] [/F <filter>] [/G] [/I] {/N <infname>} {/O <dir>} [/P] [Q <output>] [/R] [/S <output>] [/T <count>] [/V <version>] [/W <textfile>] [/X <textfile>] [/Y] [/Z] [SourcePath]\n\n"));
_tprintf(TEXT("Options:\n\n"));
_tprintf(TEXT("/B <textfile> (build special) Filter /E based on a list of \"unchanged\" files\n"));
_tprintf(TEXT(" variation /B1 - based on copied files only\n"));
_tprintf(TEXT(" variation /B2 - based on INF files only\n"));
_tprintf(TEXT("/C <output> Create INF filter/report based on errors\n"));
_tprintf(TEXT("/D Determine non-driver installation sections\n"));
_tprintf(TEXT("/E <output> Create a DeviceToInf filter INF\n"));
_tprintf(TEXT("/F <filter> Filter based on INF: FilterInfPath\n"));
_tprintf(TEXT("/G Generate Pnfs first (see also /Z)\n"));
_tprintf(TEXT("/I Ignore errors (for when generating file list)\n"));
_tprintf(TEXT("/N <infname> Specify single INF name (/N may be used multiple times)\n"));
_tprintf(TEXT("/O <dir> Specify an override directory (/O may be used multiple times and parsed in order)\n"));
_tprintf(TEXT("/P Pedantic mode (show potential problems too)\n"));
_tprintf(TEXT("/Q <output> Source+Target copied files list (filtered by layout.inf) see also /S\n"));
_tprintf(TEXT("/R Trace (list all INF's)\n"));
_tprintf(TEXT("/S <output> Source copied files list (filtered by layout.inf) see also /Q\n"));
_tprintf(TEXT("/T <count> Specify number of threads to use\n"));
_tprintf(TEXT("/V <version> Version (eg NTx86.5.1)\n"));
_tprintf(TEXT("/W <textfile> List of files to include (alternative to /N)\n"));
_tprintf(TEXT("/X <textfile> List of files to exclude (same format as /W) overrides later includes\n"));
_tprintf(TEXT("/Y Don't check per-inf [SourceDisksFiles*]\n"));
_tprintf(TEXT("/Z Generate Pnfs and quit (see also /G)\n"));
_tprintf(TEXT("/? or /H Display brief usage message\n"));
}
bool MyGetStringField(PINFCONTEXT Context,DWORD FieldIndex,SafeString & result,bool downcase)
/*++
Routine Description:
Get a string field from an INF
downcase it if flag indicates it needs to be (typical case)
Arguments:
Context - from SetupFindFirstLine/SetupFindNextLine etc
FieldIndex - 0 for key, 1-n for parameter
result - string obtained
downcase - true (typical) to return result as lower-case
Return Value:
TRUE if success (result modified), FALSE otherwise (result left untouched)
--*/
{
TCHAR Buf[MAX_INF_STRING_LENGTH];
if(SetupGetStringField(Context,FieldIndex,Buf,MAX_INF_STRING_LENGTH,NULL)) {
if(downcase) {
_tcslwr(Buf);
}
result = Buf;
return true;
} else {
//
// leave result as is, allowing default capability
//
return false;
}
}
SafeString QuoteIt(const SafeString & val)
/*++
Routine Description:
Quote a string in such a way that it will be correctly parsed by SetupAPI
Arguments:
val - unquoted string
Return Value:
quoted string
--*/
{
if(val.empty()) {
//
// don't quote empty string
//
return val;
}
basic_ostringstream<TCHAR> result;
result << TEXT("\"");
LPCTSTR p = val.c_str();
LPCTSTR q;
while((q = wcsstr(p,TEXT("%\""))) != NULL) {
TCHAR c = *q;
q++; // include the special char
result << SafeString(p,q-p) << c; // write what we have so far, double up the special char
p = q;
}
result << p << TEXT("\"");
return result.str();
}
int GeneratePnf(const SafeString & pnf)
/*++
Routine Description:
Generate a single PNF
Arguments:
none
Return Value:
0 on success
--*/
{
HINF hInf;
hInf = SetupOpenInfFile(pnf.c_str(),
NULL,
INF_STYLE_WIN4 | INF_STYLE_CACHE_ENABLE,
NULL
);
if(hInf != INVALID_HANDLE_VALUE) {
SetupCloseInfFile(hInf);
}
return 0;
}
void Write(HANDLE hFile,const SafeStringW & str)
/*++
Routine Description:
Write a string to specified file, converting UNICODE to ANSI
Arguments:
NONE
Return Value:
0 on success
--*/
{
int len = WideCharToMultiByte(CP_ACP,0,str.c_str(),str.length(),NULL,0,NULL,NULL);
if(!len) {
return;
}
LPSTR buf = new CHAR[len];
if(!buf) {
return;
}
int nlen = WideCharToMultiByte(CP_ACP,0,str.c_str(),str.length(),buf,len,NULL,NULL);
if(!nlen) {
delete [] buf;
return;
}
DWORD written;
BOOL f = WriteFile(hFile,buf,len,&written,NULL);
delete [] buf;
}
void Write(HANDLE hFile,const SafeStringA & str)
/*++
Routine Description:
Write a string to specified file as-is
Arguments:
NONE
Return Value:
0 on success
--*/
{
DWORD written;
BOOL f = WriteFile(hFile,str.c_str(),str.length(),&written,NULL);
}