windows-nt/Source/XPSP1/NT/base/ntsetup/opktools/depend/depend.cpp

412 lines
13 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
#include <string.h>
#include <iostream>
#include <io.h>
#include <stdio.h>
#include <windows.h>
#include <new.h>
#include "List.h"
#include "File.h"
#include "File32.h"
#include "File64.h"
#include "Object.h"
#include "depend.h"
List* pQueue;
List* pDependQueue;
List* pSearchPath;
List* pMissingFiles;
bool bNoisy;
bool bListDependencies;
DWORD dwERROR;
//
// Global variables used to get formatted message for this program.
//
HMODULE ThisModule = NULL;
WCHAR Message[4096];
// Define a function to be called if new fails to allocate memory.
//
int __cdecl MyNewHandler( size_t size )
{
_putws( GetFormattedMessage( ThisModule,
FALSE,
Message,
sizeof(Message)/sizeof(Message[0]),
MSG_MEM_ALLOC_FAILED) );
// Exit program
//
ExitProcess(errOUT_OF_MEMORY);
}
/*
usage: depend [/s] [/l] /f:filespec;filespec;... [/d:directory;directory;..]
If directories are not specififed the Windows search path will be used to look for dependencies
/s Specifies silent mode.
filespec - file path and name. Can include wildcards.
*/
DWORD _cdecl wmain(int argc,wchar_t *argv[]) {
// Set the failure handler for new operator.
//
_set_new_handler( MyNewHandler );
TCHAR *pszFileName = new TCHAR[256];
File* pTempFile,*pCurrentFile;
StringNode* pCurFile;
char buf[256];
dwERROR = 0;
pSearchPath = 0;
bNoisy = true;
bListDependencies = false;
pQueue = new List();
pDependQueue = new List();
pMissingFiles = new List();
ThisModule = GetModuleHandle(NULL);
//Load the initial files into the queue and load the search path
if (!ParseCommandLine(argc,argv)) goto CLEANUP;
pCurFile = (StringNode*)pQueue->tail;
//while the queue isn't empty
while (pCurFile!=0) {
WideCharToMultiByte(CP_ACP,0,pCurFile->Data(),-1,buf,256,0,0);
//get a file pointer for the current file
if (!(pCurrentFile = CreateFile(pCurFile->Data()))) {
if (bListDependencies) {
StringNode* s;
if (s = (StringNode*)pDependQueue->Find(pCurFile->Data())) {
pDependQueue->Remove(pCurFile->Data());
}
}
//if there was an error and we are running in silent mode, quit
if (!bNoisy) goto CLEANUP;
}
else { //if we got a file pointer, proceed
if (bListDependencies) {
StringNode* s;
if (s = (StringNode*)pDependQueue->Find(pCurFile->Data())) {
pDependQueue->Remove(pCurFile->Data());
pDependQueue->Add(pCurrentFile);
}
}
//Check this files dependencies
pCurrentFile->CheckDependencies();
if ((dwERROR)&&(!bNoisy)) goto CLEANUP;
//Close the file
pCurrentFile->CloseFile();
}
//next file
pCurFile = (StringNode*)pCurFile->prev;
}
StringNode* s;
//if list dependencies is set, print out all dependencies
if (bListDependencies) {
pCurrentFile = (File*)pDependQueue->head;
//while the queue isn't empty
while (pCurrentFile!=0) {
_putws( GetFormattedMessage(ThisModule,
FALSE,
Message,
sizeof(Message)/sizeof(Message[0]),
MSG_DEPENDENCY_HEAD,
pCurrentFile->Data()) );
s = (StringNode*)pCurrentFile->dependencies->head;
while(s) {
_putws( GetFormattedMessage(ThisModule,
FALSE,
Message,
sizeof(Message)/sizeof(Message[0]),
MSG_FILE_NAME,
s->Data()) );
s = (StringNode*)s->next;
}
pCurrentFile = (File*)pCurrentFile->next;
}
}
//print out list of broken files
pTempFile = (File*)pMissingFiles->head;
while (pTempFile) {
if(bNoisy){
_putws( GetFormattedMessage(ThisModule,
FALSE,
Message,
sizeof(Message)/sizeof(Message[0]),
MSG_LIST_OF_BROKEN_FILES,
pTempFile->Data()) );
}
s = (StringNode*)pTempFile->owners->head;
while(s) {
if(bNoisy) {
_putws( GetFormattedMessage(ThisModule,
FALSE,
Message,
sizeof(Message)/sizeof(Message[0]),
MSG_FILE_NAME,
s->Data()) );
}
s = (StringNode*)s->next;
}
pTempFile = (File*)pTempFile->next;
}
//Done. Clean up and go home.
if(bNoisy) {
_putws( GetFormattedMessage(ThisModule,
FALSE,
Message,
sizeof(Message)/sizeof(Message[0]),
MSG_COMPLETED) );
}
CLEANUP:
delete [] pszFileName;
delete pQueue;
pszFileName = 0;pQueue = 0;
return dwERROR;
}
//Given path and filename in 'pathname', fill 'path' with just the path
void GetPath(TCHAR * pathname,TCHAR* path) {
TCHAR* end,t;
path[0] = '\0';
//find last \ in the filename
end = wcsrchr(pathname,'\\');
if (!end) return;
//copy just the path
t = end[1];
end[1] = '\0';
wcscpy(path,pathname);
end[1] = t;
return;
}
/*Fill queue with the files in the command line and fill searchpath with directories in command line
usage: depend [/s] /f:filespec;filespec;... [/d:directory;directory;..]
If directories are not specififed the Windows search path will be used to look for dependencies
/s Specifies silent mode.
filespec - file path and name. Can include wildcards.
*/
bool ParseCommandLine(int argc,wchar_t* argv[]){
HANDLE handle;
int nArg,nFile = 0;
TCHAR *pszDirectory = new TCHAR[256],*pszFileName = new TCHAR[256],*ptr;
WIN32_FIND_DATA fileData;
bool bReturn;
if (argc==1) {
//if there are no arguments, display some kind of help
if(bNoisy) {
_putws( GetFormattedMessage(ThisModule,
FALSE,
Message,
sizeof(Message)/sizeof(Message[0]),
MSG_PGM_USAGE) );
}
bReturn = false;
dwERROR = errBAD_ARGUMENTS;
goto CLEANUP;
}
for (nArg=1;nArg<argc;nArg++) {
if (argv[nArg][0] == '/') {
//if this is the files argument
if (argv[nArg][1] == 'f') {
do {
ptr = wcschr(argv[nArg]+3,';');
if (ptr) {
*ptr = '\0';
wcscpy(pszFileName,ptr+1);
} else wcscpy(pszFileName,argv[nArg]+3);
//get the first file, put the path in pszDirectory
handle = FindFirstFile(pszFileName,&fileData);
GetPath(pszFileName,pszDirectory);
if (*pszDirectory=='\0') {
GetCurrentDirectory(256,pszDirectory);
pszDirectory[wcslen(pszDirectory)+1] = '\0';
pszDirectory[wcslen(pszDirectory)] = '\\';
}
//if the file wasn't found, error and quit
if (handle == INVALID_HANDLE_VALUE) {
if(bNoisy) {
_putws( GetFormattedMessage(ThisModule,
FALSE,
Message,
sizeof(Message)/sizeof(Message[0]),
MSG_ARG_NOT_FOUND,
argv[nArg]) );
}
dwERROR = errFILE_NOT_FOUND;
bReturn = false;
goto CLEANUP;
}
//put each file into the queue
nFile = 1;
while (nFile) {
//standardize the name: full path, all lowercase
wcscpy(pszFileName,pszDirectory);
wcscat(pszFileName,fileData.cFileName);
_wcslwr(pszFileName);
//add the file to the queue if it's not already there
if (!pQueue->Find(pszFileName)) pQueue->Add(new StringNode(pszFileName));
//if list all dependencies is set, add to dependQueue
if (bListDependencies)
if (!pDependQueue->Find(pszFileName))
pDependQueue->Add(new StringNode(pszFileName));
nFile = FindNextFile(handle,&fileData);
}//end while files
} while (ptr);
} else if (argv[nArg][1] == 'd') {
//load directories
pSearchPath = new List();
do {
ptr = wcschr(argv[nArg]+3,';');
if (ptr) {
*ptr = '\0';
wcscpy(pszDirectory,ptr+1);
} else wcscpy(pszDirectory,argv[nArg]+3);
if (pszDirectory[wcslen(pszDirectory)-1]!='\\') {
pszDirectory[wcslen(pszDirectory)+1] = '\0';
pszDirectory[wcslen(pszDirectory)] = '\\';
}
pSearchPath->Add(new StringNode(pszDirectory));
} while (ptr);
} else
//if silent mode, turn off noisy flag
if (argv[nArg][1] == 's') bNoisy = false;
else
//if you want to list the dependencies of all files
//turn on this flag
if (argv[nArg][1] == 'l') bListDependencies = true;
else
{
//unrecognized flag
if(bNoisy) {
_putws( GetFormattedMessage(ThisModule,
FALSE,
Message,
sizeof(Message)/sizeof(Message[0]),
MSG_BAD_ARGUMENT,
argv[nArg]) );
}
dwERROR = errBAD_ARGUMENTS;
bReturn = false;
goto CLEANUP;
}
} else {
//didn't start with a /
if(bNoisy) {
_putws( GetFormattedMessage(ThisModule,
FALSE,
Message,
sizeof(Message)/sizeof(Message[0]),
MSG_BAD_ARGUMENT,
argv[nArg]) );
}
dwERROR = errBAD_ARGUMENTS;
bReturn = false;
goto CLEANUP;
}
}//end for arguments
bReturn = true;
CLEANUP:
delete[] pszFileName;
delete[] pszDirectory;
pszFileName = pszDirectory = 0;
return bReturn;
}
//Search for the given file in the given path
//Arguments:
//pszFileName - file to look for
//pszPathName - path to look for it in
bool SearchPath(TCHAR* pszFileName,TCHAR* pszPathName) {
StringNode* s;
WIN32_FIND_DATA buf;
if (!pSearchPath) return false;
s = (StringNode*)pSearchPath->head;
while (s) {
wcscpy(pszPathName,s->Data());
wcscat(pszPathName,pszFileName);
if (FindFirstFile(pszPathName,&buf)!=INVALID_HANDLE_VALUE) return true;
s = (StringNode*)s->next;
}
pszPathName = 0;
return false;
}
//Determine what type of file was passed in (16 bit,32,64) and create the appropriate file ptr.
//pszFileName - file to be loaded
File* CreateFile(TCHAR* pszFileName) {
try {
return new File32(pszFileName);
} catch(int x) {
if (x == errFILE_LOCKED) return 0;
try {
return new File64(pszFileName);
} catch(int x) {
if (x == errFILE_LOCKED) return 0;
if (bNoisy) {
_putws( GetFormattedMessage(ThisModule,
FALSE,
Message,
sizeof(Message)/sizeof(Message[0]),
MSG_ERROR_UNRECOGNIZED_FILE_TYPE,
pszFileName) );
}
return 0;
}
}
}