6cb070281ed569545fa9342d4c04224cf09ac092
[reactos.git] / reactos / subsystems / win32 / win32k / ntuser / focus.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Focus functions
5 * FILE: subsystem/win32/win32k/ntuser/focus.c
6 * PROGRAMER: ReactOS Team
7 */
8
9 #include <win32k.h>
10 DBG_DEFAULT_CHANNEL(UserFocus);
11
12 PUSER_MESSAGE_QUEUE gpqForeground = NULL;
13 PUSER_MESSAGE_QUEUE gpqForegroundPrev = NULL;
14
15 HWND FASTCALL
16 IntGetCaptureWindow(VOID)
17 {
18 PUSER_MESSAGE_QUEUE ForegroundQueue = IntGetFocusMessageQueue();
19 return ForegroundQueue != NULL ? ForegroundQueue->CaptureWindow : 0;
20 }
21
22 HWND FASTCALL
23 IntGetFocusWindow(VOID)
24 {
25 PUSER_MESSAGE_QUEUE ForegroundQueue = IntGetFocusMessageQueue();
26 return ForegroundQueue != NULL ? ForegroundQueue->FocusWindow : 0;
27 }
28
29 HWND FASTCALL
30 IntGetThreadFocusWindow(VOID)
31 {
32 PTHREADINFO pti;
33 PUSER_MESSAGE_QUEUE ThreadQueue;
34
35 pti = PsGetCurrentThreadWin32Thread();
36 ThreadQueue = pti->MessageQueue;
37 return ThreadQueue != NULL ? ThreadQueue->FocusWindow : 0;
38 }
39
40 VOID FASTCALL
41 co_IntSendDeactivateMessages(HWND hWndPrev, HWND hWnd)
42 {
43 PWND WndPrev ;
44
45 if (hWndPrev && (WndPrev = UserGetWindowObject(hWndPrev)))
46 {
47 co_IntSendMessageNoWait(hWndPrev, WM_NCACTIVATE, FALSE, 0);
48 co_IntSendMessageNoWait(hWndPrev, WM_ACTIVATE,
49 MAKEWPARAM(WA_INACTIVE, WndPrev->style & WS_MINIMIZE),
50 (LPARAM)hWnd);
51 }
52 }
53
54 VOID FASTCALL
55 co_IntSendActivateMessages(HWND hWndPrev, HWND hWnd, BOOL MouseActivate)
56 {
57 USER_REFERENCE_ENTRY Ref, RefPrev;
58 PWND Window, WindowPrev = NULL;
59
60 if ((Window = UserGetWindowObject(hWnd)))
61 {
62 UserRefObjectCo(Window, &Ref);
63
64 WindowPrev = UserGetWindowObject(hWndPrev);
65
66 if (WindowPrev) UserRefObjectCo(WindowPrev, &RefPrev);
67
68 /* Send palette messages */
69 if (gpsi->PUSIFlags & PUSIF_PALETTEDISPLAY &&
70 co_IntPostOrSendMessage(hWnd, WM_QUERYNEWPALETTE, 0, 0))
71 {
72 UserSendNotifyMessage( HWND_BROADCAST,
73 WM_PALETTEISCHANGING,
74 (WPARAM)hWnd,
75 0);
76 }
77
78 if (Window->spwndPrev != NULL)
79 co_WinPosSetWindowPos(Window, HWND_TOP, 0, 0, 0, 0,
80 SWP_NOSIZE | SWP_NOMOVE);
81
82 if (!Window->spwndOwner && !IntGetParent(Window))
83 {
84 co_IntShellHookNotify(HSHELL_WINDOWACTIVATED, (LPARAM) hWnd);
85 }
86
87 if (Window)
88 { // Set last active for window and it's owner.
89 Window->hWndLastActive = hWnd;
90 if (Window->spwndOwner)
91 Window->spwndOwner->hWndLastActive = hWnd;
92 Window->state |= WNDS_ACTIVEFRAME;
93 }
94
95 if (WindowPrev)
96 WindowPrev->state &= ~WNDS_ACTIVEFRAME;
97
98 if (Window && WindowPrev)
99 {
100 PWND cWindow;
101 HWND *List, *phWnd;
102 HANDLE OldTID = IntGetWndThreadId(WindowPrev);
103 HANDLE NewTID = IntGetWndThreadId(Window);
104
105 TRACE("SendActiveMessage Old -> %x, New -> %x\n", OldTID, NewTID);
106 if (Window->style & WS_MINIMIZE)
107 {
108 TRACE("Widow was minimized\n");
109 }
110
111 if (OldTID != NewTID)
112 {
113 List = IntWinListChildren(UserGetWindowObject(IntGetDesktopWindow()));
114 if (List)
115 {
116 for (phWnd = List; *phWnd; ++phWnd)
117 {
118 cWindow = UserGetWindowObject(*phWnd);
119
120 if (cWindow && (IntGetWndThreadId(cWindow) == OldTID))
121 { // FALSE if the window is being deactivated,
122 // ThreadId that owns the window being activated.
123 co_IntSendMessageNoWait(*phWnd, WM_ACTIVATEAPP, FALSE, (LPARAM)NewTID);
124 }
125 }
126 for (phWnd = List; *phWnd; ++phWnd)
127 {
128 cWindow = UserGetWindowObject(*phWnd);
129 if (cWindow && (IntGetWndThreadId(cWindow) == NewTID))
130 { // TRUE if the window is being activated,
131 // ThreadId that owns the window being deactivated.
132 co_IntSendMessageNoWait(*phWnd, WM_ACTIVATEAPP, TRUE, (LPARAM)OldTID);
133 }
134 }
135 ExFreePool(List);
136 }
137 }
138 UserDerefObjectCo(WindowPrev); // Now allow the previous window to die.
139 }
140
141 UserDerefObjectCo(Window);
142
143 /* FIXME: IntIsWindow */
144 co_IntSendMessageNoWait(hWnd, WM_NCACTIVATE, (WPARAM)(hWnd == UserGetForegroundWindow()), 0);
145 /* FIXME: WA_CLICKACTIVE */
146 co_IntSendMessageNoWait(hWnd, WM_ACTIVATE,
147 MAKEWPARAM(MouseActivate ? WA_CLICKACTIVE : WA_ACTIVE,
148 Window->style & WS_MINIMIZE),
149 (LPARAM)hWndPrev);
150 }
151 }
152
153 VOID FASTCALL
154 co_IntSendKillFocusMessages(HWND hWndPrev, HWND hWnd)
155 {
156 if (hWndPrev)
157 {
158 IntNotifyWinEvent(EVENT_OBJECT_FOCUS, NULL, OBJID_CLIENT, CHILDID_SELF, 0);
159 co_IntPostOrSendMessage(hWndPrev, WM_KILLFOCUS, (WPARAM)hWnd, 0);
160 }
161 }
162
163 VOID FASTCALL
164 co_IntSendSetFocusMessages(HWND hWndPrev, HWND hWnd)
165 {
166 if (hWnd)
167 {
168 PWND pWnd = UserGetWindowObject(hWnd);
169 IntNotifyWinEvent(EVENT_OBJECT_FOCUS, pWnd, OBJID_CLIENT, CHILDID_SELF, 0);
170 co_IntPostOrSendMessage(hWnd, WM_SETFOCUS, (WPARAM)hWndPrev, 0);
171 }
172 }
173
174 HWND FASTCALL
175 IntFindChildWindowToOwner(PWND Root, PWND Owner)
176 {
177 HWND Ret;
178 PWND Child, OwnerWnd;
179
180 for(Child = Root->spwndChild; Child; Child = Child->spwndNext)
181 {
182 OwnerWnd = Child->spwndOwner;
183 if(!OwnerWnd)
184 continue;
185
186 if(OwnerWnd == Owner)
187 {
188 Ret = Child->head.h;
189 return Ret;
190 }
191 }
192
193 return NULL;
194 }
195
196 /*
197 MSDN:
198 The system restricts which processes can set the foreground window. A process
199 can set the foreground window only if one of the following conditions is true:
200
201 * The process is the foreground process.
202 * The process was started by the foreground process.
203 * The process received the last input event.
204 * There is no foreground process.
205 * The foreground process is being debugged.
206 * The foreground is not locked (see LockSetForegroundWindow).
207 * The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo).
208 * No menus are active.
209 */
210 static BOOL FASTCALL
211 co_IntSetForegroundAndFocusWindow(PWND Wnd, PWND FocusWindow, BOOL MouseActivate)
212 {
213 CBTACTIVATESTRUCT cbt;
214 HWND hWnd = Wnd->head.h;
215 HWND hWndPrev = NULL;
216 HWND hWndFocus = FocusWindow->head.h;
217 HWND hWndFocusPrev = NULL;
218 PUSER_MESSAGE_QUEUE PrevForegroundQueue;
219
220 ASSERT_REFS_CO(Wnd);
221
222 TRACE("IntSetForegroundAndFocusWindow(%x, %x, %s)\n", hWnd, hWndFocus, MouseActivate ? "TRUE" : "FALSE");
223
224 if ((Wnd->style & (WS_CHILD | WS_POPUP)) == WS_CHILD)
225 {
226 TRACE("Failed - Child\n");
227 return FALSE;
228 }
229
230 if (0 == (Wnd->style & WS_VISIBLE) &&
231 Wnd->head.pti->pEThread->ThreadsProcess != CsrProcess)
232 {
233 ERR("Failed - Invisible\n");
234 return FALSE;
235 }
236
237 PrevForegroundQueue = IntGetFocusMessageQueue();
238 if (PrevForegroundQueue != 0)
239 {
240 hWndPrev = PrevForegroundQueue->ActiveWindow;
241 hWndFocusPrev = PrevForegroundQueue->FocusWindow;
242 }
243
244 if (hWndPrev == hWnd)
245 {
246 TRACE("Failed - Same\n");
247 return TRUE;
248 }
249
250 /* call CBT hook chain */
251 cbt.fMouse = MouseActivate;
252 cbt.hWndActive = hWndPrev;
253 if (co_HOOK_CallHooks( WH_CBT, HCBT_ACTIVATE, (WPARAM)hWnd, (LPARAM)&cbt))
254 {
255 ERR("IntSetForegroundAndFocusWindow WH_CBT Call Hook return!\n");
256 return 0;
257 }
258
259 co_IntSendDeactivateMessages(hWndPrev, hWnd);
260 co_IntSendKillFocusMessages(hWndFocusPrev, hWndFocus);
261
262
263 IntSetFocusMessageQueue(Wnd->head.pti->MessageQueue);
264
265 if (Wnd->head.pti->MessageQueue)
266 {
267 Wnd->head.pti->MessageQueue->ActiveWindow = hWnd;
268 }
269
270 if (FocusWindow->head.pti->MessageQueue)
271 {
272 FocusWindow->head.pti->MessageQueue->FocusWindow = hWndFocus;
273 }
274
275 if (PrevForegroundQueue != Wnd->head.pti->MessageQueue)
276 {
277 /* FIXME: Send WM_ACTIVATEAPP to all thread windows. */
278 }
279
280 co_IntSendSetFocusMessages(hWndFocusPrev, hWndFocus);
281 co_IntSendActivateMessages(hWndPrev, hWnd, MouseActivate);
282
283 return TRUE;
284 }
285
286 BOOL FASTCALL
287 co_IntSetForegroundWindow(PWND Window)//FIXME: can Window be NULL??
288 {
289 /*if (Window)*/ ASSERT_REFS_CO(Window);
290
291 return co_IntSetForegroundAndFocusWindow(Window, Window, FALSE);
292 }
293
294 BOOL FASTCALL
295 co_IntMouseActivateWindow(PWND Wnd)
296 {
297 HWND Top;
298 PWND TopWindow;
299 USER_REFERENCE_ENTRY Ref;
300
301 ASSERT_REFS_CO(Wnd);
302
303 if(Wnd->style & WS_DISABLED)
304 {
305 BOOL Ret;
306 PWND TopWnd;
307 PWND DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
308 if(DesktopWindow)
309 {
310 Top = IntFindChildWindowToOwner(DesktopWindow, Wnd);
311 if((TopWnd = UserGetWindowObject(Top)))
312 {
313 UserRefObjectCo(TopWnd, &Ref);
314 Ret = co_IntMouseActivateWindow(TopWnd);
315 UserDerefObjectCo(TopWnd);
316
317 return Ret;
318 }
319 }
320 return FALSE;
321 }
322
323
324 TopWindow = UserGetAncestor(Wnd, GA_ROOT);
325 if (!TopWindow) return FALSE;
326
327 /* TMN: Check return valud from this function? */
328 UserRefObjectCo(TopWindow, &Ref);
329
330 co_IntSetForegroundAndFocusWindow(TopWindow, Wnd, TRUE);
331
332 UserDerefObjectCo(TopWindow);
333
334 return TRUE;
335 }
336
337 HWND FASTCALL
338 co_IntSetActiveWindow(PWND Wnd OPTIONAL)
339 {
340 PTHREADINFO pti;
341 PUSER_MESSAGE_QUEUE ThreadQueue;
342 HWND hWndPrev;
343 HWND hWnd = 0;
344 CBTACTIVATESTRUCT cbt;
345
346 if (Wnd)
347 ASSERT_REFS_CO(Wnd);
348
349 pti = PsGetCurrentThreadWin32Thread();
350 ThreadQueue = pti->MessageQueue;
351 ASSERT(ThreadQueue != 0);
352
353 if (Wnd != 0)
354 {
355 if ((Wnd->style & (WS_POPUP | WS_CHILD)) == WS_CHILD)
356 {
357 /* Windows doesn't seem to return an error here */
358 return ThreadQueue->ActiveWindow;
359 }
360 hWnd = Wnd->head.h;
361 }
362
363 hWndPrev = ThreadQueue->ActiveWindow;
364 if (hWndPrev == hWnd)
365 {
366 return hWndPrev;
367 }
368
369 /* call CBT hook chain */
370 cbt.fMouse = FALSE;
371 cbt.hWndActive = hWndPrev;
372 if (co_HOOK_CallHooks( WH_CBT, HCBT_ACTIVATE, (WPARAM)hWnd, (LPARAM)&cbt))
373 {
374 ERR("SetActiveWindow WH_CBT Call Hook return!\n");
375 return 0;
376 }
377
378 co_IntSendDeactivateMessages(hWndPrev, hWnd);
379
380 ThreadQueue->ActiveWindow = hWnd;
381
382 co_IntSendActivateMessages(hWndPrev, hWnd, FALSE);
383
384 /* FIXME */
385 /* return IntIsWindow(hWndPrev) ? hWndPrev : 0;*/
386 return hWndPrev;
387 }
388
389 HWND FASTCALL
390 co_UserSetFocus(PWND Window)
391 {
392 HWND hWndPrev = 0;
393 PWND pwndTop;
394 PTHREADINFO pti;
395 PUSER_MESSAGE_QUEUE ThreadQueue;
396
397 if (Window)
398 ASSERT_REFS_CO(Window);
399
400 pti = PsGetCurrentThreadWin32Thread();
401 ThreadQueue = pti->MessageQueue;
402 ASSERT(ThreadQueue != 0);
403
404 hWndPrev = ThreadQueue->FocusWindow;
405
406 if (Window != 0)
407 {
408 if (hWndPrev == Window->head.h)
409 {
410 return hWndPrev; /* nothing to do */
411 }
412
413 /* Check if we can set the focus to this window */
414 for (pwndTop = Window; pwndTop != NULL; pwndTop = pwndTop->spwndParent )
415 {
416 if (pwndTop->style & (WS_MINIMIZED|WS_DISABLED)) return 0;
417 if ((pwndTop->style & (WS_POPUP|WS_CHILD)) != WS_CHILD) break;
418 }
419
420 if (co_HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)Window->head.h, (LPARAM)hWndPrev))
421 {
422 ERR("SetFocus 1 WH_CBT Call Hook return!\n");
423 return 0;
424 }
425
426 /* activate pwndTop if needed. */
427 if (pwndTop->head.h != ThreadQueue->ActiveWindow)
428 {
429 co_IntSetActiveWindow(pwndTop);
430 /* Abort if window destroyed */
431 if (Window->state2 & WNDS2_INDESTROY) return 0;
432 /* Do not change focus if the window is no longer active */
433 if (pwndTop->head.h != ThreadQueue->ActiveWindow)
434 {
435 ERR("SetFocus Top window did not go active!\n");
436 return 0;
437 }
438 }
439
440 ThreadQueue->FocusWindow = Window->head.h;
441 TRACE("Focus: %d -> %d\n", hWndPrev, Window->head.h);
442
443 co_IntSendKillFocusMessages(hWndPrev, Window->head.h);
444 co_IntSendSetFocusMessages(hWndPrev, Window->head.h);
445 }
446 else
447 {
448 ThreadQueue->FocusWindow = 0;
449 if (co_HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)0, (LPARAM)hWndPrev))
450 {
451 ERR("SetFocusWindow 2 WH_CBT Call Hook return!\n");
452 return 0;
453 }
454
455 co_IntSendKillFocusMessages(hWndPrev, 0);
456 }
457 return hWndPrev;
458 }
459
460 HWND FASTCALL
461 UserGetForegroundWindow(VOID)
462 {
463 PUSER_MESSAGE_QUEUE ForegroundQueue;
464
465 ForegroundQueue = IntGetFocusMessageQueue();
466 return( ForegroundQueue != NULL ? ForegroundQueue->ActiveWindow : 0);
467 }
468
469 HWND FASTCALL UserGetActiveWindow(VOID)
470 {
471 PTHREADINFO pti;
472 PUSER_MESSAGE_QUEUE ThreadQueue;
473
474 pti = PsGetCurrentThreadWin32Thread();
475 ThreadQueue = pti->MessageQueue;
476 return( ThreadQueue ? ThreadQueue->ActiveWindow : 0);
477 }
478
479 HWND APIENTRY
480 IntGetCapture(VOID)
481 {
482 PTHREADINFO pti;
483 PUSER_MESSAGE_QUEUE ThreadQueue;
484 DECLARE_RETURN(HWND);
485
486 TRACE("Enter IntGetCapture\n");
487
488 pti = PsGetCurrentThreadWin32Thread();
489 ThreadQueue = pti->MessageQueue;
490 RETURN( ThreadQueue ? ThreadQueue->CaptureWindow : 0);
491
492 CLEANUP:
493 TRACE("Leave IntGetCapture, ret=%i\n",_ret_);
494 END_CLEANUP;
495 }
496
497 HWND FASTCALL
498 co_UserSetCapture(HWND hWnd)
499 {
500 PTHREADINFO pti;
501 PUSER_MESSAGE_QUEUE ThreadQueue;
502 PWND Window, pWnd;
503 HWND hWndPrev;
504
505 pti = PsGetCurrentThreadWin32Thread();
506 ThreadQueue = pti->MessageQueue;
507
508 if (ThreadQueue->QF_flags & QF_CAPTURELOCKED)
509 return NULL;
510
511 if ((Window = UserGetWindowObject(hWnd)))
512 {
513 if (Window->head.pti->MessageQueue != ThreadQueue)
514 {
515 return NULL;
516 }
517 }
518
519 hWndPrev = MsqSetStateWindow(ThreadQueue, MSQ_STATE_CAPTURE, hWnd);
520
521 if (hWndPrev)
522 {
523 pWnd = UserGetWindowObject(hWndPrev);
524 if (pWnd)
525 IntNotifyWinEvent(EVENT_SYSTEM_CAPTUREEND, pWnd, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI);
526 }
527
528 if (Window)
529 IntNotifyWinEvent(EVENT_SYSTEM_CAPTURESTART, Window, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI);
530
531 if (hWndPrev && hWndPrev != hWnd)
532 {
533 if (ThreadQueue->MenuOwner && Window) ThreadQueue->QF_flags |= QF_CAPTURELOCKED;
534
535 co_IntPostOrSendMessage(hWndPrev, WM_CAPTURECHANGED, 0, (LPARAM)hWnd);
536
537 ThreadQueue->QF_flags &= ~QF_CAPTURELOCKED;
538 }
539
540 ThreadQueue->CaptureWindow = hWnd;
541
542 if (hWnd == NULL) // Release mode.
543 {
544 MOUSEINPUT mi;
545 /// These are hacks!
546 /* also remove other windows if not capturing anymore */
547 MsqSetStateWindow(ThreadQueue, MSQ_STATE_MENUOWNER, NULL);
548 MsqSetStateWindow(ThreadQueue, MSQ_STATE_MOVESIZE, NULL);
549 ///
550 /* Somebody may have missed some mouse movements */
551 mi.dx = 0;
552 mi.dy = 0;
553 mi.mouseData = 0;
554 mi.dwFlags = MOUSEEVENTF_MOVE;
555 mi.time = 0;
556 mi.dwExtraInfo = 0;
557 UserSendMouseInput(&mi, FALSE);
558 }
559 return hWndPrev;
560 }
561
562 BOOL
563 FASTCALL
564 IntReleaseCapture(VOID)
565 {
566 PTHREADINFO pti;
567 PUSER_MESSAGE_QUEUE ThreadQueue;
568
569 pti = PsGetCurrentThreadWin32Thread();
570 ThreadQueue = pti->MessageQueue;
571
572 // Can not release inside WM_CAPTURECHANGED!!
573 if (ThreadQueue->QF_flags & QF_CAPTURELOCKED) return FALSE;
574
575 co_UserSetCapture(NULL);
576
577 return TRUE;
578 }
579
580 /*
581 * @implemented
582 */
583 HWND APIENTRY
584 NtUserGetForegroundWindow(VOID)
585 {
586 DECLARE_RETURN(HWND);
587
588 TRACE("Enter NtUserGetForegroundWindow\n");
589 UserEnterExclusive();
590
591 RETURN( UserGetForegroundWindow());
592
593 CLEANUP:
594 TRACE("Leave NtUserGetForegroundWindow, ret=%i\n",_ret_);
595 UserLeave();
596 END_CLEANUP;
597 }
598
599 HWND APIENTRY
600 NtUserSetActiveWindow(HWND hWnd)
601 {
602 USER_REFERENCE_ENTRY Ref;
603 DECLARE_RETURN(HWND);
604
605 TRACE("Enter NtUserSetActiveWindow(%x)\n", hWnd);
606 UserEnterExclusive();
607
608 if (hWnd)
609 {
610 PWND Window;
611 PTHREADINFO pti;
612 PUSER_MESSAGE_QUEUE ThreadQueue;
613 HWND hWndPrev;
614
615 if (!(Window = UserGetWindowObject(hWnd)))
616 {
617 RETURN( 0);
618 }
619
620 pti = PsGetCurrentThreadWin32Thread();
621 ThreadQueue = pti->MessageQueue;
622
623 if (Window->head.pti->MessageQueue != ThreadQueue)
624 {
625 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE);
626 RETURN( 0);
627 }
628
629 UserRefObjectCo(Window, &Ref);
630 hWndPrev = co_IntSetActiveWindow(Window);
631 UserDerefObjectCo(Window);
632
633 RETURN( hWndPrev);
634 }
635 else
636 {
637 RETURN( co_IntSetActiveWindow(0));
638 }
639
640 CLEANUP:
641 TRACE("Leave NtUserSetActiveWindow, ret=%i\n",_ret_);
642 UserLeave();
643 END_CLEANUP;
644 }
645
646 /*
647 * @implemented
648 */
649 HWND APIENTRY
650 NtUserSetCapture(HWND hWnd)
651 {
652 DECLARE_RETURN(HWND);
653
654 TRACE("Enter NtUserSetCapture(%x)\n", hWnd);
655 UserEnterExclusive();
656
657 RETURN( co_UserSetCapture(hWnd));
658
659 CLEANUP:
660 TRACE("Leave NtUserSetCapture, ret=%i\n",_ret_);
661 UserLeave();
662 END_CLEANUP;
663 }
664
665 /*
666 * @implemented
667 */
668 HWND APIENTRY
669 NtUserSetFocus(HWND hWnd)
670 {
671 PWND Window;
672 USER_REFERENCE_ENTRY Ref;
673 DECLARE_RETURN(HWND);
674 HWND ret;
675
676 TRACE("Enter NtUserSetFocus(%x)\n", hWnd);
677 UserEnterExclusive();
678
679 if (hWnd)
680 {
681 if (!(Window = UserGetWindowObject(hWnd)))
682 {
683 RETURN(NULL);
684 }
685
686 UserRefObjectCo(Window, &Ref);
687 ret = co_UserSetFocus(Window);
688 UserDerefObjectCo(Window);
689
690 RETURN(ret);
691 }
692 else
693 {
694 RETURN( co_UserSetFocus(0));
695 }
696
697 CLEANUP:
698 TRACE("Leave NtUserSetFocus, ret=%i\n",_ret_);
699 UserLeave();
700 END_CLEANUP;
701 }
702
703 /* EOF */