如何在 Delphi 中使用 WriteProcessMemory
How to use WriteProcessMemory in Delphi
我无法编译这段代码。我能帮忙吗?谢谢
procedure ChangeOutsideDateTime(h: HWND; dt: TDateTime);
var
st: TSystemTime;
pst: Pointer;
hDTP: Cardinal;
hProc: THandle;
dwWrote: DWORD;
begin
DateTimeToSystemTime(dt, st);
pst:= VirtualAllocEx(h, nil, SizeOf(st), MEM_COMMIT, 0);
if pst <> nil then begin
if GetWindowThreadProcessId(h, hDTP) > 0 then begin
hProc:= OpenProcess(PROCESS_VM_OPERATION, false, hDTP);
if WriteProcessMemory(hProc, pst, @st, SizeOf(st), dwWrote) > 0 then begin
SendMessage(h, DTM_SETSYSTEMTIME, GDT_VALID, hDTP);
CloseHandle(hProc);
end;
end;
VirtualFreeEx(h, pst, 0, MEM_RELEASE);
end;
end;
它在使用 "WriteProcessMemory" 的行显示 "Types of actual and formal var parameters must be identical"。
Types of actual and formal var parameters must be identical
这是编译器错误 E2003。如果遇到不理解的编译错误,首先要做的是阅读documentation。它说:
For a variable parameter, the actual argument must be of the exact type of the formal parameter.
导致此错误的函数调用是WriteProcessMemory
。让我们看看它的声明:
function WriteProcessMemory(hProcess: THandle; const lpBaseAddress: Pointer;
lpBuffer: Pointer; nSize: SIZE_T; var lpNumberOfBytesWritten: SIZE_T): BOOL; stdcall;
这里只有一个var
参数,最后一个参数。您传递的变量必须是 SIZE_T
类型,但您传递的是 DWORD
类型的变量。那就是不匹配。
其他一些评论:
- 对
VirtualAllocEx
的调用必然会失败,因为您传递的是window 句柄而不是进程句柄。
- 从语义上讲,测试正线程 ID 毫无意义。测试不等于零是否成功。
- 您没有检查
OpenProcess
return 值。那很容易失败。
- 您没有打开具有
PROCESS_VM_WRITE
访问权限的进程,这是 WriteProcessMemory
所必需的。
- 如果对
WriteProcessMemory
的调用失败,您将泄漏句柄。
WriteProcessMemory
的return类型是BOOL
。
hDTP
是一个奇怪的进程 ID 名称。该名称表明您认为它是日期时间选择器控件的句柄。不是。这是进程ID。
- 您在
SendMessage
调用中传递了该进程 ID,而不是您刚刚写入的系统时间地址。
您的代码中有几个错误。
您正在将 HWND
传递给 VirtualAllocEx()
,但它期望将 THandle
传递给打开的进程。在打开进程句柄之前,您正在调用 VirtualAllocEx()
。而且您没有请求对分配的内存的写入权限。
调用 OpenProcess()
时,您没有请求 PROCESS_VM_WRITE
许可,而 WriteProcessMemory()
需要。
您对 WriteProcessMemory()
的使用与其声明不符。这就是您收到编译器错误的原因。
您将 HWND
的进程 ID 作为 DTM_SETSYSTEMTIME
的 LPARAM
传递,但它需要分配的 TSystemTime
指针。
试试这样的东西:
procedure ChangeOutsideDateTime(h: HWND; dt: TDateTime);
var
st: TSystemTime;
PID: DWORD;
hProc: THandle;
pst: Pointer;
NumWrote: SIZE_T;
begin
GetWindowThreadProcessId(h, PID);
hProc := OpenProcess(PROCESS_VM_OPERATION or PROCESS_VM_WRITE, false, PID);
if hProc <> 0 then
try
pst := VirtualAllocEx(hProc, nil, SizeOf(st), MEM_COMMIT, PAGE_READWRITE);
if pst <> nil then
try
DateTimeToSystemTime(dt, st);
if WriteProcessMemory(hProc, pst, @st, SizeOf(st), NumWrote) then begin
SendMessage(h, DTM_SETSYSTEMTIME, GDT_VALID, LPARAM(pst));
end;
finally
VirtualFreeEx(hProc, pst, 0, MEM_RELEASE);
end;
finally
CloseHandle(hProc);
end;
end;
我无法编译这段代码。我能帮忙吗?谢谢
procedure ChangeOutsideDateTime(h: HWND; dt: TDateTime);
var
st: TSystemTime;
pst: Pointer;
hDTP: Cardinal;
hProc: THandle;
dwWrote: DWORD;
begin
DateTimeToSystemTime(dt, st);
pst:= VirtualAllocEx(h, nil, SizeOf(st), MEM_COMMIT, 0);
if pst <> nil then begin
if GetWindowThreadProcessId(h, hDTP) > 0 then begin
hProc:= OpenProcess(PROCESS_VM_OPERATION, false, hDTP);
if WriteProcessMemory(hProc, pst, @st, SizeOf(st), dwWrote) > 0 then begin
SendMessage(h, DTM_SETSYSTEMTIME, GDT_VALID, hDTP);
CloseHandle(hProc);
end;
end;
VirtualFreeEx(h, pst, 0, MEM_RELEASE);
end;
end;
它在使用 "WriteProcessMemory" 的行显示 "Types of actual and formal var parameters must be identical"。
Types of actual and formal var parameters must be identical
这是编译器错误 E2003。如果遇到不理解的编译错误,首先要做的是阅读documentation。它说:
For a variable parameter, the actual argument must be of the exact type of the formal parameter.
导致此错误的函数调用是WriteProcessMemory
。让我们看看它的声明:
function WriteProcessMemory(hProcess: THandle; const lpBaseAddress: Pointer;
lpBuffer: Pointer; nSize: SIZE_T; var lpNumberOfBytesWritten: SIZE_T): BOOL; stdcall;
这里只有一个var
参数,最后一个参数。您传递的变量必须是 SIZE_T
类型,但您传递的是 DWORD
类型的变量。那就是不匹配。
其他一些评论:
- 对
VirtualAllocEx
的调用必然会失败,因为您传递的是window 句柄而不是进程句柄。 - 从语义上讲,测试正线程 ID 毫无意义。测试不等于零是否成功。
- 您没有检查
OpenProcess
return 值。那很容易失败。 - 您没有打开具有
PROCESS_VM_WRITE
访问权限的进程,这是WriteProcessMemory
所必需的。 - 如果对
WriteProcessMemory
的调用失败,您将泄漏句柄。 WriteProcessMemory
的return类型是BOOL
。hDTP
是一个奇怪的进程 ID 名称。该名称表明您认为它是日期时间选择器控件的句柄。不是。这是进程ID。- 您在
SendMessage
调用中传递了该进程 ID,而不是您刚刚写入的系统时间地址。
您的代码中有几个错误。
您正在将
HWND
传递给VirtualAllocEx()
,但它期望将THandle
传递给打开的进程。在打开进程句柄之前,您正在调用VirtualAllocEx()
。而且您没有请求对分配的内存的写入权限。调用
OpenProcess()
时,您没有请求PROCESS_VM_WRITE
许可,而WriteProcessMemory()
需要。您对
WriteProcessMemory()
的使用与其声明不符。这就是您收到编译器错误的原因。您将
HWND
的进程 ID 作为DTM_SETSYSTEMTIME
的LPARAM
传递,但它需要分配的TSystemTime
指针。
试试这样的东西:
procedure ChangeOutsideDateTime(h: HWND; dt: TDateTime);
var
st: TSystemTime;
PID: DWORD;
hProc: THandle;
pst: Pointer;
NumWrote: SIZE_T;
begin
GetWindowThreadProcessId(h, PID);
hProc := OpenProcess(PROCESS_VM_OPERATION or PROCESS_VM_WRITE, false, PID);
if hProc <> 0 then
try
pst := VirtualAllocEx(hProc, nil, SizeOf(st), MEM_COMMIT, PAGE_READWRITE);
if pst <> nil then
try
DateTimeToSystemTime(dt, st);
if WriteProcessMemory(hProc, pst, @st, SizeOf(st), NumWrote) then begin
SendMessage(h, DTM_SETSYSTEMTIME, GDT_VALID, LPARAM(pst));
end;
finally
VirtualFreeEx(hProc, pst, 0, MEM_RELEASE);
end;
finally
CloseHandle(hProc);
end;
end;