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.

651 lines
18 KiB

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