2012年7月5日星期四

MessageBox.asm


;额外的说明,如果要在连接的时候加入一个资源选项,这个资源选项是一个xml文件,功能是在windows 7中以管理员运行,MessageBox可能会运行不会失败,但就是弹不出消息框,可能是我的xml文件写错了。
.386
.model flat,stdcall
option casemap:none
include windows.inc

include kernel32.inc
includelib kernel32.lib

include user32.inc
includelib user32.lib

.code
szSoftModalMessageBox db "SoftModalMessageBox",0
szMessageBoxIndirect db "MessageBoxIndirectA",0
szMessageBoxTimeoutA db "MessageBoxTimeoutA",0
szMessageBoxExA db "MessageBoxExA",0
szuser32 db "user32.dll",0

huser32 dd 0
pMessageBoxExA dd 0
pMessageBoxTimeoutA dd 0
pMessageBoxIndirect dd 0

szcaption db "made by correy",0
sztext db "http://correy.webs.com",0
my_MSGBOXPARAMSA dd 40,0,0,offset sztext,offset szcaption,0,0,0,0,0

msgboxProc proc lparam:LPARAM
  invoke MessageBox,0,0,0,MB_TOPMOST ;好像必须加MB_TOPMOST才能显示在csrss.exe进程中。
  ret                                                              ;另一种办法是在uType参数中加入MB_SERVICE_NOTIFICATION属性。
msgboxProc endp

u_correy dw 'c','o','r','r','e','y',0

MSGBOXDATA struct ;其实SoftModalMessageBox和MessageBoxIndirect一样简单,就是填充好一个结构。为了省事,我不在自己写例子了。
  params              MSGBOXPARAMS <>
  pwndOwner           DWORD ?
  wLanguageId         DWORD ?
  pidButton           DWORD ?         ; // Array of button IDs
  ppszButtonText      DWORD ?         ; // Array of button text strings
  cButtons            DWORD ?
  DefButton           DWORD ?
  CancelId            DWORD ?
  Timeout             DWORD ?
MSGBOXDATA ends

num  equ 10

CallProc proc uses ebx lparam:LPARAM
  local mbd:MSGBOXDATA
  local bufid[num]:DWORD
  local bufstr[num]:DWORD
  lea eax,bufid
  lea edx,bufstr
  xor ecx,ecx
  .while ecx!=num
    mov ebx,ecx
    inc ebx
    mov dword ptr[eax+4*ecx],ebx
    mov dword ptr[edx+4*ecx],offset u_correy
    inc ecx
    inc ebx
  .endw
  mov mbd.params.cbSize,sizeof MSGBOXPARAMS
  mov mbd.params.hwndOwner,0
  mov mbd.params.lpszText,offset u_correy
  mov mbd.params.lpszCaption,offset u_correy
  mov mbd.params.dwStyle,MB_ICONQUESTION or MB_SERVICE_NOTIFICATION or MB_TOPMOST or MB_DEFAULT_DESKTOP_ONLY ; or MB_RIGHT
  mov mbd.pwndOwner,0
  mov mbd.wLanguageId,0
  mov mbd.pidButton,eax
  mov mbd.ppszButtonText,edx
  mov mbd.cButtons,num
  mov mbd.DefButton,4
  mov mbd.CancelId,0
  mov mbd.Timeout,-1
  lea eax,mbd
  push eax
  call lparam ;这其实是正规调用方式的一种变形。
  ret
CallProc endp

start:

invoke LoadLibrary,addr szuser32
mov huser32,eax

invoke GetProcAddress,huser32,addr szMessageBoxExA
mov pMessageBoxExA,eax

push 0 ;句柄
push 0
push 0
push 0
push 0
call MessageBoxExA

invoke GetProcAddress,huser32,addr szMessageBoxTimeoutA
mov pMessageBoxTimeoutA,eax

push 3000 ;时间,-1是无限。
push 0    ;句柄
push 0
push 0
push 0
push 0
call pMessageBoxTimeoutA

invoke GetProcAddress,huser32,addr szMessageBoxIndirect
mov pMessageBoxIndirect,eax
push offset my_MSGBOXPARAMSA
call pMessageBoxIndirect ;其实这个变量可以省略。

invoke CreateThread,0,0,offset msgboxProc,0,0,0
invoke CloseHandle,eax

invoke GetProcAddress,huser32,addr szSoftModalMessageBox
;push 0 ;SoftModalMessageBox是有一个参数的。是一个结构的地址。 
;call eax ;下面的c++代码是正规的,规范的调用方式。
invoke CallProc,eax

exit:invoke ExitProcess,0
end start
;made at 2011.08.10
;一下代码是c/c++的。

mov eax,11d0
mov edx,7ffeo300
call ntdll.kifastSystemCall

;;;;;;;;;;;;;;;;;;;;;;;;;;

