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.

157 lines
6.0 KiB

  1. // File64.cpp: implementation of the File64 class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include <windows.h>
  5. #include <imagehlp.h>
  6. #include <stdio.h>
  7. #include "File64.h"
  8. #include "depend.h"
  9. //////////////////////////////////////////////////////////////////////
  10. // Construction/Destruction
  11. //////////////////////////////////////////////////////////////////////
  12. //pszFileName - file to be loaded, including path
  13. File64::File64(TCHAR *pszFileName) : File(pszFileName)
  14. {
  15. HANDLE hFileMap;
  16. //open the file
  17. if ((hFile = CreateFile(pszFileName,GENERIC_READ,0,0,OPEN_EXISTING,0,0)) == INVALID_HANDLE_VALUE) {
  18. if(bNoisy) {
  19. _putws( GetFormattedMessage( ThisModule,
  20. FALSE,
  21. Message,
  22. sizeof(Message)/sizeof(Message[0]),
  23. MSG_ERROR_FILE_OPEN,
  24. pszFileName) );
  25. }
  26. dwERROR = errFILE_LOCKED;
  27. throw errFILE_LOCKED;
  28. }
  29. //create a memory map
  30. hFileMap = CreateFileMapping(hFile,0,PAGE_READONLY,0,0,0);
  31. pImageBase = MapViewOfFile(hFileMap,FILE_MAP_READ,0,0,0);
  32. //try to create an NTHeader structure to give file information
  33. if (pNthdr = ImageNtHeader(pImageBase)) {
  34. if ((pNthdr->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64) ||
  35. (pNthdr->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64)) {
  36. pNthdr64 = (PIMAGE_NT_HEADERS64)pNthdr;
  37. return;
  38. }
  39. else { CloseHandle(hFile); hFile = INVALID_HANDLE_VALUE; throw 0; }
  40. } else { CloseHandle(hFile); hFile = INVALID_HANDLE_VALUE; throw 0; }
  41. }
  42. File64::~File64()
  43. {
  44. delete pImageBase;
  45. pImageBase = 0;
  46. }
  47. //Checks the dependencies of this file, and adds the dependencies to the queue so
  48. //their dependencies can be checked later
  49. //If a file comes up missing add it to the MissingFiles queue. Add the file that was looking for it to the missing files'
  50. //list of broken files.
  51. //This function has logic in it to handle the special case of 'ntoskrnl.exe'. If a file is
  52. //looking for 'ntoskrnl.exe' and it is missing then the function also looks for 'ntkrnlmp.exe'
  53. void File64::CheckDependencies() {
  54. char *pszDllName = new char[256];
  55. TCHAR*pwsDllName = new TCHAR[256],*pszBuf = new TCHAR[256],*pszBufName;
  56. int temp = 0;
  57. File* pTempFile;
  58. DWORD dwOffset;
  59. DWORD dwVA = pNthdr64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
  60. PIMAGE_SECTION_HEADER pSectHdr = IMAGE_FIRST_SECTION( pNthdr64 ),pImportHdr = 0;
  61. PIMAGE_IMPORT_DESCRIPTOR pImportDir;
  62. //figure out which section the imports table is in
  63. for ( unsigned i = 0; i < pNthdr64->FileHeader.NumberOfSections; i++, pSectHdr++ ) {
  64. DWORD cbMaxOnDisk = min( pSectHdr->Misc.VirtualSize, pSectHdr->SizeOfRawData );
  65. DWORD startSectRVA = pSectHdr->VirtualAddress;
  66. DWORD endSectRVA = startSectRVA + cbMaxOnDisk;
  67. if ( (dwVA >= startSectRVA) && (dwVA < endSectRVA) ) {
  68. dwOffset = pSectHdr->PointerToRawData + (dwVA - startSectRVA);
  69. pImportHdr = pSectHdr;
  70. i = pNthdr64->FileHeader.NumberOfSections;
  71. }
  72. }
  73. //if we found the imports table, create a pointer to it
  74. if (pImportHdr) {
  75. pImportDir = (PIMAGE_IMPORT_DESCRIPTOR) (((PBYTE)pImageBase) + (DWORD)dwOffset);
  76. //go through each import, try and find it, and add it to the queue
  77. while ((DWORD)(pImportDir->Name)!=0) {
  78. strcpy(pszDllName,(char*)(pImportDir->Name + ((PBYTE)pImageBase) - pImportHdr->VirtualAddress + pImportHdr->PointerToRawData));
  79. _strlwr(pszDllName);
  80. //if the ListDependencies flag is set, add this file to the dependencies list
  81. if (bListDependencies) {
  82. MultiByteToWideChar(CP_ACP,0,pszDllName,-1,pwsDllName,256);
  83. if (!dependencies->Find(pwsDllName)) dependencies->Add(new StringNode(pwsDllName));
  84. }
  85. if (strcmp(pszDllName,"ntoskrnl.exe")) {
  86. //if the file is already known to be missing
  87. temp = MultiByteToWideChar(CP_ACP,0,pszDllName,-1,pwsDllName,256);
  88. if (pTempFile = (File*)pMissingFiles->Find(pwsDllName)) {
  89. dwERROR = errMISSING_DEPENDENCY;
  90. //add this file to the list of broken files
  91. pTempFile->AddDependant(new StringNode(fileName));
  92. } else {
  93. //either search the windows path or the path specified in the command line
  94. if ( ((!pSearchPath)&&(!(SearchPath(0,pwsDllName,0,256,pszBuf,&pszBufName))))|| ((pSearchPath)&&(!SearchPath(pwsDllName,pszBuf))) ) {
  95. //if the file is not found, add it to missing files list and throw an error
  96. pMissingFiles->Add(new File(pwsDllName));
  97. ((File*)(pMissingFiles->head))->AddDependant(new StringNode(fileName));
  98. dwERROR = errMISSING_DEPENDENCY;
  99. if (!bNoisy) goto CLEANUP;
  100. }
  101. else {
  102. //if the file is found, add it to the queue
  103. _wcslwr(pszBuf);
  104. if (!(pQueue->Find(pszBuf))) pQueue->Add(new StringNode(pszBuf));
  105. }
  106. }
  107. } else {
  108. //if the file is already known to be missing
  109. if ((pTempFile = (File*)pMissingFiles->Find(L"ntoskrnl.exe"))) {
  110. dwERROR = errMISSING_DEPENDENCY;
  111. pTempFile->AddDependant(new StringNode(fileName));
  112. } else {
  113. //either search the windows path or the path specified in the command line
  114. if ( (((!pSearchPath)&&(!(SearchPath(0,L"ntoskrnl.exe",0,256,pszBuf,&pszBufName))))||((pSearchPath)&&(!SearchPath(L"ntoskrnl.exe",pszBuf))))
  115. &&(((!pSearchPath)&&(!(SearchPath(0,L"ntkrnlmp.exe",0,256,pszBuf,&pszBufName))))||((pSearchPath)&&(!SearchPath(L"ntkrnlmp.exe",pszBuf))))) {
  116. //if the file is not found, add it to missing files list and throw an error
  117. pMissingFiles->Add(new File(L"ntoskrnl.exe"));
  118. ((File*)(pMissingFiles->head))->AddDependant(new StringNode(fileName));
  119. dwERROR = errMISSING_DEPENDENCY;
  120. if (!bNoisy) goto CLEANUP;
  121. }
  122. else {
  123. //if the file is found, add it to the queue
  124. _wcslwr(pszBuf);
  125. if (!(pQueue->Find(pszBuf))) pQueue->Add(new StringNode(pszBuf));
  126. }
  127. }
  128. }
  129. pImportDir++;
  130. }
  131. }
  132. CLEANUP:
  133. delete [] pszDllName;
  134. delete [] pszBuf;
  135. }