reactos操作系统实现(169)

来源:互联网 发布:android网络通信 编辑:程序博客网 时间:2024/05/17 04:59

当用USER32.DLL里调用获取消息之后,就调用到WIN32K.SYS里处理的函数NtUserGetMessage,这个函数实现的代码如下:

#001  BOOL APIENTRY

#002  NtUserGetMessage(PNTUSERGETMESSAGEINFOUnsafeInfo,

#003                   HWND hWnd,

#004                   UINT MsgFilterMin,

#005                   UINT MsgFilterMax)

#006  /*

#007   * FUNCTION: Get a message from the callingthread's message queue.

#008   * ARGUMENTS:

#009   *     UnsafeMsg - Pointer to the structure which receives the returnedmessage.

#010   *     Wnd - Window whose messages are to be retrieved.

#011   *     MsgFilterMin - Integer value of the lowest message value to be

#012   *                     retrieved.

#013   *     MsgFilterMax - Integer value of the highest message value to be

#014   *                     retrieved.

#015   */

#016  {

#017     BOOL GotMessage;

#018     NTUSERGETMESSAGEINFO Info;

#019     NTSTATUS Status;

#020     /* FIXME: if initialization is removed,gcc complains that this may be used before initialization. Please review */

#021     PWINDOW_OBJECT Window = NULL;

#022     PMSGMEMORY MsgMemoryEntry;

#023     PVOID UserMem;

#024     UINT Size;

#025     USER_MESSAGE Msg;

#026     DECLARE_RETURN(BOOL);

#027  //  USER_REFERENCE_ENTRY Ref;

#028 

#029     DPRINT("EnterNtUserGetMessage/n");

 

进入临界区代码。

#030     UserEnterExclusive();

#031 

#032     /* Validate input */

 

获取窗口对象,并检查窗口句柄是否有效。

#033     if (hWnd && !(Window =UserGetWindowObject(hWnd)))

#034     {

#035        RETURN(-1);

#036     }

#037 

#038  //   if(Window) UserRefObjectCo(Window, &Ref);

#039 

 

如果设置消息最大值比最小值还小,就使用缺省的方式。

#040     if (MsgFilterMax <MsgFilterMin)

#041     {

#042        MsgFilterMin = 0;

#043        MsgFilterMax = 0;

#044     }

#045 

 

循环地获取消息,直到成功为止。

#046     do

#047     {

 

这里调用函数co_IntPeekMessage来查看消息队列是否有消息。

#048        GotMessage =co_IntPeekMessage(&Msg, hWnd, MsgFilterMin, MsgFilterMax, PM_REMOVE);

#049        if (GotMessage)

#050        {

 

如果获取消息成功。

#051           Info.Msg = Msg.Msg;

#052           /* See if this message type ispresent in the table */

 

查找消息是否在消息表里,如果不在里面不需要分配消息保存的内存,否则就需要给消息分配内存。

#053           MsgMemoryEntry =FindMsgMemory(Info.Msg.message);

#054           if (NULL == MsgMemoryEntry)

#055           {

#056              /* Not present, no copying needed*/

#057              Info.LParamSize = 0;

#058           }

#059           else

#060           {

 

检测消息所需要内存的大小。

#061              /* Determine required size */

#062              Size =MsgMemorySize(MsgMemoryEntry, Info.Msg.wParam,

#063                                  Info.Msg.lParam);

#064              /* Allocate required amount ofuser-mode memory */

#065              Info.LParamSize = Size;

#066              UserMem = NULL;

 

给用户分配消息占用的内存。

#067              Status =ZwAllocateVirtualMemory(NtCurrentProcess(), &UserMem, 0,

#068                                              &Info.LParamSize, MEM_COMMIT, PAGE_READWRITE);

#069 

#070              if (! NT_SUCCESS(Status))

#071              {

#072                 SetLastNtError(Status);

#073                 RETURN( (BOOL) -1);

#074              }

#075              /* Transfer lParam data touser-mode mem */

 

把消息拷贝到用户空间的内存。

#076              Status = MmCopyToCaller(UserMem,(PVOID) Info.Msg.lParam, Size);

#077              if (! NT_SUCCESS(Status))

#078              {

#079                ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID *) &UserMem,

#080                                     &Info.LParamSize,MEM_DECOMMIT);

#081                 SetLastNtError(Status);

#082                 RETURN( (BOOL) -1);

#083              }

#084              Info.Msg.lParam = (LPARAM)UserMem;

#085           }

#086           if (Msg.FreeLParam && 0 !=Msg.Msg.lParam)

#087           {

#088              ExFreePool((void *)Msg.Msg.lParam);

#089           }

#090           Status = MmCopyToCaller(UnsafeInfo,&Info, sizeof(NTUSERGETMESSAGEINFO));

#091           if (! NT_SUCCESS(Status))

#092           {

#093              SetLastNtError(Status);

#094              RETURN( (BOOL) -1);

#095           }

#096        }

 

在这里调用co_IntWaitMessage函数继续等到窗口出现消息。

#097        else if (! co_IntWaitMessage(hWnd,MsgFilterMin, MsgFilterMax))

#098        {

#099           RETURN( (BOOL) -1);

#100        }

#101     }

#102     while (! GotMessage);

#103 

 

如果消息不等于退出消息,就返回TRUE,否则返回FALSE,也就是0值。

#104     RETURN( WM_QUIT != Info.Msg.message);

#105 

#106  CLEANUP:

#107  //   if(Window) UserDerefObjectCo(Window);

#108 

#109     DPRINT("LeaveNtUserGetMessage/n");

#110     UserLeave();

#111     END_CLEANUP;

#112  }