|
|
#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; delete pDependQueue; delete pMissingFiles;
pszFileName = 0;pQueue = 0; pDependQueue = 0; pMissingFiles = 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; } }
}
|