Activator/10.2.3/Activator/WinUtils.pas
2018-09-23 00:11:41 +08:00

384 lines
13 KiB
ObjectPascal
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{ *********************************************************************** }
{ }
{ Win 辅助函数单元 }
{ }
{ 设计Lsuper 2013.04.26 }
{ 备注: }
{ 审核: }
{ }
{ Copyright (c) 1998-2014 Super Studio }
{ }
{ *********************************************************************** }
unit WinUtils;
{$WARNINGS OFF}
interface
uses
SysUtils, Windows;
function GetCommandLineOutput(const ACommandLine, AWorkDir: string;
out ExitCode: LongWord): string;
function GetFileBuildVersion(const AFile: string): Integer;
function GetShellFolderPath(nFolder: Integer): string;
function GetWindowsPath: string;
function TaskMessageBox(const AHandle: THandle; const AText, ACaption: string;
const Icon, Buttons: Integer): Integer;
function IsWindowsVista: Boolean;
procedure Delay(ASeconds: Double);
function CreateProcessEx(lpApplicationName: PChar; lpCommandLine: PChar;
lpProcessAttributes, lpThreadAttributes: PSecurityAttributes;
bInheritHandles: BOOL; dwCreationFlags: DWORD; lpEnvironment: Pointer;
lpCurrentDirectory: PChar; const lpStartupInfo: TStartupInfo;
var lpProcessInformation: TProcessInformation; const ALibraryName: AnsiString): Boolean;
function InjectLibraryModule(AProcessID: LongWord; const ALibraryName: AnsiString): Boolean;
procedure LogMessage(const AMessage: string);
procedure ShowMessage(const ACaption, AMessage: string);
procedure ShowError(const AMessage: string);
procedure SetMainFormHandle(const AHandle: HWND);
implementation
uses
ShlObj;
const
TD_BUTTON_OK = 01;
TD_BUTTON_YES = 02;
TD_BUTTON_NO = 04;
TD_BUTTON_CANCEL = 08;
TD_BUTTON_RETRY = 16;
TD_BUTTON_CLOSE = 32;
TD_ICON_BLANK = 00;
TD_ICON_WARNING = 84;
TD_ICON_QUESTION = 99;
TD_ICON_ERROR = 98;
TD_ICON_INFORMATION = 81;
TD_ICON_SHIELD_QUESTION = 104;
TD_ICON_SHIELD_ERROR = 105;
TD_ICON_SHIELD_OK = 106;
TD_ICON_SHIELD_WARNING = 107;
var
MainFormHandle: HWND = 0;
////////////////////////////////////////////////////////////////////////////////
// 说明用于延迟n秒
// 参数ASeconds -- 延迟秒数
////////////////////////////////////////////////////////////////////////////////
procedure Delay(ASeconds: Double);
////////////////////////////////////////////////////////////////////////////////
//设计: Lsuper 2004.11.10
//功能: 调用消息循环,防止僵死
//参数:
////////////////////////////////////////////////////////////////////////////////
procedure ProcessMessages;
const
WM_QUIT = $0012;
var
Msg: TMsg;
begin
while PeekMessage(Msg, 0, 0, 0, PM_REMOVE) do
begin
if Msg.Message = WM_QUIT then
Halt(Msg.wParam);
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
end;
var
nTimeOut: TDateTime;
nHours, nMins, nSeconds, nMilliSecs: Integer;
begin
nSeconds := Trunc(ASeconds);
nMilliSecs := Round(Frac(ASeconds) * 1000);
nHours := nSeconds div 3600;
nMins := (nSeconds mod 3600) div 60;
nSeconds := nSeconds mod 60;
nTimeOut := Now + EncodeTime(nHours, nMins, nSeconds, nMilliSecs);
// wait until the TimeOut time
while Now < nTimeOut do
ProcessMessages;
end;
////////////////////////////////////////////////////////////////////////////////
//设计: Lsuper 2003.09.21
//功能: 取得运行命令行的输出
//参数:
////////////////////////////////////////////////////////////////////////////////
function GetCommandLineOutput(const ACommandLine, AWorkDir: string;
out ExitCode: LongWord): string;
var
strCommandLine,
strWorkDir: string;
strOutLine,
strBuffer: AnsiString;
bRunResult: Boolean;
nBytesRead: Cardinal;
nStdOutPipeRead,
nStdOutPipeWrite: THandle;
PI: TProcessInformation;
SA: TSecurityAttributes;
SI: TStartupInfo;
begin
with SA do
begin
nLength := SizeOf(SA);
bInheritHandle := True;
lpSecurityDescriptor := nil;
end;
if not CreatePipe(nStdOutPipeRead, nStdOutPipeWrite, @SA, 0) then
RaiseLastOSError;
try
with SI do
begin
FillChar(SI, SizeOf(SI), 0);
cb := SizeOf(SI);
dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
wShowWindow := SW_HIDE;
hStdInput := GetStdHandle(STD_INPUT_HANDLE);
hStdOutput := nStdOutPipeWrite;
hStdError := nStdOutPipeWrite;
end;
if DirectoryExists(AWorkDir) then
strWorkDir := AWorkDir
else strWorkDir := GetCurrentDir;
strCommandLine := ACommandLine;
UniqueString(strCommandLine);
bRunResult := CreateProcess(nil, PChar(strCommandLine), nil, nil, True, 0, nil,
PChar(strWorkDir), SI, PI);
CloseHandle(nStdOutPipeWrite);
if bRunResult then
try
strOutLine := '';
SetLength(strBuffer, MAXBYTE);
repeat
nBytesRead := 0;
bRunResult := ReadFile(nStdOutPipeRead, PAnsiChar(strBuffer)^, Length(strBuffer), nBytesRead, nil);
if nBytesRead > 0 then
strOutLine := strOutLine + Copy(strBuffer, 1, nBytesRead);
until not bRunResult or (nBytesRead = 0);
WaitForSingleObject(PI.hProcess, INFINITE);
GetExitCodeProcess(PI.hProcess, ExitCode);
finally
CloseHandle(PI.hThread);
CloseHandle(PI.hProcess);
end
else RaiseLastOSError;
finally
CloseHandle(nStdOutPipeRead);
Result := string(strOutLine);
end;
end;
function GetFileBuildVersion(const AFile: string): Integer;
var
nInfoSize, dwHandle: DWORD;
cFileInfo: PVSFixedFileInfo;
nVerSize: DWORD;
strBuffer: AnsiString;
begin
Result := 0;
nInfoSize := GetFileVersionInfoSize(PChar(AFile), dwHandle);
if nInfoSize = 0 then
Exit;
SetLength(strBuffer, nInfoSize);
if not GetFileVersionInfo(PChar(AFile), dwHandle, nInfoSize, Pointer(strBuffer)) then
Exit;
if VerQueryValue(Pointer(strBuffer), '\', Pointer(cFileInfo), nVerSize) then
Result := LOWORD(cFileInfo.dwFileVersionLS);
end;
////////////////////////////////////////////////////////////////////////////////
//设计Lsuper 2010.04.09
//功能:获取 Shell 文件夹位置,如 GetSpecialFolderPath(CSIDL_COMMON_APPDATA) 等
//参数:
////////////////////////////////////////////////////////////////////////////////
function GetShellFolderPath(nFolder: Integer): string;
begin
SetLength(Result, MAX_PATH);
SHGetSpecialFolderPath(0, PChar(Result), nFolder, False);
SetLength(Result, StrLen(PChar(Result)));
if (Result <> '') and (Result[Length(Result)] <> '\') then
Result := Result + '\';
end;
function GetWindowsPath: string;
var
nRet: LongWord;
begin
SetLength(Result, MAX_PATH);
nRet := GetWindowsDirectory(PChar(Result), MAX_PATH);
if nRet = 0 then
Result := ''
else begin
SetLength(Result, nRet);
if (Result <> '') and (Result[Length(Result)] <> '\') then
Result := Result + '\';
end;
end;
////////////////////////////////////////////////////////////////////////////////
//设计Lsuper 2013.05.01
//功能:创建注入进程
//参数:
//注意:加入 500ms 等待时间,确保 dll 加载成功后执行
////////////////////////////////////////////////////////////////////////////////
function CreateProcessEx(lpApplicationName: PChar; lpCommandLine: PChar;
lpProcessAttributes, lpThreadAttributes: PSecurityAttributes;
bInheritHandles: BOOL; dwCreationFlags: DWORD; lpEnvironment: Pointer;
lpCurrentDirectory: PChar; const lpStartupInfo: TStartupInfo;
var lpProcessInformation: TProcessInformation; const ALibraryName: AnsiString): Boolean;
begin
Result := False;
if not CreateProcess(lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags or CREATE_SUSPENDED, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation) then
Exit;
Result := InjectLibraryModule(lpProcessInformation.hProcess, ALibraryName);
{
Result := uallHook.InjectLibrary(lpProcessInformation.dwProcessId, PChar(ALibraryName));
}
Sleep(500);
ResumeThread(lpProcessInformation.hThread);
end;
////////////////////////////////////////////////////////////////////////////////
//设计Lsuper 2013.05.01
//功能:注入 DLL
//参数:
////////////////////////////////////////////////////////////////////////////////
function InjectLibraryModule(AProcessID: LongWord; const ALibraryName: AnsiString): Boolean;
var
dwProcessID2: DWord;
dwMemSize: DWord;
dwWritten: DWord;
dwThreadID: DWord;
pLLA: Pointer;
pTargetMemory: Pointer;
begin
Assert(ALibraryName <> '');
Result := False;
dwProcessID2 := OpenProcess(PROCESS_ALL_ACCESS, False, AProcessID);
if (dwProcessID2 <> 0) then
AProcessID := dwProcessID2;
dwMemSize := Length(ALibraryName) + 1;
pTargetMemory := VirtualAllocEx(AProcessID, nil, dwMemSize, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE);
pLLA := GetProcAddress(GetModuleHandleA('kernel32.dll'), 'LoadLibraryA');
if (pLLA <> nil) and (pTargetMemory <> nil) then
begin
if WriteProcessMemory(AProcessID, pTargetMemory, PChar(ALibraryName), dwMemSize, dwWritten) and (dwWritten = dwMemSize) then
Result := CreateRemoteThread(AProcessID, nil, 0, pLLA, pTargetMemory, 0, dwThreadID) <> 0;
end;
if (dwProcessID2 <> 0) then
CloseHandle(dwProcessID2);
end;
////////////////////////////////////////////////////////////////////////////////
//设计Lsuper 2009.10.25
//功能:判断是否 Vista/7
//参数:
////////////////////////////////////////////////////////////////////////////////
function IsWindowsVista: Boolean;
var
hKernel32: HMODULE;
begin
hKernel32 := GetModuleHandle('kernel32');
if hKernel32 > 0 then
Result := GetProcAddress(hKernel32, 'GetLocaleInfoEx') <> nil
else Result := false;
end;
procedure LogMessage(const AMessage: string);
begin
OutputDebugString(PChar(AMessage));
end;
procedure SetMainFormHandle(const AHandle: HWND);
begin
MainFormHandle := AHandle;
end;
procedure ShowError(const AMessage: string);
begin
TaskMessageBox(MainFormHandle, AMessage, 'Error', TD_ICON_ERROR, TD_BUTTON_OK);
end;
procedure ShowMessage(const ACaption, AMessage: string);
begin
TaskMessageBox(MainFormHandle, AMessage, ACaption, TD_ICON_INFORMATION, TD_BUTTON_OK);
end;
////////////////////////////////////////////////////////////////////////////////
//设计Lsuper 2009.10.25
//功能: 内部使用的用于显示对话框的函数,适应 Vista/7 系统风格
//参数:
//注意:参考 Application 的 MessageBox 和 Dialogs 的 代码,忽略多显示器判断代码
// http://www.tmssoftware.com/site/atbdev5.asp
////////////////////////////////////////////////////////////////////////////////
function TaskMessageBox(const AHandle: THandle; const AText, ACaption: string;
const Icon, Buttons: Integer): Integer;
const
conTaskDialogProcName = 'TaskDialog';
var
DLLHandle: THandle;
wTitle, wContent: array[0..1024] of widechar;
TaskDialogProc: function(HWND: THandle; hInstance: THandle; cTitle,
cDescription, cContent: PWideChar; Buttons: Integer; Icon: Integer;
ResButton: PInteger): Integer; cdecl stdcall;
Flags: Integer;
begin
Result := 0;
if IsWindowsVista then
begin
DLLHandle := LoadLibrary(comctl32);
@TaskDialogProc := GetProcAddress(DLLHandle, conTaskDialogProcName);
end
else TaskDialogProc := nil;
if Assigned(TaskDialogProc) then
begin
StringToWideChar(ACaption, wTitle, SizeOf(wTitle));
StringToWideChar(AText, wContent, SizeOf(wContent));
TaskDialogProc(AHandle, 0, wTitle, nil, wContent, Buttons, Icon, @Result);
end
else begin
Flags := 0;
if Buttons = TD_BUTTON_OK then
Flags := MB_OK;
if Buttons = TD_BUTTON_OK or TD_BUTTON_CANCEL then
Flags := MB_OKCANCEL;
if Buttons = TD_BUTTON_CLOSE or TD_BUTTON_RETRY or TD_BUTTON_CANCEL then
Flags := MB_ABORTRETRYIGNORE;
if Buttons = TD_BUTTON_YES or TD_BUTTON_NO or TD_BUTTON_CANCEL then
Flags := MB_YESNOCANCEL;
if Buttons = TD_BUTTON_YES or TD_BUTTON_NO then
Flags := MB_YESNO;
if Buttons = TD_BUTTON_RETRY or TD_BUTTON_CANCEL then
Flags := MB_RETRYCANCEL;
case Icon of
TD_ICON_BLANK:
;
TD_ICON_WARNING, TD_ICON_SHIELD_WARNING:
Flags := Flags or MB_ICONWARNING;
TD_ICON_QUESTION, TD_ICON_SHIELD_QUESTION:
Flags := Flags or MB_ICONQUESTION;
TD_ICON_ERROR, TD_ICON_SHIELD_ERROR:
Flags := Flags or MB_ICONERROR;
TD_ICON_INFORMATION, TD_ICON_SHIELD_OK:
Flags := Flags or MB_ICONINFORMATION;
end;
Result := Windows.MessageBox(AHandle, PChar(AText), PChar(ACaption), Flags);
end;
end;
end.