From ab5063b217d39b0c30b72ef0b557842fd21dbd64 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Fri, 11 Oct 2002 18:50:15 +0000 Subject: [PATCH] Added server-side infrastructure for the thread input structure. Reimplemented AttachThreadInput() and added GetGUIThreadInfo(). --- dlls/user/message.c | 55 +++++++++ dlls/user/user32.spec | 1 + include/wine/server_protocol.h | 42 ++++++- include/winuser.h | 40 +++++-- server/protocol.def | 23 ++++ server/queue.c | 198 ++++++++++++++++++++++++++++++++- server/request.h | 4 + server/trace.c | 31 ++++++ server/user.h | 1 + server/window.c | 3 + windows/queue.c | 85 -------------- 11 files changed, 386 insertions(+), 97 deletions(-) diff --git a/dlls/user/message.c b/dlls/user/message.c index 55270a525ac..8621241abe8 100644 --- a/dlls/user/message.c +++ b/dlls/user/message.c @@ -2231,3 +2231,58 @@ BOOL WINAPI SetMessageQueue( INT size ) /* now obsolete the message queue will be expanded dynamically as necessary */ return TRUE; } + + +/********************************************************************** + * AttachThreadInput (USER32.@) + * + * Attaches the input processing mechanism of one thread to that of + * another thread. + */ +BOOL WINAPI AttachThreadInput( DWORD from, DWORD to, BOOL attach ) +{ + BOOL ret; + + SERVER_START_REQ( attach_thread_input ) + { + req->tid_from = from; + req->tid_to = to; + req->attach = attach; + ret = !wine_server_call_err( req ); + } + SERVER_END_REQ; + return ret; +} + + +/********************************************************************** + * GetGUIThreadInfo (USER32.@) + */ +BOOL WINAPI GetGUIThreadInfo( DWORD id, GUITHREADINFO *info ) +{ + BOOL ret; + + SERVER_START_REQ( get_thread_input ) + { + req->tid = id; + if ((ret = !wine_server_call_err( req ))) + { + info->flags = 0; + info->hwndActive = reply->active; + info->hwndFocus = reply->focus; + info->hwndCapture = reply->capture; + info->hwndMenuOwner = reply->menu_owner; + info->hwndMoveSize = reply->move_size; + info->hwndCaret = reply->caret; + info->rcCaret.left = reply->rect.left; + info->rcCaret.top = reply->rect.top; + info->rcCaret.right = reply->rect.right; + info->rcCaret.bottom = reply->rect.bottom; + if (reply->menu_owner) info->flags |= GUI_INMENUMODE; + if (reply->move_size) info->flags |= GUI_INMOVESIZE; + if (reply->caret) info->flags |= GUI_CARETBLINKING; + } + } + SERVER_END_REQ; + return ret; +} diff --git a/dlls/user/user32.spec b/dlls/user/user32.spec index 19da4e62ce0..e7cfc38367d 100644 --- a/dlls/user/user32.spec +++ b/dlls/user/user32.spec @@ -244,6 +244,7 @@ init UserClientDllInitialize @ stdcall GetDoubleClickTime() GetDoubleClickTime @ stdcall GetFocus() GetFocus @ stdcall GetForegroundWindow() GetForegroundWindow +@ stdcall GetGUIThreadInfo(long ptr) GetGUIThreadInfo @ stdcall GetIconInfo(long ptr) GetIconInfo @ stub GetInputDesktop @ stdcall GetInputState() GetInputState diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 8b2a63fae7d..01b6e19ead9 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -2729,6 +2729,40 @@ struct get_window_properties_reply }; + +struct attach_thread_input_request +{ + struct request_header __header; + thread_id_t tid_from; + thread_id_t tid_to; + int attach; +}; +struct attach_thread_input_reply +{ + struct reply_header __header; +}; + + + +struct get_thread_input_request +{ + struct request_header __header; + thread_id_t tid; +}; +struct get_thread_input_reply +{ + struct reply_header __header; + user_handle_t focus; + user_handle_t capture; + user_handle_t active; + user_handle_t foreground; + user_handle_t menu_owner; + user_handle_t move_size; + user_handle_t caret; + rectangle_t rect; +}; + + enum request { REQ_new_process, @@ -2887,6 +2921,8 @@ enum request REQ_remove_window_property, REQ_get_window_property, REQ_get_window_properties, + REQ_attach_thread_input, + REQ_get_thread_input, REQ_NB_REQUESTS }; @@ -3050,6 +3086,8 @@ union generic_request struct remove_window_property_request remove_window_property_request; struct get_window_property_request get_window_property_request; struct get_window_properties_request get_window_properties_request; + struct attach_thread_input_request attach_thread_input_request; + struct get_thread_input_request get_thread_input_request; }; union generic_reply { @@ -3211,8 +3249,10 @@ union generic_reply struct remove_window_property_reply remove_window_property_reply; struct get_window_property_reply get_window_property_reply; struct get_window_properties_reply get_window_properties_reply; + struct attach_thread_input_reply attach_thread_input_reply; + struct get_thread_input_reply get_thread_input_reply; }; -#define SERVER_PROTOCOL_VERSION 84 +#define SERVER_PROTOCOL_VERSION 85 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/include/winuser.h b/include/winuser.h index cce01e4fe5b..f7c29ffb3e7 100644 --- a/include/winuser.h +++ b/include/winuser.h @@ -397,6 +397,27 @@ typedef struct tagINPUT } INPUT, *PINPUT, *LPINPUT; +typedef struct tagGUITHREADINFO +{ + DWORD cbSize; + DWORD flags; + HWND hwndActive; + HWND hwndFocus; + HWND hwndCapture; + HWND hwndMenuOwner; + HWND hwndMoveSize; + HWND hwndCaret; + RECT rcCaret; +} GUITHREADINFO, *PGUITHREADINFO, *LPGUITHREADINFO; + +#define GUI_CARETBLINKING 0x00000001 +#define GUI_INMOVESIZE 0x00000002 +#define GUI_INMENUMODE 0x00000004 +#define GUI_SYSTEMMENUMODE 0x00000008 +#define GUI_POPUPMENUMODE 0x00000010 +#define GUI_16BITTASK 0x00000020 + + /***** Dialogs *****/ /* Gcc on Solaris has a version of this that we don't care about */ @@ -4079,15 +4100,16 @@ UINT WINAPI GetDlgItemInt(HWND,INT,BOOL*,BOOL); INT WINAPI GetDlgItemTextA(HWND,INT,LPSTR,UINT); INT WINAPI GetDlgItemTextW(HWND,INT,LPWSTR,UINT); #define GetDlgItemText WINELIB_NAME_AW(GetDlgItemText) -UINT WINAPI GetDoubleClickTime(void); -HWND WINAPI GetFocus(void); -HWND WINAPI GetForegroundWindow(void); -BOOL WINAPI GetInputState(void); -UINT WINAPI GetInternalWindowPos(HWND,LPRECT,LPPOINT); -UINT WINAPI GetKBCodePage(void); -INT WINAPI GetKeyboardType(INT); -INT WINAPI GetKeyNameTextA(LONG,LPSTR,INT); -INT WINAPI GetKeyNameTextW(LONG,LPWSTR,INT); +UINT WINAPI GetDoubleClickTime(void); +HWND WINAPI GetFocus(void); +HWND WINAPI GetForegroundWindow(void); +BOOL WINAPI GetGUIThreadInfo(DWORD,GUITHREADINFO*); +BOOL WINAPI GetInputState(void); +UINT WINAPI GetInternalWindowPos(HWND,LPRECT,LPPOINT); +UINT WINAPI GetKBCodePage(void); +INT WINAPI GetKeyboardType(INT); +INT WINAPI GetKeyNameTextA(LONG,LPSTR,INT); +INT WINAPI GetKeyNameTextW(LONG,LPWSTR,INT); #define GetKeyNameText WINELIB_NAME_AW(GetKeyNameText) INT WINAPI GetKeyboardLayoutNameA(LPSTR); INT WINAPI GetKeyboardLayoutNameW(LPWSTR); diff --git a/server/protocol.def b/server/protocol.def index 1aeb6c4b244..43f4fa0fce9 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1908,3 +1908,26 @@ enum message_type int total; /* total number of properties */ VARARG(props,properties); /* list of properties */ @END + + +/* Attach (or detach) thread inputs */ +@REQ(attach_thread_input) + thread_id_t tid_from; /* thread to be attached */ + thread_id_t tid_to; /* thread to which tid_from should be attached */ + int attach; /* is it an attach? */ +@END + + +/* Get input data for a given thread */ +@REQ(get_thread_input) + thread_id_t tid; /* id of thread */ +@REPLY + user_handle_t focus; /* handle to the focus window */ + user_handle_t capture; /* handle to the capture window */ + user_handle_t active; /* handle to the active window */ + user_handle_t foreground; /* handle to the global foreground window */ + user_handle_t menu_owner; /* handle to the menu owner */ + user_handle_t move_size; /* handle to the moving/resizing window */ + user_handle_t caret; /* handle to the caret window */ + rectangle_t rect; /* caret rectangle */ +@END diff --git a/server/queue.c b/server/queue.c index e250faecb4e..5a08668563a 100644 --- a/server/queue.c +++ b/server/queue.c @@ -89,6 +89,19 @@ struct timer unsigned int lparam; /* lparam for message */ }; +struct thread_input +{ + struct object obj; /* object header */ + user_handle_t focus; /* focus window */ + user_handle_t capture; /* capture window */ + user_handle_t active; /* active window */ + user_handle_t menu_owner; /* current menu owner window */ + user_handle_t move_size; /* current moving/resizing window */ + user_handle_t caret; /* caret window */ + rectangle_t rect; /* caret rectangle */ + unsigned char keystate[256]; /* state of each key */ +}; + struct msg_queue { struct object obj; /* object header */ @@ -106,6 +119,7 @@ struct msg_queue struct timer *last_timer; /* tail of timer list */ struct timer *next_timer; /* next timer to expire */ struct timeout_user *timeout; /* timeout for next timer to expire */ + struct thread_input *input; /* thread input descriptor */ }; static void msg_queue_dump( struct object *obj, int verbose ); @@ -114,6 +128,8 @@ static void msg_queue_remove_queue( struct object *obj, struct wait_queue_entry static int msg_queue_signaled( struct object *obj, struct thread *thread ); static int msg_queue_satisfied( struct object *obj, struct thread *thread ); static void msg_queue_destroy( struct object *obj ); +static void thread_input_dump( struct object *obj, int verbose ); +static void thread_input_destroy( struct object *obj ); static void timer_callback( void *private ); static const struct object_ops msg_queue_ops = @@ -134,11 +150,55 @@ static const struct object_ops msg_queue_ops = }; -static struct msg_queue *create_msg_queue( struct thread *thread ) +static const struct object_ops thread_input_ops = +{ + sizeof(struct thread_input), /* size */ + thread_input_dump, /* dump */ + no_add_queue, /* add_queue */ + NULL, /* remove_queue */ + NULL, /* signaled */ + NULL, /* satisfied */ + NULL, /* get_poll_events */ + NULL, /* poll_event */ + no_get_fd, /* get_fd */ + no_flush, /* flush */ + no_get_file_info, /* get_file_info */ + NULL, /* queue_async */ + thread_input_destroy /* destroy */ +}; + +/* create a thread input object */ +static struct thread_input *create_thread_input(void) +{ + struct thread_input *input; + + if ((input = alloc_object( &thread_input_ops, -1 ))) + { + input->focus = 0; + input->capture = 0; + input->active = 0; + input->menu_owner = 0; + input->move_size = 0; + input->caret = 0; + input->rect.left = 0; + input->rect.top = 0; + input->rect.right = 0; + input->rect.bottom = 0; + memset( input->keystate, 0, sizeof(input->keystate) ); + } + return input; +} + +/* pointer to input structure of foreground thread */ +static struct thread_input *foreground_input; + +/* create a message queue object */ +static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_input *input ) { struct msg_queue *queue; int i; + if (!input && !(input = create_thread_input())) return NULL; if ((queue = alloc_object( &msg_queue_ops, -1 ))) { queue->wake_bits = 0; @@ -153,6 +213,7 @@ static struct msg_queue *create_msg_queue( struct thread *thread ) queue->last_timer = NULL; queue->next_timer = NULL; queue->timeout = NULL; + queue->input = (struct thread_input *)grab_object( input ); for (i = 0; i < NB_MSG_KINDS; i++) queue->msg_list[i].first = queue->msg_list[i].last = NULL; @@ -160,6 +221,7 @@ static struct msg_queue *create_msg_queue( struct thread *thread ) if (!thread->process->queue) thread->process->queue = (struct msg_queue *)grab_object( queue ); } + release_object( input ); return queue; } @@ -217,7 +279,7 @@ inline static int get_hardware_msg_bit( struct message *msg ) inline static struct msg_queue *get_current_queue(void) { struct msg_queue *queue = current->queue; - if (!queue) queue = create_msg_queue( current ); + if (!queue) queue = create_msg_queue( current, NULL ); return queue; } @@ -529,8 +591,76 @@ static void msg_queue_destroy( struct object *obj ) timer = next; } if (queue->timeout) remove_timeout_user( queue->timeout ); + if (queue->input) release_object( queue->input ); } +static void thread_input_dump( struct object *obj, int verbose ) +{ + struct thread_input *input = (struct thread_input *)obj; + fprintf( stderr, "Thread input focus=%x capture=%x active=%x\n", + input->focus, input->capture, input->active ); +} + +static void thread_input_destroy( struct object *obj ) +{ + struct thread_input *input = (struct thread_input *)obj; + + if (foreground_input == input) foreground_input = NULL; +} + +/* fix the thread input data when a window is destroyed */ +inline static void thread_input_cleanup_window( struct msg_queue *queue, user_handle_t window ) +{ + struct thread_input *input = queue->input; + + if (window == input->focus) input->focus = 0; + if (window == input->capture) input->capture = 0; + if (window == input->active) input->active = 0; + if (window == input->menu_owner) input->menu_owner = 0; + if (window == input->move_size) input->move_size = 0; + if (window == input->caret) input->caret = 0; +} + +/* attach two thread input data structures */ +int attach_thread_input( struct thread *thread_from, struct thread *thread_to ) +{ + struct thread_input *input; + + if (!thread_to->queue && !(thread_to->queue = create_msg_queue( thread_to, NULL ))) return 0; + input = (struct thread_input *)grab_object( thread_to->queue->input ); + + if (thread_from->queue) + { + release_object( thread_from->queue->input ); + thread_from->queue->input = input; + } + else + { + if (!(thread_from->queue = create_msg_queue( thread_from, input ))) return 0; + } + memset( input->keystate, 0, sizeof(input->keystate) ); + return 1; +} + +/* detach two thread input data structures */ +static void detach_thread_input( struct thread *thread_from, struct thread *thread_to ) +{ + struct thread_input *input; + + if (!thread_from->queue || !thread_to->queue || + thread_from->queue->input != thread_to->queue->input) + { + set_error( STATUS_ACCESS_DENIED ); + return; + } + if ((input = create_thread_input())) + { + release_object( thread_from->queue->input ); + thread_from->queue->input = input; + } +} + + /* set the next timer to expire */ static void set_next_timer( struct msg_queue *queue, struct timer *timer ) { @@ -706,6 +836,8 @@ void queue_cleanup_window( struct thread *thread, user_handle_t win ) msg = next; } } + + thread_input_cleanup_window( queue, win ); } /* post a message to a window; used by socket handling */ @@ -1098,3 +1230,65 @@ DECL_HANDLER(kill_win_timer) if (!queue || !kill_timer( queue, get_user_full_handle(req->win), req->msg, req->id )) set_error( STATUS_INVALID_PARAMETER ); } + + +/* attach (or detach) thread inputs */ +DECL_HANDLER(attach_thread_input) +{ + struct thread *thread_from = get_thread_from_id( req->tid_from ); + struct thread *thread_to = get_thread_from_id( req->tid_to ); + + if (!thread_from || !thread_to) + { + if (thread_from) release_object( thread_from ); + if (thread_to) release_object( thread_to ); + return; + } + if (thread_from != thread_to) + { + if (req->attach) attach_thread_input( thread_from, thread_to ); + else detach_thread_input( thread_from, thread_to ); + } + else set_error( STATUS_ACCESS_DENIED ); + release_object( thread_from ); + release_object( thread_to ); +} + + +/* get thread input data */ +DECL_HANDLER(get_thread_input) +{ + struct thread *thread = NULL; + struct thread_input *input; + + if (req->tid) + { + if (!(thread = get_thread_from_id( req->tid ))) return; + input = thread->queue ? thread->queue->input : NULL; + } + else input = foreground_input; /* get the foreground thread info */ + + if (input) + { + reply->focus = input->focus; + reply->capture = input->capture; + reply->active = input->active; + reply->menu_owner = input->menu_owner; + reply->move_size = input->move_size; + reply->caret = input->caret; + reply->rect = input->rect; + } + else + { + reply->focus = 0; + reply->capture = 0; + reply->active = 0; + reply->menu_owner = 0; + reply->move_size = 0; + reply->caret = 0; + reply->rect.left = reply->rect.top = reply->rect.right = reply->rect.bottom = 0; + } + /* foreground window is active window of foreground thread */ + reply->foreground = foreground_input ? foreground_input->active : 0; + if (thread) release_object( thread ); +} diff --git a/server/request.h b/server/request.h index 0c744b4befd..3f1a0367dab 100644 --- a/server/request.h +++ b/server/request.h @@ -259,6 +259,8 @@ DECL_HANDLER(set_window_property); DECL_HANDLER(remove_window_property); DECL_HANDLER(get_window_property); DECL_HANDLER(get_window_properties); +DECL_HANDLER(attach_thread_input); +DECL_HANDLER(get_thread_input); #ifdef WANT_REQUEST_HANDLERS @@ -421,6 +423,8 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = (req_handler)req_remove_window_property, (req_handler)req_get_window_property, (req_handler)req_get_window_properties, + (req_handler)req_attach_thread_input, + (req_handler)req_get_thread_input, }; #endif /* WANT_REQUEST_HANDLERS */ diff --git a/server/trace.c b/server/trace.c index 18cda73d3ce..776370f7999 100644 --- a/server/trace.c +++ b/server/trace.c @@ -2175,6 +2175,31 @@ static void dump_get_window_properties_reply( const struct get_window_properties dump_varargs_properties( cur_size ); } +static void dump_attach_thread_input_request( const struct attach_thread_input_request *req ) +{ + fprintf( stderr, " tid_from=%08x,", req->tid_from ); + fprintf( stderr, " tid_to=%08x,", req->tid_to ); + fprintf( stderr, " attach=%d", req->attach ); +} + +static void dump_get_thread_input_request( const struct get_thread_input_request *req ) +{ + fprintf( stderr, " tid=%08x", req->tid ); +} + +static void dump_get_thread_input_reply( const struct get_thread_input_reply *req ) +{ + fprintf( stderr, " focus=%08x,", req->focus ); + fprintf( stderr, " capture=%08x,", req->capture ); + fprintf( stderr, " active=%08x,", req->active ); + fprintf( stderr, " foreground=%08x,", req->foreground ); + fprintf( stderr, " menu_owner=%08x,", req->menu_owner ); + fprintf( stderr, " move_size=%08x,", req->move_size ); + fprintf( stderr, " caret=%08x,", req->caret ); + fprintf( stderr, " rect=" ); + dump_rectangle( &req->rect ); +} + static const dump_func req_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_new_process_request, (dump_func)dump_get_new_process_info_request, @@ -2332,6 +2357,8 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_remove_window_property_request, (dump_func)dump_get_window_property_request, (dump_func)dump_get_window_properties_request, + (dump_func)dump_attach_thread_input_request, + (dump_func)dump_get_thread_input_request, }; static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { @@ -2491,6 +2518,8 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_remove_window_property_reply, (dump_func)dump_get_window_property_reply, (dump_func)dump_get_window_properties_reply, + (dump_func)0, + (dump_func)dump_get_thread_input_reply, }; static const char * const req_names[REQ_NB_REQUESTS] = { @@ -2650,6 +2679,8 @@ static const char * const req_names[REQ_NB_REQUESTS] = { "remove_window_property", "get_window_property", "get_window_properties", + "attach_thread_input", + "get_thread_input", }; /* ### make_requests end ### */ diff --git a/server/user.h b/server/user.h index 6d5766e6024..b1cc439c000 100644 --- a/server/user.h +++ b/server/user.h @@ -46,6 +46,7 @@ extern void *next_user_handle( user_handle_t *handle, enum user_object type ); extern void free_msg_queue( struct thread *thread ); extern void inc_queue_paint_count( struct thread *thread, int incr ); extern void queue_cleanup_window( struct thread *thread, user_handle_t win ); +extern int attach_thread_input( struct thread *thread_from, struct thread *thread_to ); extern void post_message( user_handle_t win, unsigned int message, unsigned int wparam, unsigned int lparam ); diff --git a/server/window.c b/server/window.c index e513b877297..ad51288bd9a 100644 --- a/server/window.c +++ b/server/window.c @@ -287,6 +287,9 @@ static struct window *create_window( struct window *parent, struct window *owner } else win->next = win->prev = NULL; + /* if parent belongs to a different thread, attach the two threads */ + if (parent && parent->thread && parent->thread != current) + attach_thread_input( current, parent->thread ); return win; } diff --git a/windows/queue.c b/windows/queue.c index 83c2d3e459e..291c2cca588 100644 --- a/windows/queue.c +++ b/windows/queue.c @@ -593,88 +593,3 @@ LONG WINAPI GetMessageExtraInfo(void) if (!(queue = QUEUE_Current())) return 0; return queue->GetMessageExtraInfoVal; } - - -/********************************************************************** - * AttachThreadInput (USER32.@) Attaches input of 1 thread to other - * - * Attaches the input processing mechanism of one thread to that of - * another thread. - * - * RETURNS - * Success: TRUE - * Failure: FALSE - * - * TODO: - * 1. Reset the Key State (currenly per thread key state is not maintained) - */ -BOOL WINAPI AttachThreadInput( - DWORD idAttach, /* [in] Thread to attach */ - DWORD idAttachTo, /* [in] Thread to attach to */ - BOOL fAttach) /* [in] Attach or detach */ -{ - MESSAGEQUEUE *pSrcMsgQ = 0, *pTgtMsgQ = 0; - BOOL16 bRet = 0; - - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - /* A thread cannot attach to itself */ - if ( idAttach == idAttachTo ) - goto CLEANUP; - - /* According to the docs this method should fail if a - * "Journal record" hook is installed. (attaches all input queues together) - */ - if ( HOOK_IsHooked( WH_JOURNALRECORD ) ) - goto CLEANUP; - - /* Retrieve message queues corresponding to the thread id's */ - pTgtMsgQ = QUEUE_Lock( GetThreadQueue16( idAttach ) ); - pSrcMsgQ = QUEUE_Lock( GetThreadQueue16( idAttachTo ) ); - - /* Ensure we have message queues and that Src and Tgt threads - * are not system threads. - */ - if ( !pSrcMsgQ || !pTgtMsgQ || !pSrcMsgQ->pQData || !pTgtMsgQ->pQData ) - goto CLEANUP; - - if (fAttach) /* Attach threads */ - { - /* Only attach if currently detached */ - if ( pTgtMsgQ->pQData != pSrcMsgQ->pQData ) - { - /* First release the target threads perQData */ - PERQDATA_Release( pTgtMsgQ->pQData ); - - /* Share a reference to the source threads perQDATA */ - PERQDATA_Addref( pSrcMsgQ->pQData ); - pTgtMsgQ->pQData = pSrcMsgQ->pQData; - } - } - else /* Detach threads */ - { - /* Only detach if currently attached */ - if ( pTgtMsgQ->pQData == pSrcMsgQ->pQData ) - { - /* First release the target threads perQData */ - PERQDATA_Release( pTgtMsgQ->pQData ); - - /* Give the target thread its own private perQDATA once more */ - pTgtMsgQ->pQData = PERQDATA_CreateInstance(); - } - } - - /* TODO: Reset the Key State */ - - bRet = 1; /* Success */ - -CLEANUP: - - /* Unlock the queues before returning */ - if ( pSrcMsgQ ) - QUEUE_Unlock( pSrcMsgQ ); - if ( pTgtMsgQ ) - QUEUE_Unlock( pTgtMsgQ ); - - return bRet; -}