Source code of Windows XP (NT5)
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.

411 lines
13 KiB

  1. #include <string.h>
  2. #include <iostream>
  3. #include <io.h>
  4. #include <stdio.h>
  5. #include <windows.h>
  6. #include <new.h>
  7. #include "List.h"
  8. #include "File.h"
  9. #include "File32.h"
  10. #include "File64.h"
  11. #include "Object.h"
  12. #include "depend.h"
  13. List* pQueue;
  14. List* pDependQueue;
  15. List* pSearchPath;
  16. List* pMissingFiles;
  17. bool bNoisy;
  18. bool bListDependencies;
  19. DWORD dwERROR;
  20. //
  21. // Global variables used to get formatted message for this program.
  22. //
  23. HMODULE ThisModule = NULL;
  24. WCHAR Message[4096];
  25. // Define a function to be called if new fails to allocate memory.
  26. //
  27. int __cdecl MyNewHandler( size_t size )
  28. {
  29. _putws( GetFormattedMessage( ThisModule,
  30. FALSE,
  31. Message,
  32. sizeof(Message)/sizeof(Message[0]),
  33. MSG_MEM_ALLOC_FAILED) );
  34. // Exit program
  35. //
  36. ExitProcess(errOUT_OF_MEMORY);
  37. }
  38. /*
  39. usage: depend [/s] [/l] /f:filespec;filespec;... [/d:directory;directory;..]
  40. If directories are not specififed the Windows search path will be used to look for dependencies
  41. /s Specifies silent mode.
  42. filespec - file path and name. Can include wildcards.
  43. */
  44. DWORD _cdecl wmain(int argc,wchar_t *argv[]) {
  45. // Set the failure handler for new operator.
  46. //
  47. _set_new_handler( MyNewHandler );
  48. TCHAR *pszFileName = new TCHAR[256];
  49. File* pTempFile,*pCurrentFile;
  50. StringNode* pCurFile;
  51. char buf[256];
  52. dwERROR = 0;
  53. pSearchPath = 0;
  54. bNoisy = true;
  55. bListDependencies = false;
  56. pQueue = new List();
  57. pDependQueue = new List();
  58. pMissingFiles = new List();
  59. ThisModule = GetModuleHandle(NULL);
  60. //Load the initial files into the queue and load the search path
  61. if (!ParseCommandLine(argc,argv)) goto CLEANUP;
  62. pCurFile = (StringNode*)pQueue->tail;
  63. //while the queue isn't empty
  64. while (pCurFile!=0) {
  65. WideCharToMultiByte(CP_ACP,0,pCurFile->Data(),-1,buf,256,0,0);
  66. //get a file pointer for the current file
  67. if (!(pCurrentFile = CreateFile(pCurFile->Data()))) {
  68. if (bListDependencies) {
  69. StringNode* s;
  70. if (s = (StringNode*)pDependQueue->Find(pCurFile->Data())) {
  71. pDependQueue->Remove(pCurFile->Data());
  72. }
  73. }
  74. //if there was an error and we are running in silent mode, quit
  75. if (!bNoisy) goto CLEANUP;
  76. }
  77. else { //if we got a file pointer, proceed
  78. if (bListDependencies) {
  79. StringNode* s;
  80. if (s = (StringNode*)pDependQueue->Find(pCurFile->Data())) {
  81. pDependQueue->Remove(pCurFile->Data());
  82. pDependQueue->Add(pCurrentFile);
  83. }
  84. }
  85. //Check this files dependencies
  86. pCurrentFile->CheckDependencies();
  87. if ((dwERROR)&&(!bNoisy)) goto CLEANUP;
  88. //Close the file
  89. pCurrentFile->CloseFile();
  90. }
  91. //next file
  92. pCurFile = (StringNode*)pCurFile->prev;
  93. }
  94. StringNode* s;
  95. //if list dependencies is set, print out all dependencies
  96. if (bListDependencies) {
  97. pCurrentFile = (File*)pDependQueue->head;
  98. //while the queue isn't empty
  99. while (pCurrentFile!=0) {
  100. _putws( GetFormattedMessage(ThisModule,
  101. FALSE,
  102. Message,
  103. sizeof(Message)/sizeof(Message[0]),
  104. MSG_DEPENDENCY_HEAD,
  105. pCurrentFile->Data()) );
  106. s = (StringNode*)pCurrentFile->dependencies->head;
  107. while(s) {
  108. _putws( GetFormattedMessage(ThisModule,
  109. FALSE,
  110. Message,
  111. sizeof(Message)/sizeof(Message[0]),
  112. MSG_FILE_NAME,
  113. s->Data()) );
  114. s = (StringNode*)s->next;
  115. }
  116. pCurrentFile = (File*)pCurrentFile->next;
  117. }
  118. }
  119. //print out list of broken files
  120. pTempFile = (File*)pMissingFiles->head;
  121. while (pTempFile) {
  122. if(bNoisy){
  123. _putws( GetFormattedMessage(ThisModule,
  124. FALSE,
  125. Message,
  126. sizeof(Message)/sizeof(Message[0]),
  127. MSG_LIST_OF_BROKEN_FILES,
  128. pTempFile->Data()) );
  129. }
  130. s = (StringNode*)pTempFile->owners->head;
  131. while(s) {
  132. if(bNoisy) {
  133. _putws( GetFormattedMessage(ThisModule,
  134. FALSE,
  135. Message,
  136. sizeof(Message)/sizeof(Message[0]),
  137. MSG_FILE_NAME,
  138. s->Data()) );
  139. }
  140. s = (StringNode*)s->next;
  141. }
  142. pTempFile = (File*)pTempFile->next;
  143. }
  144. //Done. Clean up and go home.
  145. if(bNoisy) {
  146. _putws( GetFormattedMessage(ThisModule,
  147. FALSE,
  148. Message,
  149. sizeof(Message)/sizeof(Message[0]),
  150. MSG_COMPLETED) );
  151. }
  152. CLEANUP:
  153. delete [] pszFileName;
  154. delete pQueue;
  155. pszFileName = 0;pQueue = 0;
  156. return dwERROR;
  157. }
  158. //Given path and filename in 'pathname', fill 'path' with just the path
  159. void GetPath(TCHAR * pathname,TCHAR* path) {
  160. TCHAR* end,t;
  161. path[0] = '\0';
  162. //find last \ in the filename
  163. end = wcsrchr(pathname,'\\');
  164. if (!end) return;
  165. //copy just the path
  166. t = end[1];
  167. end[1] = '\0';
  168. wcscpy(path,pathname);
  169. end[1] = t;
  170. return;
  171. }
  172. /*Fill queue with the files in the command line and fill searchpath with directories in command line
  173. usage: depend [/s] /f:filespec;filespec;... [/d:directory;directory;..]
  174. If directories are not specififed the Windows search path will be used to look for dependencies
  175. /s Specifies silent mode.
  176. filespec - file path and name. Can include wildcards.
  177. */
  178. bool ParseCommandLine(int argc,wchar_t* argv[]){
  179. HANDLE handle;
  180. int nArg,nFile = 0;
  181. TCHAR *pszDirectory = new TCHAR[256],*pszFileName = new TCHAR[256],*ptr;
  182. WIN32_FIND_DATA fileData;
  183. bool bReturn;
  184. if (argc==1) {
  185. //if there are no arguments, display some kind of help
  186. if(bNoisy) {
  187. _putws( GetFormattedMessage(ThisModule,
  188. FALSE,
  189. Message,
  190. sizeof(Message)/sizeof(Message[0]),
  191. MSG_PGM_USAGE) );
  192. }
  193. bReturn = false;
  194. dwERROR = errBAD_ARGUMENTS;
  195. goto CLEANUP;
  196. }
  197. for (nArg=1;nArg<argc;nArg++) {
  198. if (argv[nArg][0] == '/') {
  199. //if this is the files argument
  200. if (argv[nArg][1] == 'f') {
  201. do {
  202. ptr = wcschr(argv[nArg]+3,';');
  203. if (ptr) {
  204. *ptr = '\0';
  205. wcscpy(pszFileName,ptr+1);
  206. } else wcscpy(pszFileName,argv[nArg]+3);
  207. //get the first file, put the path in pszDirectory
  208. handle = FindFirstFile(pszFileName,&fileData);
  209. GetPath(pszFileName,pszDirectory);
  210. if (*pszDirectory=='\0') {
  211. GetCurrentDirectory(256,pszDirectory);
  212. pszDirectory[wcslen(pszDirectory)+1] = '\0';
  213. pszDirectory[wcslen(pszDirectory)] = '\\';
  214. }
  215. //if the file wasn't found, error and quit
  216. if (handle == INVALID_HANDLE_VALUE) {
  217. if(bNoisy) {
  218. _putws( GetFormattedMessage(ThisModule,
  219. FALSE,
  220. Message,
  221. sizeof(Message)/sizeof(Message[0]),
  222. MSG_ARG_NOT_FOUND,
  223. argv[nArg]) );
  224. }
  225. dwERROR = errFILE_NOT_FOUND;
  226. bReturn = false;
  227. goto CLEANUP;
  228. }
  229. //put each file into the queue
  230. nFile = 1;
  231. while (nFile) {
  232. //standardize the name: full path, all lowercase
  233. wcscpy(pszFileName,pszDirectory);
  234. wcscat(pszFileName,fileData.cFileName);
  235. _wcslwr(pszFileName);
  236. //add the file to the queue if it's not already there
  237. if (!pQueue->Find(pszFileName)) pQueue->Add(new StringNode(pszFileName));
  238. //if list all dependencies is set, add to dependQueue
  239. if (bListDependencies)
  240. if (!pDependQueue->Find(pszFileName))
  241. pDependQueue->Add(new StringNode(pszFileName));
  242. nFile = FindNextFile(handle,&fileData);
  243. }//end while files
  244. } while (ptr);
  245. } else if (argv[nArg][1] == 'd') {
  246. //load directories
  247. pSearchPath = new List();
  248. do {
  249. ptr = wcschr(argv[nArg]+3,';');
  250. if (ptr) {
  251. *ptr = '\0';
  252. wcscpy(pszDirectory,ptr+1);
  253. } else wcscpy(pszDirectory,argv[nArg]+3);
  254. if (pszDirectory[wcslen(pszDirectory)-1]!='\\') {
  255. pszDirectory[wcslen(pszDirectory)+1] = '\0';
  256. pszDirectory[wcslen(pszDirectory)] = '\\';
  257. }
  258. pSearchPath->Add(new StringNode(pszDirectory));
  259. } while (ptr);
  260. } else
  261. //if silent mode, turn off noisy flag
  262. if (argv[nArg][1] == 's') bNoisy = false;
  263. else
  264. //if you want to list the dependencies of all files
  265. //turn on this flag
  266. if (argv[nArg][1] == 'l') bListDependencies = true;
  267. else
  268. {
  269. //unrecognized flag
  270. if(bNoisy) {
  271. _putws( GetFormattedMessage(ThisModule,
  272. FALSE,
  273. Message,
  274. sizeof(Message)/sizeof(Message[0]),
  275. MSG_BAD_ARGUMENT,
  276. argv[nArg]) );
  277. }
  278. dwERROR = errBAD_ARGUMENTS;
  279. bReturn = false;
  280. goto CLEANUP;
  281. }
  282. } else {
  283. //didn't start with a /
  284. if(bNoisy) {
  285. _putws( GetFormattedMessage(ThisModule,
  286. FALSE,
  287. Message,
  288. sizeof(Message)/sizeof(Message[0]),
  289. MSG_BAD_ARGUMENT,
  290. argv[nArg]) );
  291. }
  292. dwERROR = errBAD_ARGUMENTS;
  293. bReturn = false;
  294. goto CLEANUP;
  295. }
  296. }//end for arguments
  297. bReturn = true;
  298. CLEANUP:
  299. delete[] pszFileName;
  300. delete[] pszDirectory;
  301. pszFileName = pszDirectory = 0;
  302. return bReturn;
  303. }
  304. //Search for the given file in the given path
  305. //Arguments:
  306. //pszFileName - file to look for
  307. //pszPathName - path to look for it in
  308. bool SearchPath(TCHAR* pszFileName,TCHAR* pszPathName) {
  309. StringNode* s;
  310. WIN32_FIND_DATA buf;
  311. if (!pSearchPath) return false;
  312. s = (StringNode*)pSearchPath->head;
  313. while (s) {
  314. wcscpy(pszPathName,s->Data());
  315. wcscat(pszPathName,pszFileName);
  316. if (FindFirstFile(pszPathName,&buf)!=INVALID_HANDLE_VALUE) return true;
  317. s = (StringNode*)s->next;
  318. }
  319. pszPathName = 0;
  320. return false;
  321. }
  322. //Determine what type of file was passed in (16 bit,32,64) and create the appropriate file ptr.
  323. //pszFileName - file to be loaded
  324. File* CreateFile(TCHAR* pszFileName) {
  325. try {
  326. return new File32(pszFileName);
  327. } catch(int x) {
  328. if (x == errFILE_LOCKED) return 0;
  329. try {
  330. return new File64(pszFileName);
  331. } catch(int x) {
  332. if (x == errFILE_LOCKED) return 0;
  333. if (bNoisy) {
  334. _putws( GetFormattedMessage(ThisModule,
  335. FALSE,
  336. Message,
  337. sizeof(Message)/sizeof(Message[0]),
  338. MSG_ERROR_UNRECOGNIZED_FILE_TYPE,
  339. pszFileName) );
  340. }
  341. return 0;
  342. }
  343. }
  344. }