tags:

views:

224

answers:

2

I'm no delphi wizard but I found this function on a board and I need it badly for C++, Is there somebody who knows Delphi and C++ well enough to convert it?

function GetModuleBase(hProcID: Cardinal; lpModName: PChar):Cardinal;
var
  hSnap: Cardinal;
  tm: TModuleEntry32;
begin
  result := 0;
  hSnap := CreateToolHelp32Snapshot(TH32CS_SNAPMODULE, hProcID);
  if hSnap <> 0 then
  begin
    tm.dwSize := sizeof(TModuleEntry32);
    if Module32First(hSnap, tm) = true then
    begin
      while Module32Next(hSnap, tm) = true do
      begin
        if lstrcmpi(tm.szModule, lpModName) = 0 then
        begin
          result := Cardinal(tm.modBaseAddr);
          break;
        end;
      end;
    end;
    CloseHandle(hSnap);
  end;
end;
+1  A: 

The following is untested, but should be close:

#include <windows.h>
#include <tlhelp32.h>

byte *getModuleBase(DWORD hProcId, TCHAR *lpModName)
{
    byte *result = NULL;
    HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, hProcId);

    if (hSnap)
    {
        MODULEENTRY32 tm;
        tm.dwSize = sizeof(MODULEENTRY32);

        if (Module32First(hSnap, &tm))
        {
            while (Module32Next(hSnap, &tm))
            {
                if (lstrcmpi(tm.szModule, lpModName) == 0)
                {
                    result = tm.modBaseAddr;
                    break;
                }
            }
        }

        CloseHandle(hSnap);
    }

    return result;
}

Note that this code doesn't check the name of the first module. If you want to check the first module too, then you could try something like this:

if (Module32First(hSnap, &tm))
{
    do 
    {
        if (lstrcmpi(tm.szModule, lpModName) == 0)
        {
            result = tm.modBaseAddr;
            break;
        }
    }
    while (Module32Next(hSnap, &tm));
}
Phil Ross
AFAIK it should be `DWORD*getModuleBase(DWORD hProcId, TCHAR *lpModName)`, not byte. Delphi's Cardinal is unsigned 32bit integer
Gerry
@Gerry: According to http://msdn.microsoft.com/en-us/library/ms684225%28VS.85%29.aspx `BYTE *` is correct.
mghie
So presumably the original Delphi code was technically incorrect
Gerry
I think do-while would be a more elegant construct for that second example, i.e.' if (Module32First(hSnap, }'Which removes the necessity to repeat the test
Bob Moore
@Bob Moore Yes, do-while would make a lot more sense. I've updated my answer.
Phil Ross
@Gerry The result of the function is the base address of the module in memory. This is a declared as a pointer to a byte in the Windows API (i.e. the value of the pointer is the base address). The Delphi code returns the value of the pointer as a Cardinal (pointers are 32-bit unsigned integers on 32-bit machines, so this is an appropriate type to use).
Phil Ross
A: 

you could also use WinAPI's GetModuleHandle or GetModuleHandleEx, they do the same thing(and are probably safer than what you have), you would just cast the HANDLE to a BYTE* or DWORD or whatever else is needed

Necrolis
Please provide a link to the documentation that guarantees that a module handle is equivalent to the module's base address. Without that guarantee, it's much better to use the API that returns a value specifically designated as the base address. (Why would you think that method isn't safe?)
Rob Kennedy
well windows the docs on DLL are pretty skeleton-like, which is why my information comes from sources like: http://msdn.microsoft.com/en-us/magazine/cc301805.aspx and seeing as its in msdn magazine its endorsed my microsoft`Call GetModuleHandle with the name of the DLL. The HMODULE that's returned is just a load address; you can apply your knowledge of the PE file structures to find anything you want within the module.`
Necrolis