#include #include #include #include #include #include #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;nArgFind(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; } } }