重新启动Windows,不是重新启动机器!包含Thunk技术。
感谢http://www.experts-exchange.com/Q.10115419, 以下代码RestartWindows可以实现:
{$StackFrames On} //QT_Thunk needs a stack frame, Thunking call to 16-bit USER.EXE. The ThunkTrash argument allocates space on the stack for QT_Thunk
function LoadLibrary16(LibraryName: PChar): THandle; stdcall; external kernel32 index 35;
procedure FreeLibrary16(HInstance: THandle); stdcall; external kernel32 index 36;
function GetProcAddress16(Hinstance: THandle; ProcName: PChar): Pointer; stdcall; external kernel32 index 37;
procedure QT_Thunk; cdecl; external kernel32 name 'QT_Thunk';
var
hInst16: THandle;
GFSR: Pointer;
function RestartWindows: WordBool;
var
ThunkTrash: array[0..$20] of Word;
dw: DWord;
w: Word;
begin
if Win32Platform = VER_PLATFORM_WIN32_NT then
begin
Result := False;
Exit;
end;
ThunkTrash[0] := hInst16; //Prevent the optimizer from getting rid of ThunkTrash
hInst16 := LoadLibrary16('user.exe');
if hInst16 < 32 then
raise Exception.Create('Cannot load USER.EXE');
FreeLibrary16(hInst16); //Decrement the usage count. This doesn't really free the library, since USER.EXE is always loaded
GFSR := GetProcAddress16(hInst16, 'ExitWindows'); //Get the function pointer for the 16-bit function in USER.EXE
if GFSR = nil then
raise Exception.Create('Cannot get address of ExitWindows');
dw := EW_RestartWindows;
w := 0;
asm //Thunk down to USER.EXE
push dw { push arguments }
push w
mov edx, GFSR { load 16-bit procedure pointer }
call QT_Thunk { call thunk }
mov Result, ax { save the result }
end;
end;
{$StackFrames Off}