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.

556 lines
15 KiB

  1. /*++
  2. Copyright (c) 1994-96 Microsoft Corporation
  3. Module Name:
  4. map.c
  5. Abstract:
  6. Implementation for the MapAndLoad API
  7. Author:
  8. Revision History:
  9. --*/
  10. #include <private.h>
  11. #include <globals.h>
  12. BOOL
  13. MapAndLoad(
  14. LPSTR ImageName,
  15. LPSTR DllPath,
  16. PLOADED_IMAGE LoadedImage,
  17. BOOL DotDll,
  18. BOOL ReadOnly
  19. )
  20. {
  21. HANDLE hFile;
  22. HANDLE hMappedFile;
  23. CHAR SearchBuffer[MAX_PATH];
  24. DWORD dw;
  25. LPSTR FilePart;
  26. LPSTR OpenName;
  27. // open and map the file.
  28. // then fill in the loaded image descriptor
  29. LoadedImage->hFile = INVALID_HANDLE_VALUE;
  30. OpenName = ImageName;
  31. dw = 0;
  32. retry:
  33. hFile = CreateFile(
  34. OpenName,
  35. ReadOnly ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
  36. g.OSVerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT ? (FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE) : (FILE_SHARE_READ | FILE_SHARE_WRITE),
  37. NULL,
  38. OPEN_EXISTING,
  39. 0,
  40. NULL
  41. );
  42. if ( hFile == INVALID_HANDLE_VALUE ) {
  43. if ( !dw ) {
  44. //
  45. // open failed try to find the file on the search path
  46. //
  47. dw = SearchPath(
  48. DllPath,
  49. ImageName,
  50. DotDll ? ".dll" : ".exe",
  51. MAX_PATH,
  52. SearchBuffer,
  53. &FilePart
  54. );
  55. if ( dw && dw < MAX_PATH ) {
  56. OpenName = SearchBuffer;
  57. goto retry;
  58. }
  59. }
  60. return FALSE;
  61. }
  62. if (MapIt(hFile, LoadedImage, ReadOnly) == FALSE) {
  63. CloseHandle(hFile);
  64. return FALSE;
  65. } else {
  66. LoadedImage->ModuleName = (LPSTR) MemAlloc( strlen(OpenName)+16 );
  67. if (!LoadedImage->ModuleName) {
  68. return FALSE;
  69. }
  70. strcpy( LoadedImage->ModuleName, OpenName );
  71. // If readonly, no need to keep the file open..
  72. if (ReadOnly) {
  73. CloseHandle(hFile);
  74. }
  75. return TRUE;
  76. }
  77. }
  78. BOOL
  79. MapIt(
  80. HANDLE hFile,
  81. PLOADED_IMAGE LoadedImage,
  82. BOOL ReadOnly
  83. )
  84. {
  85. HANDLE hMappedFile;
  86. hMappedFile = CreateFileMapping(
  87. hFile,
  88. NULL,
  89. ReadOnly ? PAGE_READONLY : PAGE_READWRITE,
  90. 0,
  91. 0,
  92. NULL
  93. );
  94. if ( !hMappedFile ) {
  95. return FALSE;
  96. }
  97. LoadedImage->MappedAddress = (PUCHAR) MapViewOfFile(
  98. hMappedFile,
  99. ReadOnly ? FILE_MAP_READ : FILE_MAP_WRITE,
  100. 0,
  101. 0,
  102. 0
  103. );
  104. CloseHandle(hMappedFile);
  105. LoadedImage->SizeOfImage = GetFileSize(hFile, NULL);
  106. if (!LoadedImage->MappedAddress ||
  107. !CalculateImagePtrs(LoadedImage)) {
  108. return(FALSE);
  109. }
  110. if (ReadOnly) {
  111. LoadedImage->hFile = INVALID_HANDLE_VALUE;
  112. } else {
  113. LoadedImage->hFile = hFile;
  114. }
  115. return(TRUE);
  116. }
  117. BOOL
  118. CalculateImagePtrs(
  119. PLOADED_IMAGE LoadedImage
  120. )
  121. {
  122. PIMAGE_DOS_HEADER DosHeader;
  123. PIMAGE_NT_HEADERS NtHeaders;
  124. PIMAGE_FILE_HEADER FileHeader;
  125. BOOL fRC;
  126. // Everything is mapped. Now check the image and find nt image headers
  127. fRC = TRUE; // Assume the best
  128. __try {
  129. DosHeader = (PIMAGE_DOS_HEADER)LoadedImage->MappedAddress;
  130. if ((DosHeader->e_magic != IMAGE_DOS_SIGNATURE) &&
  131. (DosHeader->e_magic != IMAGE_NT_SIGNATURE)) {
  132. fRC = FALSE;
  133. goto tryout;
  134. }
  135. if (DosHeader->e_magic == IMAGE_DOS_SIGNATURE) {
  136. if (DosHeader->e_lfanew == 0) {
  137. LoadedImage->fDOSImage = TRUE;
  138. fRC = FALSE;
  139. goto tryout;
  140. }
  141. LoadedImage->FileHeader = (PIMAGE_NT_HEADERS)((ULONG_PTR)DosHeader + DosHeader->e_lfanew);
  142. if (
  143. // If IMAGE_NT_HEADERS would extend past the end of file...
  144. (PBYTE)LoadedImage->FileHeader + sizeof(IMAGE_NT_HEADERS) >
  145. (PBYTE)LoadedImage->MappedAddress + LoadedImage->SizeOfImage ||
  146. // ..or if it would begin in, or before the IMAGE_DOS_HEADER...
  147. (PBYTE)LoadedImage->FileHeader <
  148. (PBYTE)LoadedImage->MappedAddress + sizeof(IMAGE_DOS_HEADER) )
  149. {
  150. // ...then e_lfanew is not as expected.
  151. // (Several Win95 files are in this category.)
  152. fRC = FALSE;
  153. goto tryout;
  154. }
  155. } else {
  156. // No DOS header indicates an image built w/o a dos stub
  157. LoadedImage->FileHeader = (PIMAGE_NT_HEADERS)((ULONG_PTR)DosHeader);
  158. }
  159. NtHeaders = LoadedImage->FileHeader;
  160. if ( NtHeaders->Signature != IMAGE_NT_SIGNATURE ) {
  161. if ( (USHORT)NtHeaders->Signature == (USHORT)IMAGE_OS2_SIGNATURE ||
  162. (USHORT)NtHeaders->Signature == (USHORT)IMAGE_OS2_SIGNATURE_LE
  163. ) {
  164. LoadedImage->fDOSImage = TRUE;
  165. }
  166. fRC = FALSE;
  167. goto tryout;
  168. } else {
  169. LoadedImage->fDOSImage = FALSE;
  170. }
  171. FileHeader = &NtHeaders->FileHeader;
  172. // No optional header indicates an object...
  173. if ( FileHeader->SizeOfOptionalHeader == 0 ) {
  174. fRC = FALSE;
  175. goto tryout;
  176. }
  177. if (NtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
  178. // 32-bit image. Do some tests.
  179. if (((PIMAGE_NT_HEADERS32)NtHeaders)->OptionalHeader.ImageBase >= 0x80000000) {
  180. LoadedImage->fSystemImage = TRUE;
  181. } else {
  182. LoadedImage->fSystemImage = FALSE;
  183. }
  184. if (((PIMAGE_NT_HEADERS32)NtHeaders)->OptionalHeader.MajorLinkerVersion < 3 &&
  185. ((PIMAGE_NT_HEADERS32)NtHeaders)->OptionalHeader.MinorLinkerVersion < 5)
  186. {
  187. fRC = FALSE;
  188. goto tryout;
  189. }
  190. } else {
  191. LoadedImage->fSystemImage = FALSE;
  192. }
  193. LoadedImage->Sections = IMAGE_FIRST_SECTION(NtHeaders);
  194. InitializeListHead( &LoadedImage->Links );
  195. LoadedImage->Characteristics = FileHeader->Characteristics;
  196. LoadedImage->NumberOfSections = FileHeader->NumberOfSections;
  197. LoadedImage->LastRvaSection = LoadedImage->Sections;
  198. tryout:
  199. if (fRC == FALSE) {
  200. UnmapViewOfFile(LoadedImage->MappedAddress);
  201. SetLastError(ERROR_BAD_FORMAT);
  202. }
  203. } __except ( EXCEPTION_EXECUTE_HANDLER ) {
  204. fRC = FALSE;
  205. }
  206. return fRC;
  207. }
  208. BOOL
  209. UnMapAndLoad(
  210. PLOADED_IMAGE pLi
  211. )
  212. {
  213. UnMapIt(pLi);
  214. if (pLi->hFile != INVALID_HANDLE_VALUE) {
  215. CloseHandle(pLi->hFile);
  216. }
  217. return TRUE;
  218. }
  219. BOOL
  220. GrowMap (
  221. PLOADED_IMAGE pLi,
  222. LONG lSizeOfDelta
  223. )
  224. {
  225. if (pLi->hFile == INVALID_HANDLE_VALUE) {
  226. // Can't grow read/only files.
  227. return FALSE;
  228. } else {
  229. HANDLE hMappedFile;
  230. FlushViewOfFile(pLi->MappedAddress, pLi->SizeOfImage);
  231. UnmapViewOfFile(pLi->MappedAddress);
  232. pLi->SizeOfImage += lSizeOfDelta;
  233. SetFilePointer(pLi->hFile, pLi->SizeOfImage, NULL, FILE_BEGIN);
  234. SetEndOfFile(pLi->hFile);
  235. hMappedFile = CreateFileMapping(
  236. pLi->hFile,
  237. NULL,
  238. PAGE_READWRITE,
  239. 0,
  240. pLi->SizeOfImage,
  241. NULL
  242. );
  243. if ( !hMappedFile ) {
  244. CloseHandle(pLi->hFile);
  245. pLi->hFile = INVALID_HANDLE_VALUE;
  246. return FALSE;
  247. }
  248. pLi->MappedAddress = (PUCHAR) MapViewOfFile(
  249. hMappedFile,
  250. FILE_MAP_WRITE,
  251. 0,
  252. 0,
  253. 0
  254. );
  255. CloseHandle(hMappedFile);
  256. if (!pLi->MappedAddress) {
  257. CloseHandle(pLi->hFile);
  258. pLi->hFile = INVALID_HANDLE_VALUE;
  259. return(FALSE);
  260. }
  261. // Win95 doesn't zero fill when it extends. Do it here.
  262. if (lSizeOfDelta > 0) {
  263. memset(pLi->MappedAddress + pLi->SizeOfImage - lSizeOfDelta, 0, lSizeOfDelta);
  264. }
  265. // Recalc the LoadedImage struct (remapping may have changed the map address)
  266. if (!CalculateImagePtrs(pLi)) {
  267. CloseHandle(pLi->hFile);
  268. pLi->hFile = INVALID_HANDLE_VALUE;
  269. return(FALSE);
  270. }
  271. return TRUE;
  272. }
  273. }
  274. VOID
  275. UnMapIt(
  276. PLOADED_IMAGE pLi
  277. )
  278. {
  279. DWORD HeaderSum, CheckSum;
  280. BOOL bl;
  281. DWORD dw;
  282. PIMAGE_NT_HEADERS NtHeaders;
  283. // Test for read-only
  284. if (pLi->hFile == INVALID_HANDLE_VALUE) {
  285. UnmapViewOfFile(pLi->MappedAddress);
  286. } else {
  287. CheckSumMappedFile( pLi->MappedAddress,
  288. pLi->SizeOfImage,
  289. &HeaderSum,
  290. &CheckSum
  291. );
  292. NtHeaders = pLi->FileHeader;
  293. if (NtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
  294. ((PIMAGE_NT_HEADERS32)NtHeaders)->OptionalHeader.CheckSum = CheckSum;
  295. } else {
  296. if (NtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
  297. ((PIMAGE_NT_HEADERS64)NtHeaders)->OptionalHeader.CheckSum = CheckSum;
  298. }
  299. }
  300. FlushViewOfFile(pLi->MappedAddress, pLi->SizeOfImage);
  301. UnmapViewOfFile(pLi->MappedAddress);
  302. if (pLi->SizeOfImage != GetFileSize(pLi->hFile, NULL)) {
  303. dw = SetFilePointer(pLi->hFile, pLi->SizeOfImage, NULL, FILE_BEGIN);
  304. dw = GetLastError();
  305. bl = SetEndOfFile(pLi->hFile);
  306. dw = GetLastError();
  307. }
  308. }
  309. }
  310. BOOL
  311. GetImageConfigInformation(
  312. PLOADED_IMAGE LoadedImage,
  313. PIMAGE_LOAD_CONFIG_DIRECTORY ImageConfigInformation
  314. )
  315. {
  316. PIMAGE_LOAD_CONFIG_DIRECTORY ImageConfigData;
  317. ULONG i;
  318. ImageConfigData = (PIMAGE_LOAD_CONFIG_DIRECTORY) ImageDirectoryEntryToData( LoadedImage->MappedAddress,
  319. FALSE,
  320. IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG,
  321. &i
  322. );
  323. if (ImageConfigData != NULL && i == sizeof( *ImageConfigData )) {
  324. memcpy( ImageConfigInformation, ImageConfigData, sizeof( *ImageConfigData ) );
  325. return TRUE;
  326. } else {
  327. return FALSE;
  328. }
  329. }
  330. BOOL
  331. SetImageConfigInformation(
  332. PLOADED_IMAGE LoadedImage,
  333. PIMAGE_LOAD_CONFIG_DIRECTORY ImageConfigInformation
  334. )
  335. {
  336. PIMAGE_LOAD_CONFIG_DIRECTORY ImageConfigData;
  337. ULONG i;
  338. ULONG DirectoryAddress;
  339. PIMAGE_NT_HEADERS NtHeaders;
  340. PIMAGE_DATA_DIRECTORY pLoadCfgDataDir;
  341. if (LoadedImage->hFile == INVALID_HANDLE_VALUE) {
  342. return FALSE;
  343. }
  344. ImageConfigData = (PIMAGE_LOAD_CONFIG_DIRECTORY) ImageDirectoryEntryToData( LoadedImage->MappedAddress,
  345. FALSE,
  346. IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG,
  347. &i
  348. );
  349. if (ImageConfigData != NULL && i == sizeof( *ImageConfigData )) {
  350. memcpy( ImageConfigData, ImageConfigInformation, sizeof( *ImageConfigData ) );
  351. return TRUE;
  352. }
  353. DirectoryAddress = GetImageUnusedHeaderBytes( LoadedImage, &i );
  354. if (i < sizeof(*ImageConfigData)) {
  355. return FALSE;
  356. }
  357. NtHeaders = LoadedImage->FileHeader;
  358. if (NtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
  359. pLoadCfgDataDir = &((PIMAGE_NT_HEADERS32)NtHeaders)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG];
  360. } else {
  361. pLoadCfgDataDir = &((PIMAGE_NT_HEADERS64)NtHeaders)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG];
  362. }
  363. pLoadCfgDataDir->VirtualAddress = DirectoryAddress;
  364. pLoadCfgDataDir->Size = sizeof(*ImageConfigData);
  365. ImageConfigData = (PIMAGE_LOAD_CONFIG_DIRECTORY) ((PCHAR)LoadedImage->MappedAddress + DirectoryAddress);
  366. memcpy( ImageConfigData, ImageConfigInformation, sizeof( *ImageConfigData ) );
  367. return TRUE;
  368. }
  369. BOOLEAN ImageLoadInit;
  370. LIST_ENTRY ImageLoadList;
  371. PLOADED_IMAGE
  372. ImageLoad(
  373. LPSTR DllName,
  374. LPSTR DllPath
  375. )
  376. {
  377. PLIST_ENTRY Head,Next;
  378. PLOADED_IMAGE LoadedImage;
  379. CHAR Drive[_MAX_DRIVE];
  380. CHAR Dir[_MAX_DIR];
  381. CHAR Filename[_MAX_FNAME];
  382. CHAR Ext[_MAX_EXT];
  383. CHAR LoadedModuleName[_MAX_PATH];
  384. BOOL fFileNameOnly;
  385. if (!ImageLoadInit) {
  386. InitializeListHead( &ImageLoadList );
  387. ImageLoadInit = TRUE;
  388. }
  389. Head = &ImageLoadList;
  390. Next = Head->Flink;
  391. _splitpath(DllName, Drive, Dir, Filename, Ext);
  392. if (!strlen(Drive) && !strlen(Dir)) {
  393. // The user only specified a filename (no drive/path).
  394. fFileNameOnly = TRUE;
  395. } else {
  396. fFileNameOnly = FALSE;
  397. }
  398. while (Next != Head) {
  399. LoadedImage = CONTAINING_RECORD( Next, LOADED_IMAGE, Links );
  400. if (fFileNameOnly) {
  401. _splitpath(LoadedImage->ModuleName, NULL, NULL, Filename, Ext);
  402. strcpy(LoadedModuleName, Filename);
  403. strcat(LoadedModuleName, Ext);
  404. } else {
  405. strcpy(LoadedModuleName, LoadedImage->ModuleName);
  406. }
  407. if (!_stricmp( DllName, LoadedModuleName )) {
  408. return LoadedImage;
  409. }
  410. Next = Next->Flink;
  411. }
  412. LoadedImage = (PLOADED_IMAGE) MemAlloc( sizeof( *LoadedImage ) + strlen( DllName ) + 1 );
  413. if (LoadedImage != NULL) {
  414. LoadedImage->ModuleName = (LPSTR)(LoadedImage + 1);
  415. strcpy( LoadedImage->ModuleName, DllName );
  416. if (MapAndLoad( DllName, DllPath, LoadedImage, TRUE, TRUE )) {
  417. InsertTailList( &ImageLoadList, &LoadedImage->Links );
  418. return LoadedImage;
  419. }
  420. MemFree( LoadedImage );
  421. LoadedImage = NULL;
  422. }
  423. return LoadedImage;
  424. }
  425. BOOL
  426. ImageUnload(
  427. PLOADED_IMAGE LoadedImage
  428. )
  429. {
  430. if (!IsListEmpty( &LoadedImage->Links )) {
  431. RemoveEntryList( &LoadedImage->Links );
  432. }
  433. UnMapAndLoad( LoadedImage );
  434. MemFree( LoadedImage );
  435. return TRUE;
  436. }
  437. BOOL
  438. UnloadAllImages()
  439. {
  440. PLIST_ENTRY Head,Next;
  441. PLOADED_IMAGE LoadedImage;
  442. if (!ImageLoadInit) {
  443. return(TRUE);
  444. }
  445. Head = &ImageLoadList;
  446. Next = Head->Flink;
  447. while (Next != Head) {
  448. LoadedImage = CONTAINING_RECORD( Next, LOADED_IMAGE, Links );
  449. Next = Next->Flink;
  450. ImageUnload(LoadedImage);
  451. }
  452. ImageLoadInit = FALSE;
  453. return (TRUE);
  454. }