psimag.c 56 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360
  1. /*++
  2. Copyright (c) 2012 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. psimag.c
  5. Abstract:
  6. This module implements the underlying support routines for the image
  7. library to be run in the kernel.
  8. Author:
  9. Evan Green 14-Oct-2012
  10. Environment:
  11. Kernel
  12. --*/
  13. //
  14. // ------------------------------------------------------------------- Includes
  15. //
  16. #include <minoca/kernel/kernel.h>
  17. #include <minoca/kernel/kdebug.h>
  18. #include "psp.h"
  19. //
  20. // ---------------------------------------------------------------- Definitions
  21. //
  22. #define PROCESS_USER_MODULE_MAX_NAME 100
  23. #define PROCESS_USER_MODULE_MAX_COUNT 200
  24. //
  25. // ------------------------------------------------------ Data Type Definitions
  26. //
  27. /*++
  28. Structure Description:
  29. This structure stores associations between images in two processes during
  30. a clone operation.
  31. Members:
  32. SourceImage - Stores a pointer to the loaded image the source process.
  33. DestinationImage - Stores a pointer to the loaded image in the destination
  34. process.
  35. --*/
  36. typedef struct _IMAGE_ASSOCIATION {
  37. PLOADED_IMAGE SourceImage;
  38. PLOADED_IMAGE DestinationImage;
  39. } IMAGE_ASSOCIATION, *PIMAGE_ASSOCIATION;
  40. //
  41. // ----------------------------------------------- Internal Function Prototypes
  42. //
  43. PVOID
  44. PspImAllocateMemory (
  45. ULONG Size,
  46. ULONG Tag
  47. );
  48. VOID
  49. PspImFreeMemory (
  50. PVOID Allocation
  51. );
  52. KSTATUS
  53. PspImOpenFile (
  54. PVOID SystemContext,
  55. PSTR BinaryName,
  56. PIMAGE_FILE_INFORMATION File
  57. );
  58. VOID
  59. PspImCloseFile (
  60. PIMAGE_FILE_INFORMATION File
  61. );
  62. KSTATUS
  63. PspImLoadFile (
  64. PIMAGE_FILE_INFORMATION File,
  65. PIMAGE_BUFFER Buffer
  66. );
  67. KSTATUS
  68. PspImReadFile (
  69. PIMAGE_FILE_INFORMATION File,
  70. ULONGLONG Offset,
  71. UINTN Size,
  72. PIMAGE_BUFFER Buffer
  73. );
  74. VOID
  75. PspImUnloadBuffer (
  76. PIMAGE_FILE_INFORMATION File,
  77. PIMAGE_BUFFER Buffer
  78. );
  79. KSTATUS
  80. PspImAllocateAddressSpace (
  81. PLOADED_IMAGE Image
  82. );
  83. VOID
  84. PspImFreeAddressSpace (
  85. PLOADED_IMAGE Image
  86. );
  87. KSTATUS
  88. PspImMapImageSegment (
  89. HANDLE AddressSpaceHandle,
  90. PVOID AddressSpaceAllocation,
  91. PIMAGE_FILE_INFORMATION File,
  92. ULONGLONG FileOffset,
  93. PIMAGE_SEGMENT Segment,
  94. PIMAGE_SEGMENT PreviousSegment
  95. );
  96. VOID
  97. PspImUnmapImageSegment (
  98. HANDLE AddressSpaceHandle,
  99. PIMAGE_SEGMENT Segment
  100. );
  101. KSTATUS
  102. PspImNotifyImageLoad (
  103. PLOADED_IMAGE Image
  104. );
  105. VOID
  106. PspImNotifyImageUnload (
  107. PLOADED_IMAGE Image
  108. );
  109. VOID
  110. PspImInvalidateInstructionCacheRegion (
  111. PVOID Address,
  112. ULONG Size
  113. );
  114. PSTR
  115. PspImGetEnvironmentVariable (
  116. PSTR Variable
  117. );
  118. KSTATUS
  119. PspImFinalizeSegments (
  120. HANDLE AddressSpaceHandle,
  121. PIMAGE_SEGMENT Segments,
  122. UINTN SegmentCount
  123. );
  124. KSTATUS
  125. PspImCloneImage (
  126. PKPROCESS Source,
  127. PKPROCESS Destination,
  128. PLOADED_IMAGE SourceImage,
  129. PLOADED_IMAGE *NewDestinationImage
  130. );
  131. PLOADED_IMAGE
  132. PspImGetAssociatedImage (
  133. PLOADED_IMAGE QueryImage,
  134. PIMAGE_ASSOCIATION AssociationMapping,
  135. ULONG AssociationCount
  136. );
  137. KSTATUS
  138. PspLoadProcessImageIntoKernelDebugger (
  139. PKPROCESS Process,
  140. PLOADED_IMAGE Image
  141. );
  142. //
  143. // -------------------------------------------------------------------- Globals
  144. //
  145. //
  146. // Set this global to always load all user mode images into the kernel mode
  147. // debugger. Setting this is great for debugging as all usermode symbols are
  148. // always visible. It's not on by default however because it's wasteful (as
  149. // it costs lots of non-paged pool allocations) and adds buckets of symbols to
  150. // the debugger.
  151. //
  152. BOOL PsKdLoadAllImages = FALSE;
  153. //
  154. // Store a handle to the OS base library.
  155. //
  156. PIO_HANDLE PsOsBaseLibrary;
  157. //
  158. // Store the image library function table.
  159. //
  160. IM_IMPORT_TABLE PsImFunctionTable = {
  161. PspImAllocateMemory,
  162. PspImFreeMemory,
  163. PspImOpenFile,
  164. PspImCloseFile,
  165. PspImLoadFile,
  166. PspImReadFile,
  167. PspImUnloadBuffer,
  168. PspImAllocateAddressSpace,
  169. PspImFreeAddressSpace,
  170. PspImMapImageSegment,
  171. PspImUnmapImageSegment,
  172. PspImNotifyImageLoad,
  173. PspImNotifyImageUnload,
  174. PspImInvalidateInstructionCacheRegion,
  175. PspImGetEnvironmentVariable,
  176. PspImFinalizeSegments,
  177. NULL,
  178. };
  179. //
  180. // ------------------------------------------------------------------ Functions
  181. //
  182. KSTATUS
  183. PspInitializeImageSupport (
  184. PVOID KernelLowestAddress,
  185. PLIST_ENTRY ListHead
  186. )
  187. /*++
  188. Routine Description:
  189. This routine initializes the image library for use in the kernel.
  190. Arguments:
  191. KernelLowestAddress - Supplies the lowest address of the kernel's image.
  192. This is used to avoid loading the kernel image in the debugger twice.
  193. ListHead - Supplies a pointer to the head of the list of loaded images.
  194. Return Value:
  195. Status code.
  196. --*/
  197. {
  198. PLIST_ENTRY CurrentEntry;
  199. PLOADED_IMAGE Image;
  200. IMAGE_BUFFER ImageBuffer;
  201. PKPROCESS KernelProcess;
  202. PLOADED_IMAGE NewImage;
  203. KSTATUS Status;
  204. RtlZeroMemory(&ImageBuffer, sizeof(IMAGE_BUFFER));
  205. Status = ImInitialize(&PsImFunctionTable);
  206. if (!KSUCCESS(Status)) {
  207. goto InitializeImageSupportEnd;
  208. }
  209. KernelProcess = PsGetKernelProcess();
  210. CurrentEntry = ListHead->Next;
  211. while (CurrentEntry != ListHead) {
  212. Image = LIST_VALUE(CurrentEntry, LOADED_IMAGE, ListEntry);
  213. CurrentEntry = CurrentEntry->Next;
  214. ImageBuffer.Data = Image->LoadedLowestAddress;
  215. ImageBuffer.Size = Image->Size;
  216. Status = ImAddImage(Image->BinaryName, &ImageBuffer, &NewImage);
  217. if (!KSUCCESS(Status)) {
  218. ASSERT(FALSE);
  219. goto InitializeImageSupportEnd;
  220. }
  221. NewImage->Flags = Image->Flags | IMAGE_FLAG_INITIALIZED |
  222. IMAGE_FLAG_RELOCATED | IMAGE_FLAG_IMPORTS_LOADED;
  223. NewImage->LoadFlags = Image->LoadFlags;
  224. NewImage->ImportDepth = Image->ImportDepth;
  225. NewImage->File.ModificationDate = Image->File.ModificationDate;
  226. NewImage->File.Size = Image->File.Size;
  227. NewImage->Size = Image->Size;
  228. INSERT_BEFORE(&(NewImage->ListEntry), &(KernelProcess->ImageListHead));
  229. KernelProcess->ImageCount += 1;
  230. KernelProcess->ImageListSignature +=
  231. NewImage->File.ModificationDate +
  232. (UINTN)(NewImage->LoadedLowestAddress);
  233. //
  234. // Load this image into the kernel debugger, but skip the kernel
  235. // image as that was already loaded.
  236. //
  237. if (NewImage->LoadedLowestAddress != KernelLowestAddress) {
  238. Status = PspLoadProcessImageIntoKernelDebugger(KernelProcess,
  239. NewImage);
  240. if (!KSUCCESS(Status)) {
  241. goto InitializeImageSupportEnd;
  242. }
  243. }
  244. }
  245. Status = STATUS_SUCCESS;
  246. InitializeImageSupportEnd:
  247. return Status;
  248. }
  249. KSTATUS
  250. PspImCloneProcessImages (
  251. PKPROCESS Source,
  252. PKPROCESS Destination
  253. )
  254. /*++
  255. Routine Description:
  256. This routine makes a copy of the given process' image list.
  257. Arguments:
  258. Source - Supplies a pointer to the source process.
  259. Destination - Supplies a pointer to the destination process.
  260. Return Value:
  261. Status code.
  262. --*/
  263. {
  264. PIMAGE_ASSOCIATION Association;
  265. ULONG AssociationIndex;
  266. PLIST_ENTRY CurrentEntry;
  267. ULONG ImageCount;
  268. ULONG ImportIndex;
  269. PLOADED_IMAGE NewImage;
  270. PLOADED_IMAGE SourceImage;
  271. KSTATUS Status;
  272. ASSERT(KeGetRunLevel() == RunLevelLow);
  273. PsAcquireImageListLock(Source);
  274. ImageCount = Source->ImageCount;
  275. //
  276. // Allocate space for the association mapping.
  277. //
  278. Association = MmAllocatePagedPool(sizeof(IMAGE_ASSOCIATION) * ImageCount,
  279. PS_ALLOCATION_TAG);
  280. if (Association == NULL) {
  281. Status = STATUS_INSUFFICIENT_RESOURCES;
  282. goto ImCloneProcessImagesEnd;
  283. }
  284. //
  285. // Loop through copying images.
  286. //
  287. AssociationIndex = 0;
  288. CurrentEntry = Source->ImageListHead.Next;
  289. while (CurrentEntry != &(Source->ImageListHead)) {
  290. SourceImage = LIST_VALUE(CurrentEntry, LOADED_IMAGE, ListEntry);
  291. CurrentEntry = CurrentEntry->Next;
  292. ASSERT(AssociationIndex < ImageCount);
  293. //
  294. // Clone the image.
  295. //
  296. Status = PspImCloneImage(Source, Destination, SourceImage, &NewImage);
  297. if (!KSUCCESS(Status)) {
  298. goto ImCloneProcessImagesEnd;
  299. }
  300. //
  301. // Remember the association between source and destination image.
  302. //
  303. Association[AssociationIndex].SourceImage = SourceImage;
  304. Association[AssociationIndex].DestinationImage = NewImage;
  305. AssociationIndex += 1;
  306. }
  307. //
  308. // Now loop through the new process image list and restore all the import
  309. // relationships.
  310. //
  311. CurrentEntry = Source->ImageListHead.Next;
  312. while (CurrentEntry != &(Source->ImageListHead)) {
  313. NewImage = LIST_VALUE(CurrentEntry, LOADED_IMAGE, ListEntry);
  314. CurrentEntry = CurrentEntry->Next;
  315. if (NewImage->ImportCount == 0) {
  316. continue;
  317. }
  318. //
  319. // Get the source image associated with this destination image.
  320. //
  321. SourceImage = PspImGetAssociatedImage(NewImage,
  322. Association,
  323. ImageCount);
  324. ASSERT(SourceImage != NULL);
  325. ASSERT(SourceImage->ImportCount == NewImage->ImportCount);
  326. //
  327. // Loop through and match up every import in the source with its
  328. // corresponding image in the destination.
  329. //
  330. for (ImportIndex = 0;
  331. ImportIndex < NewImage->ImportCount;
  332. ImportIndex += 1) {
  333. NewImage->Imports[ImportIndex] =
  334. PspImGetAssociatedImage(SourceImage->Imports[ImportIndex],
  335. Association,
  336. ImageCount);
  337. ASSERT(NewImage->Imports[ImportIndex] != NULL);
  338. }
  339. }
  340. Status = STATUS_SUCCESS;
  341. ImCloneProcessImagesEnd:
  342. PsReleaseImageListLock(Source);
  343. if (Association != NULL) {
  344. MmFreePagedPool(Association);
  345. }
  346. return Status;
  347. }
  348. VOID
  349. PspImUnloadAllImages (
  350. PKPROCESS Process
  351. )
  352. /*++
  353. Routine Description:
  354. This routine unloads all images in the given process.
  355. Arguments:
  356. Process - Supplies a pointer to the process whose images should be unloaded.
  357. Return Value:
  358. None.
  359. --*/
  360. {
  361. PLIST_ENTRY CurrentEntry;
  362. PLOADED_IMAGE Image;
  363. //
  364. // Unload all images. Be careful traversing this list as it will shift
  365. // as images and their imports are unloaded.
  366. //
  367. PsAcquireImageListLock(Process);
  368. while (LIST_EMPTY(&(Process->ImageListHead)) == FALSE) {
  369. CurrentEntry = Process->ImageListHead.Next;
  370. while (CurrentEntry != &(Process->ImageListHead)) {
  371. Image = LIST_VALUE(CurrentEntry, LOADED_IMAGE, ListEntry);
  372. if (Image->ImportDepth == 0) {
  373. //
  374. // Mark the image as having unload called on it, and then
  375. // unload the image.
  376. //
  377. Image->ImportDepth = -1;
  378. ImImageReleaseReference(Image);
  379. break;
  380. }
  381. CurrentEntry = CurrentEntry->Next;
  382. }
  383. //
  384. // If the image list is not empty but no images were found with a
  385. // depth of zero, then a reference counting problem has occurred.
  386. // Decrementing the reference count on all images with a depth
  387. // of zero should cause a domino effect that unloads all images.
  388. //
  389. ASSERT(CurrentEntry != &(Process->ImageListHead));
  390. }
  391. PsReleaseImageListLock(Process);
  392. return;
  393. }
  394. KSTATUS
  395. PspProcessUserModeModuleChange (
  396. PPROCESS_DEBUG_MODULE_CHANGE ModuleChangeUser
  397. )
  398. /*++
  399. Routine Description:
  400. This routine handles module change notifications from user mode.
  401. Arguments:
  402. ModuleChangeUser - Supplies the module change notification from user mode.
  403. Return Value:
  404. None.
  405. --*/
  406. {
  407. UINTN AllocationSize;
  408. PROCESS_DEBUG_MODULE_CHANGE Change;
  409. PLIST_ENTRY CurrentEntry;
  410. PLOADED_IMAGE CurrentImage;
  411. PLOADED_IMAGE ExistingImage;
  412. LOADED_IMAGE Image;
  413. BOOL LockHeld;
  414. PLOADED_IMAGE NewImage;
  415. PKPROCESS Process;
  416. KSTATUS Status;
  417. LockHeld = FALSE;
  418. NewImage = NULL;
  419. Process = PsGetCurrentProcess();
  420. Status = MmCopyFromUserMode(&Change,
  421. ModuleChangeUser,
  422. sizeof(PROCESS_DEBUG_MODULE_CHANGE));
  423. if (!KSUCCESS(Status)) {
  424. goto ProcessUserModeModuleChangeEnd;
  425. }
  426. if (Change.Version < PROCESS_DEBUG_MODULE_CHANGE_VERSION) {
  427. Status = STATUS_NOT_SUPPORTED;
  428. goto ProcessUserModeModuleChangeEnd;
  429. }
  430. Status = MmCopyFromUserMode(&Image, Change.Image, sizeof(LOADED_IMAGE));
  431. if (!KSUCCESS(Status)) {
  432. goto ProcessUserModeModuleChangeEnd;
  433. }
  434. if (Image.Format != ImageElf32) {
  435. ASSERT(FALSE);
  436. Status = STATUS_INVALID_PARAMETER;
  437. goto ProcessUserModeModuleChangeEnd;
  438. }
  439. //
  440. // Try to find a module matching this base address.
  441. //
  442. PsAcquireImageListLock(Process);
  443. LockHeld = TRUE;
  444. CurrentEntry = Process->ImageListHead.Next;
  445. ExistingImage = NULL;
  446. while (CurrentEntry != &(Process->ImageListHead)) {
  447. CurrentImage = LIST_VALUE(CurrentEntry, LOADED_IMAGE, ListEntry);
  448. CurrentEntry = CurrentEntry->Next;
  449. if (CurrentImage->LoadedLowestAddress == Image.LoadedLowestAddress) {
  450. ExistingImage = CurrentImage;
  451. break;
  452. }
  453. }
  454. //
  455. // Handle an unload.
  456. //
  457. if (Change.Load == FALSE) {
  458. if (ExistingImage == NULL) {
  459. Status = STATUS_NOT_FOUND;
  460. goto ProcessUserModeModuleChangeEnd;
  461. }
  462. if ((ExistingImage->LoadFlags & IMAGE_LOAD_FLAG_PLACEHOLDER) == 0) {
  463. Status = STATUS_INVALID_PARAMETER;
  464. goto ProcessUserModeModuleChangeEnd;
  465. }
  466. PspImNotifyImageUnload(ExistingImage);
  467. LIST_REMOVE(&(ExistingImage->ListEntry));
  468. PspImFreeMemory(ExistingImage);
  469. Status = STATUS_SUCCESS;
  470. goto ProcessUserModeModuleChangeEnd;
  471. }
  472. //
  473. // This is a load. Handle shenanigans.
  474. //
  475. if (ExistingImage != NULL) {
  476. Status = STATUS_RESOURCE_IN_USE;
  477. goto ProcessUserModeModuleChangeEnd;
  478. }
  479. if (Process->ImageCount >= PROCESS_USER_MODULE_MAX_COUNT) {
  480. Status = STATUS_TOO_MANY_HANDLES;
  481. goto ProcessUserModeModuleChangeEnd;
  482. }
  483. if (Change.BinaryNameSize > PROCESS_USER_MODULE_MAX_NAME) {
  484. Status = STATUS_NAME_TOO_LONG;
  485. goto ProcessUserModeModuleChangeEnd;
  486. }
  487. if (Change.BinaryNameSize == 0) {
  488. Status = STATUS_INVALID_PARAMETER;
  489. goto ProcessUserModeModuleChangeEnd;
  490. }
  491. //
  492. // Create a faked up image.
  493. //
  494. AllocationSize = sizeof(LOADED_IMAGE) + Change.BinaryNameSize;
  495. NewImage = PspImAllocateMemory(AllocationSize, PS_IMAGE_ALLOCATION_TAG);
  496. if (NewImage == NULL) {
  497. Status = STATUS_INSUFFICIENT_RESOURCES;
  498. goto ProcessUserModeModuleChangeEnd;
  499. }
  500. RtlZeroMemory(NewImage, sizeof(LOADED_IMAGE));
  501. NewImage->BinaryName = (PSTR)(NewImage + 1);
  502. Status = MmCopyFromUserMode(NewImage->BinaryName,
  503. Image.BinaryName,
  504. Change.BinaryNameSize);
  505. if (!KSUCCESS(Status)) {
  506. goto ProcessUserModeModuleChangeEnd;
  507. }
  508. NewImage->BinaryName[Change.BinaryNameSize - 1] = '\0';
  509. NewImage->File.Handle = INVALID_HANDLE;
  510. NewImage->AllocatorHandle = INVALID_HANDLE;
  511. NewImage->Format = Image.Format;
  512. NewImage->Machine = Image.Machine;
  513. NewImage->Size = Image.Size;
  514. NewImage->DeclaredBase = Image.DeclaredBase;
  515. NewImage->PreferredLowestAddress = Image.PreferredLowestAddress;
  516. NewImage->LoadedLowestAddress = Image.LoadedLowestAddress;
  517. NewImage->EntryPoint = Image.EntryPoint;
  518. NewImage->ReferenceCount = 1;
  519. NewImage->LoadFlags = IMAGE_LOAD_FLAG_PLACEHOLDER;
  520. INSERT_BEFORE(&(NewImage->ListEntry), &(Process->ImageListHead));
  521. Status = PspImNotifyImageLoad(NewImage);
  522. if (!KSUCCESS(Status)) {
  523. LIST_REMOVE(&(NewImage->ListEntry));
  524. goto ProcessUserModeModuleChangeEnd;
  525. }
  526. Status = STATUS_SUCCESS;
  527. ProcessUserModeModuleChangeEnd:
  528. if (LockHeld != FALSE) {
  529. PsReleaseImageListLock(Process);
  530. }
  531. if (!KSUCCESS(Status)) {
  532. if (NewImage != NULL) {
  533. PspImFreeMemory(NewImage);
  534. }
  535. }
  536. return Status;
  537. }
  538. KSTATUS
  539. PspLoadProcessImagesIntoKernelDebugger (
  540. PKPROCESS Process
  541. )
  542. /*++
  543. Routine Description:
  544. This routine loads the images in the given process into the kernel debugger.
  545. Arguments:
  546. Process - Supplies a pointer to the process.
  547. Return Value:
  548. Status code.
  549. --*/
  550. {
  551. PLIST_ENTRY CurrentEntry;
  552. PLOADED_IMAGE Image;
  553. KSTATUS Status;
  554. KSTATUS TotalStatus;
  555. ASSERT((KeGetRunLevel() == RunLevelLow) &&
  556. (Process != PsGetKernelProcess()));
  557. PsAcquireImageListLock(Process);
  558. TotalStatus = STATUS_SUCCESS;
  559. CurrentEntry = Process->ImageListHead.Next;
  560. while (CurrentEntry != &(Process->ImageListHead)) {
  561. Image = LIST_VALUE(CurrentEntry, LOADED_IMAGE, ListEntry);
  562. CurrentEntry = CurrentEntry->Next;
  563. Status = PspLoadProcessImageIntoKernelDebugger(Process, Image);
  564. if (!KSUCCESS(Status)) {
  565. TotalStatus = Status;
  566. }
  567. }
  568. PsReleaseImageListLock(Process);
  569. return TotalStatus;
  570. }
  571. //
  572. // --------------------------------------------------------- Internal Functions
  573. //
  574. PVOID
  575. PspImAllocateMemory (
  576. ULONG Size,
  577. ULONG Tag
  578. )
  579. /*++
  580. Routine Description:
  581. This routine allocates memory from the kernel for the image library.
  582. Arguments:
  583. Size - Supplies the number of bytes required for the memory allocation.
  584. Tag - Supplies a 32-bit ASCII identifier used to tag the memroy allocation.
  585. Return Value:
  586. Returns a pointer to the memory allocation on success.
  587. NULL on failure.
  588. --*/
  589. {
  590. return MmAllocatePagedPool(Size, Tag);
  591. }
  592. VOID
  593. PspImFreeMemory (
  594. PVOID Allocation
  595. )
  596. /*++
  597. Routine Description:
  598. This routine frees memory to the kernel allocated by the image library.
  599. Arguments:
  600. Allocation - Supplies a pointer the allocation to free.
  601. Return Value:
  602. None.
  603. --*/
  604. {
  605. MmFreePagedPool(Allocation);
  606. return;
  607. }
  608. KSTATUS
  609. PspImOpenFile (
  610. PVOID SystemContext,
  611. PSTR BinaryName,
  612. PIMAGE_FILE_INFORMATION File
  613. )
  614. /*++
  615. Routine Description:
  616. This routine opens a file.
  617. Arguments:
  618. SystemContext - Supplies the context pointer passed to the load executable
  619. function.
  620. BinaryName - Supplies the name of the executable image to open.
  621. File - Supplies a pointer where the information for the file including its
  622. open handle will be returned.
  623. Return Value:
  624. Status code.
  625. --*/
  626. {
  627. FILE_PROPERTIES FileProperties;
  628. BOOL FromKernelMode;
  629. ULONGLONG LocalFileSize;
  630. ULONG NameLength;
  631. PIO_HANDLE OutputHandle;
  632. PKPROCESS Process;
  633. KSTATUS Status;
  634. OutputHandle = INVALID_HANDLE;
  635. Process = (PKPROCESS)SystemContext;
  636. NameLength = RtlStringLength(BinaryName) + 1;
  637. //
  638. // If this is for the kernel process, then a driver is being loaded.
  639. // Always use the path directly as the kernel processes current working
  640. // directory should aways be the drivers directory on the system partition.
  641. //
  642. if (Process == PsGetKernelProcess()) {
  643. if (Process != PsGetCurrentProcess()) {
  644. FromKernelMode = FALSE;
  645. } else {
  646. FromKernelMode = TRUE;
  647. }
  648. Status = IoOpen(FromKernelMode,
  649. NULL,
  650. BinaryName,
  651. NameLength,
  652. IO_ACCESS_READ | IO_ACCESS_EXECUTE,
  653. 0,
  654. FILE_PERMISSION_NONE,
  655. &OutputHandle);
  656. goto ImOpenFileEnd;
  657. } else {
  658. //
  659. // If this is the first image being opened in a user mode app, then
  660. // it's always the OS base library.
  661. //
  662. if (Process->ImageCount == 0) {
  663. ASSERT(RtlAreStringsEqual(BinaryName,
  664. OS_BASE_LIBRARY,
  665. NameLength) != FALSE);
  666. IoIoHandleAddReference(PsOsBaseLibrary);
  667. OutputHandle = PsOsBaseLibrary;
  668. Status = STATUS_SUCCESS;
  669. } else {
  670. Status = IoOpen(FALSE,
  671. NULL,
  672. BinaryName,
  673. NameLength,
  674. IO_ACCESS_READ | IO_ACCESS_EXECUTE,
  675. 0,
  676. FILE_PERMISSION_NONE,
  677. &OutputHandle);
  678. if (KSUCCESS(Status)) {
  679. goto ImOpenFileEnd;
  680. }
  681. }
  682. }
  683. ImOpenFileEnd:
  684. if (KSUCCESS(Status)) {
  685. Status = IoGetFileInformation(OutputHandle, &FileProperties);
  686. if (KSUCCESS(Status)) {
  687. READ_INT64_SYNC(&(FileProperties.FileSize), &LocalFileSize);
  688. File->Size = LocalFileSize;
  689. File->ModificationDate = FileProperties.ModifiedTime.Seconds;
  690. }
  691. } else {
  692. OutputHandle = INVALID_HANDLE;
  693. }
  694. File->Handle = OutputHandle;
  695. return Status;
  696. }
  697. VOID
  698. PspImCloseFile (
  699. PIMAGE_FILE_INFORMATION File
  700. )
  701. /*++
  702. Routine Description:
  703. This routine closes an open file, invalidating any memory mappings to it.
  704. Arguments:
  705. File - Supplies a pointer to the file information.
  706. Return Value:
  707. None.
  708. --*/
  709. {
  710. if (File->Handle == INVALID_HANDLE) {
  711. return;
  712. }
  713. IoClose(File->Handle);
  714. return;
  715. }
  716. KSTATUS
  717. PspImLoadFile (
  718. PIMAGE_FILE_INFORMATION File,
  719. PIMAGE_BUFFER Buffer
  720. )
  721. /*++
  722. Routine Description:
  723. This routine loads an entire file into memory so the image library can
  724. access it.
  725. Arguments:
  726. File - Supplies a pointer to the file information.
  727. Buffer - Supplies a pointer where the buffer will be returned on success.
  728. Return Value:
  729. Status code.
  730. --*/
  731. {
  732. ULONGLONG AlignedSize;
  733. UINTN PageSize;
  734. KSTATUS Status;
  735. VM_ALLOCATION_PARAMETERS VaRequest;
  736. PageSize = MmPageSize();
  737. AlignedSize = ALIGN_RANGE_UP(File->Size, PageSize);
  738. if (AlignedSize > MAX_UINTN) {
  739. return STATUS_NOT_SUPPORTED;;
  740. }
  741. VaRequest.Address = NULL;
  742. VaRequest.Size = AlignedSize;
  743. VaRequest.Alignment = PageSize;
  744. VaRequest.Min = 0;
  745. VaRequest.Max = MAX_ADDRESS;
  746. VaRequest.MemoryType = MemoryTypeReserved;
  747. VaRequest.Strategy = AllocationStrategyAnyAddress;
  748. Status = MmMapFileSection(File->Handle,
  749. 0,
  750. &VaRequest,
  751. IMAGE_SECTION_READABLE | IMAGE_SECTION_WRITABLE,
  752. TRUE,
  753. NULL);
  754. if (!KSUCCESS(Status)) {
  755. return Status;
  756. }
  757. Buffer->Data = VaRequest.Address;
  758. Buffer->Size = File->Size;
  759. return STATUS_SUCCESS;
  760. }
  761. KSTATUS
  762. PspImReadFile (
  763. PIMAGE_FILE_INFORMATION File,
  764. ULONGLONG Offset,
  765. UINTN Size,
  766. PIMAGE_BUFFER Buffer
  767. )
  768. /*++
  769. Routine Description:
  770. This routine reads a portion of the given file into a buffer, allocated by
  771. this function.
  772. Arguments:
  773. File - Supplies a pointer to the file information.
  774. Offset - Supplies the file offset to read from in bytes.
  775. Size - Supplies the size to read, in bytes.
  776. Buffer - Supplies a pointer where the buffer will be returned on success.
  777. Return Value:
  778. Status code.
  779. --*/
  780. {
  781. UINTN AlignedSize;
  782. UINTN BytesComplete;
  783. PIO_BUFFER IoBuffer;
  784. UINTN PageSize;
  785. KSTATUS Status;
  786. PageSize = MmPageSize();
  787. AlignedSize = ALIGN_RANGE_UP(Size, PageSize);
  788. IoBuffer = MmAllocateUninitializedIoBuffer(AlignedSize, 0);
  789. if (IoBuffer == NULL) {
  790. Status = STATUS_INSUFFICIENT_RESOURCES;
  791. goto ImReadFileEnd;
  792. }
  793. Status = IoReadAtOffset(File->Handle,
  794. IoBuffer,
  795. Offset,
  796. AlignedSize,
  797. 0,
  798. WAIT_TIME_INDEFINITE,
  799. &BytesComplete,
  800. NULL);
  801. if (Status == STATUS_END_OF_FILE) {
  802. Status = STATUS_SUCCESS;
  803. } else if (!KSUCCESS(Status)) {
  804. goto ImReadFileEnd;
  805. }
  806. Status = MmMapIoBuffer(IoBuffer, FALSE, FALSE, TRUE);
  807. if (!KSUCCESS(Status)) {
  808. goto ImReadFileEnd;
  809. }
  810. Buffer->Context = IoBuffer;
  811. Buffer->Data = IoBuffer->Fragment[0].VirtualAddress;
  812. Buffer->Size = BytesComplete;
  813. Status = STATUS_SUCCESS;
  814. ImReadFileEnd:
  815. if (!KSUCCESS(Status)) {
  816. if (IoBuffer != NULL) {
  817. MmFreeIoBuffer(IoBuffer);
  818. IoBuffer = NULL;
  819. }
  820. }
  821. return Status;
  822. }
  823. VOID
  824. PspImUnloadBuffer (
  825. PIMAGE_FILE_INFORMATION File,
  826. PIMAGE_BUFFER Buffer
  827. )
  828. /*++
  829. Routine Description:
  830. This routine unloads a file buffer created from either the load file or
  831. read file function, and frees the buffer.
  832. Arguments:
  833. File - Supplies a pointer to the file information.
  834. Buffer - Supplies the buffer returned by the load file function.
  835. Return Value:
  836. None.
  837. --*/
  838. {
  839. ULONGLONG AlignedSize;
  840. UINTN PageSize;
  841. KSTATUS Status;
  842. ASSERT(Buffer->Data != NULL);
  843. if (Buffer->Context != NULL) {
  844. MmFreeIoBuffer(Buffer->Context);
  845. } else {
  846. PageSize = MmPageSize();
  847. AlignedSize = ALIGN_RANGE_UP(File->Size, PageSize);
  848. Status = MmUnmapFileSection(NULL, Buffer->Data, AlignedSize, NULL);
  849. ASSERT(KSUCCESS(Status));
  850. }
  851. Buffer->Data = NULL;
  852. Buffer->Context = NULL;
  853. return;
  854. }
  855. KSTATUS
  856. PspImAllocateAddressSpace (
  857. PLOADED_IMAGE Image
  858. )
  859. /*++
  860. Routine Description:
  861. This routine allocates a section of virtual address space that an image
  862. can be mapped in to.
  863. Arguments:
  864. Image - Supplies a pointer to the image being loaded. The system context,
  865. size, file information, load flags, and preferred virtual address will
  866. be initialized. This routine should set up the loaded image buffer,
  867. loaded lowest address, and allocator handle if needed.
  868. Return Value:
  869. Status code.
  870. --*/
  871. {
  872. PVOID Address;
  873. PVOID AlignedPreferredAddress;
  874. BOOL KernelMode;
  875. PVOID Max;
  876. UINTN PageOffset;
  877. UINTN PageSize;
  878. PKPROCESS Process;
  879. PMEMORY_RESERVATION Reservation;
  880. KSTATUS Status;
  881. ALLOCATION_STRATEGY Strategy;
  882. PageSize = MmPageSize();
  883. Process = (PKPROCESS)(Image->SystemContext);
  884. Address = NULL;
  885. AlignedPreferredAddress = NULL;
  886. if (Process == PsGetKernelProcess()) {
  887. KernelMode = TRUE;
  888. Max = MAX_ADDRESS;
  889. Strategy = AllocationStrategyAnyAddress;
  890. } else {
  891. KernelMode = FALSE;
  892. Max = Process->AddressSpace->MaxMemoryMap;
  893. Strategy = AllocationStrategyHighestAddress;
  894. if ((Image->LoadFlags & IMAGE_LOAD_FLAG_PRIMARY_EXECUTABLE) != 0) {
  895. Strategy = AllocationStrategyAnyAddress;
  896. Address = Image->PreferredLowestAddress;
  897. AlignedPreferredAddress =
  898. (PVOID)(UINTN)ALIGN_RANGE_DOWN((UINTN)Address, PageSize);
  899. }
  900. }
  901. //
  902. // Align the preferred address down to a page.
  903. //
  904. PageOffset = (UINTN)Address - (UINTN)AlignedPreferredAddress;
  905. Reservation = MmCreateMemoryReservation(AlignedPreferredAddress,
  906. Image->Size + PageOffset,
  907. 0,
  908. Max,
  909. Strategy,
  910. KernelMode);
  911. if (Reservation == NULL) {
  912. Status = STATUS_INSUFFICIENT_RESOURCES;
  913. goto AllocateAddressSpaceEnd;
  914. }
  915. //
  916. // Upon success, return the virtual address, accessible address, and return
  917. // the reservation as the handle. Since images are set up the process they
  918. // run in, the accessible VA is the same as the final VA.
  919. //
  920. Address = Reservation->VirtualBase + PageOffset;
  921. Image->LoadedLowestAddress = Address;
  922. Image->LoadedImageBuffer = Address;
  923. Image->AllocatorHandle = (HANDLE)Reservation;
  924. Status = STATUS_SUCCESS;
  925. AllocateAddressSpaceEnd:
  926. if (!KSUCCESS(Status)) {
  927. if (Reservation != NULL) {
  928. MmFreeMemoryReservation(Reservation);
  929. }
  930. }
  931. return Status;
  932. }
  933. VOID
  934. PspImFreeAddressSpace (
  935. PLOADED_IMAGE Image
  936. )
  937. /*++
  938. Routine Description:
  939. This routine frees a section of virtual address space that was previously
  940. allocated.
  941. Arguments:
  942. Image - Supplies a pointer to the loaded (or partially loaded) image.
  943. Return Value:
  944. None.
  945. --*/
  946. {
  947. PMEMORY_RESERVATION Reservation;
  948. Reservation = (PMEMORY_RESERVATION)(Image->AllocatorHandle);
  949. if ((Reservation != NULL) && (Reservation != INVALID_HANDLE)) {
  950. MmFreeMemoryReservation(Reservation);
  951. }
  952. return;
  953. }
  954. KSTATUS
  955. PspImMapImageSegment (
  956. HANDLE AddressSpaceHandle,
  957. PVOID AddressSpaceAllocation,
  958. PIMAGE_FILE_INFORMATION File,
  959. ULONGLONG FileOffset,
  960. PIMAGE_SEGMENT Segment,
  961. PIMAGE_SEGMENT PreviousSegment
  962. )
  963. /*++
  964. Routine Description:
  965. This routine maps a section of the image to the given virtual address.
  966. Arguments:
  967. AddressSpaceHandle - Supplies the handle used to claim the overall region
  968. of address space.
  969. AddressSpaceAllocation - Supplies the original lowest virtual address for
  970. this image.
  971. File - Supplies an optional pointer to the file being mapped. If this
  972. parameter is NULL, then a zeroed memory section is being mapped.
  973. FileOffset - Supplies the offset from the beginning of the file to the
  974. beginning of the mapping, in bytes.
  975. Segment - Supplies a pointer to the segment information to map. On output,
  976. the virtual address will contain the actual mapped address, and the
  977. mapping handle may be set.
  978. PreviousSegment - Supplies an optional pointer to the previous segment
  979. that was mapped, so this routine can handle overlap appropriately. This
  980. routine can assume that segments are always mapped in increasing order.
  981. Return Value:
  982. Status code.
  983. --*/
  984. {
  985. UINTN BytesCompleted;
  986. PIO_HANDLE FileHandle;
  987. PVOID FileRegion;
  988. UINTN FileRegionSize;
  989. UINTN FileSize;
  990. IO_BUFFER IoBuffer;
  991. ULONG IoBufferFlags;
  992. UINTN IoSize;
  993. BOOL KernelMode;
  994. PKPROCESS KernelProcess;
  995. ULONG MapFlags;
  996. UINTN MemorySize;
  997. UINTN NextPage;
  998. UINTN PageMask;
  999. UINTN PageOffset;
  1000. UINTN PageSize;
  1001. UINTN PreviousEnd;
  1002. PKPROCESS Process;
  1003. UINTN RegionEnd;
  1004. UINTN RegionSize;
  1005. PMEMORY_RESERVATION Reservation;
  1006. UINTN SegmentAddress;
  1007. KSTATUS Status;
  1008. VM_ALLOCATION_PARAMETERS VaRequest;
  1009. ASSERT((PreviousSegment == NULL) ||
  1010. (Segment->VirtualAddress > PreviousSegment->VirtualAddress));
  1011. FileRegion = NULL;
  1012. FileRegionSize = 0;
  1013. FileHandle = NULL;
  1014. IoBufferFlags = 0;
  1015. if (File != NULL) {
  1016. FileHandle = File->Handle;
  1017. }
  1018. FileSize = Segment->FileSize;
  1019. MemorySize = Segment->MemorySize;
  1020. ASSERT((FileSize == Segment->FileSize) &&
  1021. (MemorySize == Segment->MemorySize));
  1022. Reservation = AddressSpaceHandle;
  1023. KernelMode = FALSE;
  1024. KernelProcess = PsGetKernelProcess();
  1025. MapFlags = SYS_MAP_FLAG_READ;
  1026. if ((Segment->Flags & IMAGE_MAP_FLAG_WRITE) != 0) {
  1027. MapFlags |= SYS_MAP_FLAG_WRITE;
  1028. }
  1029. //
  1030. // Map everything writable for now, it will get fixed up during
  1031. // finalization.
  1032. //
  1033. MapFlags = IMAGE_SECTION_READABLE | IMAGE_SECTION_WRITABLE;
  1034. if ((Segment->Flags & IMAGE_MAP_FLAG_EXECUTE) != 0) {
  1035. MapFlags |= IMAGE_SECTION_EXECUTABLE;
  1036. }
  1037. VaRequest.Alignment = 0;
  1038. VaRequest.Min = 0;
  1039. VaRequest.MemoryType = MemoryTypeReserved;
  1040. VaRequest.Strategy = AllocationStrategyFixedAddress;
  1041. Process = Reservation->Process;
  1042. if (Process == KernelProcess) {
  1043. KernelMode = TRUE;
  1044. MapFlags |= IMAGE_SECTION_NON_PAGED;
  1045. IoBufferFlags |= IO_BUFFER_FLAG_KERNEL_MODE_DATA;
  1046. VaRequest.Max = MAX_ADDRESS;
  1047. } else {
  1048. VaRequest.Max = Process->AddressSpace->MaxMemoryMap;
  1049. }
  1050. //
  1051. // Handle the first part, which may overlap with the previous segment.
  1052. //
  1053. PageSize = MmPageSize();
  1054. PageMask = PageSize - 1;
  1055. SegmentAddress = (UINTN)(Segment->VirtualAddress);
  1056. if (PreviousSegment != NULL) {
  1057. PreviousEnd = (UINTN)(PreviousSegment->VirtualAddress) +
  1058. PreviousSegment->MemorySize;
  1059. RegionEnd = ALIGN_RANGE_UP(PreviousEnd, PageSize);
  1060. if (RegionEnd > SegmentAddress) {
  1061. //
  1062. // Fail if this region is executable but the previous one was not,
  1063. // as the kernel can't go make a portion of the previous section
  1064. // executable. One potential workaround would be to make the entire
  1065. // previous section executable. So far this is not needed.
  1066. //
  1067. if (((Segment->Flags & IMAGE_MAP_FLAG_EXECUTE) != 0) &&
  1068. ((PreviousSegment->Flags & IMAGE_MAP_FLAG_EXECUTE) == 0)) {
  1069. RtlDebugPrint("Error: Executable image section at 0x%x "
  1070. "overlaps with non-executable section at "
  1071. "0x%x.\n",
  1072. Segment->VirtualAddress,
  1073. PreviousSegment->VirtualAddress);
  1074. Status = STATUS_MEMORY_CONFLICT;
  1075. goto MapImageSegmentEnd;
  1076. }
  1077. //
  1078. // Compute the portion of this section that needs to be read or
  1079. // zeroed into it.
  1080. //
  1081. if (SegmentAddress + MemorySize < RegionEnd) {
  1082. RegionEnd = SegmentAddress + MemorySize;
  1083. }
  1084. RegionSize = RegionEnd - SegmentAddress;
  1085. IoSize = FileSize;
  1086. if (IoSize > RegionSize) {
  1087. IoSize = RegionSize;
  1088. }
  1089. Status = MmInitializeIoBuffer(&IoBuffer,
  1090. (PVOID)SegmentAddress,
  1091. INVALID_PHYSICAL_ADDRESS,
  1092. IoSize,
  1093. IoBufferFlags);
  1094. if (!KSUCCESS(Status)) {
  1095. goto MapImageSegmentEnd;
  1096. }
  1097. Status = IoReadAtOffset(FileHandle,
  1098. &IoBuffer,
  1099. FileOffset,
  1100. IoSize,
  1101. 0,
  1102. WAIT_TIME_INDEFINITE,
  1103. &BytesCompleted,
  1104. NULL);
  1105. if (!KSUCCESS(Status)) {
  1106. goto MapImageSegmentEnd;
  1107. }
  1108. if (BytesCompleted != IoSize) {
  1109. Status = STATUS_END_OF_FILE;
  1110. goto MapImageSegmentEnd;
  1111. }
  1112. if (IoSize < RegionSize) {
  1113. RtlZeroMemory((PVOID)SegmentAddress + IoSize,
  1114. RegionSize - IoSize);
  1115. }
  1116. if (((Segment->Flags | PreviousSegment->Flags) &
  1117. IMAGE_MAP_FLAG_EXECUTE) != 0) {
  1118. Status = MmSyncCacheRegion((PVOID)SegmentAddress, RegionSize);
  1119. ASSERT(KSUCCESS(Status));
  1120. }
  1121. FileOffset += IoSize;
  1122. FileSize -= IoSize;
  1123. MemorySize -= RegionSize;
  1124. SegmentAddress = RegionEnd;
  1125. }
  1126. }
  1127. //
  1128. // This is the main portion. If the file offset and address have the same
  1129. // page alignment, then it can be mapped directly. Otherwise, it must be
  1130. // read in.
  1131. //
  1132. if (FileSize != 0) {
  1133. PageOffset = FileOffset & PageMask;
  1134. FileRegion = (PVOID)(SegmentAddress - PageOffset);
  1135. FileRegionSize = ALIGN_RANGE_UP(FileSize + PageOffset, PageSize);
  1136. VaRequest.Address = FileRegion;
  1137. VaRequest.Size = FileRegionSize;
  1138. //
  1139. // Try to memory map the file directly.
  1140. //
  1141. if (PageOffset == (SegmentAddress & PageMask)) {
  1142. Status = MmMapFileSection(FileHandle,
  1143. FileOffset - PageOffset,
  1144. &VaRequest,
  1145. MapFlags,
  1146. KernelMode,
  1147. Reservation);
  1148. if (!KSUCCESS(Status)) {
  1149. RtlDebugPrint("Failed to map %x bytes at %x: %x\n",
  1150. FileRegionSize,
  1151. FileRegion,
  1152. Status);
  1153. FileRegionSize = 0;
  1154. goto MapImageSegmentEnd;
  1155. }
  1156. IoSize = 0;
  1157. //
  1158. // The file offsets don't agree. Allocate a region for reading.
  1159. //
  1160. } else {
  1161. Status = MmMapFileSection(INVALID_HANDLE,
  1162. 0,
  1163. &VaRequest,
  1164. MapFlags,
  1165. KernelMode,
  1166. Reservation);
  1167. if (!KSUCCESS(Status)) {
  1168. RtlDebugPrint("Failed to map %x bytes at %x: %x\n",
  1169. FileRegionSize,
  1170. FileRegion,
  1171. Status);
  1172. FileRegionSize = 0;
  1173. goto MapImageSegmentEnd;
  1174. }
  1175. IoSize = FileSize;
  1176. }
  1177. Segment->MappingStart = FileRegion;
  1178. ASSERT((UINTN)FileRegion == SegmentAddress - PageOffset);
  1179. //
  1180. // Read from the file if the file wasn't mapped directly.
  1181. //
  1182. if (IoSize != 0) {
  1183. Status = MmInitializeIoBuffer(&IoBuffer,
  1184. (PVOID)SegmentAddress,
  1185. INVALID_PHYSICAL_ADDRESS,
  1186. IoSize,
  1187. IoBufferFlags);
  1188. if (!KSUCCESS(Status)) {
  1189. goto MapImageSegmentEnd;
  1190. }
  1191. Status = IoReadAtOffset(FileHandle,
  1192. &IoBuffer,
  1193. FileOffset,
  1194. IoSize,
  1195. 0,
  1196. WAIT_TIME_INDEFINITE,
  1197. &BytesCompleted,
  1198. NULL);
  1199. if (!KSUCCESS(Status)) {
  1200. goto MapImageSegmentEnd;
  1201. }
  1202. if (BytesCompleted != IoSize) {
  1203. Status = STATUS_END_OF_FILE;
  1204. goto MapImageSegmentEnd;
  1205. }
  1206. if ((Segment->Flags & IMAGE_MAP_FLAG_EXECUTE) != 0) {
  1207. Status = MmSyncCacheRegion((PVOID)SegmentAddress, IoSize);
  1208. ASSERT(KSUCCESS(Status));
  1209. }
  1210. }
  1211. SegmentAddress += FileSize;
  1212. MemorySize -= FileSize;
  1213. //
  1214. // Zero out any region between the end of the file portion and the next
  1215. // page.
  1216. //
  1217. NextPage = ALIGN_RANGE_UP(SegmentAddress, PageSize);
  1218. if (NextPage - SegmentAddress != 0) {
  1219. RtlZeroMemory((PVOID)SegmentAddress, NextPage - SegmentAddress);
  1220. if ((Segment->Flags & IMAGE_MAP_FLAG_EXECUTE) != 0) {
  1221. Status = MmSyncCacheRegion((PVOID)SegmentAddress,
  1222. NextPage - SegmentAddress);
  1223. ASSERT(KSUCCESS(Status));
  1224. }
  1225. }
  1226. if (NextPage >= SegmentAddress + MemorySize) {
  1227. Status = STATUS_SUCCESS;
  1228. goto MapImageSegmentEnd;
  1229. }
  1230. MemorySize -= NextPage - SegmentAddress;
  1231. SegmentAddress = NextPage;
  1232. }
  1233. //
  1234. // Memory map the remaining region, which is not backed by the image.
  1235. //
  1236. PageOffset = SegmentAddress & PageMask;
  1237. VaRequest.Address = (PVOID)(SegmentAddress - PageOffset);
  1238. VaRequest.Size = ALIGN_RANGE_UP(MemorySize + PageOffset, PageSize);
  1239. Status = MmMapFileSection(INVALID_HANDLE,
  1240. 0,
  1241. &VaRequest,
  1242. MapFlags,
  1243. KernelMode,
  1244. Reservation);
  1245. if (!KSUCCESS(Status)) {
  1246. ASSERT(FALSE);
  1247. goto MapImageSegmentEnd;
  1248. }
  1249. //
  1250. // If this is a kernel mode segment, then the anonymous non-paged section
  1251. // just created will have been backed by fresh pages but not initialized to
  1252. // zero.
  1253. //
  1254. if (KernelMode != FALSE) {
  1255. RtlZeroMemory(VaRequest.Address, VaRequest.Size);
  1256. }
  1257. if (Segment->MappingStart == NULL) {
  1258. Segment->MappingStart = VaRequest.Address;
  1259. }
  1260. MapImageSegmentEnd:
  1261. if (!KSUCCESS(Status)) {
  1262. if (FileRegionSize != 0) {
  1263. MmUnmapFileSection(Reservation->Process,
  1264. FileRegion,
  1265. FileRegionSize,
  1266. Reservation);
  1267. }
  1268. }
  1269. return Status;
  1270. }
  1271. VOID
  1272. PspImUnmapImageSegment (
  1273. HANDLE AddressSpaceHandle,
  1274. PIMAGE_SEGMENT Segment
  1275. )
  1276. /*++
  1277. Routine Description:
  1278. This routine maps unmaps an image segment.
  1279. Arguments:
  1280. AddressSpaceHandle - Supplies the handle used to claim the overall region
  1281. of address space.
  1282. Segment - Supplies a pointer to the segment information to unmap.
  1283. Return Value:
  1284. None.
  1285. --*/
  1286. {
  1287. UINTN End;
  1288. UINTN PageSize;
  1289. PMEMORY_RESERVATION Reservation;
  1290. UINTN SectionBegin;
  1291. KSTATUS Status;
  1292. PageSize = MmPageSize();
  1293. Reservation = AddressSpaceHandle;
  1294. if (AddressSpaceHandle == INVALID_HANDLE) {
  1295. Reservation = NULL;
  1296. }
  1297. if (Segment->MappingStart == NULL) {
  1298. return;
  1299. }
  1300. SectionBegin = (UINTN)(Segment->MappingStart);
  1301. End = (UINTN)(Segment->VirtualAddress) + Segment->MemorySize;
  1302. End = ALIGN_RANGE_UP((UINTN)End, PageSize);
  1303. Status = MmUnmapFileSection(NULL,
  1304. (PVOID)SectionBegin,
  1305. End - SectionBegin,
  1306. Reservation);
  1307. ASSERT(KSUCCESS(Status));
  1308. return;
  1309. }
  1310. KSTATUS
  1311. PspImNotifyImageLoad (
  1312. PLOADED_IMAGE Image
  1313. )
  1314. /*++
  1315. Routine Description:
  1316. This routine notifies the primary consumer of the image library that an
  1317. image has been loaded.
  1318. Arguments:
  1319. Image - Supplies the image that has just been loaded. This image should
  1320. be subsequently returned to the image library upon requests for loaded
  1321. images with the given name.
  1322. Return Value:
  1323. Status code. Failing status codes veto the image load.
  1324. --*/
  1325. {
  1326. PKPROCESS KernelProcess;
  1327. PKPROCESS Process;
  1328. PMEMORY_RESERVATION Reservation;
  1329. KSTATUS Status;
  1330. if (Image->AllocatorHandle == INVALID_HANDLE) {
  1331. Process = PsGetCurrentProcess();
  1332. } else {
  1333. Reservation = (PMEMORY_RESERVATION)(Image->AllocatorHandle);
  1334. Process = Reservation->Process;
  1335. }
  1336. KernelProcess = PsGetKernelProcess();
  1337. ASSERT((KeIsQueuedLockHeld(Process->QueuedLock) != FALSE) ||
  1338. (Process == KernelProcess));
  1339. Process->ImageCount += 1;
  1340. Process->ImageListSignature += Image->File.ModificationDate +
  1341. (UINTN)(Image->LoadedLowestAddress);
  1342. //
  1343. // If the debug flag is enabled, then make the kernel debugger aware of
  1344. // this user mode module.
  1345. //
  1346. if ((PsKdLoadAllImages != FALSE) ||
  1347. (Image->SystemContext == KernelProcess)) {
  1348. PspLoadProcessImageIntoKernelDebugger(Process, Image);
  1349. }
  1350. //
  1351. // Let I/O do some initialization if this is a driver.
  1352. //
  1353. if (Image->SystemContext == KernelProcess) {
  1354. if (Image->TlsSize != 0) {
  1355. Status = STATUS_NOT_SUPPORTED;
  1356. goto ImNotifyImageLoadEnd;
  1357. }
  1358. Status = IoCreateDriverStructure(Image);
  1359. if (!KSUCCESS(Status)) {
  1360. goto ImNotifyImageLoadEnd;
  1361. }
  1362. }
  1363. Status = STATUS_SUCCESS;
  1364. ImNotifyImageLoadEnd:
  1365. return Status;
  1366. }
  1367. VOID
  1368. PspImNotifyImageUnload (
  1369. PLOADED_IMAGE Image
  1370. )
  1371. /*++
  1372. Routine Description:
  1373. This routine notifies the primary consumer of the image library that an
  1374. image is about to be unloaded from memory. Once this routine returns, the
  1375. image should not be referenced again as it will be freed.
  1376. Arguments:
  1377. Image - Supplies the image that is about to be unloaded.
  1378. Return Value:
  1379. None.
  1380. --*/
  1381. {
  1382. PKPROCESS KernelProcess;
  1383. PKPROCESS Process;
  1384. KernelProcess = PsGetKernelProcess();
  1385. Process = Image->SystemContext;
  1386. if (Process == NULL) {
  1387. Process = PsGetCurrentProcess();
  1388. }
  1389. ASSERT((KeIsQueuedLockHeld(Process->QueuedLock) != FALSE) ||
  1390. (Process == KernelProcess));
  1391. ASSERT(Process->ImageCount != 0);
  1392. Process->ImageCount -= 1;
  1393. Process->ImageListSignature -= Image->File.ModificationDate +
  1394. (UINTN)(Image->LoadedLowestAddress);
  1395. if (Image->DebuggerModule != NULL) {
  1396. KdReportModuleChange(Image->DebuggerModule, FALSE);
  1397. MmFreeNonPagedPool(Image->DebuggerModule);
  1398. Image->DebuggerModule = NULL;
  1399. }
  1400. //
  1401. // Let I/O destroy its structures if this is a driver.
  1402. //
  1403. if (Image->SystemContext == KernelProcess) {
  1404. IoDestroyDriverStructure(Image);
  1405. }
  1406. return;
  1407. }
  1408. VOID
  1409. PspImInvalidateInstructionCacheRegion (
  1410. PVOID Address,
  1411. ULONG Size
  1412. )
  1413. /*++
  1414. Routine Description:
  1415. This routine invalidates an instruction cache region after code has been
  1416. modified.
  1417. Arguments:
  1418. Address - Supplies the virtual address of the revion to invalidate.
  1419. Size - Supplies the number of bytes to invalidate.
  1420. Return Value:
  1421. None.
  1422. --*/
  1423. {
  1424. KSTATUS Status;
  1425. Status = MmSyncCacheRegion(Address, Size);
  1426. ASSERT(KSUCCESS(Status));
  1427. return;
  1428. }
  1429. PSTR
  1430. PspImGetEnvironmentVariable (
  1431. PSTR Variable
  1432. )
  1433. /*++
  1434. Routine Description:
  1435. This routine gets an environment variable value for the image library.
  1436. Arguments:
  1437. Variable - Supplies a pointer to a null terminated string containing the
  1438. name of the variable to get.
  1439. Return Value:
  1440. Returns a pointer to the value of the environment variable. The image
  1441. library will not free or modify this value.
  1442. NULL if the given environment variable is not set.
  1443. --*/
  1444. {
  1445. BOOL Match;
  1446. PKPROCESS Process;
  1447. UINTN VariableLength;
  1448. //
  1449. // User mode gets no help.
  1450. //
  1451. Process = PsGetCurrentProcess();
  1452. if (Process != PsGetKernelProcess()) {
  1453. return NULL;
  1454. }
  1455. VariableLength = RtlStringLength(Variable);
  1456. Match = RtlAreStringsEqual(Variable,
  1457. IMAGE_DYNAMIC_LIBRARY_PATH_VARIABLE,
  1458. VariableLength + 1);
  1459. if (Match != FALSE) {
  1460. //
  1461. // Return a separator, which will append an empty prefix.
  1462. //
  1463. return ":";
  1464. }
  1465. return NULL;
  1466. }
  1467. KSTATUS
  1468. PspImFinalizeSegments (
  1469. HANDLE AddressSpaceHandle,
  1470. PIMAGE_SEGMENT Segments,
  1471. UINTN SegmentCount
  1472. )
  1473. /*++
  1474. Routine Description:
  1475. This routine applies the final memory protection attributes to the given
  1476. segments. Read and execute bits can be applied at the time of mapping, but
  1477. write protection may be applied here.
  1478. Arguments:
  1479. AddressSpaceHandle - Supplies the handle used to claim the overall region
  1480. of address space.
  1481. Segments - Supplies the final array of segments.
  1482. SegmentCount - Supplies the number of segments.
  1483. Return Value:
  1484. Status code.
  1485. --*/
  1486. {
  1487. UINTN End;
  1488. ULONG MapFlags;
  1489. UINTN PageSize;
  1490. PIMAGE_SEGMENT Segment;
  1491. UINTN SegmentIndex;
  1492. UINTN Size;
  1493. KSTATUS Status;
  1494. PageSize = MmPageSize();
  1495. for (SegmentIndex = 0; SegmentIndex < SegmentCount; SegmentIndex += 1) {
  1496. Segment = &(Segments[SegmentIndex]);
  1497. if (Segment->Type == ImageSegmentInvalid) {
  1498. continue;
  1499. }
  1500. //
  1501. // If the segment has no protection features, then there's nothing to
  1502. // tighten up.
  1503. //
  1504. if ((Segment->Flags & IMAGE_MAP_FLAG_WRITE) != 0) {
  1505. continue;
  1506. }
  1507. //
  1508. // If the image was so small it fit entirely in some other segment's
  1509. // remainder, skip it.
  1510. //
  1511. if (Segment->MappingStart == NULL) {
  1512. continue;
  1513. }
  1514. //
  1515. // Compute the region whose protection should actually be changed.
  1516. //
  1517. End = (UINTN)(Segment->VirtualAddress) + Segment->MemorySize;
  1518. End = ALIGN_RANGE_UP(End, PageSize);
  1519. //
  1520. // If the region has a real size, changed its protection to read-only.
  1521. //
  1522. if ((PVOID)End > Segment->MappingStart) {
  1523. Size = End - (UINTN)(Segment->MappingStart);
  1524. MapFlags = IMAGE_SECTION_READABLE;
  1525. if ((Segment->Flags & IMAGE_MAP_FLAG_EXECUTE) != 0) {
  1526. MapFlags |= IMAGE_SECTION_EXECUTABLE;
  1527. }
  1528. Status = MmChangeImageSectionRegionAccess(Segment->MappingStart,
  1529. Size,
  1530. MapFlags);
  1531. if (!KSUCCESS(Status)) {
  1532. goto FinalizeSegmentsEnd;
  1533. }
  1534. }
  1535. }
  1536. Status = STATUS_SUCCESS;
  1537. FinalizeSegmentsEnd:
  1538. return Status;
  1539. }
  1540. KSTATUS
  1541. PspImCloneImage (
  1542. PKPROCESS Source,
  1543. PKPROCESS Destination,
  1544. PLOADED_IMAGE SourceImage,
  1545. PLOADED_IMAGE *NewDestinationImage
  1546. )
  1547. /*++
  1548. Routine Description:
  1549. This routine makes a copy of the given process' image. This routine creates
  1550. the imports array but every entry is null, and needs to be filled in later.
  1551. Arguments:
  1552. Source - Supplies a pointer to the source process.
  1553. Destination - Supplies a pointer to the destination process.
  1554. SourceImage - Supplies a pointer to the image to copy.
  1555. NewDestinationImage - Supplies a pointer where a pointer to the newly
  1556. created destination image will be returned.
  1557. Return Value:
  1558. Status code.
  1559. --*/
  1560. {
  1561. ULONG AllocationSize;
  1562. ULONG NameSize;
  1563. PLOADED_IMAGE NewImage;
  1564. KSTATUS Status;
  1565. //
  1566. // Allocate a new image.
  1567. //
  1568. NameSize = RtlStringLength(SourceImage->BinaryName) + 1;
  1569. AllocationSize = sizeof(LOADED_IMAGE) + NameSize;
  1570. NewImage = PspImAllocateMemory(AllocationSize, PS_ALLOCATION_TAG);
  1571. if (NewImage == NULL) {
  1572. Status = STATUS_INSUFFICIENT_RESOURCES;
  1573. goto ImCloneImageEnd;
  1574. }
  1575. //
  1576. // Initialize the new image.
  1577. //
  1578. ASSERT(SourceImage->BinaryName == (PSTR)(SourceImage + 1));
  1579. RtlCopyMemory(NewImage, SourceImage, AllocationSize);
  1580. NewImage->BinaryName = (PSTR)(NewImage + 1);
  1581. NewImage->ListEntry.Next = NULL;
  1582. NewImage->ListEntry.Previous = NULL;
  1583. if (NewImage->File.Handle != INVALID_HANDLE) {
  1584. IoIoHandleAddReference(NewImage->File.Handle);
  1585. }
  1586. NewImage->SystemContext = Destination;
  1587. NewImage->AllocatorHandle = INVALID_HANDLE;
  1588. NewImage->Segments = NULL;
  1589. NewImage->Imports = NULL;
  1590. NewImage->DebuggerModule = NULL;
  1591. NewImage->StaticFunctions = NULL;
  1592. NewImage->ImageContext = NULL;
  1593. //
  1594. // Create the image segments.
  1595. //
  1596. if (NewImage->SegmentCount != 0) {
  1597. AllocationSize = sizeof(IMAGE_SEGMENT) * NewImage->SegmentCount;
  1598. NewImage->Segments = PspImAllocateMemory(AllocationSize,
  1599. PS_ALLOCATION_TAG);
  1600. if (NewImage->Segments == NULL) {
  1601. Status = STATUS_INSUFFICIENT_RESOURCES;
  1602. goto ImCloneImageEnd;
  1603. }
  1604. RtlCopyMemory(NewImage->Segments,
  1605. SourceImage->Segments,
  1606. AllocationSize);
  1607. }
  1608. //
  1609. // Allocate space for the imports array. Unfortunately it cannot be
  1610. // populated yet because it may point to images that have not yet been
  1611. // cloned.
  1612. //
  1613. if (SourceImage->ImportCount != 0) {
  1614. AllocationSize = SourceImage->ImportCount * sizeof(PLOADED_IMAGE);
  1615. NewImage->Imports = PspImAllocateMemory(AllocationSize,
  1616. PS_ALLOCATION_TAG);
  1617. if (NewImage->Imports == NULL) {
  1618. Status = STATUS_INSUFFICIENT_RESOURCES;
  1619. goto ImCloneImageEnd;
  1620. }
  1621. RtlZeroMemory(NewImage->Imports, AllocationSize);
  1622. }
  1623. INSERT_BEFORE(&(NewImage->ListEntry), &(Destination->ImageListHead));
  1624. Destination->ImageCount += 1;
  1625. if (PsKdLoadAllImages != FALSE) {
  1626. PspLoadProcessImageIntoKernelDebugger(Destination, NewImage);
  1627. }
  1628. Destination->ImageListSignature += NewImage->File.ModificationDate +
  1629. (UINTN)(NewImage->LoadedLowestAddress);
  1630. Status = STATUS_SUCCESS;
  1631. ImCloneImageEnd:
  1632. if (!KSUCCESS(Status)) {
  1633. if (NewImage != NULL) {
  1634. if (NewImage->Imports != NULL) {
  1635. PspImFreeMemory(NewImage->Imports);
  1636. }
  1637. if (NewImage->Segments != NULL) {
  1638. PspImFreeMemory(NewImage->Segments);
  1639. }
  1640. PspImFreeMemory(NewImage);
  1641. NewImage = NULL;
  1642. }
  1643. }
  1644. *NewDestinationImage = NewImage;
  1645. return Status;
  1646. }
  1647. PLOADED_IMAGE
  1648. PspImGetAssociatedImage (
  1649. PLOADED_IMAGE QueryImage,
  1650. PIMAGE_ASSOCIATION AssociationMapping,
  1651. ULONG AssociationCount
  1652. )
  1653. /*++
  1654. Routine Description:
  1655. This routine searches through the given association mapping looking for
  1656. an image that maps to the query.
  1657. Arguments:
  1658. QueryImage - Supplies a pointer to the image whose associated image is
  1659. requested.
  1660. AssociationMapping - Supplies a pointer to the association mapping array.
  1661. AssociationCount - Supplies the number of elements in the association array.
  1662. Return Value:
  1663. Returns a pointer to the image associated with the query image on success.
  1664. NULL if no mapping could be found.
  1665. --*/
  1666. {
  1667. ULONG AssociationIndex;
  1668. for (AssociationIndex = 0;
  1669. AssociationIndex < AssociationCount;
  1670. AssociationIndex += 1) {
  1671. if (AssociationMapping[AssociationIndex].SourceImage == QueryImage) {
  1672. return AssociationMapping[AssociationIndex].DestinationImage;
  1673. }
  1674. if (AssociationMapping[AssociationIndex].DestinationImage ==
  1675. QueryImage) {
  1676. return AssociationMapping[AssociationIndex].SourceImage;
  1677. }
  1678. }
  1679. return NULL;
  1680. }
  1681. KSTATUS
  1682. PspLoadProcessImageIntoKernelDebugger (
  1683. PKPROCESS Process,
  1684. PLOADED_IMAGE Image
  1685. )
  1686. /*++
  1687. Routine Description:
  1688. This routine loads the given image into the kernel debugger. This routine
  1689. assumes the process image list lock is already held.
  1690. Arguments:
  1691. Process - Supplies a pointer to the process.
  1692. Image - Supplies a pointer to the image to load into the kernel debugger.
  1693. Return Value:
  1694. Status code.
  1695. --*/
  1696. {
  1697. ULONG AllocationSize;
  1698. UINTN BaseDifference;
  1699. PDEBUG_MODULE DebuggerModule;
  1700. ULONG NameSize;
  1701. ASSERT(KeGetRunLevel() == RunLevelLow);
  1702. //
  1703. // If the image is already loaded, skip it.
  1704. //
  1705. if (Image->DebuggerModule != NULL) {
  1706. return STATUS_SUCCESS;
  1707. }
  1708. //
  1709. // If for some odd reason the image doesn't have a name, skip it.
  1710. //
  1711. if (Image->BinaryName == NULL) {
  1712. return STATUS_INVALID_PARAMETER;
  1713. }
  1714. //
  1715. // Allocate and initialize the debugger module structure.
  1716. //
  1717. NameSize = ((RtlStringLength(Image->BinaryName) + 1) * sizeof(CHAR));
  1718. AllocationSize = sizeof(DEBUG_MODULE) + NameSize -
  1719. (sizeof(CHAR) * ANYSIZE_ARRAY);
  1720. DebuggerModule = MmAllocateNonPagedPool(AllocationSize,
  1721. PS_DEBUG_ALLOCATION_TAG);
  1722. if (DebuggerModule == NULL) {
  1723. return STATUS_INSUFFICIENT_RESOURCES;
  1724. }
  1725. RtlZeroMemory(DebuggerModule, AllocationSize);
  1726. DebuggerModule->StructureSize = AllocationSize;
  1727. DebuggerModule->Timestamp = Image->File.ModificationDate;
  1728. BaseDifference = (UINTN)Image->LoadedLowestAddress -
  1729. (UINTN)Image->PreferredLowestAddress;
  1730. DebuggerModule->BaseAddress = Image->DeclaredBase + BaseDifference;
  1731. DebuggerModule->LowestAddress = Image->LoadedLowestAddress;
  1732. DebuggerModule->EntryPoint = Image->EntryPoint;
  1733. DebuggerModule->Size = Image->Size;
  1734. DebuggerModule->Process = Process->Identifiers.ProcessId;
  1735. RtlStringCopy(DebuggerModule->BinaryName, Image->BinaryName, NameSize);
  1736. //
  1737. // Save the pointer and make the debugger aware of this new module.
  1738. //
  1739. Image->DebuggerModule = DebuggerModule;
  1740. KdReportModuleChange(DebuggerModule, TRUE);
  1741. return STATUS_SUCCESS;
  1742. }