psimag.c 57 KB

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