3

I've been trying to create a function that will write a minidump file for a given process ID. So far I have this:

import win32con, win32api, win32file, ctypes
dbghelp = ctypes.windll.dbghelp 

def createMiniDump(pid, file_name):
    # Adjust privileges.
    adjustPrivilege(win32security.SE_DEBUG_NAME)
    pHandle = win32api.OpenProcess(
                win32con.PROCESS_QUERY_INFORMATION | win32con.PROCESS_VM_READ ,
                0, pid)
    print 'pHandle Status: ', win32api.FormatMessage(win32api.GetLastError())
    fHandle = win32file.CreateFile(file_name,
                               win32file.GENERIC_READ | win32file.GENERIC_WRITE,
                               win32file.FILE_SHARE_READ | win32file.FILE_SHARE_WRITE,
                               None,
                               win32file.CREATE_ALWAYS,
                               win32file.FILE_ATTRIBUTE_NORMAL,
                               None)

    print 'fHandle Status: ', win32api.FormatMessage(win32api.GetLastError())
    success = dbghelp.MiniDumpWriteDump(pHandle.handle,   # Process handle
                                     pid,                 # Process ID
                                     fHandle.handle,      # File handle
                                     0,         # Dump type - MiniDumpNormal
                                     None,      # Exception parameter
                                     None,      # User stream parameter
                                     None,      # Callback parameter
                                     )
    print 'MiniDump Status: ', win32api.FormatMessage(win32api.GetLastError())
    return success

The process and file handles are created successfully. However, the call to MiniDumpWriteDump sets the following error: Only part of a ReadProcessMemory or WriteProcessMemory request was completed.

Does anyone have any ideas of why this is happening?

Luiz C.
  • 746
  • 11
  • 22
  • What is the value of `dump_type`? I assume this is set externally to the function? – icabod Dec 12 '11 at 13:19
  • The value of dump_type is 0 (MiniDumpNormal). Sorry, bad copy and paste on my part. Fixed this in the question. – Luiz C. Dec 12 '11 at 15:21
  • I have in the past successfully created a dump file from processes that have not raised an exception by using different tools. – Luiz C. Jan 10 '12 at 23:29

2 Answers2

3

The only issues I've ever encountered would be is cross architecture dumps ie dumping a 32 bit processes when your local process is a 64 bit process or vice versa. If you look around the net you can find plenty of references to the standard recomendation is to take a 32 bit dump from a 32 bit process and a 64 from a 64. see Do not collect 32bit process' dumps with 64 bit task manager and Capturing memory dumps for 32-bit processes on an x64 machine I don't know why, but I'd like to. (even though technically on x64 windows they all are 64 bit processes, the 32 bit ones are just lying to themselves.. with an extra thread stack and TEB and PEB.

The exception pointers and current Thread id are only relevant when you are dumping from within the process. If you read the MSDN entry completely it suggests creating a helper thread and excluding it from the dump to get the current thread stack meaningfully which obviously only has meaning if you are dumping the current process. Also dumping an external process which is very helpful sometimes in diagnosing hanging processes wouldn't have PEXCEPTION_POINTER information. Also I have done plenty of minidumps of external processes without PEXCEPTION_POINTER being set, or callback, but callback is very useful.

Dan
  • 1,981
  • 1
  • 14
  • 18
  • The code worked all along! As soon as the architecture of the calling process matched the target process, it started working. Thanks for answer! – Luiz C. Jan 12 '12 at 19:45
0

You're missing a prepared MINIDUMP_EXCEPTION_INFORMATION structure as the 5th parameter to MiniDumpWriteDump(). It's necessary for a successful dump.

Set its ThreadId field to GetCurrentThreadId(). Set its ClientPointers field to FALSE. The real trick here is the ExceptionPointers field. The only way I know of getting a PEXCEPTION_POINTERS is via a callback assigned through AddVectoredExceptionHandler(). The callback gets passed a single PEXCEPTION_POINTERS parameter. So, you'll need to move all your dump code into that callback to have access to a PEXCEPTION_POINTERS at the time of the dump. Unfortunately, this also means that you're at the mercy of an unhandled exception triggering the dump (unless you can find another way to get a PEXCEPTION_POINTERS).

kipkennedy
  • 372
  • 1
  • 6
  • This makes sense. However, shouldn't ClientPointers be set to True since the dump being collected is in a different process space than the calling process? Also, I don't really care about creating a dump when an exception happens. My idea was to create the dump file on demand, even if there are no exceptions on the target process. – Luiz C. Jan 06 '12 at 20:53
  • Sorry, I don't think it's possible to generate a complete minidump without triggering an exception. See 3rd paragraph of remarks about [MiniDumpWriteDump](http://msdn.microsoft.com/en-us/library/windows/desktop/ms680360(v=vs.85).aspx). – kipkennedy Jan 10 '12 at 00:01
  • I have in the past successfully created a dump file from processes that have not raised an exception by using different tools. – Luiz C. Jan 10 '12 at 23:30
  • So? The original question is why does `MiniDumpWriteDump()` give a partial dump error. It's because `MINIDUMP_EXCEPTION_INFORMATION` is missing. Maybe the intended question was "How can a complete minidump be created from python?" but that's not what was asked. – kipkennedy Jan 11 '12 at 18:25
  • The error is that a partial dump was created. However the file is empty. – Luiz C. Jan 11 '12 at 18:33