最近遇到一个逆向类课题,是关于GOM20151108版本对应登录器研究。刚接触传奇的时候是2002年,那时候网吧玩SF,都是手动用IP直接连接,当时的一款 联创传奇 很好玩,有传送戒子,木域戒指,土域戒指,麻痹戒子,护手戒子,法师的圣言术可以直接把2000厚血的教主直接秒掉,星星战甲这个衣服更是拉风,穿上直接是一个双头精钢。

现在市场上主流微端模式的技术架构,到处都易语言写的登录器生成器,各种各样的版本。不过对于其中的技术,大部分都是一样的,只是有的插入了自己写的DLL。Delphi程式内存数据结构也比较特殊,这款GOM引擎客户端其实很小,只有3.5M左右。在注册账号、修改密码的功能上目前已经实现,接下来是是做客户端文件的启动,即 Clent.dat这个文件的启动,这个文件很多人被忽视,其实这个文件才是GOM引擎的核心精髓,所谓的引擎也主要是指这个文件,这个文件里面包含了游戏的所有逻辑代码。但是要调用起这个文件可没有那么容易,难点也是在这里。这个文件很多商业登录器生成器上直接隐藏的,被嵌入了登录器里面,dat文件其实也是和EXE结构一样的PE文件,即他们的做法是易语言写的EXE登录器和Delphi写的GOM20151108版本的Client.dat文件合并在一起,玩家点击登录器的时候就显示出登录器,玩家点击登录器界面上的启动游戏按钮后登录器是会创建一个和登录器本身一样的进程,不过这个进程启动界面是游戏画面的客户端程序,即Client.dat在内存中被创建,里面用到了PELoad的技术(也可以说是傀儡进程技术、僵尸进程技术,只是这次这种技术没有将系统进程作为宿主而已,而是将登录器作为了宿主启动了Client.dat)。此刻我们看到任务管理器上有两个登录器进程,其中一个其实不是登录器而是 Client.dat。小小一个登录器原来这么复杂,真是够隐蔽的,技术上其实已经超越了官方的登录器了。

对于GOM的背景历史暂时不知道,只知道这款引擎非常的出色。但是在2015年11月8日被停止了更新,GOM官方解散了。网上有早期版本的源代码,都是delphi语言写的。但是网上应该没有人拿到2015年11月8日停更版本的源代码。只能靠逆向技术来给这款引擎加上额外的功能和优化了。

这客户端可不是随随便便都可以调用的,各种校验。经过研究后掉线问题解决了。如下

unit Main;interfaceusesWindows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs, jpeg, ExtCtrls, RzBmpBtn, StdCtrls, RzLstBox, RzButton, RzRadChk,OleCtrls, SHDocVw, ComCtrls, ShlObj, ComObj, ActiveX, Grobal2, JSocket,Registry, winsock, WinInet, ShellApi, IniFiles, GameShare, IdBaseComponent,IdComponent, IdTCPConnection, IdTCPClient, IdHTTP, {ZLib,} tlHelp32, RzForms;typeTSearchThread = class(TThread)protectedprocedure Execute; override;publicconstructor Create(CreateSuspended: Boolean);destructor Destroy; override;end;TfrmMain = class(TForm)RzBmpButtonHomePage: TRzBmpButton;RzBmpButtonEditGameList: TRzBmpButton;RzBmpButtonNewAccount: TRzBmpButton;RzBmpButtonGetBakPassWord: TRzBmpButton;RzBmpButtonChgPassWord: TRzBmpButton;RzBmpButtonAutoLogin: TRzBmpButton;RzBmpButtonFullScreenStart: TRzBmpButton;RzBmpButtonClose: TRzBmpButton;Timer: TTimer;ClientSocket: TClientSocket;TimerStart: TTimer;CloseTimer: TTimer;RzBmpButtonMin: TRzBmpButton;TreeView: TTreeView;RzBmpButtonStart: TRzBmpButton;RzBmpButtonExitGame: TRzBmpButton;RzBmpButtonUpgrade: TRzBmpButton;Image: TRzFormShape;LabelStatus: TLabel;TimerReakSkin: TTimer;ComboBox: TComboBox;procedure TimerTimer(Sender: TObject);procedure ClientSocketConnect(Sender: TObject;Socket: TCustomWinSocket);procedure ClientSocketConnecting(Sender: TObject;Socket: TCustomWinSocket);procedure ClientSocketDisconnect(Sender: TObject;Socket: TCustomWinSocket);procedure ClientSocketError(Sender: TObject; Socket: TCustomWinSocket;ErrorEvent: TErrorEvent; var ErrorCode: Integer);procedure ClientSocketRead(Sender: TObject; Socket: TCustomWinSocket);procedure FormCreate(Sender: TObject);procedure RzBmpButtonCloseClick(Sender: TObject);procedure RzBmpButtonHomePageClick(Sender: TObject);procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);procedure RzBmpButtonFullScreenStartClick(Sender: TObject);procedure RzBmpButtonEditGameListClick(Sender: TObject);procedure TimerStartTimer(Sender: TObject);procedure RzBmpButtonNewAccountClick(Sender: TObject);procedure RzBmpButtonGetBakPassWordClick(Sender: TObject);procedure RzBmpButtonChgPassWordClick(Sender: TObject);procedure RzBmpButtonAutoLoginClick(Sender: TObject);procedure CloseTimerTimer(Sender: TObject);procedure ImageMouseDown(Sender: TObject; Button: TMouseButton;Shift: TShiftState; X, Y: Integer);procedure RzBmpButtonMinClick(Sender: TObject);procedure TreeViewClick(Sender: TObject);procedure TimerReakSkinTimer(Sender: TObject);procedure RzBmpButtonUpgradeClick(Sender: TObject);private{ Private declarations }procedure CreateUlr(sCreateUlrName: string);procedure DecodeMessagePacket(datablock: string);procedure ChgButtonStatus(btStatus: Byte);procedure ReleaseClient(sDirectory: string; GameZone: TGameZone);
//    function RunApp(AppName: string; I: Integer): Integer;procedure OnProgramException(Sender: TObject; E: Exception);function GetProcesses: Boolean;function GetModules(ProcessID: DWORD): Boolean;procedure ReadSkin;function SearchMirClient(Path: string): Boolean;procedure LoadUserConfig;procedure SaveUserConfig;public{ Public declarations }procedure SendGetRandomCode;procedure SendUpdateAccount(ue: TUserEntry; ua: TUserEntryAdd; nRandomCode: Integer);procedure SendGetBackPassword(sAccount, sQuest1, sAnswer1,sQuest2, sAnswer2, sBirthDay: string);procedure SendChgPw(sAccount, sPasswd, sNewPasswd: string);procedure SendCSocket(sendstr: string);procedure LoadListToBox();procedure ProcessMessage(var Msg: TMsg; var Handled: Boolean);procedure MyMessage(var MsgData: TWmCopyData); message WM_COPYDATA;end;varfrmMain: TfrmMain;MirClient: TMemoryStream;WebBrowser: TWebBrowser;
function CheckLegendPath(Path: string): Boolean;
function CheckMirPath(Path: string): Boolean;
function CheckFullPath(Path: string): Boolean;
procedure LoopFiles(Path, Mask: string; SubDir: TStrings);
function GetDrives: string;
function RunApp(AppName: string): Integer;
function SearchPath: Boolean;
implementation
uses EncryptUnit, HUtil32, LNewAccount, LChgPassword, LGetBackPassword {, SecrchInfoMain},LEditGame, LUpgrade, { CMain, NPCDialog, NPCMain,} CheckPrevious, ZLibEx;
constR_MyRootKey = HKEY_LOCAL_MACHINE; //注册表根键R_MySubKey = '\SOFTWARE\cqfir\Legend of mir'; //注册表子键R_SndaSubKey = '\SOFTWARE\snda\Legend of mir';R_Key = 'Path';
{$R *.dfm}procedure TSearchThread.Execute;
varDriverList: string;I, Len: Integer;
beginDriverList := GetDrives; //得到可写的磁盘列表 //遍历每个磁盘驱动器Len := Length(DriverList);for I := 1 to Len do beging_SearchList.Add(DriverList[I] + ':\');end;while (not Terminated) and (not SearchPath) and (not g_boClose) do beginend;
end;constructor TSearchThread.Create(CreateSuspended: Boolean);
begininherited;end;destructor TSearchThread.Destroy;
begininherited;
end;function ReadRegKey(const iMode: Integer; const sPath,sKeyName: string; var sResult: string): Boolean;
varrRegObject: TRegistry;
beginrRegObject := TRegistry.Create;Result := False;trywith rRegObject do beginRootKey := R_MyRootKey;if OpenKey(sPath, True) then begincase iMode of1: sResult := Trim(ReadString(sKeyName));2: sResult := IntToStr(ReadInteger(sKeyName));//3: sResult := ReadBinaryData(sKeyName, Buffer, BufSize);end;if sResult = '' then Result := False else Result := True;endelseResult := False;CloseKey;end;finallyrRegObject.Free;end;
end;
//_____________________________________________________________________//function WriteRegKey(const iMode: Integer; const sPath, sKeyName,sKeyValue: string): Boolean;
varrRegObject: TRegistry;bData: Byte;
beginrRegObject := TRegistry.Create;trywith rRegObject do beginRootKey := R_MyRootKey;if OpenKey(sPath, True) then begincase iMode of1: WriteString(sKeyName, sKeyValue);2: WriteInteger(sKeyName, StrToInt(sKeyValue));3: WriteBinaryData(sKeyName, bData, 1);end;Result := True;endelseResult := False;CloseKey;end;finallyrRegObject.Free;end;
end;
//_____________________________________________________________________//function SelectDirCB(Wnd: Hwnd; uMsg: UINT; LPARAM, lpData: LPARAM): Integer stdcall;
beginif (uMsg = BFFM_INITIALIZED) and (lpData <> 0) thenSendMessage(Wnd, BFFM_SETSELECTION, Integer(True), lpData);Result := 0;
end;function SelectDirectory(const Caption: string; const Root: WideString;var Directory: string; Owner: THandle): Boolean;
varWindowList: Pointer;BrowseInfo: TBrowseInfo;Buffer: PChar;RootItemIDList, ItemIDList: PItemIDList;ShellMalloc: IMalloc;IDesktopFolder: IShellFolder;Eaten, Flags: LongWord;
beginResult := False;if not DirectoryExists(Directory) thenDirectory := '';FillChar(BrowseInfo, SizeOf(BrowseInfo), 0);if (ShGetMalloc(ShellMalloc) = S_OK) and (ShellMalloc <> nil) then beginBuffer := ShellMalloc.Alloc(MAX_PATH);tryRootItemIDList := nil;if Root <> '' then beginSHGetDesktopFolder(IDesktopFolder);IDesktopFolder.ParseDisplayName(Application.Handle, nil,POleStr(Root), Eaten, RootItemIDList, Flags);end;with BrowseInfo do beginhwndOwner := Owner;pidlRoot := RootItemIDList;pszDisplayName := Buffer;lpszTitle := PChar(Caption);ulFlags := BIF_RETURNONLYFSDIRS;if Directory <> '' then beginlpfn := SelectDirCB;LPARAM := Integer(PChar(Directory));end;end;WindowList := DisableTaskWindows(0);tryItemIDList := ShBrowseForFolder(BrowseInfo);finallyEnableTaskWindows(WindowList);end;Result := ItemIDList <> nil;if Result then beginShGetPathFromIDList(ItemIDList, Buffer);ShellMalloc.Free(ItemIDList);Directory := Buffer;end;finallyShellMalloc.Free(Buffer);end;end;
end;
//_____________________________________________________________________//function AddString(S: string): string;
beginResult := S;if S[Length(S)] <> '\' then Result := S + '\';
end;//获取当前的硬盘所有的盘符
{Lbl_DriveType:Tlabel;DriveType:WORD; //定义驱动器类型变量DriveType:=GetDriveType(RootPathName); //获得RootPathName所对应的磁盘驱动器信息case DriveType ofDRIVE_REMOVABLE:Lbl_DriveType.Caption:= '软盘驱动器';DRIVE_FIXED : Lbl_DriveType.Caption:= '硬盘驱动器';DRIVE_REMOTE: Lbl_DriveType.Caption:= '网络驱动器';DRIVE_CDROM: Lbl_DriveType.Caption:= '光盘驱动器';DRIVE_RAMDISK: Lbl_DriveType.Caption:= '内存虚拟盘';end; //将该磁盘信息显示在Lbl_DriveType中}function GetDrives: string;
varDiskType: Word;D: Char;Str: string;I: Integer;
beginfor I := 0 to 25 do //遍历26个字母beginD := Chr(I + 65);Str := D + ':';DiskType := GetDriveType(PChar(Str));//得到本地磁盘和网络盘if (DiskType = DRIVE_FIXED) {or (DiskType = DRIVE_REMOTE)} thenResult := Result + D;end;
end;{ 遍历目录 }
{
procedure LoopFiles(Path, Mask: string);
varI, Count: Integer;Fn, Ext: string;SubDir: TStrings;SearchRec: TSearchRec;Msg: TMsg;function IsValidDir(SearchRec: TSearchRec): Integer;beginif (SearchRec.Attr <> 16) and (SearchRec.Name <> '.') and(SearchRec.Name <> '..') thenResult := 0 //不是目录else if (SearchRec.Attr = 16) and (SearchRec.Name <> '.') and(SearchRec.Name <> '..') thenResult := 1 //不是根目录else Result := 2; //是根目录end;
beginSubDir := TStringList.Create;if (FindFirst(Path + '*.*', faDirectory, SearchRec) = 0) thenbeginrepeatif g_boClose then break;Application.ProcessMessages;if IsValidDir(SearchRec) = 1 then beginif not CheckMirPath(Path + SearchRec.Name + '\') then beginSubDir.Add(SearchRec.Name);FrmMain.LabelStatus.Caption := Path + SearchRec.Name;end else beging_sMirPath := Path + SearchRec.Name + '\';WriteRegKey(1, R_MySubKey, R_Key, g_sMirPath);Break;end;end;Sleep(1);until (FindNext(SearchRec) <> 0);end;FindClose(SearchRec);if not CheckMirPath(g_sMirPath) then beginCount := SubDir.Count - 1;for I := 0 to Count do beginif g_boClose then break;LoopFiles(Path + SubDir.Strings[I] + '\', Mask);end;end;FreeAndNil(SubDir);
end;}//缩短显示不下的长路径名function FormatPath(APath: string; Width: Integer): string;
varSLen: Integer;i, j: Integer;TString: string;
beginSLen := Length(APath);if (SLen <= Width) or (Width <= 6) thenbeginResult := APath;Exitendelsebegini := SLen;TString := APath;for j := 1 to 2 dobeginwhile (TString[i] <> '\') and (SLen - i < Width - 8) doi := i - 1;i := i - 1;end;for j := SLen - i - 1 downto 0 doTString[Width - j] := TString[SLen - j];for j := SLen - i to SLen - i + 2 doTString[Width - j] := '.';Delete(TString, Width + 1, 255);Result := TString;end;
end;procedure LoopFiles(Path, Mask: string; SubDir: TStrings);
varI, Count: Integer;Fn, Ext, FullPath: string;SearchRec: TSearchRec;Msg: TMsg;function IsValidDir(SearchRec: TSearchRec): Integer;beginif (SearchRec.Attr <> 16) and (SearchRec.Name <> '.') and(SearchRec.Name <> '..') thenResult := 0 //不是目录else if (SearchRec.Attr = 16) and (SearchRec.Name <> '.') and(SearchRec.Name <> '..') thenResult := 1 //不是根目录else Result := 2; //是根目录end;
beginif (FindFirst(Path + '*.*', faDirectory, SearchRec) = 0) then beginrepeatif g_boClose then break;Application.ProcessMessages;if IsValidDir(SearchRec) = 1 then beginFullPath := Path + SearchRec.Name + '\';if not CheckFullPath(FullPath) then begin//if CheckLegendPath(FullPath) thenif CheckLegendPath(FullPath) theng_LegendPathList.Add(FullPath);SubDir.Add(FullPath);FrmMain.LabelStatus.Caption := FormatPath(FullPath, 40);{if Length(FullPath) > 30 then beginFrmMain.LabelStatus.Caption := ExtractShortPathName(FullPath);end else beginFrmMain.LabelStatus.Caption := FullPath;end; }end else beging_sMirPath := FullPath;WriteRegKey(1, R_MySubKey, R_Key, g_sMirPath);Break;end;end;Sleep(1);until (FindNext(SearchRec) <> 0);end;FindClose(SearchRec);
end;function CheckLegendPath(Path: string): Boolean;
beginResult := (DirectoryExists(Path + 'Data')) and(DirectoryExists(Path + 'Map')) and(DirectoryExists(Path + 'Wav'));
end;function CheckFullPath(Path: string): Boolean;
beginResult := (DirectoryExists(Path + 'Data')) and(DirectoryExists(Path + 'Map')) and(DirectoryExists(Path + 'Wav')) and(not FileExists(Path + 'Data\ChrSel_16.wil')) and(not FileExists(Path + 'Data\Prguse_16.wil')) and(not FileExists(Path + 'Data\Prguse2_16.wil')) and(not FileExists(Path + 'Data\Prguse3_16.wil'));
end;function CheckMirPath(Path: string): Boolean;
varsKeyValue: string;
beginif CheckLegendPath(Path) then beging_sMirPath := Path;Result := True;end else beginif ReadRegKey(1, R_MySubKey, R_Key, sKeyValue) then beginif CheckLegendPath(sKeyValue) then beging_sMirPath := sKeyValue;Result := True;Exit;end;end;if ReadRegKey(1, R_SndaSubKey, R_Key, sKeyValue) then beginif CheckLegendPath(sKeyValue) then beging_sMirPath := sKeyValue;WriteRegKey(1, R_MySubKey, R_Key, g_sMirPath);Result := True;Exit;end;end;Result := False;end;
end;function SearchPath: Boolean;
varI: Integer;SubDir: TStrings;
beginResult := False;SubDir := TStringList.Create;for I := 0 to g_SearchList.Count - 1 do beginLoopFiles(g_SearchList[I], '*.*', SubDir);if g_boClose or CheckFullPath(g_sMirPath) then beginbreak;end;end;if not CheckFullPath(g_sMirPath) then beging_SearchList.Clear;g_SearchList.AddStrings(SubDir);end else Result := True;FreeAndNil(SubDir);
end;function TFrmMain.SearchMirClient(Path: string): Boolean;
varDriverList: string;sKeyValue: string;I, Len: Integer;
beginResult := False;if not CheckLegendPath(Path) then beginif ReadRegKey(1, R_MySubKey, R_Key, sKeyValue) then beginif CheckLegendPath(sKeyValue) then beging_sMirPath := sKeyValue;Result := True;Exit;end;end;if ReadRegKey(1, R_SndaSubKey, R_Key, sKeyValue) then beginif CheckLegendPath(sKeyValue) then beging_sMirPath := sKeyValue;WriteRegKey(1, R_MySubKey, R_Key, g_sMirPath);Result := True;Exit;end;end;DriverList := GetDrives; //得到可写的磁盘列表 //遍历每个磁盘驱动器Len := Length(DriverList);for I := 1 to Len do beging_SearchList.Add(DriverList[I] + ':\');end;while (not SearchPath) and (not g_boClose) do beginend;if (not CheckMirPath(g_sMirPath)) and (g_LegendPathList.Count > 0) then beging_sMirPath := g_LegendPathList.Strings[0];end;Result := CheckLegendPath(g_sMirPath);{DriverList := GetDrives; //得到可写的磁盘列表Len := Length(DriverList);for I := Len downto 1 do begin //遍历每个磁盘驱动器tryLoopFiles(DriverList[I] + ':\', '*.*');if CheckMirPath(g_sMirPath) then beginResult := True;Break;end;exceptend;if g_boClose then break;end;}end else beging_sMirPath := Path;if not ReadRegKey(1, R_MySubKey, R_Key, sKeyValue) then beginWriteRegKey(1, R_MySubKey, R_Key, g_sMirPath);end else beginif not CheckLegendPath(sKeyValue) then beginWriteRegKey(1, R_MySubKey, R_Key, g_sMirPath);end;end;Result := True;end;
end;procedure TfrmMain.ProcessMessage(var Msg: TMsg; var Handled: Boolean);
beginif Msg.message = WM_SENDPROCMSG then begin//    ShowMessage('asfd');Handled := True;end;
end;procedure TfrmMain.MyMessage(var MsgData: TWmCopyData);
varI, nHandle: Integer;sData: string;wIdent, wRecog: Word;
beginif not g_boClose then beginwIdent := HiWord(MsgData.From);wRecog := LoWord(MsgData.From);sData := StrPas(MsgData.CopyDataStruct^.lpData);case wIdent ofCM_HANDLE: beginnHandle := Str_ToInt(sData, 0);for I := 0 to g_ClientHandleList.Count - 1 do beginif nHandle = Integer(g_ClientHandleList.Items[I]) then beginExit;end;end;g_ClientHandleList.Add(Pointer(nHandle));//Showmessage('CM_HANDLE:'+IntToStr(nHandle));end;CM_QUIT: beginnHandle := Str_ToInt(sData, 0);//Showmessage('CM_QUIT:'+IntToStr(nHandle));for I := 0 to g_ClientHandleList.Count - 1 do beginif nHandle = Integer(g_ClientHandleList.Items[I]) then beging_ClientHandleList.Delete(I);Break;end;end;if IsIconic(Application.Handle) thenShowWindow(Application.Handle, SW_RESTORE);SetForegroundWindow(Application.Handle);end;end;end;
end;procedure TfrmMain.CreateUlr(sCreateUlrName: string); //创建快捷方式
varShLink: IShellLink;PFile: IPersistFile;FileName: string;WFileName: WideString;Reg: TRegIniFile;AnObj: IUnknown;UrlName: string;
beginUrlName := Trim(sCreateUlrName);if UrlName <> '' then beginAnObj := CreateComObject(CLSID_ShellLink);ShLink := AnObj as IShellLink;PFile := AnObj as IPersistFile;FileName := ParamStr(0);ShLink.SetPath(PChar(FileName));ShLink.SetWorkingDirectory(PChar(ExtractFilePath(FileName)));Reg := TRegIniFile.Create('Software\MicroSoft\Windows\CurrentVersion\Explorer');WFileName := Reg.ReadString('Shell Folders', 'Desktop', '') + '\' + UrlName + '.lnk';PFile.Save(PWChar(WFileName), True);end;
end;procedure TfrmMain.SendCSocket(sendstr: string);
varsSendText: string;
beginif ClientSocket.Socket.Connected then begin  //是否被连接sSendText := '#' + IntToStr(btCode) + sendstr + '!'; //btcode =1  #+btcode+sendstr+!ClientSocket.Socket.SendText('#' + IntToStr(btCode) + sendstr + '!');Inc(btCode);//+1if btCode >= 10 then btCode := 1;//>=10 则 赋值1end;
end;procedure TfrmMain.SendChgPw(sAccount, sPasswd, sNewPasswd: string); //发送修改密码
varMsg: TDefaultMessage;
beginMsg := MakeDefaultMsg(CM_CHANGEPASSWORD, 0, 0, 0, 0);//修改密码SendCSocket(EncodeMessage(Msg) + EncodeString(sAccount + #9 + sPasswd + #9 + sNewPasswd));
end;procedure TfrmMain.SendGetBackPassword(sAccount, sQuest1, sAnswer1,sQuest2, sAnswer2, sBirthDay: string); //发送找回密码
varMsg: TDefaultMessage;
beginMsg := MakeDefaultMsg(CM_GETBACKPASSWORD, 0, 0, 0, 0);//知足找回密码消息SendCSocket(EncodeMessage(Msg) + EncodeString(sAccount + #9 + sQuest1 + #9 + sAnswer1 + #9 + sQuest2 + #9 + sAnswer2 + #9 + sBirthDay));//消息代码 + 编码字符串 tab分割参数
end;procedure TfrmMain.SendGetRandomCode;
varMsg: TDefaultMessage;
beginMsg := MakeDefaultMsg(CM_RANDOMCODE, 0, 0, 0, 0); //make 一个默认消息SendCSocket(EncodeMessage(Msg)); //加密消息 发送消息
end;procedure TfrmMain.SendUpdateAccount(ue: TUserEntry; ua: TUserEntryAdd; nRandomCode: Integer); //发送新建账号
varMsg: TDefaultMessage;  //发送更新用户 新建用户
beginsMakeNewAccount := ue.sAccount;//全局变量Msg := MakeDefaultMsg(CM_ADDNEWUSER, nRandomCode, 0, 0, 0);//发送消息SendCSocket(EncodeMessage(Msg) + EncodeBuffer(@ue, SizeOf(TUserEntry)) + EncodeBuffer(@ua, SizeOf(TUserEntryAdd))); //329//发送 消息码+编码缓冲区ue+编码缓冲区ua
end;procedure TfrmMain.TimerTimer(Sender: TObject);
varStr, data: string;len, I, n, mcnt: Integer;
beginif boBusy then Exit;boBusy := True;trysBufferStr := sBufferStr + sSocStr;sSocStr := '';if sBufferStr <> '' then beginmcnt := 0;while Length(sBufferStr) >= 2 do beginif Pos('!', sBufferStr) <= 0 then Break;sBufferStr := ArrestStringEx(sBufferStr, '#', '!', data);if data <> '' then beginDecodeMessagePacket(data);end elseif Pos('!', sBufferStr) = 0 thenBreak;end;end;{if frmNewAccount.Visible then beginfrmNewAccount.LabelRandomCode.Caption := g_sRandomCode;end;}finallyboBusy := False;end;
end;procedure TfrmMain.TreeViewClick(Sender: TObject);
varTreeNode: TTreeNode;GameZone: TGameZone;sServerAddr: string;sServerPort: string;
beging_SelGameZone := nil;TreeNode := TreeView.Selected;if (TreeNode = nil) or (TreeNode.Parent = nil) then begin//Showmessage('TreeNode.Parent = nil');Exit;end;g_SelGameZone := TGameZone(TreeNode.Data);tryif not g_SelGameZone.Connected then beginClientSocket.Active := False;ClientSocket.Host := '';ClientSocket.Address := '';if g_SelGameZone.Encrypt then beginsServerAddr := DeCodeString(g_SelGameZone.GameHost);sServerPort := DeCodeString(g_SelGameZone.GameIPPort);end else beginsServerAddr := g_SelGameZone.GameHost;sServerPort := g_SelGameZone.GameIPPort;end;if IsIpAddr(sServerAddr) then beginClientSocket.Address := sServerAddr;end else beginClientSocket.Host := sServerAddr;end;ClientSocket.Port := Str_ToInt(sServerPort, 7000);ClientSocket.Active := True;end else beging_boClientSocketConnect := True;LabelStatus.Font.Color := g_GameLoginConfig.LabelConnectColor;LabelStatus.Caption := sClientConnect;RzBmpButtonFullScreenStart.Enabled := True;RzBmpButtonStart.Enabled := True;RzBmpButtonAutoLogin.Enabled := True;RzBmpButtonNewAccount.Enabled := True;RzBmpButtonGetBakPassWord.Enabled := True;RzBmpButtonChgPassWord.Enabled := True;end;//WebBrowser.Height := g_nWebHeiht;//WebBrowser.Width := g_WebBrowser.Width;WebBrowser.Navigate(g_SelGameZone.NoticeUrl);//WebBrowser.Width := g_WebBrowser.Width;{Showmessage(IntToStr(WebBrowser.Width));Showmessage(IntToStr(WebBrowser.Height));}exceptend;
end;procedure TfrmMain.DecodeMessagePacket(datablock: string);
varhead, body, body2, tagstr, data, rdstr, Str: string;Msg: TDefaultMessage;smsg: TShortMessage;mbw: TMessageBodyW;desc: TCharDesc;wl: TMessageBodyWL;featureEx: word;L, I, j, n, BLKSize, param, sound, cltime, svtime: Integer;tempb: Boolean;
beginif datablock[1] = '+' then Exit;if Length(datablock) < DEFBLOCKSIZE then Exit;head := Copy(datablock, 1, DEFBLOCKSIZE);body := Copy(datablock, DEFBLOCKSIZE + 1, Length(datablock) - DEFBLOCKSIZE);Msg := DecodeMessage(head);case Msg.Ident ofSM_NEWID_SUCCESS: beginApplication.MessageBox('您的帐号创建成功。' + #13 +'请妥善保管您的帐号和密码,' + #13 + '并且不要因任何原因把帐号和密码告诉任何其他人。' + #13 +'如果忘记了密码,你可以通过我们的主页重新找回。', '提示信息', MB_OK);frmNewAccount.Close;end;SM_NEWID_FAIL: begincase Msg.Recog of0: beginApplication.MessageBox(PChar('帐号 "' + sMakeNewAccount + '" 已被其他的玩家使用了。' + #13 +'请选择其它帐号名注册。'), '提示信息', MB_OK);end;1: beginApplication.MessageBox('验证码输入错误,请重新输入!!!', '提示信息', MB_OK);//frmNewAccount.EditRandomCode.SetFocus;end;-2: Application.MessageBox('此帐号名被禁止使用!', '提示信息', MB_OK);else Application.MessageBox(PChar('帐号创建失败,请确认帐号是否包括空格、及非法字符!Code: ' + IntToStr(Msg.Recog)), '提示信息', MB_OK);end;frmNewAccount.ButtonOK.Enabled := True;Exit;end;SM_RANDOMCODE: beginend;SM_CHGPASSWD_SUCCESS: beginApplication.MessageBox('密码修改成功。', '提示信息', MB_OK);{frmChangePassword.ChgEditAccount.Text:='';frmChangePassword.ChgEditPassword.Text:='';frmChangePassword.ChgEditConfirm.Text:='';frmChangePassword.ChgEditNewPassword.Text:='';}frmChangePassword.ButtonOK.Enabled := False;//frmNewAccount.Close;Exit;end;SM_CHGPASSWD_FAIL: begincase Msg.Recog of0: Application.MessageBox('输入的帐号不存在!!!', '提示信息', MB_OK);-1: Application.MessageBox('输入的原始密码不正确!', '提示信息', MB_OK);-2: Application.MessageBox('此帐号被锁定!', '提示信息', MB_OK);else Application.MessageBox('输入的新密码长度小于四位!', '提示信息', MB_OK);end;frmChangePassword.ButtonOK.Enabled := True;Exit;end;SM_GETBACKPASSWD_SUCCESS: beginfrmGetBackPassword.EditPassword.Text := DecodeString(body);Application.MessageBox(PChar('密码找回成功。'), '提示信息', MB_OK);Exit;end;SM_GETBACKPASSWD_FAIL: begincase Msg.Recog of0: Application.MessageBox('输入的帐号不存在!!!', '提示信息', MB_OK + MB_ICONERROR);-1: Application.MessageBox('问题答案不正确!!!', '提示信息', MB_OK + MB_ICONERROR);-2: Application.MessageBox(PChar('此帐号被锁定!!!' + #13 + '请稍候三分钟再重新找回。'), '提示信息', MB_OK + MB_ICONERROR);-3: Application.MessageBox('答案输入不正确!!!', '提示信息', MB_OK + MB_ICONERROR);else Application.MessageBox('未知错误!', '提示信息', MB_OK + MB_ICONERROR);end;frmGetBackPassword.ButtonOK.Enabled := True;Exit;end;end;
end;procedure TfrmMain.ClientSocketConnect(Sender: TObject;Socket: TCustomWinSocket);
beginif g_SelGameZone <> nil then beging_SelGameZone.GameIPaddr := Socket.RemoteAddress;g_SelGameZone.Connected := True;end;//ChgButtonStatus(0);g_boClientSocketConnect := True;LabelStatus.Font.Color := g_GameLoginConfig.LabelConnectColor;//LabelStatus.Font.Color := clLime;LabelStatus.Caption := sClientConnect;//frmGetBackPassword.LabelStatus.Caption := sClientConnect;//frmNewAccount.LabelStatus.Caption := sClientConnect;//frmChangePassword.LabelStatus.Caption := sClientConnect;RzBmpButtonFullScreenStart.Enabled := True;RzBmpButtonStart.Enabled := True;RzBmpButtonAutoLogin.Enabled := True;RzBmpButtonNewAccount.Enabled := True;RzBmpButtonGetBakPassWord.Enabled := True;RzBmpButtonChgPassWord.Enabled := True;
end;procedure TfrmMain.ClientSocketConnecting(Sender: TObject;Socket: TCustomWinSocket);
begin//ChgButtonStatus(1);g_boClientSocketConnect := False;LabelStatus.Font.Color := g_GameLoginConfig.LabelConnectingColor; //clFuchsia;LabelStatus.Caption := sClientConnecting;frmGetBackPassword.LabelStatus.Caption := sClientConnecting;//frmNewAccount.LabelStatus.Caption := sClientConnecting;//frmChangePassword.LabelStatus.Caption := sClientConnecting;RzBmpButtonFullScreenStart.Enabled := False;RzBmpButtonStart.Enabled := False;RzBmpButtonAutoLogin.Enabled := False;RzBmpButtonNewAccount.Enabled := False;RzBmpButtonGetBakPassWord.Enabled := False;RzBmpButtonChgPassWord.Enabled := False;
end;procedure TfrmMain.ClientSocketDisconnect(Sender: TObject;Socket: TCustomWinSocket);
begin//ChgButtonStatus(2);g_boClientSocketConnect := False;if not g_SelGameZone.Connected then beginLabelStatus.Font.Color := g_GameLoginConfig.LabelDisconnectColor; //clYellow;LabelStatus.Caption := sClientDisconnect;//frmGetBackPassword.LabelStatus.Caption := sClientDisconnect;//frmNewAccount.LabelStatus.Caption := sClientDisconnect;//frmChangePassword.LabelStatus.Caption := sClientDisconnect;RzBmpButtonFullScreenStart.Enabled := False;RzBmpButtonStart.Enabled := False;RzBmpButtonAutoLogin.Enabled := False;RzBmpButtonNewAccount.Enabled := False;RzBmpButtonGetBakPassWord.Enabled := False;RzBmpButtonChgPassWord.Enabled := False;end;
end;procedure TfrmMain.ClientSocketError(Sender: TObject;Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;var ErrorCode: Integer);
begin//ChgButtonStatus(2);ErrorCode := 0;Socket.Close;
end;procedure TfrmMain.ClientSocketRead(Sender: TObject;Socket: TCustomWinSocket);
varn: Integer;data, data2: string;
begindata := Socket.ReceiveText;n := Pos('*', data);if n > 0 then begindata2 := Copy(data, 1, n - 1);data := data2 + Copy(data, n + 1, Length(data));ClientSocket.Socket.SendText('*');end;sSocStr := sSocStr + data;
end;procedure TfrmMain.OnProgramException(Sender: TObject; E: Exception);
beginDebugOutStr(E.Message);
end;procedure TFrmMain.LoadUserConfig;
varConf: TIniFile;
beginConf := TIniFile.Create(g_sSelfFilePath + 'User.ini');//RzCheckBoxWindowMode.Checked := Conf.ReadBool('Settings', 'WindowMode', False);//ComboBoxScreenMode.ItemIndex := Conf.ReadInteger('Settings', 'ScreenMode', 0);ComboBox.ItemIndex := Conf.ReadInteger('Settings', 'ScreenMode', 0);Conf.Free;
end;procedure TFrmMain.SaveUserConfig;
varConf: TIniFile;
beginConf := TIniFile.Create(g_sSelfFilePath + 'User.ini');//Conf.WriteBool('Settings', 'WindowMode', RzCheckBoxWindowMode.Checked);//Conf.WriteInteger('Settings', 'ScreenMode', ComboBoxScreenMode.ItemIndex);Conf.WriteInteger('Settings', 'ScreenMode', ComboBox.ItemIndex);Conf.Free;
end;procedure TfrmMain.FormCreate(Sender: TObject);varBatchFileName: string;sCopyFile: string;MemoryStream: TMemoryStream;//FileStream: TMemoryStream;PlugStream: TMemoryStream;Config: TConfig;sText: string;nCount: Integer;nCount1: Integer;Buffer: Pointer;OutBuf: Pointer;OutBytes: Integer;SrcP: Pointer;nLen: Integer;//JPE: TJpegImage;Bitmap: TBitmap;I: Integer;
beginApplication.ShowMainForm := False;//隐藏主窗口g_sSelfFileName := ExtractFileName(Application.ExeName);//自身文件名g_sSelfFilePath := ExtractFilePath(Application.ExeName);//自身路径g_SearchList := TStringList.Create;//搜索列表g_LegendPathList := TStringList.Create;//传奇客户端路径g_ClientHandleList := TList.Create;//客户端句柄WebBrowser := TWebBrowser.Create(Self);//游览器g_ComponentList.Add(RzBmpButtonFullScreenStart);//全屏启动g_ComponentList.Add(RzBmpButtonEditGameList);//编辑游戏g_ComponentList.Add(RzBmpButtonHomePage);//官方主页g_ComponentList.Add(RzBmpButtonAutoLogin);//脱机登陆g_ComponentList.Add(RzBmpButtonUpgrade);//游戏更新g_ComponentList.Add(RzBmpButtonStart);//窗口登陆g_ComponentList.Add(RzBmpButtonNewAccount);//帐号注册g_ComponentList.Add(RzBmpButtonGetBakPassWord);//密码找回g_ComponentList.Add(RzBmpButtonChgPassWord);//修改密码g_ComponentList.Add(RzBmpButtonExitGame);//退出游戏g_ComponentList.Add(RzBmpButtonMin);//最小化g_ComponentList.Add(RzBmpButtonClose);//关闭g_ComponentList.Add(TreeView);//列表g_ComponentList.Add(WebBrowser);//游览器g_ComponentList.Add(LabelStatus);//状态g_ComponentList.Add(ComboBox);//分辨率MirClient := nil;//内存变量
{------------------------------------------------------------------------------}
{------------------------------------------------------------------------------}
{------------------------------------------------------------------------------}MirClient := TMemoryStream.Create;//创建MemoryStream := TMemoryStream.Create; //创建trynLen := SizeOf(TGameLoginConfig);//获取游戏配置大小MemoryStream.LoadFromFile(Application.ExeName);//载入exeMemoryStream.Seek(-nLen, soFromEnd);//移动底部 倒退配置大小MemoryStream.Read(g_GameLoginConfig, nLen);//读取到内存  配置文件中for I := 0 to Length(g_GameLoginConfig.ComponentImages) - 1 do beginInc(nLen, g_GameLoginConfig.ComponentImages[I].UpSize); //图片 大小Inc(nLen, g_GameLoginConfig.ComponentImages[I].HotSize); //图片大小Inc(nLen, g_GameLoginConfig.ComponentImages[I].DownSize);//大小Inc(nLen, g_GameLoginConfig.ComponentImages[I].Disabled);//大小end;{------------------------------------------------------------------------------}
{------------------------------------------------------------------------------}
{------------------------------------------------------------------------------}//读取界面数据MemoryStream.Seek(-nLen, soFromEnd);//移动GetMem(g_Buffer, nLen - SizeOf(TGameLoginConfig));//分配内存MemoryStream.Read(g_Buffer^, nLen - SizeOf(TGameLoginConfig));//读取
{------------------------------------------------------------------------------}
{------------------------------------------------------------------------------}
{------------------------------------------------------------------------------}MemoryStream.Seek(-(nLen + SizeOf(Integer)), soFromEnd); //移动MemoryStream.Read(nCount, SizeOf(Integer));//读取整形countMemoryStream.Seek(-(nLen + SizeOf(Integer) + nCount), soFromEnd);//再移动GetMem(Buffer, nCount);//分配内存tryMemoryStream.Read(Buffer^, nCount); //读到buffer中DecompressBuf(Buffer, nCount, 0, OutBuf, OutBytes);//解压指针finallyFreeMem(Buffer);//释放内存end;Move(OutBuf^, Config, OutBytes);//将解压后的配置 移动到 ConfigFreeMem(OutBuf);//释放内存GetMem(Buffer, Config.nClientSize);//分配内存tryMemoryStream.Seek(Config.nClientPos, soFromBeginning);//客户端的位置MemoryStream.Read(Buffer^, Config.nClientSize);//读取到bufferMirClient.Write(Buffer^, Config.nClientSize);//将读取到的buffer写入到mirclient内存流中finallyFreeMem(Buffer);end;exceptend;MemoryStream.Free;{------------------------------------------------------------------------------}
{------------------------------------------------------------------------------}
{------------------------------------------------------------------------------}g_CreateUlrName := EncodeString(Config.sUlrName);//解码快捷方式名称g_sHomePage := EncodeString(Config.sHomePage);//解码地址g_sRemoteConfigAddress := EncodeString(Config.sConfigAddress);//解码配置地址g_sGameRemoteAddress := EncodeString(Config.sGameAddress);//解码游戏地址g_boClose := False;CreateUlr(DeCodeString(g_CreateUlrName));//创建快捷方式g_AllGameList := TGameZone.Create;//所有游戏列表g_GameList := TGameZone.Create();//游戏列表g_LocalGameList := TGameZone.Create();//本地列表//g_MessageDlg := TMessageDlg.Create(Owner);//g_NpcDlg := TNpcDlg.Create(Owner);//TimerReakSkin.Enabled := TRUE;ReadSkin;//读取皮肤if CheckMirPath(g_sSelfFilePath) then begin  //检查客户端路径{ g_MirsClient.sDirectory := g_sMirPath;g_MirsClient.sDirectory := g_sMirPath; }frmUpgradeDownload := TfrmUpgradeDownload.Create(Owner); //创建更新窗口frmUpgradeDownload.Open;//打开frmUpgradeDownload.Free;//释放{Self.Repaint;Self.Refresh; }end;LoadUserConfig;//载入配置if g_boNeedUpgradeSelf then beginCloseTimer.Enabled := True;end else beginTimerStart.Enabled := True;Application.ShowMainForm := True;end;//Image.RecreateRegion;{if g_boClose then beginApplication.ShowMainForm := False;CloseTimer.Enabled := True;end else beginTimerStart.Enabled := True;end;}
end;procedure TfrmMain.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
varI: Integer;nHandle: Integer;
beging_boClose := True;for I := 0 to g_ClientHandleList.Count - 1 do beginnHandle := Integer(g_ClientHandleList.Items[I]);SendProgramMsg(nHandle, GL_QUIT, '');end;tryif not g_boClose theng_LocalGameList.SaveToFile(g_sLocalGameListFileName);g_GameList.Free;g_LocalGameList.Free;g_AllGameList.Free;WebBrowser.Free;g_ClientHandleList.Free;if MirClient <> nil then MirClient.Free;g_SearchList.Free;g_LegendPathList.Free;exceptend;
end;function TfrmMain.GetProcesses: Boolean;
varhSnap: THandle;ProcessEntry: TProcessEntry32;Proceed: Boolean;
beginResult := False;hSnap := CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0); //创建系统快照if hSnap <> -1 thenbeginProcessEntry.dwSize := SizeOf(TProcessEntry32); //先初始化 FProcessEntry32 的大小Proceed := Process32First(hSnap, ProcessEntry);while Proceed do beginwith ProcessEntry doif (CompareText(StrPas(szEXEFile), 'JS.UCU') = 0) then begin//CloseProcess(Th32ProcessID);Result := True;Break;end else beginif GetModules(Th32ProcessID) then beginResult := True;Break;end;end;{ with listview_pro.Items.Add dobeginCaption := szEXEFile;subitems.Add(IntToStr(Th32ProcessID));subitems.Add(IntToStr(th32ParentProcessID));subitems.Add(IntToStr(Th32ModuleID));subitems.Add(IntToStr(cntUsage));subitems.Add(IntToStr(cntThreads));subitems.Add(IntToStr(pcPriClassBase));end; }Proceed := Process32Next(hSnap, ProcessEntry);end;CloseHandle(hSnap);end;{elseShowMessage( 'Oops...' + SysErrorMessage(GetLastError)); }
end;function TfrmMain.GetModules(ProcessID: DWORD): Boolean;
var hSnap: THandle;ModuleEntry: TModuleEntry32;Proceed: Boolean;
beginResult := False;hSnap := CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, ProcessID);if hSnap <> -1 thenbeginModuleEntry.dwSize := SizeOf(TModuleEntry32);Proceed := Module32First(hSnap, ModuleEntry);while Proceed dobeginwith ModuleEntry doif (CompareText(szModule, 'WINIO.DLL') = 0) or (CompareText(szModule, 'JSHJ.DLL') = 0) then begin//CloseProcess(ProcessID);Result := True;Break;end;{with listview_mod.Items.Add dobeginCaption := szModule;subitems.Add(ExtractFilePath(szEXEPath));subitems.Add(IntToStr(Th32ModuleID));subitems.Add(FloatToStr(ModBaseSize / 1024));subitems.Add(IntToStr(GlblCntUsage));end; }Proceed := Module32Next(hSnap, ModuleEntry);end;CloseHandle(hSnap);end;{elseShowMessage( 'Oops...' + SysErrorMessage(GetLastError));  }
end;function RunProgram(GameZone: TGameZone; sDirectory, sProgramFile, sHandle: string; dwWaitTime: LongWord; nScreenWidth, nScreenHegiht: Integer): LongWord;
varStartupInfo: TStartupInfo;sCommandLine: string;sCurDirectory: string;ProcessInfo: TProcessInformation;dwTick: LongWord;MirServer: TMirServer;
beginResult := 0;FillChar(StartupInfo, SizeOf(TStartupInfo), #0);{StartupInfo.cb:=SizeOf(TStartupInfo);StartupInfo.lpReserved:=nil;StartupInfo.lpDesktop:=nil;StartupInfo.lpTitle:=nil;StartupInfo.dwFillAttribute:=0;StartupInfo.cbReserved2:=0;StartupInfo.lpReserved2:=nil;}if GameZone.Encrypt then beginMirServer.sServeraddr := DeCodeString(GameZone.GameHost);MirServer.nServerPort := Str_ToInt(DeCodeString(GameZone.GameIPPort), 0);end else beginMirServer.sServeraddr := GameZone.GameHost;MirServer.nServerPort := Str_ToInt(GameZone.GameIPPort, 0);end;MirServer.sServerName := GameZone.ServerName;MirServer.boFullScreen := g_boFullScreen;MirServer.nScreenWidth := nScreenWidth;MirServer.nScreenHegiht := nScreenHegiht;GetStartupInfo(StartupInfo);StartupInfo.wShowWindow := SW_SHOW;StartupInfo.dwFlags := STARTF_USEFILLATTRIBUTE;StartupInfo.dwFillAttribute := FOREGROUND_INTENSITY or BACKGROUND_BLUE;sCommandLine := Format('%s%s %s %s', [sDirectory, sProgramFile, sHandle, EncodeBuffer(@MirServer, SizeOf(TMirServer))]);dwTick := GetTickCount;sCurDirectory := sDirectory;if not CreateProcess(nil, //lpApplicationName,PChar(sCommandLine), //lpCommandLine,nil, //lpProcessAttributes,nil, //lpThreadAttributes,True, //bInheritHandles,0, //dwCreationFlags,nil, //lpEnvironment,PChar(sCurDirectory), //lpCurrentDirectory,StartupInfo, //lpStartupInfo,ProcessInfo) then begin //lpProcessInformationResult := GetLastError();end;//Sleep(dwWaitTime);
end;procedure TfrmMain.RzBmpButtonFullScreenStartClick(Sender: TObject);
varI: Integer;nScreenWidth: Integer;nScreenHegiht: Integer;
beginif g_SelGameZone <> nil then beging_boFullScreen := Sender = RzBmpButtonFullScreenStart;FileSetAttr(g_sMirPath + g_sProgamFile, 0);tryMirClient.SaveToFile(g_sMirPath + g_sProgamFile);  // 释放 MirClient.dat 客户端文件exceptend;Application.Minimize; //自身最小化窗口//RunApp(g_sMirPath + g_sProgamFile); //启动客户端nScreenWidth := 800;nScreenHegiht := 600;case ComboBox.ItemIndex of0: beginnScreenWidth := 800;nScreenHegiht := 600;end;1: beginnScreenWidth := 1024;nScreenHegiht := 768;end;end;SaveUserConfig;RunProgram(g_SelGameZone, g_sMirPath, g_sProgamFile, IntToStr(Handle), 0, nScreenWidth, nScreenHegiht);end;
end;procedure TfrmMain.ChgButtonStatus(btStatus: Byte);
begin//RzBmpButtonStatus.Bitmaps.Up.LoadFromResourceName(HInstance, 'Connect');{case btStatus of0: beginConnectRes := TResourceStream.Create(HInstance, 'Connect', PChar('Bmp'));RzBmpButtonStatus.Bitmaps.Up.LoadFromStream(ConnectRes);ConnectRes.Free;end;1: beginConnectingRes := TResourceStream.Create(HInstance, 'Connecting', PChar('Bmp'));RzBmpButtonStatus.Bitmaps.Up.LoadFromStream(ConnectingRes);ConnectingRes.Free;end;2: beginDisconnectRes := TResourceStream.Create(HInstance, 'Disconnect', PChar('Bmp'));RzBmpButtonStatus.Bitmaps.Up.LoadFromStream(DisconnectRes);DisconnectRes.Free;end;end;}
end;procedure TfrmMain.RzBmpButtonCloseClick(Sender: TObject);
beginClose;
end;procedure TfrmMain.RzBmpButtonHomePageClick(Sender: TObject);
beginif g_SelGameZone = nil then Exit;ShellExecute(0, 'Open', PChar(g_SelGameZone.HomePage), nil, nil, SW_SHOWNORMAL);//打开网页
end;procedure TfrmMain.RzBmpButtonNewAccountClick(Sender: TObject);
beginfrmMain.SendGetRandomCode;//frmNewAccount.LabelStatus.Caption := MsgLabel.Caption;frmNewAccount.Open;
end;procedure TfrmMain.RzBmpButtonUpgradeClick(Sender: TObject);
begin
//升级代码也是假的
end;procedure TfrmMain.RzBmpButtonGetBakPassWordClick(Sender: TObject);
begin//frmGetBackPassword.LabelStatus.Caption := MsgLabel.Caption;frmGetBackPassword.Open;
end;procedure TfrmMain.RzBmpButtonChgPassWordClick(Sender: TObject);
begin//frmChangePassword.LabelStatus.Caption := MsgLabel.Caption;frmChangePassword.Open;
end;procedure TfrmMain.ReleaseClient(sDirectory: string; GameZone: TGameZone);{function HostToIP(Name: string; var Ip: string): Boolean;varwsdata: TWSAData;hostName: array[0..255] of char;hostEnt: PHostEnt;addr: PChar;beginWSAStartup($0101, wsdata);trygethostname(hostName, SizeOf(hostName));StrPCopy(hostName, Name);hostEnt := gethostbyname(hostName);if Assigned(hostEnt) thenif Assigned(hostEnt^.h_addr_list) then beginaddr := hostEnt^.h_addr_list^;if Assigned(addr) then beginIp := Format('%d.%d.%d.%d', [Byte(addr[0]),Byte(addr[1]), Byte(addr[2]), Byte(addr[3])]);Result := True;endelseResult := FALSE;endelseResult := FALSEelse beginResult := FALSE;end;finallyWSACleanup;endend; }
varRes: TResourceStream;//sIpAddr: string;Myinifile: TIniFile;sServerAddr: string;sServerPort: string;
beginFileSetAttr(sDirectory + g_sProgamFile, 0);tryMirClient.SaveToFile(sDirectory + g_sProgamFile);exceptend;{  Res := TResourceStream.Create(HInstance, 'MirClient', PChar('exe'));tryFileSetAttr(sDirectory + g_sProgamFile, 0);Res.SaveToFile(sDirectory + g_sProgamFile);exceptend;Res.Free;}{ FileSetAttr(sDirectory + g_sClientFile, 0);Res := TResourceStream.Create(HInstance, 'FirClient', PChar('dll'));tryRes.SaveToFile(sDirectory + g_sClientFile);Res.Free;Res := nil;exceptRes.Free;Res := nil;end;  }if GameZone.Encrypt then beginsServerAddr := DeCodeString(GameZone.GameHost);sServerPort := DeCodeString(GameZone.GameIPPort);end else beginsServerAddr := GameZone.GameHost;sServerPort := GameZone.GameIPPort;end;FileSetAttr(sDirectory + 'mir.ini', 0);Myinifile := TIniFile.Create(sDirectory + 'mir.ini');if Myinifile <> nil then beginMyinifile.WriteString('Setup', 'FontName', '宋体');Myinifile.WriteBool('Setup', 'FullScreen', g_boFullScreen);Myinifile.WriteString('Setup', 'Serveraddr', GameZone.GameIPaddr); //IP地址Myinifile.WriteString('Setup', 'ServerPort', sServerPort); //端口Myinifile.Free;end;{ FileSetAttr(sDirectory + 'ftp.ini', 0);Myinifile := TIniFile.Create(sDirectory + 'ftp.ini');if Myinifile <> nil then beginMyinifile.WriteInteger('Server', 'Servercount', 1);Myinifile.WriteString('Server', 'server1caption', GameZone.ServerName); //开门名称Myinifile.WriteString('Server', 'server1name', GameZone.ServerName); //服务器名称Myinifile.Free;end;   }{FileSetAttr(sDirectory + g_sProgamFile, 2);FileSetAttr(sDirectory + g_sClientFile, 2); }
end;function RunApp(AppName: string): Integer;
varSti: TStartupInfo;ProcessInfo: TProcessInformation;
beginFillMemory(@Sti, SizeOf(Sti), 0);Sti.wShowWindow := SW_SHOW;Sti.dwFlags := STARTF_USEFILLATTRIBUTE;Sti.dwFillAttribute := FOREGROUND_INTENSITY or BACKGROUND_BLUE;if CreateProcess(PChar(AppName), nil,nil, nil, False,0, nil, PChar(ExtractFilePath(AppName)),Sti, ProcessInfo) then beginResult := ProcessInfo.dwProcessId;end else Result := -1;
end;{procedure CopyFile(const Sour, Dest: string);
varFileOp: TSHFileOpStruct;
beginwith FileOp do beginWnd := FrmMain.HandLe;wFunc := FO_Copy; //更换此参数可实现拷贝和更名pFrom := PChar(Sour);pTo := PChar(Dest);fFlags := FOF_NoConfirmation;fAnyOperationsAborted := False;hNameMappings := nil;lpszProgressTitle := nilend;SHFileOperation(FileOp);
end;}//判断文件是否正在使用function IsFileInUse(FName: string): Boolean;
varHFileRes: HFILE;
beginResult := False;if not FileExists(FName) thenExit;HFileRes := CreateFile(PChar(FName), GENERIC_READ or GENERIC_WRITE, 0,nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);Result := (HFileRes = INVALID_HANDLE_VALUE);if not Result thenCloseHandle(HFileRes);
end;procedure TfrmMain.TimerStartTimer(Sender: TObject);
varI, n01: Integer;GameZone: TGameZone;TreeNode: TTreeNode;ChildTreeNode: TTreeNode;sFileName: string;//GameArea: pTGameArea;
beginTimerStart.Enabled := False;//ParamStr(1);if not CheckMirPath(g_sSelfFilePath) then beginif Application.MessageBox('目录不正确,是否自动搜索热血传奇客户端?','提示信息',MB_YESNO + MB_ICONQUESTION) = IDYES then beginif SearchMirClient(g_sSelfFilePath) then beginif IsFileInUse(g_sMirPath + g_sSelfFileName) then beginif Pos('.', g_sSelfFileName) > 0 then beging_sSelfFileName := Copy(g_sSelfFileName, 1, Pos('.', g_sSelfFileName) - 1);end;//g_sSelfFileName := Copy(g_sSelfFileName, 1, Length(g_sSelfFileName) - 4);//ChangeFileExt(ExtractFileName(sFileName),'');n01 := 0;while TRUE do beginsFileName := g_sMirPath + g_sSelfFileName + IntToStr(n01) + '.exe';if not FileExists(sFileName) then Break;end;g_sSelfFileName := g_sSelfFileName + IntToStr(n01) + '.exe';end else beginFileSetAttr(g_sMirPath + g_sSelfFileName, 0);DeleteFile(g_sMirPath + g_sSelfFileName);end;CopyFile(PChar(Application.ExeName), PChar(g_sMirPath + g_sSelfFileName), True); //复制自己RunApp(g_sMirPath + g_sSelfFileName); //启动Application.Terminate;Exit;end;end else beginif not SelectDirectory('请选择您的热血传奇客户端“Legend of mir2”目录', '', g_sMirPath, Handle) then beginClose;Exit;end;if (g_sMirPath <> '') and (g_sMirPath[Length(g_sMirPath)] <> '\') then g_sMirPath := g_sMirPath + '\';if not CheckMirPath(g_sMirPath) then beginClose;Exit;end else beginWriteRegKey(1, R_MySubKey, R_Key, g_sMirPath);if IsFileInUse(g_sMirPath + g_sSelfFileName) then beginif Pos('.', g_sSelfFileName) > 0 then beging_sSelfFileName := Copy(g_sSelfFileName, 1, Pos('.', g_sSelfFileName) - 1);end;//g_sSelfFileName := Copy(g_sSelfFileName, 1, Length(g_sSelfFileName) - 4);//ChangeFileExt(ExtractFileName(sFileName),'');n01 := 0;while TRUE do beginsFileName := g_sMirPath + g_sSelfFileName + IntToStr(n01) + '.exe';if not FileExists(sFileName) then Break;end;g_sSelfFileName := g_sSelfFileName + IntToStr(n01) + '.exe';end else beginFileSetAttr(g_sMirPath + g_sSelfFileName, 0);DeleteFile(g_sMirPath + g_sSelfFileName);end;CopyFile(PChar(Application.ExeName), PChar(g_sMirPath + g_sSelfFileName), True); //复制自己RunApp(g_sMirPath + g_sSelfFileName); //启动Application.Terminate;Exit;end;end;end;g_sLocalGameListFileName := g_sMirPath + 'LocalCqfir.Dat';Timer.Enabled := True;//g_GameList.LoadFromFile(g_sGameListFileName);g_LocalGameList.LoadFromFile(g_sLocalGameListFileName);LoadListToBox();TreeNode := TreeView.Items.GetFirstNode;if TreeNode <> nil then beginChildTreeNode := TreeNode.getFirstChild;if ChildTreeNode <> nil then beginTreeView.SetFocus;ChildTreeNode.Selected := True;ChildTreeNode.Focused := True;TreeViewClick(TreeView);end;end;
end;procedure TfrmMain.LoadListToBox();
varI, II: Integer;GameZone: TGameZone;ChildGameZone: TGameZone;TreeNode: TTreeNode;ChildTreeNode: TTreeNode;
beginTreeView.Items.Clear;g_AllGameList.Clear;g_AllGameList.Strings.AddStrings(g_GameList.Strings);g_AllGameList.Strings.AddStrings(g_LocalGameList.Strings);for I := 0 to g_AllGameList.Count - 1 do beginGameZone := g_AllGameList.Items[I];if GameZone.Count > 0 then beginTreeNode := TreeView.Items.AddObject(nil, GameZone.Caption, GameZone);TreeNode.HasChildren := True;//TreeNode.EndEdit(False);for II := 0 to GameZone.Count - 1 do beginChildGameZone := GameZone.Items[II];ChildTreeNode := TreeView.Items.AddChildObject(TreeNode, ChildGameZone.Caption, ChildGameZone);//TreeNode.Expand(ChildGameZone.Expand);//ChildTreeNode.EndEdit(False);//Showmessage(ChildGameZone.Caption);end;ChildTreeNode.Expand(ChildGameZone.Expand);end;end;
end;procedure TfrmMain.RzBmpButtonEditGameListClick(Sender: TObject);
beginfrmEditGame := TfrmEditGame.Create(Owner);//打开编辑列表frmEditGame.Open();frmEditGame.Free;
end;procedure TfrmMain.RzBmpButtonAutoLoginClick(Sender: TObject);
begin   //脱机登陆{tryif g_SelGameZone <> nil then beginfrmCMain := TfrmCMain.Create(Application);frmCMain.Open;Application.Minimize;end;exceptend; }
end;procedure TfrmMain.CloseTimerTimer(Sender: TObject);
varBatchFile: TextFile;BatchFileName: string;ProcessInfo: TProcessInformation;StartUpInfo: TStartupInfo;
beginCloseTimer.Enabled := False;BatchFileName := ExtractFilePath(ParamStr(0)) + '$$s$$.bat';FileSetAttr(BatchFileName, 0);DeleteFile(BatchFileName);AssignFile(BatchFile, BatchFileName);Rewrite(BatchFile);Writeln(BatchFile, ':tryn');Writeln(BatchFile, 'ren ' + g_sSelfFileName + ' ' + g_sSelfFileName + '.Del');Writeln(BatchFile, 'if exist "' + g_sSelfFileName + '.Del' + '"' + ' goto try');Writeln(BatchFile, 'if exist "' + g_sSelfFileName + '"' + ' goto tryn');Writeln(BatchFile, ':try');Writeln(BatchFile, 'del "' + g_sSelfFileName + '.Del' + '"');Writeln(BatchFile, 'if exist "' + g_sSelfFileName + '.Del' + '"' + ' goto try');Writeln(BatchFile, ':refren');Writeln(BatchFile, 'ren ' + g_sUpgradeSelfFileName + ' ' + g_sSelfFileName);Writeln(BatchFile, 'if not exist "' + g_sSelfFileName + '"' + ' goto refren');Writeln(BatchFile, 'start ' + g_sSelfFileName);Writeln(BatchFile, 'del %0');Writeln(BatchFile, 'exit');CloseFile(BatchFile);//FileSetAttr(BatchFileName, 2);FileSetAttr(ExtractFilePath(ParamStr(0)) + g_sSelfFileName, 0);FillChar(StartUpInfo, SizeOf(StartUpInfo), $00);StartUpInfo.dwFlags := STARTF_USESHOWWINDOW;StartUpInfo.wShowWindow := SW_Hide;if CreateProcess(nil, PChar(BatchFileName), nil, nil,False, IDLE_PRIORITY_CLASS, nil, nil, StartUpInfo,ProcessInfo) then beginCloseHandle(ProcessInfo.hThread);CloseHandle(ProcessInfo.hProcess);end;Close;
end;procedure TfrmMain.ImageMouseDown(Sender: TObject; Button: TMouseButton;Shift: TShiftState; X, Y: Integer);
beginif Button = mbLeft then beginReleaseCapture;Perform(WM_SYSCOMMAND, $F012, 0);end;
end;procedure TfrmMain.RzBmpButtonMinClick(Sender: TObject);
beginApplication.Minimize;
end;procedure TfrmMain.ReadSkin;function IncPointer(Buffer: Pointer; Size: Integer): Pointer;beginResult := Pointer(Integer(Buffer) + Size);end;varI: Integer;nLen: Integer;Buffer: Pointer;ReadBuffer: Pointer;OutBuf: Pointer;OutBytes: Integer;Bitmap: TBitmap;FileStream: TMemoryStream;
beginBuffer := g_Buffer;FileStream := TMemoryStream.Create;Application.ProcessMessages;if g_GameLoginConfig.ComponentImages[0].UpSize > 0 then beginDecompressBuf(Buffer, g_GameLoginConfig.ComponentImages[0].UpSize, 0, OutBuf, OutBytes);Buffer := IncPointer(Buffer, g_GameLoginConfig.ComponentImages[0].UpSize);FileStream.Clear;FileStream.Write(OutBuf^, OutBytes);FileStream.Position := 0;FreeMem(OutBuf);//设置背景Bitmap := TBitmap.Create;Bitmap.LoadFromStream(FileStream);FileStream.Position := 0;//Bitmap.SaveToFile('Bitmap.bmp');ClientHeight := Bitmap.Height;ClientWidth := Bitmap.Width;Image.Picture.Bitmap.Assign(Bitmap);Image.Transparent := g_GameLoginConfig.Transparent;//Image.Picture.Bitmap.LoadFromStream(FileStream);//Image.Picture.Bitmap.TransparentColor := clBlack;//Image.Picture.Bitmap.Transparent := True;if Image.Transparent thenImage.RecreateRegion;Bitmap.Free;end;Application.ProcessMessages;
{------------------------------------------------------------------------------}//设置其他控件位置for I := 0 to Length(g_GameLoginConfig.ComponentConfigs) - 1 do beginApplication.ProcessMessages;if WebBrowser = g_ComponentList.Items[I] then beging_nWebHeiht := g_GameLoginConfig.ComponentConfigs[I].Height;g_WebBrowser := g_GameLoginConfig.ComponentConfigs[I];end else beginTWinControl(g_ComponentList.Items[I]).Left := g_GameLoginConfig.ComponentConfigs[I].Left;TWinControl(g_ComponentList.Items[I]).Top := g_GameLoginConfig.ComponentConfigs[I].Top;TWinControl(g_ComponentList.Items[I]).Width := g_GameLoginConfig.ComponentConfigs[I].Width;TWinControl(g_ComponentList.Items[I]).Height := g_GameLoginConfig.ComponentConfigs[I].Height;if TWinControl(g_ComponentList.Items[I]).Visible thenwith TWinControl(g_ComponentList.Items[I]) doSetBounds(Left, Top, Width, Height);end;TWinControl(g_ComponentList.Items[I]).Visible := g_GameLoginConfig.ComponentConfigs[I].Visible;end;//设置游览器位置WebBrowser.Left := g_WebBrowser.Left;WebBrowser.Top := g_WebBrowser.Top;WebBrowser.Width := g_WebBrowser.Width;WebBrowser.Height := g_WebBrowser.Height;WebBrowser.ParentWindow := Handle;with g_WebBrowser doWebBrowser.SetBounds(Left, Top, Width, Height);
//设置按钮图片for I := 1 to Length(g_GameLoginConfig.ComponentImages) - 1 do beginApplication.ProcessMessages;if TRzBmpButton(g_ComponentList.Items[I - 1]).Visible then beginif (g_GameLoginConfig.ComponentImages[I].UpSize > 0) and (TRzBmpButton(g_ComponentList.Items[I - 1]).Bitmaps.Up <> nil) then beginFileStream.Clear;FileStream.Write(Buffer^, g_GameLoginConfig.ComponentImages[I].UpSize);Buffer := IncPointer(Buffer, g_GameLoginConfig.ComponentImages[I].UpSize);FileStream.Position := 0;TRzBmpButton(g_ComponentList.Items[I - 1]).Bitmaps.Up.LoadFromStream(FileStream);end;if (g_GameLoginConfig.ComponentImages[I].HotSize > 0) and (TRzBmpButton(g_ComponentList.Items[I - 1]).Bitmaps.Hot <> nil) then beginFileStream.Clear;FileStream.Write(Buffer^, g_GameLoginConfig.ComponentImages[I].HotSize);Buffer := IncPointer(Buffer, g_GameLoginConfig.ComponentImages[I].HotSize);FileStream.Position := 0;TRzBmpButton(g_ComponentList.Items[I - 1]).Bitmaps.Hot.LoadFromStream(FileStream);end;if (g_GameLoginConfig.ComponentImages[I].DownSize > 0) and (TRzBmpButton(g_ComponentList.Items[I - 1]).Bitmaps.Down <> nil) then beginFileStream.Clear;FileStream.Write(Buffer^, g_GameLoginConfig.ComponentImages[I].DownSize);Buffer := IncPointer(Buffer, g_GameLoginConfig.ComponentImages[I].DownSize);FileStream.Position := 0;TRzBmpButton(g_ComponentList.Items[I - 1]).Bitmaps.Down.LoadFromStream(FileStream);end;if (g_GameLoginConfig.ComponentImages[I].Disabled > 0) and (TRzBmpButton(g_ComponentList.Items[I - 1]).Bitmaps.Disabled <> nil) then beginFileStream.Clear;FileStream.Write(Buffer^, g_GameLoginConfig.ComponentImages[I].Disabled);Buffer := IncPointer(Buffer, g_GameLoginConfig.ComponentImages[I].Disabled);FileStream.Position := 0;TRzBmpButton(g_ComponentList.Items[I - 1]).Bitmaps.Disabled.LoadFromStream(FileStream);end;end;end;FreeMem(g_Buffer);FileStream.Free;//设置列表TreeView.Color := g_GameLoginConfig.ViewBColor;TreeView.Font.Color := g_GameLoginConfig.ViewFColor;g_boReadSkin := True;
end;procedure TfrmMain.TimerReakSkinTimer(Sender: TObject);
beginTimerReakSkin.Enabled := False;ReadSkin;
end;initializationbeging_ComponentList := TList.Create;end;
finalizationbeging_ComponentList.Free;end;
end.

编写GOM引擎登录器,直接启动GOM客户端DAT文件不掉线相关推荐

  1. 传奇单机架设教程——GOM引擎登录器配置教程

    传奇单机架设教程--GOM引擎登录器配置教程 1.安装DBC,配置引擎 2.上传列表,配置登录器 3.安装客户端,解压补丁 4.登录游戏 架设传奇单机需要准备以下程序: 传奇服务端(版本Mirserv ...

  2. 传奇GOM引擎登录器生成配置教程

    传奇GOM引擎登录器生成配置教程 本课教学流程与方法也适用于GEE引擎登录器的配置,略过第一步直接使用版本里自带的登录器配置器即可 我们讲第三课的时候站长已经为VIP学员附带了GOM引擎登录器更新包( ...

  3. 传奇战盟GOM引擎登录器配置教程

    战盟GOM引擎配置器教程,先到战盟官方网站下载登录器配置器,下载好后按下面说明使用.战盟GOM登录器教程大分类目录引导说明 一.解压配置器文件包后,打开KEY文件夹然后选择KEY 二.复制你选择好的 ...

  4. gom引擎登录器_GOM传奇引擎微端配置详细架设语音教程

    今天分享的教程:GOM引擎微端配置详细语音教程 什么是微端? 就是玩家不需要下载补丁文件,就可以进入游戏并显示游戏界面. 玩家玩到那里,补丁文件就自动更新到那里.当然支持微端的引擎不是很多. 比如LE ...

  5. 传奇GOM引擎登录器配置教程

    登录器教程大分类目录引导说明 (01): 解压配置器文件包后,打开KEY文件夹然后选择KEY (02): 战盟官方提供5种不同功能KEY,请打开KEY文件夹里面有载图说明功能,选择你需要的功能KEY使 ...

  6. 关于传奇皓月GOM引擎登录器配置与生成完整教程

    欢迎使用皓月GOM登录器生成器 **首先到皓月登录器官网下载最新版登陆器生成器,下载完成后请按照下面的说明操作. 01:解压配置器压缩文件包,打开KEY文件夹(解压密码为 gom.hym2.com) ...

  7. GOM引擎登录器配置教程

    GOM引擎我最近发布的比较多了,其他的坛友我都喜欢分享这款引擎的版本,原因就是这款引擎的版本都非常的漂亮,功能系统非常的多,活动和玩法也都非常的丰富,还有很多的功能是其他引擎无法做到的,所以我最近研究 ...

  8. 传奇GM问答时间-GOM引擎登录器生成器设置+列表优化修改

    教程准备: 0325注册机.0325登陆器生成器. 登陆器生成器设置 无论登陆器选择有还是无签名,都会报毒. 背景图片格式有点要是BMP 分辨率设置:默认的800x1920 600x1080 1024 ...

  9. GOM传奇引擎登录器商业版与免费版的区别

    商业版与免费版登录器的区别: 1商业版自定义界面功能可以保存配置 2商业版登录器支持读取二次加密的Pak.需要购买Pak二次加密工具. 3商业版增加数字证书,防止杀毒软件误报 4商业版支持163博客远 ...

  10. 传奇开服一条龙GEE引擎登录器配置教程

    1.首先我们打开我们版本文件夹找到登录器文件夹进入找到GEE登录器配置器(MakeGameLogin.exe)打开 2.接下来开始填写我们的主列表和备列表,这时候我们要自己创建一个列表,因为登录器自带 ...

最新文章

  1. jquery text html width heigth的用法
  2. 【P1326】超级教主
  3. 编程之美-蚂蚁爬杆方法整理
  4. vivado在远程服务器上完成本地设备的程序烧写和调试(vivado远程调试)
  5. html语言简单,简单的html语言计算器
  6. ios开发笔记之 线程间通信
  7. spark stage 划分 源码
  8. python xml.dom模块解析xml
  9. MySQL索引背后的数据结构及算法原理(employees实例)
  10. 全图中第K小路径/团问题(有向/无向)
  11. MySQL多表-笔记
  12. 中国DNA测序在药物发现市场中的应用市场深度研究分析报告
  13. 【Greenplum走遍全国】济南技术研讨会
  14. Find My资讯|苹果 Find My 找到因交通事故坠崖的一名女子
  15. 计算机网络与通信实验报告——HTTP协议分析
  16. mac外接显示器 竖屏 黑苹果_借人气问一个黑苹果外接显示器的问题
  17. 淘宝/天猫盗图投诉之提交盗图申诉材料时,图片过大,如何缩小呢?
  18. Android架构组件Room功能详解,面试必问
  19. 计算型存储: 异构计算的下一个关键应用
  20. 计算机主机是否接电源,台式机电脑主机电源是否损坏准确检测方法/步骤

热门文章

  1. windows下安装,配置gcc编译器
  2. linux gnu编译器下载,GNU Compiler Collection(gcc编译器)下载_GNU Compiler Collection(gcc编译器)官方下载-太平洋下载中心...
  3. Trend Micro officescan隔离删除文件恢复
  4. 分享一个好看的个人主页源码
  5. 精美的拟态个人主页源码
  6. mysql数据库异地备份
  7. github安卓版下载_Pandownload安卓版+IDM神器,手机还有下载不了的资源吗?
  8. 如何用Primer6批量设计引物(非全cDNA引物)
  9. 欧姆龙编程软件SysmacStudio卸载方法
  10. J1939 入门教程