Search code examples
c#windows-messages

Update dateTimePicker in another process by DTM_SETSYSTEMTIME


I am trying to update the dateTimeController in another application using DTM_SETSYSTEMTIME.

bool retVal = false;
ushort GDT_VALID = 0;

SYSTEMTIME td = new SYSTEMTIME();
td.wYear = 1990;
td.wMonth = 4;
td.wDay = 2;
td.wDayOfWeek = 0;
td.wHour = 0;
td.wMilliseconds = 0;
td.wMinute = 0;
td.wSecond = 0;

int erc = SendMessage(handle, DTM_SETSYSTEMTIME, GDT_VALID, ref td);

Unfortunately the attempt was failed, the picker is not updated, every time return value is zero. Important thing is occasionally the application having the dataTimePicker gives an error message that illegal memory access exception after I execute the SendMessage command.

Can anybody help me to fix this up ?


Solution

  • Your information is really helpful for me to fix my issue. Following is the code.

    private static bool injectMemory(IntPtr windowHandle, byte[] buffer, out IntPtr hndProc, out IntPtr lpAddress)
        {
            hndProc = IntPtr.Zero;
            lpAddress = IntPtr.Zero;
            //open local process object
            Process mainWindowProcess = FindProcess(windowHandle);
            hndProc = OpenProcess(
                (0x2 | 0x8 | 0x10 | 0x20 | 0x400), //create thread, query info, operation 
                //write, and read 
                1,
                (uint)mainWindowProcess.Id);
            if (hndProc == (IntPtr)0)
            {
                Console.WriteLine("Unable to attach process");
                return false;
            }
            //allocate memory for process object
            lpAddress = VirtualAllocEx(hndProc, (IntPtr)null, (uint)buffer.Length,
                 AllocationType.Commit | AllocationType.Reserve, MemoryProtection.ExecuteReadWrite);
            if (lpAddress == (IntPtr)0)
            {
                Console.WriteLine("Unable to allocate memory to target proces");
                return false;
            }
            //wite data
            uint wrotelen = 0;
            WriteProcessMemory(hndProc, lpAddress, buffer, (uint)buffer.Length, out wrotelen);
            if (Marshal.GetLastWin32Error() != 0)
            {
                Console.WriteLine("Unable to write memory to process.");
                return false;
            }
            return true;
        }
    

    Method is called by,

            int structMemLen =  Marshal.SizeOf(typeof(SYSTEMTIME));
            byte[] buffer = new byte[structMemLen];
            ushort GDT_VALID = 0;
            SYSTEMTIME sysTime = new SYSTEMTIME();
            //Assign the values as you prefer
    
            IntPtr dataPtr = Marshal.AllocHGlobal(structMemLen);
            Marshal.StructureToPtr(sysTime, dataPtr, true);
            Marshal.Copy(dataPtr, buffer, 0, structMemLen);
            Marshal.FreeHGlobal(dataPtr);
    
            IntPtr hndProc = IntPtr.Zero;
            IntPtr lpAddress = IntPtr.Zero;
            injectMemory(mainWindowHandle, buffer, out hndProc, out lpAddress); 
            SendMessage(handle, DTM_SETSYSTEMTIME, (IntPtr)GDT_VALID, lpAddress);
            CloseHandle(hndProc);