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.

315 lines
8.4 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. smashlck.c
  5. Abstract:
  6. This function smashes lock prefixes replacing them with NOPs
  7. Author:
  8. Mark Lucovsky (markl) 30-Apr-1993
  9. Revision History:
  10. Ted Miller (tedm) 7-Dec-1993 -- copied from imagehlp, modified for setup.
  11. --*/
  12. #include "spprecmp.h"
  13. #pragma hdrstop
  14. #define OPCODE_LOCK_PREFIX ((UCHAR)0xf0)
  15. #define OPCODE_NO_OP ((UCHAR)0x90)
  16. typedef struct _LOADED_IMAGE {
  17. HANDLE hFile;
  18. HANDLE hSection;
  19. PUCHAR MappedAddress;
  20. ULONG FileSize;
  21. ULONG Characteristics;
  22. PIMAGE_NT_HEADERS NtHeader;
  23. PIMAGE_SECTION_HEADER LastRvaSection;
  24. ULONG NumberOfSections;
  25. PIMAGE_SECTION_HEADER Sections;
  26. } LOADED_IMAGE, *PLOADED_IMAGE;
  27. PVOID
  28. RvaToVa(
  29. PVOID Rva,
  30. PLOADED_IMAGE Image
  31. )
  32. {
  33. PIMAGE_SECTION_HEADER Section;
  34. ULONG i;
  35. PVOID Va;
  36. Rva = (PVOID)((PUCHAR)Rva-(PUCHAR)Image->NtHeader->OptionalHeader.ImageBase);
  37. Va = NULL;
  38. Section = Image->LastRvaSection;
  39. if ( (ULONG)Rva >= Section->VirtualAddress &&
  40. (ULONG)Rva < Section->VirtualAddress + Section->SizeOfRawData ) {
  41. Va = (PVOID)((ULONG)Rva - Section->VirtualAddress + Section->PointerToRawData + Image->MappedAddress);
  42. }
  43. else {
  44. for(Section = Image->Sections,i=0; i<Image->NumberOfSections; i++,Section++) {
  45. if ( (ULONG)Rva >= Section->VirtualAddress &&
  46. (ULONG)Rva < Section->VirtualAddress + Section->SizeOfRawData ) {
  47. Va = (PVOID)((ULONG)Rva - Section->VirtualAddress + Section->PointerToRawData + Image->MappedAddress);
  48. Image->LastRvaSection = Section;
  49. break;
  50. }
  51. }
  52. }
  53. if ( !Va ) {
  54. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: RvaToVa %lx failed\n",Rva));
  55. }
  56. return Va;
  57. }
  58. BOOLEAN
  59. pSpLoadForSmash(
  60. IN PWSTR ImageName, OPTIONAL
  61. IN HANDLE FileHandle, OPTIONAL
  62. OUT PLOADED_IMAGE LoadedImage
  63. )
  64. {
  65. NTSTATUS Status;
  66. PIMAGE_NT_HEADERS NtHeader;
  67. //
  68. // open and map the file.
  69. // then fill in the loaded image descriptor
  70. //
  71. if(FileHandle) {
  72. LoadedImage->hFile = FileHandle;
  73. Status = SpGetFileSize(FileHandle,&LoadedImage->FileSize);
  74. if(NT_SUCCESS(Status)) {
  75. Status = SpMapEntireFile(
  76. FileHandle,
  77. &LoadedImage->hSection,
  78. &LoadedImage->MappedAddress,
  79. TRUE
  80. );
  81. }
  82. } else {
  83. ASSERT(ImageName);
  84. Status = SpOpenAndMapFile(
  85. ImageName,
  86. &LoadedImage->hFile,
  87. &LoadedImage->hSection,
  88. &LoadedImage->MappedAddress,
  89. &LoadedImage->FileSize,
  90. TRUE
  91. );
  92. }
  93. if(!NT_SUCCESS(Status)) {
  94. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  95. "SETUP: pSpLoadForSmash: open/map %ws failed (%lx)\n",
  96. ImageName ? ImageName : L"(by handle)",
  97. Status
  98. ));
  99. return FALSE;
  100. }
  101. //
  102. // Check the image and find nt image headers
  103. //
  104. if((NtHeader = RtlImageNtHeader(LoadedImage->MappedAddress))
  105. && NtHeader->FileHeader.SizeOfOptionalHeader)
  106. {
  107. LoadedImage->Characteristics = NtHeader->FileHeader.Characteristics;
  108. LoadedImage->NumberOfSections = NtHeader->FileHeader.NumberOfSections;
  109. LoadedImage->Sections = (PIMAGE_SECTION_HEADER)((PUCHAR)NtHeader + sizeof(IMAGE_NT_HEADERS));
  110. LoadedImage->LastRvaSection = LoadedImage->Sections;
  111. LoadedImage->NtHeader = NtHeader;
  112. } else {
  113. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  114. "SETUP: pSpLoadForSmash: %ws is not an NT image\n",
  115. ImageName ? ImageName : L"(by handle)"
  116. ));
  117. SpUnmapFile(LoadedImage->hSection,LoadedImage->MappedAddress);
  118. ZwClose(LoadedImage->hFile);
  119. }
  120. return (BOOLEAN)(NtHeader != NULL);
  121. }
  122. VOID
  123. SpMashemSmashem(
  124. IN HANDLE FileHandle, OPTIONAL
  125. IN PWSTR Name1, OPTIONAL
  126. IN PWSTR Name2, OPTIONAL
  127. IN PWSTR Name3 OPTIONAL
  128. )
  129. {
  130. PWSTR FullFilename;
  131. LOADED_IMAGE LoadedImage;
  132. ULONG whocares;
  133. PIMAGE_LOAD_CONFIG_DIRECTORY ConfigInfo;
  134. ULONG CheckSum;
  135. ULONG HeaderSum;
  136. BOOLEAN LocksSmashed;
  137. BOOLEAN b;
  138. //
  139. // Determine whether we really need to smash locks.
  140. // We need to do this if we are installing for a UP machine.
  141. //
  142. if(SpInstallingMp()) {
  143. return;
  144. }
  145. //
  146. // Form the full name of the file if a file handle is not specified.
  147. //
  148. if(FileHandle) {
  149. FullFilename = NULL;
  150. } else {
  151. ASSERT(Name1);
  152. wcscpy((PWSTR)TemporaryBuffer,Name1);
  153. if(Name2) {
  154. SpConcatenatePaths((PWSTR)TemporaryBuffer,Name2);
  155. }
  156. if(Name3) {
  157. SpConcatenatePaths((PWSTR)TemporaryBuffer,Name3);
  158. }
  159. FullFilename = SpDupStringW((PWSTR)TemporaryBuffer);
  160. }
  161. //
  162. // Attempt to load and map the image for smashing.
  163. //
  164. try {
  165. b = pSpLoadForSmash(FullFilename,FileHandle,&LoadedImage);
  166. } except(EXCEPTION_EXECUTE_HANDLER) {
  167. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  168. "SETUP: Warning: exception while loading %ws for smash\n",
  169. FullFilename ? FullFilename : L"(by handle)"
  170. ));
  171. b = FALSE;
  172. }
  173. if(b) {
  174. //
  175. // make sure the image has correct configuration information,
  176. // and that the LockPrefixTable is set up properly
  177. //
  178. // Put exception handling around this since we haven't yet verified the file
  179. // and it may be corrupted.
  180. //
  181. try {
  182. ConfigInfo = (PIMAGE_LOAD_CONFIG_DIRECTORY)RtlImageDirectoryEntryToData(
  183. LoadedImage.MappedAddress,
  184. FALSE,
  185. IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG,
  186. &whocares
  187. );
  188. if(ConfigInfo && ConfigInfo->LockPrefixTable) {
  189. //
  190. // Walk through the lock prefix table
  191. //
  192. PUCHAR *LockPrefixs;
  193. PUCHAR LockPrefix;
  194. LockPrefixs = (PUCHAR *)RvaToVa((PVOID)ConfigInfo->LockPrefixTable,&LoadedImage);
  195. while(LockPrefixs && *LockPrefixs) {
  196. LockPrefix = RvaToVa(*LockPrefixs,&LoadedImage);
  197. if(LockPrefix && (*LockPrefix == OPCODE_LOCK_PREFIX)) {
  198. LocksSmashed = TRUE;
  199. *LockPrefix = OPCODE_NO_OP;
  200. }
  201. LockPrefixs++;
  202. }
  203. if(LocksSmashed) {
  204. //
  205. // recompute the checksum.
  206. //
  207. LoadedImage.NtHeader->OptionalHeader.CheckSum = 0;
  208. SpChecksumMappedFile(
  209. LoadedImage.MappedAddress,
  210. LoadedImage.FileSize,
  211. &HeaderSum,
  212. &CheckSum
  213. );
  214. LoadedImage.NtHeader->OptionalHeader.CheckSum = CheckSum;
  215. //
  216. // Flush changes.
  217. //
  218. SpFlushVirtualMemory(LoadedImage.MappedAddress,0);
  219. }
  220. }
  221. } except(EXCEPTION_EXECUTE_HANDLER) {
  222. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  223. "SETUP: Warning: exception while smashing locks for %ws\n",
  224. FullFilename ? FullFilename : L"(by handle)"
  225. ));
  226. }
  227. SpUnmapFile(LoadedImage.hSection,LoadedImage.MappedAddress);
  228. if(!FileHandle) {
  229. ZwClose(LoadedImage.hFile);
  230. }
  231. } else {
  232. //
  233. // This is not really a fatal problem
  234. // but we probably ought to alert the user.
  235. //
  236. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Failed to smash a lock.\n"));
  237. }
  238. if(FullFilename) {
  239. SpMemFree(FullFilename);
  240. }
  241. }