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.

415 lines
14 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. delete pDependQueue;
  156. delete pMissingFiles;
  157. pszFileName = 0;pQueue = 0;
  158. pDependQueue = 0; pMissingFiles = 0;
  159. return dwERROR;
  160. }
  161. //Given path and filename in 'pathname', fill 'path' with just the path
  162. void GetPath(TCHAR * pathname,TCHAR* path) {
  163. TCHAR* end,t;
  164. path[0] = '\0';
  165. //find last \ in the filename
  166. end = wcsrchr(pathname,'\\');
  167. if (!end) return;
  168. //copy just the path
  169. t = end[1];
  170. end[1] = '\0';
  171. wcscpy(path,pathname);
  172. end[1] = t;
  173. return;
  174. }
  175. /*Fill queue with the files in the command line and fill searchpath with directories in command line
  176. usage: depend [/s] /f:filespec;filespec;... [/d:directory;directory;..]
  177. If directories are not specififed the Windows search path will be used to look for dependencies
  178. /s Specifies silent mode.
  179. filespec - file path and name. Can include wildcards.
  180. */
  181. bool ParseCommandLine(int argc,wchar_t* argv[]){
  182. HANDLE handle;
  183. int nArg,nFile = 0;
  184. TCHAR *pszDirectory = new TCHAR[256],*pszFileName = new TCHAR[256],*ptr;
  185. WIN32_FIND_DATA fileData;
  186. bool bReturn;
  187. if (argc==1) {
  188. //if there are no arguments, display some kind of help
  189. if(bNoisy) {
  190. _putws( GetFormattedMessage(ThisModule,
  191. FALSE,
  192. Message,
  193. sizeof(Message)/sizeof(Message[0]),
  194. MSG_PGM_USAGE) );
  195. }
  196. bReturn = false;
  197. dwERROR = errBAD_ARGUMENTS;
  198. goto CLEANUP;
  199. }
  200. for (nArg=1;nArg<argc;nArg++) {
  201. if (argv[nArg][0] == '/') {
  202. //if this is the files argument
  203. if (argv[nArg][1] == 'f') {
  204. do {
  205. ptr = wcschr(argv[nArg]+3,';');
  206. if (ptr) {
  207. *ptr = '\0';
  208. wcscpy(pszFileName,ptr+1);
  209. } else wcscpy(pszFileName,argv[nArg]+3);
  210. //get the first file, put the path in pszDirectory
  211. handle = FindFirstFile(pszFileName,&fileData);
  212. GetPath(pszFileName,pszDirectory);
  213. if (*pszDirectory=='\0') {
  214. GetCurrentDirectory(256,pszDirectory);
  215. pszDirectory[wcslen(pszDirectory)+1] = '\0';
  216. pszDirectory[wcslen(pszDirectory)] = '\\';
  217. }
  218. //if the file wasn't found, error and quit
  219. if (handle == INVALID_HANDLE_VALUE) {
  220. if(bNoisy) {
  221. _putws( GetFormattedMessage(ThisModule,
  222. FALSE,
  223. Message,
  224. sizeof(Message)/sizeof(Message[0]),
  225. MSG_ARG_NOT_FOUND,
  226. argv[nArg]) );
  227. }
  228. dwERROR = errFILE_NOT_FOUND;
  229. bReturn = false;
  230. goto CLEANUP;
  231. }
  232. //put each file into the queue
  233. nFile = 1;
  234. while (nFile) {
  235. //standardize the name: full path, all lowercase
  236. wcscpy(pszFileName,pszDirectory);
  237. wcscat(pszFileName,fileData.cFileName);
  238. _wcslwr(pszFileName);
  239. //add the file to the queue if it's not already there
  240. if (!pQueue->Find(pszFileName)) pQueue->Add(new StringNode(pszFileName));
  241. //if list all dependencies is set, add to dependQueue
  242. if (bListDependencies)
  243. if (!pDependQueue->Find(pszFileName))
  244. pDependQueue->Add(new StringNode(pszFileName));
  245. nFile = FindNextFile(handle,&fileData);
  246. }//end while files
  247. } while (ptr);
  248. } else if (argv[nArg][1] == 'd') {
  249. //load directories
  250. pSearchPath = new List();
  251. do {
  252. ptr = wcschr(argv[nArg]+3,';');
  253. if (ptr) {
  254. *ptr = '\0';
  255. wcscpy(pszDirectory,ptr+1);
  256. } else wcscpy(pszDirectory,argv[nArg]+3);
  257. if (pszDirectory[wcslen(pszDirectory)-1]!='\\') {
  258. pszDirectory[wcslen(pszDirectory)+1] = '\0';
  259. pszDirectory[wcslen(pszDirectory)] = '\\';
  260. }
  261. pSearchPath->Add(new StringNode(pszDirectory));
  262. } while (ptr);
  263. } else
  264. //if silent mode, turn off noisy flag
  265. if (argv[nArg][1] == 's') bNoisy = false;
  266. else
  267. //if you want to list the dependencies of all files
  268. //turn on this flag
  269. if (argv[nArg][1] == 'l') bListDependencies = true;
  270. else
  271. {
  272. //unrecognized flag
  273. if(bNoisy) {
  274. _putws( GetFormattedMessage(ThisModule,
  275. FALSE,
  276. Message,
  277. sizeof(Message)/sizeof(Message[0]),
  278. MSG_BAD_ARGUMENT,
  279. argv[nArg]) );
  280. }
  281. dwERROR = errBAD_ARGUMENTS;
  282. bReturn = false;
  283. goto CLEANUP;
  284. }
  285. } else {
  286. //didn't start with a /
  287. if(bNoisy) {
  288. _putws( GetFormattedMessage(ThisModule,
  289. FALSE,
  290. Message,
  291. sizeof(Message)/sizeof(Message[0]),
  292. MSG_BAD_ARGUMENT,
  293. argv[nArg]) );
  294. }
  295. dwERROR = errBAD_ARGUMENTS;
  296. bReturn = false;
  297. goto CLEANUP;
  298. }
  299. }//end for arguments
  300. bReturn = true;
  301. CLEANUP:
  302. delete[] pszFileName;
  303. delete[] pszDirectory;
  304. pszFileName = pszDirectory = 0;
  305. return bReturn;
  306. }
  307. //Search for the given file in the given path
  308. //Arguments:
  309. //pszFileName - file to look for
  310. //pszPathName - path to look for it in
  311. bool SearchPath(TCHAR* pszFileName,TCHAR* pszPathName) {
  312. StringNode* s;
  313. WIN32_FIND_DATA buf;
  314. if (!pSearchPath) return false;
  315. s = (StringNode*)pSearchPath->head;
  316. while (s) {
  317. wcscpy(pszPathName,s->Data());
  318. wcscat(pszPathName,pszFileName);
  319. if (FindFirstFile(pszPathName,&buf)!=INVALID_HANDLE_VALUE) return true;
  320. s = (StringNode*)s->next;
  321. }
  322. pszPathName = 0;
  323. return false;
  324. }
  325. //Determine what type of file was passed in (16 bit,32,64) and create the appropriate file ptr.
  326. //pszFileName - file to be loaded
  327. File* CreateFile(TCHAR* pszFileName) {
  328. try {
  329. return new File32(pszFileName);
  330. } catch(int x) {
  331. if (x == errFILE_LOCKED) return 0;
  332. try {
  333. return new File64(pszFileName);
  334. } catch(int x) {
  335. if (x == errFILE_LOCKED) return 0;
  336. if (bNoisy) {
  337. _putws( GetFormattedMessage(ThisModule,
  338. FALSE,
  339. Message,
  340. sizeof(Message)/sizeof(Message[0]),
  341. MSG_ERROR_UNRECOGNIZED_FILE_TYPE,
  342. pszFileName) );
  343. }
  344. return 0;
  345. }
  346. }
  347. }