1

I am having a problem with calling GetModuleHandleA() using Python. I have a module that attaches as debugger to the process. I'm working on a function that would return address of the function in the specific DLL module. GetModuleHandleA("msvcr100") fails all of the time.

from ctypes import *
kernel32 = windll.kernel32

Function declared as part of a bigger debug class. That's the part of function declaration:

   def resolve_function(self,dll,function): 
        handle = kernel32.GetModuleHandleA(dll)
        if handle == False:
            print "kernel32.GetModuleNameA() failed!!!"
            return False
        address = kernel32.GetProcAddress(handle, function)
        if address == False:
            print "kernel32.GetProcAddress() failed!!!"
            return False
        kernel32.CloseHandle(handle)
        return address

Call the function made as:

function_address = debug.resolve_function("msvcr100", "printf")

I run separate process that uses printf() and then attach to it. Everything works fine until I get to GetModuleHandleA() that returns False all of the time.

Code that runs printf():

from ctypes import *
import time
msvcr100 = cdll.msvcr100
counter = 0
while 1:
    msvcr100.printf("Counter = %d\n" % counter)
    time.sleep(1)
    counter += 1

Any ideas?

Shog9
  • 156,901
  • 35
  • 231
  • 235
PSS
  • 5,561
  • 5
  • 28
  • 30
  • 2
    Have you verified that msvcr100 is actually loaded into the process? `GetModuleHandle()` doesn't actually do any loading itself... – Shog9 Jan 29 '11 at 02:41
  • And, uh... You might find this useful: [How to *printf* in Python?](http://stackoverflow.com/questions/493386/how-to-printf-in-python/493500#493500) – Shog9 Jan 29 '11 at 02:49
  • I have. It does load msvcr100.dll, because it prints stuff on the screen. – PSS Jan 29 '11 at 07:26

4 Answers4

5

You've found the solution to your problem, but I'm answering anyway to explain why your original effort failed (and why your fix worked).

First, msvcrt/msvcr100 are two different versions of Microsoft's C runtime library. There are other versions as well, and all of them contain their own definitions for printf(). A given process may have any one of them loaded, or multiple versions loaded, or no versions loaded - it's possible to produce console output using only WinAPI functions! In short, if it's not your process, you can't depend on any given version of the C runtime being available.

Second, GetModuleHandle() doesn't load anything. It returns a handle to the named module only if it has already been loaded. msvcr100.dll can be sitting right there on disk, but if the process hasn't already loaded it then GetModuleHandle won't give a handle to you. LoadLibrary() is the function you'd call if you wanted to both load and retrieve a handle to a named module... But you probably don't want to do this in a process you don't own.

FWIW, Process Explorer is a handy tool for viewing the DLLs already loaded by a process.

Community
  • 1
  • 1
Shog9
  • 156,901
  • 35
  • 231
  • 235
  • Thank you for your explanation. The question is: if i call printf() in a script as msvcr100 = cdll.msvcr100, msvcr100.printf("Counter = %d\n" % counter). Isn't it supposed to load msvcr100.dll and then call printf() out of msvcr100? – PSS Jan 29 '11 at 18:50
  • @PSS: I'm not really familiar with CDLL, but that looks plausible... You can double-check it using Process Explorer if you want. But as I mentioned, you probably don't want to load a different version of the runtime library dynamically if you can help it: there's a really good chance that it won't get initialized properly, and *things won't work*. Remember, this is a runtime library, not a grab-bag of utility functions. Is there a reason you're not using Python's built-in printing routines? – Shog9 Jan 29 '11 at 19:19
  • I'm learning how to attach and debug process using python. I don't really have to use printf() and python. I've created executable with C++ that uses printf()...I could use some other function...the reason for it is that i'm trying to get an address of that function so I could set a breakpoint later in my code. And printf() was my choice to experiment with. – PSS Jan 29 '11 at 22:46
1

After modifying:


...

handle = kernel32.GetModuleHandleA(dll) if handle == False: error = GetLastError() print "ERROR: %d - %s" % (error, FormatError(error)) return False

...

I get: ERROR: 126 - The specified module could not be found

I actually replaced msvcr100.dll with msvcrt.dll in my code and it worked perfect. I found out that msvcrt.dll is system dll. msvcr100.dll ships with Studio 2010. They are both located in C:\Windows\system32. It is still a mystery for me why msvcr100.dll did not work.

PSS
  • 5,561
  • 5
  • 28
  • 30
0

Use GetLastError() (or WinError) from ctypes to find out why you're getting a NULL return, then add that information to your error message. Even after you figure out this specific problem, you'll want that more robust error reporting.

See the ctypes docs for details: http://docs.python.org/library/ctypes.html

payne
  • 13,833
  • 5
  • 42
  • 49
  • I get: ERROR: 126 - The specified module could not be found. – PSS Jan 29 '11 at 07:39
  • if I use msvcrt.dll instead of msvcr100.dll everything works as it supposed to...I am confused. Both dlls are in system32 folder. – PSS Jan 29 '11 at 16:04
0

Try calling:

msvcr100 = cdll.msvcr100

before calling:

function_address = debug.resolve_function("msvcr100", "printf")

to make sure the DLL is loaded in your process. msvcrt might work because it was already loaded.

Mark Tolonen
  • 166,664
  • 26
  • 169
  • 251
  • debug.resolve_function() is in the module that hooks up to process that loads msvcr100 and uses printf() out of it. I know it works because I can see it print stuff out. – PSS Jan 29 '11 at 16:06