reactos操作系统实现(169)
当用USER32.DLL里调用获取消息之后,就调用到WIN32K.SYS里处理的函数NtUserGetMessage,这个函数实现的代码如下: #001 BOOL APIENTRY #002 NtUserGetMessage(PNTUSERGETMESSAGEINFO UnsafeInfo, #003 HWND hWnd, #004 UINT MsgFilterMin, #005 UINT MsgFilterMax) #006 /* #007 * FUNCTION: Get a message from the calling thread's message queue. #008 * ARGUMENTS: #009 * UnsafeMsg - Pointer to the structure which receives the returned message. #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("Enter NtUserGetMessage/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 is present 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 of user-mode memory */ #065 Info.LParamSize = Size; #066 UserMem = NULL;
给用户分配消息占用的内存。 #067 Status = ZwAllocateVirtualMemory(NtCurrentProcess(),&UserMem, #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 to user-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,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("Leave NtUserGetMessage/n"); #110 UserLeave(); #111 END_CLEANUP; #112} (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |