怎样修改系统函数?(300!!!)(300分)

  • 主题发起人 主题发起人 chenke
  • 开始时间 开始时间
C

chenke

Unregistered / Unconfirmed
GUEST, unregistred user!
如修改Textout函数,用自己的输出函数代替系统的,如何恢复?<br>sample:<br>&nbsp;procedure mytextout;<br>&nbsp;begin<br>&nbsp; &nbsp;恢复系统的Textout;<br>&nbsp; &nbsp;my process;<br>&nbsp; &nbsp;加载我的Textout;<br>&nbsp;end;
 
Textout,ExtTextout都是系统最基本的画字符的函数了, 除非你使paint, 否则往任<br>何地方写字符都需要这个函数.
 
可以把TextOut的原代码copy出来,做个新函数!
 
下面是一个系统函数重定位的例子,从&lt;&lt;计算机世界日报&gt;&gt;上Copy出来的.<br>&nbsp; &nbsp; //源程序 relocate.c<br>&nbsp; &nbsp; #include &lt;WINDOWS.H&gt;<br>&nbsp; &nbsp; #include &lt;dos.h&gt;<br>&nbsp; &nbsp; BOOL WINAPI MyExtTextOut(HDC hDC, int x, int y, UINT nIn<br>t1, const RECTFAR*p Rect,LPCSTR lpStr, UINT nInt2, int FAR* <br>lpInt);<br>&nbsp; &nbsp; WORD FAR PASCAL AllocCStoDSAlias(WORD code_sel);<br>&nbsp; &nbsp; typedef struct tagFUNC<br>&nbsp; &nbsp; {<br>&nbsp; &nbsp; FARPROC lpFarProcReplace; &nbsp;//替代函数地址<br>&nbsp; &nbsp; FARPROC lpFarProcWindows; &nbsp;//Windows函数地址<br>&nbsp; &nbsp; BYTE &nbsp; &nbsp;bOld; &nbsp; &nbsp; &nbsp; &nbsp;//保存原函数第一字节<br>&nbsp; &nbsp; LONG &nbsp; &nbsp;lOld; &nbsp; &nbsp; &nbsp; &nbsp;//保存原函数接后的四字节长值<br>&nbsp; &nbsp; }FUNC;<br>&nbsp; &nbsp; FUNC &nbsp;Func={MyExtTextOut,ExtTextOut};<br>&nbsp; &nbsp; //Windows主函数<br>&nbsp; &nbsp; int PASCAL WinMain(HINSTANCE hInstance,HINSTANCE hPrevIn<br>stance,LPSTR lpCmdi ne,int nCmdShow){<br>&nbsp; &nbsp; HANDLE hMemCode; &nbsp;//代码段句柄<br>&nbsp; &nbsp; WORD hMemData; &nbsp; &nbsp;//相同基址的可写数据段别名<br>&nbsp; &nbsp; WORD &nbsp; wOffset; &nbsp; //函数偏移<br>&nbsp; &nbsp; LPSTR &nbsp;lpStr;<br>&nbsp; &nbsp; LPLONG lpLong;<br>&nbsp; &nbsp; char &nbsp; lpNotice[96];<br>&nbsp; &nbsp; hMemCode=HIWORD((LONG) Func.lpFarProcWindows );<br>&nbsp; &nbsp; wOffset=LOWORD((LONG) Func.lpFarProcWindows );<br>&nbsp; &nbsp; wsprintf(lpNotice,"函数所在模块句柄 0x%4xH,偏移 0x%4xH",<br>hMemCode,wOffset);<br>&nbsp; &nbsp; &nbsp;MessageBox(NULL,lpNotice,"提示",MB_OK);<br>&nbsp; &nbsp; &nbsp;//取与代码段有相同基址的可写数据段别名<br>&nbsp; &nbsp; &nbsp;hMemData=AllocCStoDSAlias(hMemCode);<br>&nbsp; &nbsp; &nbsp;lpStr=GlobalLock(hMemData);<br>&nbsp; &nbsp; &nbsp;lpLong=(lpStr+wOffset+1 );<br>&nbsp; &nbsp; &nbsp;//保存原函数要替换的头几个字节<br>&nbsp; &nbsp; Func.bOld=*(lpStr+wOffset);<br>&nbsp; &nbsp; Func.lOld=*lpLong;<br>&nbsp; &nbsp; *(lpStr+wOffset)=0xEA;<br>&nbsp; &nbsp; *lpLong=Func.lpFarProcReplace;<br>&nbsp; &nbsp; GlobalUnlock(hMemData);<br>&nbsp; &nbsp; MessageBox(NULL,"改为自己的函数","提示",MB_OK);<br>&nbsp; &nbsp; //将保留的内容改回来<br>&nbsp; &nbsp; hMemData=AllocCStoDSAlias(hMemCode);<br>&nbsp; &nbsp; lpStr=GlobalLock(hMemData);<br>&nbsp; &nbsp; lpLong=(lpStr+wOffset+1 );<br>&nbsp; &nbsp; *(lpStr+wOffset)=Func.bOld;<br>&nbsp; &nbsp; *lpLong=Func.lOld;<br>&nbsp; &nbsp; GlobalUnlock(hMemData);<br>&nbsp; &nbsp; MessageBox(NULL,"改回原Windows函数","提示",MB_OK);<br>&nbsp; &nbsp; return 1;<br>&nbsp; &nbsp; }<br>&nbsp; &nbsp; //自己的替代函数<br>&nbsp; &nbsp; BOOL WINAPI MyExtTextOut(HDC hDC, int x, int y, UINT nIn<br>t1, const RECT FAR lpRect, LPCSTR lpStr, UINT nInt2, int FAR<br>* lpInt){<br>&nbsp; &nbsp; BYTE NameDot[96]={<br>&nbsp; &nbsp; 0x09, 0x00, 0xfd, 0x08, 0x09, 0x08, 0x09, 0x10, 0x09, 0x<br>20,<br>&nbsp; &nbsp; 0x79, 0x40, 0x41, 0x04, 0x47, 0xfe, 0x41, 0x40, 0x79, 0x<br>40,<br>&nbsp; &nbsp; 0x09, 0x20, 0x09, 0x20, 0x09, 0x10, 0x09, 0x4e, 0x51, 0x<br>84,<br>&nbsp; &nbsp; 0x21, 0x00, 0x02, 0x00, 0x01, 0x04, 0xff, 0xfe, 0x00, 0x<br>00,<br>&nbsp; &nbsp; 0x1f, 0xf0, 0x10, 0x10, 0x10, 0x10, 0x1f, 0xf0, 0x00, 0x<br>00,<br>&nbsp; &nbsp; 0x7f, 0xfc, 0x40, 0x04, 0x4f, 0xe4, 0x48, 0x24, 0x48, 0x<br>24,<br>&nbsp; &nbsp; 0x4f, 0xe4, 0x40, 0x0c, 0x10, 0x80, 0x10, 0xfc, 0x10, 0x<br>88,<br>&nbsp; &nbsp; 0x11, 0x50, 0x56, 0x20, 0x54, 0xd8, 0x57, 0x06, 0x54, 0x<br>20,<br>&nbsp; &nbsp; 0x55, 0xfc, 0x54, 0x20, 0x55, 0xfc, 0x5c, 0x20, 0x67, 0x<br>fe,<br>&nbsp; &nbsp; 0x00, 0x20, 0x00, 0x20, 0x00, 0x20<br>&nbsp; &nbsp; };<br>&nbsp; &nbsp; HBITMAP hBitmap,hOldBitmap;<br>&nbsp; &nbsp; HDC &nbsp; &nbsp; hMemDC;<br>&nbsp; &nbsp; BYTE far *lpDot;<br>&nbsp; &nbsp; int &nbsp; &nbsp; i;<br>&nbsp; &nbsp; for ( i=0;i&lt;3;i++ )<br>&nbsp; &nbsp; {<br>&nbsp; &nbsp; lpDot=(LPSTR)NameDot+i*32;<br>&nbsp; &nbsp; hMemDC=CreateCompatibleDC(hDC);<br>&nbsp; &nbsp; hBitmap=CreateBitmap(16,16,1,1,lpDot);<br>&nbsp; &nbsp; SetBitmapBits(hBitmap,32L,lpDot);<br>&nbsp; &nbsp; hOldBitmap=SelectObject(hMemDC,hBitmap);<br>&nbsp; &nbsp; BitBlt(hDC,x+i*16,y,16,16,hMemDC,0,0,SRCCOPY);<br>&nbsp; &nbsp; DeleteDC(hMemDC);<br>&nbsp; &nbsp; DeleteObject(hBitmap);<br>&nbsp; &nbsp; }<br>&nbsp; &nbsp; return TRUE;<br>&nbsp; &nbsp; }<br><br>&nbsp; &nbsp; //模块定义文件 &nbsp;relocate.def<br>&nbsp; &nbsp; NAME &nbsp; &nbsp;RELOCATE<br>&nbsp; &nbsp; EXETYPE &nbsp; WINDOWS<br>&nbsp; &nbsp; CODE &nbsp; &nbsp; &nbsp;PRELOAD MOVEABLE DISCARDABLE<br>&nbsp; &nbsp; DATA &nbsp; &nbsp; &nbsp;PRELOAD MOVEABLE MULTIPLE<br>&nbsp; &nbsp; HEAPSIZE &nbsp;1024<br>&nbsp; &nbsp; EXPORTS
 
下面是一个系统函数重定位的例子,从&lt;&lt;计算机世界日报&gt;&gt;上Copy出来的.<br><br>&nbsp; &nbsp; //源程序 relocate.c<br>&nbsp; &nbsp; #include &lt;WINDOWS.H&gt;<br>&nbsp; &nbsp; #include &lt;dos.h&gt;<br>&nbsp; &nbsp; BOOL WINAPI MyExtTextOut(HDC hDC, int x, int y, UINT nIn<br>t1, const RECTFAR*p Rect,LPCSTR lpStr, UINT nInt2, int FAR* <br>lpInt);<br>&nbsp; &nbsp; WORD FAR PASCAL AllocCStoDSAlias(WORD code_sel);<br>&nbsp; &nbsp; typedef struct tagFUNC<br>&nbsp; &nbsp; {<br>&nbsp; &nbsp; FARPROC lpFarProcReplace; &nbsp;//替代函数地址<br>&nbsp; &nbsp; FARPROC lpFarProcWindows; &nbsp;//Windows函数地址<br>&nbsp; &nbsp; BYTE &nbsp; &nbsp;bOld; &nbsp; &nbsp; &nbsp; &nbsp;//保存原函数第一字节<br>&nbsp; &nbsp; LONG &nbsp; &nbsp;lOld; &nbsp; &nbsp; &nbsp; &nbsp;//保存原函数接后的四字节长值<br>&nbsp; &nbsp; }FUNC;<br>&nbsp; &nbsp; FUNC &nbsp;Func={MyExtTextOut,ExtTextOut};<br>&nbsp; &nbsp; //Windows主函数<br>&nbsp; &nbsp; int PASCAL WinMain(HINSTANCE hInstance,HINSTANCE hPrevIn<br>stance,LPSTR lpCmdi ne,int nCmdShow){<br>&nbsp; &nbsp; HANDLE hMemCode; &nbsp;//代码段句柄<br>&nbsp; &nbsp; WORD hMemData; &nbsp; &nbsp;//相同基址的可写数据段别名<br>&nbsp; &nbsp; WORD &nbsp; wOffset; &nbsp; //函数偏移<br>&nbsp; &nbsp; LPSTR &nbsp;lpStr;<br>&nbsp; &nbsp; LPLONG lpLong;<br>&nbsp; &nbsp; char &nbsp; lpNotice[96];<br>&nbsp; &nbsp; hMemCode=HIWORD((LONG) Func.lpFarProcWindows );<br>&nbsp; &nbsp; wOffset=LOWORD((LONG) Func.lpFarProcWindows );<br>&nbsp; &nbsp; wsprintf(lpNotice,"函数所在模块句柄 0x%4xH,偏移 0x%4xH",<br>hMemCode,wOffset);<br>&nbsp; &nbsp; &nbsp;MessageBox(NULL,lpNotice,"提示",MB_OK);<br>&nbsp; &nbsp; &nbsp;//取与代码段有相同基址的可写数据段别名<br>&nbsp; &nbsp; &nbsp;hMemData=AllocCStoDSAlias(hMemCode);<br>&nbsp; &nbsp; &nbsp;lpStr=GlobalLock(hMemData);<br>&nbsp; &nbsp; &nbsp;lpLong=(lpStr+wOffset+1 );<br>&nbsp; &nbsp; &nbsp;//保存原函数要替换的头几个字节<br>&nbsp; &nbsp; Func.bOld=*(lpStr+wOffset);<br>&nbsp; &nbsp; Func.lOld=*lpLong;<br>&nbsp; &nbsp; *(lpStr+wOffset)=0xEA;<br>&nbsp; &nbsp; *lpLong=Func.lpFarProcReplace;<br>&nbsp; &nbsp; GlobalUnlock(hMemData);<br>&nbsp; &nbsp; MessageBox(NULL,"改为自己的函数","提示",MB_OK);<br>&nbsp; &nbsp; //将保留的内容改回来<br>&nbsp; &nbsp; hMemData=AllocCStoDSAlias(hMemCode);<br>&nbsp; &nbsp; lpStr=GlobalLock(hMemData);<br>&nbsp; &nbsp; lpLong=(lpStr+wOffset+1 );<br>&nbsp; &nbsp; *(lpStr+wOffset)=Func.bOld;<br>&nbsp; &nbsp; *lpLong=Func.lOld;<br>&nbsp; &nbsp; GlobalUnlock(hMemData);<br>&nbsp; &nbsp; MessageBox(NULL,"改回原Windows函数","提示",MB_OK);<br>&nbsp; &nbsp; return 1;<br>&nbsp; &nbsp; }<br>&nbsp; &nbsp; //自己的替代函数<br>&nbsp; &nbsp; BOOL WINAPI MyExtTextOut(HDC hDC, int x, int y, UINT nIn<br>t1, const RECT FAR lpRect, LPCSTR lpStr, UINT nInt2, int FAR<br>* lpInt){<br>&nbsp; &nbsp; BYTE NameDot[96]={<br>&nbsp; &nbsp; 0x09, 0x00, 0xfd, 0x08, 0x09, 0x08, 0x09, 0x10, 0x09, 0x<br>20,<br>&nbsp; &nbsp; 0x79, 0x40, 0x41, 0x04, 0x47, 0xfe, 0x41, 0x40, 0x79, 0x<br>40,<br>&nbsp; &nbsp; 0x09, 0x20, 0x09, 0x20, 0x09, 0x10, 0x09, 0x4e, 0x51, 0x<br>84,<br>&nbsp; &nbsp; 0x21, 0x00, 0x02, 0x00, 0x01, 0x04, 0xff, 0xfe, 0x00, 0x<br>00,<br>&nbsp; &nbsp; 0x1f, 0xf0, 0x10, 0x10, 0x10, 0x10, 0x1f, 0xf0, 0x00, 0x<br>00,<br>&nbsp; &nbsp; 0x7f, 0xfc, 0x40, 0x04, 0x4f, 0xe4, 0x48, 0x24, 0x48, 0x<br>24,<br>&nbsp; &nbsp; 0x4f, 0xe4, 0x40, 0x0c, 0x10, 0x80, 0x10, 0xfc, 0x10, 0x<br>88,<br>&nbsp; &nbsp; 0x11, 0x50, 0x56, 0x20, 0x54, 0xd8, 0x57, 0x06, 0x54, 0x<br>20,<br>&nbsp; &nbsp; 0x55, 0xfc, 0x54, 0x20, 0x55, 0xfc, 0x5c, 0x20, 0x67, 0x<br>fe,<br>&nbsp; &nbsp; 0x00, 0x20, 0x00, 0x20, 0x00, 0x20<br>&nbsp; &nbsp; };<br>&nbsp; &nbsp; HBITMAP hBitmap,hOldBitmap;<br>&nbsp; &nbsp; HDC &nbsp; &nbsp; hMemDC;<br>&nbsp; &nbsp; BYTE far *lpDot;<br>&nbsp; &nbsp; int &nbsp; &nbsp; i;<br>&nbsp; &nbsp; for ( i=0;i&lt;3;i++ )<br>&nbsp; &nbsp; {<br>&nbsp; &nbsp; lpDot=(LPSTR)NameDot+i*32;<br>&nbsp; &nbsp; hMemDC=CreateCompatibleDC(hDC);<br>&nbsp; &nbsp; hBitmap=CreateBitmap(16,16,1,1,lpDot);<br>&nbsp; &nbsp; SetBitmapBits(hBitmap,32L,lpDot);<br>&nbsp; &nbsp; hOldBitmap=SelectObject(hMemDC,hBitmap);<br>&nbsp; &nbsp; BitBlt(hDC,x+i*16,y,16,16,hMemDC,0,0,SRCCOPY);<br>&nbsp; &nbsp; DeleteDC(hMemDC);<br>&nbsp; &nbsp; DeleteObject(hBitmap);<br>&nbsp; &nbsp; }<br>&nbsp; &nbsp; return TRUE;<br>&nbsp; &nbsp; }<br>&nbsp; &nbsp; //模块定义文件 &nbsp;relocate.def<br>&nbsp; &nbsp; NAME &nbsp; &nbsp;RELOCATE<br>&nbsp; &nbsp; EXETYPE &nbsp; WINDOWS<br>&nbsp; &nbsp; CODE &nbsp; &nbsp; &nbsp;PRELOAD MOVEABLE DISCARDABLE<br>&nbsp; &nbsp; DATA &nbsp; &nbsp; &nbsp;PRELOAD MOVEABLE MULTIPLE<br>&nbsp; &nbsp; HEAPSIZE &nbsp;1024<br>&nbsp; &nbsp; EXPORTS<br>
 
dubhe的答案正是我要找的答案,如果试验成功,马上给分!<br>不过AllocCStoDSAlias是16位的函数,在win95下好像找不到。:-(<br>能有其他方法替代这个函数吗?另外能否告诉我是计算机世界第几期,<br>能否用Delphi改写?再次谢谢dubhe.
 
GUIHook95 and GUIHookNT have already demostrate this technic.
 
dubhe的答案是用于Windows 3.0的, Windows 3.1就不用了.
 
是呀,我刚刚试了一下,在16位下得到TextOut函数地址是正确的,32位环境下不正确,能不能得到地址部分用16位动态库,其他部分用32位,或干脆textout<br>地址用固定地址代替,好像都是一个定植,这样可以吗?<br>
 
自己的函数地址用GetProAddress从动态库中得到。
 
刚才我试了一下金山词霸,发现它的修改系统函数的dll是16位的,<br>而且用到了AllocCStoDSAlias函数,两岸通则是纯16位的,不过很奇怪,<br>金山词霸的16位dll的期望运行版本竟然是win4.0,这如何做到?<br>是不是Thunk调用起来更方便,另外,在深度历险上有个Noclick控件,<br>纯32的dll,可以屏幕抓词(不过功能不强),不知如何实现?<br>有没有Thunk控件,我Thunk调用起来老出错。
 
Thunk在深度立宪就有例子,(你如找不到,我可以<br>e-mail给你)<br>词霸确实是16位的(32位很麻烦,前面有关于这的讨论),用VC编的.<br>IE4.0需要做特殊处理才能取词<br><br>
 
to &nbsp;jiangtao:谢谢,我已有thunk的例子,是w32dll16,zthunk,cthunk等,<br>能否为我详细解释一下ie下如何取词,32位如何做,为了这些问题已花了我将<br>近5,6百分了.:-(
 
谢谢大虾们的帮助,Thunk问题已经解决,但是把TextHook用Delphi1.0改写成<br>dll时出现了一些问题,如下:<br>Library Myhook1;<br>uses<br>&nbsp; SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,<br>&nbsp; StdCtrls, Dialogs;<br>const WM_TextHook=WM_USER+$101;<br>var<br>&nbsp; &nbsp; &nbsp;OldAddr,NewAddr:array[0..4] of byte;<br><br>function &nbsp;MyTextOut( hdc:HDC; &nbsp;nxStart:integer; &nbsp;nyStart:integer; &nbsp;lpszString:PChar; cbstring:integer):boolean;far;<br>begin<br>postmessage(FindWindow(nil,'Form1'),WM_TextHook,1,LongIntlpszString));<br>{在MyTextOut中不加任何代码,没有问题,加入则出现异常?}<br>Result:=True;<br>end;<br><br>procedure Install;<br>var segment,offset,DsSegment,NewSegment,NewOffset:Word;<br>begin<br>&nbsp;Segment:=Seg(TextOut);<br>&nbsp;Offset:=Ofs(TextOut);<br>&nbsp;DsSegment:=AllocCStoDSAlias(Segment);<br>{ Showmessage(Format('%x',[dssegment]));}<br>&nbsp;GlobalLock(DsSegment);<br>&nbsp;OldAddr[0]:=PByte(Ptr(DsSegment,Offset+0))^;<br>&nbsp;OldAddr[1]:=PByte(Ptr(DsSegment,Offset+1))^;<br>&nbsp;OldAddr[2]:=PByte(Ptr(DsSegment,Offset+2))^;<br>&nbsp;OldAddr[3]:=PByte(Ptr(DsSegment,Offset+3))^;<br>&nbsp;OldAddr[4]:=PByte(Ptr(DsSegment,Offset+4))^;<br>{ showmessage(Format('%x,%x,%x,%x,%x,%x',[OldAddr[0],OldAddr[1],OldAddr[2],OldAddr[3],OldAddr[4],DsSegment]));}<br>&nbsp;NewSegment:=Seg(MyTextOut);<br>&nbsp;NewOffset:=Ofs(MyTextOut);<br>&nbsp;NewAddr[0]:=$EA;{jmp}<br>&nbsp;NewAddr[1]:=Lo(NewOffset);<br>&nbsp;NewAddr[2]:=Hi(NewOffset);<br>&nbsp;NewAddr[3]:=Lo(NewSegment);<br>&nbsp;NewAddr[4]:=Hi(NewSegment);<br>{ showmessage(Format('%x,%x,%x,%x,%x,%x',[NewAddr[0],NewAddr[1],NewAddr[2],NewAddr[3],NewAddr[4],DsSegment]));}<br>&nbsp;PByte(Ptr(DsSegment,Offset))^:=NewAddr[0];<br>&nbsp;PByte(Ptr(DsSegment,Offset+1))^:=NewAddr[1];<br>&nbsp;PByte(Ptr(DsSegment,Offset+2))^:=NewAddr[2];<br>&nbsp;PByte(Ptr(DsSegment,Offset+3))^:=NewAddr[3];<br>&nbsp;PByte(Ptr(DsSegment,Offset+4))^:=NewAddr[4];<br>&nbsp;GlobalUnLock(DsSegment);<br>end;<br><br>procedure UnInstall;<br>var segment,offset,DsSegment:Word;<br>begin<br>&nbsp;Segment:=Seg(TextOut);<br>&nbsp;Offset:=Ofs(TextOut);<br>&nbsp;DsSegment:=AllocCStoDSAlias(Segment);<br>{ Showmessage(Format('%x',[dssegment]));}<br>&nbsp;GlobalLock(DsSegment);<br>&nbsp;Segment:=Seg(TextOut);<br>&nbsp;Offset:=Ofs(TextOut);<br>&nbsp;DsSegment:=AllocCStoDSAlias(Segment);<br>&nbsp;GlobalLock(DsSegment);<br>&nbsp;PByte(Ptr(DsSegment,Offset))^:=OldAddr[0];<br>&nbsp;PByte(Ptr(DsSegment,Offset+1))^:=OldAddr[1];<br>&nbsp;PByte(Ptr(DsSegment,Offset+2))^:=OldAddr[2];<br>&nbsp;PByte(Ptr(DsSegment,Offset+3))^:=OldAddr[3];<br>&nbsp;PByte(Ptr(DsSegment,Offset+4))^:=OldAddr[4];<br>&nbsp;GlobalUnLock(DsSegment);<br>end;<br><br>{0 True,other False}<br>function TextHookCreate(input:word):word;export;<br>begin<br>Install;<br>Result:=0;<br>end;<br><br>function TextHookFree(input:word):word;export;<br>begin<br>UnInstall;<br>Result:=0;<br>end;<br><br>exports TextHookCreate Index 1 Name 'TextHookCreate' resident;<br>exports TextHookFree Index 2 Name 'TextHookFree' resident;<br><br>begin<br><br>end.<br>是不是Delphi不能写系统函数?还是..,:-(希望大虾们继续鼎力相助。<br><br><br>
 
希望你解决了问题之后能告诉我一声
 
对这个问题感兴趣,想得到邮件通知,所以留言,对问题本身我毫无见解.8-(
 
chenke :<br>&nbsp; &nbsp; AllocCsToDsAlias是16位函数,不知你在delphi中是怎么调用的.<br>又:解决了问题,请告诉一声.hehe
 
呵呵, EYES快提供意见!<br>
 
一年多了
 
后退
顶部