Mega Code Archive

 
Categories / Delphi / Examples
 

Listing all memory pages allocated by all accesible processes

How to list all memory pages allocated by all accesible processes Create a form with a button and a treeview, name the treeview tvwProcessList. Name the button btnProcessList. uses Windows; procedure TForm1.btnProcessListClick(Sender: TObject); var i,l:integer; pid:THandle; meminfo:MEMORY_BASIC_INFORMATION; memstart:pointer; memsize:Integer; s,attr:String; totuse:Integer; lpMsgBuf : PCHAR; pn, pidn, ln:TTreeNode; begin btnProcessList.Enabled := false; tvwProcessList.Items.Clear; pn:=tvwProcessList.Items.AddFirst (nil, 'This computer'); for i:=0 to 2000 do // begin //PROCESS_QUERY_INFORMATION pid:=OpenProcess (PROCESS_ALL_ACCESS{PROCESS_VM_OPERATION or PROCESS_QUERY_INFORMATION or PROCESS_VM_WRITE}, false, i*4); if pid<>0 then begin //add treenode: pidn := tvwProcessList.Items.AddChild (pn, IntToStr(i*4{pid})); memstart := 0; totuse := 0; l:=VirtualQueryEx (pid, memstart, MemInfo, SizeOf(MEMORY_BASIC_INFORMATION)); while (l=SizeOf(MEMORY_BASIC_INFORMATION)) do begin if Application.Terminated then exit; if meminfo.State=MEM_COMMIT then begin totuse := totuse+meminfo.RegionSize; attr := ''; if (0<>meminfo.Protect and PAGE_NOACCESS) then attr := attr+'NO ACCESS '; if (0<>meminfo.Protect and PAGE_READONLY) then attr := attr+'READONLY '; if (0<>meminfo.Protect and PAGE_READWRITE) then attr := attr+'READWRITE '; if (0<>meminfo.Protect and PAGE_WRITECOPY) then attr := attr+'WRITECOPY '; if (0<>meminfo.Protect and PAGE_EXECUTE) then attr := attr+'EXECUTE '; if (0<>meminfo.Protect and PAGE_EXECUTE_READ) then attr := attr+'EXECUTE_READ '; if (0<>meminfo.Protect and PAGE_EXECUTE_READWRITE) then attr := attr+'EXECUTE_READWRITE '; if (0<>meminfo.Protect and PAGE_EXECUTE_WRITECOPY) then attr := attr+'EXECUTE_WRITECOPY '; if (0<>meminfo.Protect and PAGE_GUARD) then attr := attr+'GUARD '; if (0<>meminfo.Protect and PAGE_NOCACHE) then attr := attr+'NOCACHE '; ln := tvwProcessList.Items.AddChild (pidn, Format ('Attr: %d: %s, Base: %d, size: %d', [meminfo.protect, attr, integer(meminfo.BaseAddress), meminfo.RegionSize])); Application.ProcessMessages; end; integer(memstart) := integer(meminfo.BaseAddress)+meminfo.regionsize; integer(memstart):=integer(memstart)+memsize; l:=VirtualQueryEx (pid, memstart, MemInfo, SizeOf(MEMORY_BASIC_INFORMATION)); end; pidn.Text := Format ('pid: %d, allocated: %d', [i*4, totuse]); end; CloseHandle(pid); end; btnProcessList.Enabled := true; end; Explanetion: The windows process ID is always a multiply of 4. SO, accessing process nr. 8 will access the same process as handle 9,10 and 11. We simply loop a list of possible ID's. There are better ways to do this, but that is outside the scope of this article, and this method works just fine. IF we have openened a process, we list the first page. We add the size of this page to the start address of the next page to retrieve. Not all pages are allocated, we can verify this with the MEM_COMMIT tag. If a page is commited, we examine the attributes, and add a tree node. This can take a while (especially adding all those tree nodes). After we are finished, we close the processhandle with CloseHandle. Be very sure to do this!!! Not closing the handle will lead to funny results, and if you do this several times you may well end in having to reboot your system sincew everything gets slow.