Passing Structure to Windows API in python ctypes
Question: I'm trying to set the date in a SysDateTimeObject in an application on Windows
7. I'm using python 2.7 and the ctypes library with the following code which
tries to send a DTM_SETSYSTEMTIME message to the SysDateTimeObject:

    
    
    from ctypes import *
    from ctypes.wintypes import BOOL,HWND,RECT,LPCSTR,UINT,INT,DWORD,WORD
    import sys
    import time
    
    class SYSTEMTIME(Structure):
        _fields_=[('wYear',WORD),
                  ('wMonth',WORD),
                  ('wDayOfWeek',WORD),
                  ('wDay',WORD),
                  ('wHour',WORD),
                  ('wMinute',WORD),
                  ('wSecond',WORD),
                  ('wMilliseconds',WORD)]
    
    self.user32 = windll.user32
    my_time=SYSTEMTIME(2035,0,0,0,0,0,0,0)
    self.user32.SendMessageW(window,c_uint(0x1002),0,byref(my_time))
    

window is a HWND to the correct SysDateTimeObject and 0x1002 is the code for
the DTM_SETSYSTEMTIME message. The third parameter of SendMessageW is a
constant to enable or disable the DateTimeControl. I can set it to 1 and it
will disable the control, as expected. The fourth parameter is a pointer to a
filled in SYSTEMTIME structure. However, it seems to do nothing as written
above. I am able to send other messages but when a function requires a pointer
to a structure, things start failing. Am I using ctypes wrong here?


Answer: I was using [pywinauto](http://pypi.python.org/pypi/pywinauto) and ran into
this need and managed to solve it. The cause of the trouble is that you're
trying to run it in a different process, while your `SYSTEMTIME` structure is
in your own process's private memory space. Thus, whenever it tries to do
anything with the passed structure, it fails—access denied. You need a remote
memory block to resolve the problem.

`pywinauto.controls.common_controls._RemoteMemoryBlock` does exactly this.

The eventual effect is that you will have code like this:

    
    
    remote_mem = common_controls._RemoteMemoryBlock(window)
    remote_mem.Write(my_time)
    
    user32.SendMessageW(window, win32defines.DTM_SETSYSTEMTIME,
            win32defines.GDT_VALID, remote_mem)
    

If you need to use DTM_GETSYSTEMTIME, you would then put `my_time =
remote_mem.Read(my_time)` after the SendMessage call.