void CMessageBoxesDlg::DoSoftModalMessageBox (DWORD dwFlags)
{
    struct MSGBOXDATA
    {
        MSGBOXPARAMS mbp;
        DWORD hwndOwner;
        DWORD wLanguageId;
        DWORD pidButton;
        DWORD ppszButtonText;
        DWORD dwButtons;
        DWORD dwDefButton;
        DWORD dwCancelId;
        DWORD dwTimeout;
    };

    MSGBOXDATA data = {};
    data.mbp.cbSize = sizeof (MSGBOXPARAMS);
    data.mbp.hInstance = AfxGetInstanceHandle ();
    data.mbp.lpszText = MAKEINTRESOURCE (IDS_SOFTMADALMESSAGEBOXTEXT);
    data.mbp.lpszCaption = m_caption;
    data.mbp.lpfnMsgBoxCallback = SoftModalMessageBoxCallback;
    data.mbp.dwStyle = dwFlags;

    DWORD pids [5] = 
    {
        1, 2, 3, 4, 5
    };
    const wchar_t * ppText [5] = 
    {
        L"1", L"2", L"3", L"4", L"5"
    };

    data.pidButton = (DWORD)pids;
    data.ppszButtonText = (DWORD)ppText;
    data.dwButtons = 5;
    data.dwDefButton = 1;
    data.dwCancelId = 1;
    data.dwTimeout = 5000;
    int res = 0;

    HMODULE h = LoadLibrary (L"user32.dll");
    if (h != NULL)
    {
        typedef int (WINAPI *SOFTMODALMESSAGEBOX) (MSGBOXDATA * pMsgData);
        SOFTMODALMESSAGEBOX SoftModalMessageBox = (SOFTMODALMESSAGEBOX)GetProcAddress (h, "SoftModalMessageBox");
        if (SoftModalMessageBox != NULL)
        {
            res = SoftModalMessageBox (&data);
        }
        else
            ::MessageBoxW (NULL, L"SoftModalMessageBoxW not found in user32.dll", m_caption, MB_ICONSTOP);
        FreeLibrary (h);
    }
    else
        ::MessageBoxW (NULL, L"Cannot load user32.dll", m_caption, MB_ICONSTOP);
}

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
以下两个函数由user32.dll导出,只是没有微软官方文档记载,大家在cpp中包含了以下部分,就可以调用MessageBoxTimeout了。
extern "C"
{
int WINAPI MessageBoxTimeoutA(IN HWND hWnd, IN LPCSTR lpText, IN LPCSTR lpCaption, IN UINT uType, IN WORD wLanguageId, IN DWORD dwMilliseconds);
int WINAPI MessageBoxTimeoutW(IN HWND hWnd, IN LPCWSTR lpText, IN LPCWSTR lpCaption, IN UINT uType, IN WORD wLanguageId, IN DWORD dwMilliseconds);
};
#ifdef UNICODE
#define MessageBoxTimeout MessageBoxTimeoutW
#else
#define MessageBoxTimeout MessageBoxTimeoutA
#endif 
需要指出的是,Windows 2000的user32.dll没有导出这个函数。
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;补上吧!
;关于函数的返回值,也就是你选择了哪个按钮,有待进一步的研究。
.386
.model flat,stdcall
option casemap:none
include windows.inc

include kernel32.inc
includelib kernel32.lib

include user32.inc
includelib user32.lib

.code
szSoftModalMessageBox db "SoftModalMessageBox",0
szuser32 db "user32.dll",0

huser32 dd 0
pSoftModalMessageBox dd 0

align 4

u_ok dw 'o','k',0
u_no dw 'n','o',0

bufid dword 1,2;,0 ;按钮id的序列,可以增加。也可以一个按钮也没有哟!最多支持有多少个按钮,你可以试一下!
bufstr dword offset u_ok,offset u_no;,0 ;按钮的内容,可以增加。

szCaption dw 'm','a','d','e',' ','b','y',' ','c','o','r','r','e','y',0
szText dw 'W','e','l','l','c','o','m','e',' ','t','o',' ','H','t','t','p',':','/','/','c','o','r','r','e','y','.','w','e','b','s','.','c','o','m',0

align 4 ;最好加上,不加也没有事。
mbd dd 28h ;sizeof MSGBOXPARAMS
    dd 0 ;hwndOwner
    dd 0 ;hInstance
    dd offset szText ;lpszText
    dd offset szCaption ;lpszCaption
    dd 0 ;dwStyle
    dd 0 ;lpszIcon
    dd 0 ;dwContextHelpId
    dd 0 ;lpfnMsgBoxCallback
    dd 0 ;dwLanguageId
    ;MSGBOXPARAMS 结构结束。一下是附加的定义的结构。
    dd 0 ;pwndOwner
    dd 0 ;wLanguageId
    ;dd 0 ;windows 7-64下要加这一行,可能结构变了,不然:不会显示按钮,具体的啥功能我也不知道,还没有实验。
          ;因为这个,我浪费了大半天的时间。在非windows 7-64操作系统下要去掉这一行。版权归我所有,我的新发现。
    dd offset bufid ;pidButton
    dd offset bufstr ;ppszButtonText
    dd 2 ;cButtons 按钮的数量。
    dd 0 ;DefButton 默认的按钮。
    dd 1 ;CancelId 0 1
    dd -1 ;Timeout
    ;注释:下面这个是我自己附加的。
    dd 0 ;奇哉怪哉,这样点击就不会出错了,下面的加align 4也不行。自己的新发现,必须加这一行。
    
align 4
start:
align 4

invoke LoadLibrary,addr szuser32
mov huser32,eax

invoke GetProcAddress,huser32,addr szSoftModalMessageBox
mov pSoftModalMessageBox,eax

pushad
;pushf

push offset mbd
call pSoftModalMessageBox

;popf
popad

exit:invoke ExitProcess,0
end start
;made at 2011.08.17

没有评论:

发表评论