[WINSOCK]
[reactos.git] / reactos / subsystems / win32 / win32k / ntuser / simplecall.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: NtUserCallXxx call stubs
5 * FILE: subsystem/win32/win32k/ntuser/simplecall.c
6 * PROGRAMER: Ge van Geldorp (ge@gse.nl)
7 * REVISION HISTORY:
8 * 2008/03/20 Split from misc.c
9 */
10
11 #include <win32k.h>
12
13 #define NDEBUG
14 #include <debug.h>
15
16
17 /* registered Logon process */
18 PPROCESSINFO LogonProcess = NULL;
19
20 BOOL FASTCALL
21 co_IntRegisterLogonProcess(HANDLE ProcessId, BOOL Register)
22 {
23 PEPROCESS Process;
24 NTSTATUS Status;
25 CSR_API_MESSAGE Request;
26
27 Status = PsLookupProcessByProcessId(ProcessId,
28 &Process);
29 if (!NT_SUCCESS(Status))
30 {
31 SetLastWin32Error(RtlNtStatusToDosError(Status));
32 return FALSE;
33 }
34
35 if (Register)
36 {
37 /* Register the logon process */
38 if (LogonProcess != NULL)
39 {
40 ObDereferenceObject(Process);
41 return FALSE;
42 }
43
44 LogonProcess = (PPROCESSINFO)Process->Win32Process;
45 }
46 else
47 {
48 /* Deregister the logon process */
49 if (LogonProcess != (PPROCESSINFO)Process->Win32Process)
50 {
51 ObDereferenceObject(Process);
52 return FALSE;
53 }
54
55 LogonProcess = NULL;
56 }
57
58 ObDereferenceObject(Process);
59
60 Request.Type = MAKE_CSR_API(REGISTER_LOGON_PROCESS, CSR_GUI);
61 Request.Data.RegisterLogonProcessRequest.ProcessId = ProcessId;
62 Request.Data.RegisterLogonProcessRequest.Register = Register;
63
64 Status = co_CsrNotify(&Request);
65 if (! NT_SUCCESS(Status))
66 {
67 DPRINT1("Failed to register logon process with CSRSS\n");
68 return FALSE;
69 }
70
71 return TRUE;
72 }
73
74 /*
75 * @unimplemented
76 */
77 DWORD_PTR
78 APIENTRY
79 NtUserCallNoParam(DWORD Routine)
80 {
81 DWORD_PTR Result = 0;
82 DECLARE_RETURN(DWORD_PTR);
83
84 DPRINT("Enter NtUserCallNoParam\n");
85 UserEnterExclusive();
86
87 switch(Routine)
88 {
89 case NOPARAM_ROUTINE_CREATEMENU:
90 Result = (DWORD_PTR)UserCreateMenu(FALSE);
91 break;
92
93 case NOPARAM_ROUTINE_CREATEMENUPOPUP:
94 Result = (DWORD_PTR)UserCreateMenu(TRUE);
95 break;
96
97 case NOPARAM_ROUTINE_DESTROY_CARET:
98 Result = (DWORD_PTR)co_IntDestroyCaret(PsGetCurrentThread()->Tcb.Win32Thread);
99 break;
100
101 case NOPARAM_ROUTINE_INIT_MESSAGE_PUMP:
102 Result = (DWORD_PTR)IntInitMessagePumpHook();
103 break;
104
105 case NOPARAM_ROUTINE_UNINIT_MESSAGE_PUMP:
106 Result = (DWORD_PTR)IntUninitMessagePumpHook();
107 break;
108
109 case NOPARAM_ROUTINE_GETMESSAGEEXTRAINFO:
110 Result = (DWORD_PTR)MsqGetMessageExtraInfo();
111 break;
112
113 case NOPARAM_ROUTINE_MSQCLEARWAKEMASK:
114 RETURN( (DWORD_PTR)IntMsqClearWakeMask());
115
116 default:
117 DPRINT1("Calling invalid routine number 0x%x in NtUserCallNoParam\n", Routine);
118 SetLastWin32Error(ERROR_INVALID_PARAMETER);
119 break;
120 }
121 RETURN(Result);
122
123 CLEANUP:
124 DPRINT("Leave NtUserCallNoParam, ret=%i\n",_ret_);
125 UserLeave();
126 END_CLEANUP;
127 }
128
129
130 /*
131 * @implemented
132 */
133 DWORD_PTR
134 APIENTRY
135 NtUserCallOneParam(
136 DWORD_PTR Param,
137 DWORD Routine)
138 {
139 DECLARE_RETURN(DWORD_PTR);
140
141 DPRINT("Enter NtUserCallOneParam\n");
142
143 UserEnterExclusive();
144
145 switch(Routine)
146 {
147 case ONEPARAM_ROUTINE_POSTQUITMESSAGE:
148 {
149 PTHREADINFO pti;
150 pti = PsGetCurrentThreadWin32Thread();
151 MsqPostQuitMessage(pti->MessageQueue, Param);
152 RETURN(TRUE);
153 }
154 case ONEPARAM_ROUTINE_SHOWCURSOR:
155 RETURN( (DWORD_PTR)UserShowCursor((BOOL)Param) );
156
157 case ONEPARAM_ROUTINE_GETDESKTOPMAPPING:
158 {
159 PTHREADINFO ti;
160 ti = GetW32ThreadInfo();
161 if (ti != NULL)
162 {
163 /* Try convert the pointer to a user mode pointer if the desktop is
164 mapped into the process */
165 RETURN((DWORD_PTR)DesktopHeapAddressToUser((PVOID)Param));
166 }
167 else
168 {
169 RETURN(0);
170 }
171 }
172
173 case ONEPARAM_ROUTINE_WINDOWFROMDC:
174 RETURN( (DWORD_PTR)IntWindowFromDC((HDC)Param));
175
176 case ONEPARAM_ROUTINE_SWAPMOUSEBUTTON:
177 {
178 DWORD_PTR Result;
179
180 Result = gspv.bMouseBtnSwap;
181 gspv.bMouseBtnSwap = Param ? TRUE : FALSE;
182 gpsi->aiSysMet[SM_SWAPBUTTON] = gspv.bMouseBtnSwap;
183 RETURN(Result);
184 }
185
186 case ONEPARAM_ROUTINE_SWITCHCARETSHOWING:
187 RETURN( (DWORD_PTR)IntSwitchCaretShowing((PVOID)Param));
188
189 case ONEPARAM_ROUTINE_SETCARETBLINKTIME:
190 RETURN( (DWORD_PTR)IntSetCaretBlinkTime((UINT)Param));
191
192 case ONEPARAM_ROUTINE_SETMESSAGEEXTRAINFO:
193 RETURN( (DWORD_PTR)MsqSetMessageExtraInfo((LPARAM)Param));
194
195 case ONEPARAM_ROUTINE_CREATECURICONHANDLE:
196 {
197 PCURICON_OBJECT CurIcon;
198
199 if (!(CurIcon = IntCreateCurIconHandle()))
200 {
201 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
202 RETURN(0);
203 }
204
205 RETURN((DWORD_PTR)CurIcon->Self);
206 }
207
208 case ONEPARAM_ROUTINE_GETCURSORPOSITION:
209 {
210 BOOL ret = TRUE;
211
212
213 _SEH2_TRY
214 {
215 ProbeForWrite((POINT*)Param,sizeof(POINT),1);
216 RtlCopyMemory((POINT*)Param,&gpsi->ptCursor,sizeof(POINT));
217 }
218 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
219 {
220 SetLastNtError(_SEH2_GetExceptionCode());
221 ret = FALSE;
222 }
223 _SEH2_END;
224
225 RETURN (ret);
226 }
227
228 case ONEPARAM_ROUTINE_ISWINDOWINDESTROY:
229 {
230 PWINDOW_OBJECT Window;
231 DWORD_PTR Result;
232
233 if(!(Window = UserGetWindowObject((HWND)Param)))
234 {
235 RETURN( FALSE);
236 }
237
238 Result = (DWORD_PTR)IntIsWindowInDestroy(Window);
239
240 RETURN( Result);
241 }
242
243 case ONEPARAM_ROUTINE_ENABLEPROCWNDGHSTING:
244 {
245 BOOL Enable;
246 PPROCESSINFO Process = PsGetCurrentProcessWin32Process();
247
248 if(Process != NULL)
249 {
250 Enable = (BOOL)(Param != 0);
251
252 if(Enable)
253 {
254 Process->W32PF_flags &= ~W32PF_NOWINDOWGHOSTING;
255 }
256 else
257 {
258 Process->W32PF_flags |= W32PF_NOWINDOWGHOSTING;
259 }
260
261 RETURN( TRUE);
262 }
263
264 RETURN( FALSE);
265 }
266
267 case ONEPARAM_ROUTINE_MSQSETWAKEMASK:
268 RETURN( (DWORD_PTR)IntMsqSetWakeMask(Param));
269
270 case ONEPARAM_ROUTINE_GETKEYBOARDTYPE:
271 RETURN( UserGetKeyboardType(Param));
272
273 case ONEPARAM_ROUTINE_GETKEYBOARDLAYOUT:
274 RETURN( (DWORD_PTR)UserGetKeyboardLayout(Param));
275
276 case ONEPARAM_ROUTINE_RELEASEDC:
277 RETURN (UserReleaseDC(NULL, (HDC) Param, FALSE));
278
279 case ONEPARAM_ROUTINE_REALIZEPALETTE:
280 RETURN (UserRealizePalette((HDC) Param));
281
282 case ONEPARAM_ROUTINE_GETQUEUESTATUS:
283 {
284 DWORD Ret;
285 WORD changed_bits, wake_bits;
286 Ret = IntGetQueueStatus(FALSE);
287 changed_bits = LOWORD(Ret);
288 wake_bits = HIWORD(Ret);
289 RETURN( MAKELONG(changed_bits & Param, wake_bits & Param));
290 }
291 case ONEPARAM_ROUTINE_ENUMCLIPBOARDFORMATS:
292 /* FIXME: Should use UserEnterShared */
293 RETURN(IntEnumClipboardFormats(Param));
294
295 case ONEPARAM_ROUTINE_CSRSS_GUICHECK:
296 IntUserManualGuiCheck(Param);
297 RETURN(TRUE);
298
299 case ONEPARAM_ROUTINE_GETCURSORPOS:
300 {
301 BOOL Ret = TRUE;
302 PPOINTL pptl;
303 PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
304 if (pti->hdesk != InputDesktopHandle) RETURN(FALSE);
305 _SEH2_TRY
306 {
307 pptl = (PPOINTL)Param;
308 *pptl = gpsi->ptCursor;
309 }
310 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
311 {
312 Ret = FALSE;
313 }
314 _SEH2_END;
315 RETURN(Ret);
316 }
317 }
318 DPRINT1("Calling invalid routine number 0x%x in NtUserCallOneParam(), Param=0x%x\n",
319 Routine, Param);
320 SetLastWin32Error(ERROR_INVALID_PARAMETER);
321 RETURN( 0);
322
323 CLEANUP:
324 DPRINT("Leave NtUserCallOneParam, ret=%i\n",_ret_);
325 UserLeave();
326 END_CLEANUP;
327 }
328
329
330 /*
331 * @implemented
332 */
333 DWORD_PTR
334 APIENTRY
335 NtUserCallTwoParam(
336 DWORD_PTR Param1,
337 DWORD_PTR Param2,
338 DWORD Routine)
339 {
340 NTSTATUS Status;
341 PWINDOW_OBJECT Window;
342 DECLARE_RETURN(DWORD_PTR);
343
344 DPRINT("Enter NtUserCallTwoParam\n");
345 UserEnterExclusive();
346
347 switch(Routine)
348 {
349 case TWOPARAM_ROUTINE_GETWINDOWRGNBOX:
350 {
351 DWORD_PTR Ret;
352 RECTL rcRect;
353 Window = UserGetWindowObject((HWND)Param1);
354 if (!Window) RETURN(ERROR);
355
356 Ret = (DWORD_PTR)IntGetWindowRgnBox(Window, &rcRect);
357 Status = MmCopyToCaller((PVOID)Param2, &rcRect, sizeof(RECT));
358 if(!NT_SUCCESS(Status))
359 {
360 SetLastNtError(Status);
361 RETURN( ERROR);
362 }
363 RETURN( Ret);
364 }
365 case TWOPARAM_ROUTINE_GETWINDOWRGN:
366 {
367 Window = UserGetWindowObject((HWND)Param1);
368 if (!Window) RETURN(ERROR);
369
370 RETURN( (DWORD_PTR)IntGetWindowRgn(Window, (HRGN)Param2));
371 }
372 case TWOPARAM_ROUTINE_SETMENUBARHEIGHT:
373 {
374 DWORD_PTR Ret;
375 PMENU_OBJECT MenuObject = IntGetMenuObject((HMENU)Param1);
376 if(!MenuObject)
377 RETURN( 0);
378
379 if(Param2 > 0)
380 {
381 Ret = (MenuObject->MenuInfo.Height == (int)Param2);
382 MenuObject->MenuInfo.Height = (int)Param2;
383 }
384 else
385 Ret = (DWORD_PTR)MenuObject->MenuInfo.Height;
386 IntReleaseMenuObject(MenuObject);
387 RETURN( Ret);
388 }
389
390 case TWOPARAM_ROUTINE_SETGUITHRDHANDLE:
391 {
392 PUSER_MESSAGE_QUEUE MsgQueue = ((PTHREADINFO)PsGetCurrentThread()->Tcb.Win32Thread)->MessageQueue;
393
394 ASSERT(MsgQueue);
395 RETURN( (DWORD_PTR)MsqSetStateWindow(MsgQueue, (ULONG)Param1, (HWND)Param2));
396 }
397
398 case TWOPARAM_ROUTINE_ENABLEWINDOW:
399 UNIMPLEMENTED
400 RETURN( 0);
401
402 case TWOPARAM_ROUTINE_SHOWOWNEDPOPUPS:
403 {
404 Window = UserGetWindowObject((HWND)Param1);
405 if (!Window) RETURN(0);
406
407 RETURN( (DWORD_PTR)IntShowOwnedPopups(Window, (BOOL) Param2));
408 }
409
410 case TWOPARAM_ROUTINE_ROS_UPDATEUISTATE:
411 {
412 WPARAM wParam;
413 Window = UserGetWindowObject((HWND)Param1);
414 if (!Window) RETURN(0);
415
416 /* Unpack wParam */
417 wParam = MAKEWPARAM((Param2 >> 3) & 0x3,
418 Param2 & (UISF_HIDEFOCUS | UISF_HIDEACCEL | UISF_ACTIVE));
419
420 RETURN( UserUpdateUiState(Window->Wnd, wParam) );
421 }
422
423 case TWOPARAM_ROUTINE_SWITCHTOTHISWINDOW:
424 UNIMPLEMENTED
425 RETURN( 0);
426
427
428 case TWOPARAM_ROUTINE_SETCARETPOS:
429 RETURN( (DWORD_PTR)co_IntSetCaretPos((int)Param1, (int)Param2));
430
431 case TWOPARAM_ROUTINE_REGISTERLOGONPROC:
432 RETURN( (DWORD_PTR)co_IntRegisterLogonProcess((HANDLE)Param1, (BOOL)Param2));
433
434 case TWOPARAM_ROUTINE_SETCURSORPOS:
435 RETURN( (DWORD_PTR)UserSetCursorPos((int)Param1, (int)Param2, FALSE));
436
437 }
438 DPRINT1("Calling invalid routine number 0x%x in NtUserCallTwoParam(), Param1=0x%x Parm2=0x%x\n",
439 Routine, Param1, Param2);
440 SetLastWin32Error(ERROR_INVALID_PARAMETER);
441 RETURN( 0);
442
443 CLEANUP:
444 DPRINT("Leave NtUserCallTwoParam, ret=%i\n",_ret_);
445 UserLeave();
446 END_CLEANUP;
447 }
448
449
450 /*
451 * @unimplemented
452 */
453 BOOL
454 APIENTRY
455 NtUserCallHwndLock(
456 HWND hWnd,
457 DWORD Routine)
458 {
459 BOOL Ret = 0;
460 PWINDOW_OBJECT Window;
461 PWND Wnd;
462 USER_REFERENCE_ENTRY Ref;
463 DECLARE_RETURN(BOOLEAN);
464
465 DPRINT("Enter NtUserCallHwndLock\n");
466 UserEnterExclusive();
467
468 if (!(Window = UserGetWindowObject(hWnd)) || !Window->Wnd)
469 {
470 RETURN( FALSE);
471 }
472 UserRefObjectCo(Window, &Ref);
473
474 Wnd = Window->Wnd;
475
476 /* FIXME: Routine can be 0x53 - 0x5E */
477 switch (Routine)
478 {
479 case HWNDLOCK_ROUTINE_ARRANGEICONICWINDOWS:
480 co_WinPosArrangeIconicWindows(Window);
481 break;
482
483 case HWNDLOCK_ROUTINE_DRAWMENUBAR:
484 {
485 DPRINT("HWNDLOCK_ROUTINE_DRAWMENUBAR\n");
486 Ret = TRUE;
487 if ((Wnd->style & (WS_CHILD | WS_POPUP)) != WS_CHILD)
488 co_WinPosSetWindowPos( Window,
489 HWND_DESKTOP,
490 0,0,0,0,
491 SWP_NOSIZE|
492 SWP_NOMOVE|
493 SWP_NOZORDER|
494 SWP_NOACTIVATE|
495 SWP_FRAMECHANGED );
496 break;
497 }
498
499 case HWNDLOCK_ROUTINE_REDRAWFRAME:
500 co_WinPosSetWindowPos( Window,
501 HWND_DESKTOP,
502 0,0,0,0,
503 SWP_NOSIZE|
504 SWP_NOMOVE|
505 SWP_NOZORDER|
506 SWP_NOACTIVATE|
507 SWP_FRAMECHANGED );
508 Ret = TRUE;
509 break;
510
511 case HWNDLOCK_ROUTINE_REDRAWFRAMEANDHOOK:
512 co_WinPosSetWindowPos( Window,
513 HWND_DESKTOP,
514 0,0,0,0,
515 SWP_NOSIZE|
516 SWP_NOMOVE|
517 SWP_NOZORDER|
518 SWP_NOACTIVATE|
519 SWP_FRAMECHANGED );
520 if (!Window->spwndOwner && !IntGetParent(Window))
521 {
522 co_IntShellHookNotify(HSHELL_REDRAW, (LPARAM) hWnd);
523 }
524 Ret = TRUE;
525 break;
526
527 case HWNDLOCK_ROUTINE_SETFOREGROUNDWINDOW:
528 Ret = co_IntSetForegroundWindow(Window);
529 break;
530
531 case HWNDLOCK_ROUTINE_UPDATEWINDOW:
532 Ret = co_UserRedrawWindow( Window, NULL, 0, RDW_UPDATENOW | RDW_ALLCHILDREN);
533 break;
534 }
535
536 UserDerefObjectCo(Window);
537
538 RETURN( Ret);
539
540 CLEANUP:
541 DPRINT("Leave NtUserCallHwndLock, ret=%i\n",_ret_);
542 UserLeave();
543 END_CLEANUP;
544 }
545
546 /*
547 * @unimplemented
548 */
549 HWND
550 APIENTRY
551 NtUserCallHwndOpt(
552 HWND hWnd,
553 DWORD Routine)
554 {
555 switch (Routine)
556 {
557 case HWNDOPT_ROUTINE_SETPROGMANWINDOW:
558 GetW32ThreadInfo()->pDeskInfo->hProgmanWindow = hWnd;
559 break;
560
561 case HWNDOPT_ROUTINE_SETTASKMANWINDOW:
562 GetW32ThreadInfo()->pDeskInfo->hTaskManWindow = hWnd;
563 break;
564 }
565
566 return hWnd;
567 }
568
569 DWORD
570 APIENTRY
571 NtUserCallHwnd(
572 HWND hWnd,
573 DWORD Routine)
574 {
575 switch (Routine)
576 {
577 case HWND_ROUTINE_GETWNDCONTEXTHLPID:
578 {
579 PWINDOW_OBJECT Window;
580 PPROPERTY HelpId;
581 USER_REFERENCE_ENTRY Ref;
582
583 UserEnterExclusive();
584
585 if (!(Window = UserGetWindowObject(hWnd)) || !Window->Wnd)
586 {
587 UserLeave();
588 return 0;
589 }
590 UserRefObjectCo(Window, &Ref);
591
592 HelpId = IntGetProp(Window, gpsi->atomContextHelpIdProp);
593
594 UserDerefObjectCo(Window);
595 UserLeave();
596 return (DWORD)HelpId;
597 }
598 case HWND_ROUTINE_REGISTERSHELLHOOKWINDOW:
599 if (IntIsWindow(hWnd))
600 return IntRegisterShellHookWindow(hWnd);
601 return FALSE;
602 break;
603 case HWND_ROUTINE_DEREGISTERSHELLHOOKWINDOW:
604 if (IntIsWindow(hWnd))
605 return IntDeRegisterShellHookWindow(hWnd);
606 return FALSE;
607 }
608 UNIMPLEMENTED;
609
610 return 0;
611 }
612
613 DWORD
614 APIENTRY
615 NtUserCallHwndParam(
616 HWND hWnd,
617 DWORD Param,
618 DWORD Routine)
619 {
620
621 switch (Routine)
622 {
623 case HWNDPARAM_ROUTINE_KILLSYSTEMTIMER:
624 return IntKillTimer(hWnd, (UINT_PTR)Param, TRUE);
625
626 case HWNDPARAM_ROUTINE_SETWNDCONTEXTHLPID:
627 {
628 PWINDOW_OBJECT Window;
629
630 UserEnterExclusive();
631 if(!(Window = UserGetWindowObject(hWnd)))
632 {
633 UserLeave();
634 return FALSE;
635 }
636
637 if ( Param )
638 IntSetProp(Window, gpsi->atomContextHelpIdProp, (HANDLE)Param);
639 else
640 IntRemoveProp(Window, gpsi->atomContextHelpIdProp);
641
642 UserLeave();
643 return TRUE;
644 }
645
646 case HWNDPARAM_ROUTINE_SETDIALOGPOINTER:
647 {
648 PWINDOW_OBJECT Window;
649 PWND pWnd;
650 USER_REFERENCE_ENTRY Ref;
651
652 UserEnterExclusive();
653
654 if (!(Window = UserGetWindowObject(hWnd)) || !Window->Wnd)
655 {
656 UserLeave();
657 return 0;
658 }
659 UserRefObjectCo(Window, &Ref);
660
661 pWnd = Window->Wnd;
662 if (pWnd->head.pti->ppi == PsGetCurrentProcessWin32Process() &&
663 pWnd->cbwndExtra == DLGWINDOWEXTRA &&
664 !(pWnd->state & WNDS_SERVERSIDEWINDOWPROC))
665 {
666 if (Param)
667 {
668 if (!pWnd->fnid) pWnd->fnid = FNID_DIALOG;
669 pWnd->state |= WNDS_DIALOGWINDOW;
670 }
671 else
672 {
673 pWnd->fnid |= FNID_DESTROY;
674 pWnd->state &= ~WNDS_DIALOGWINDOW;
675 }
676 }
677
678 UserDerefObjectCo(Window);
679 UserLeave();
680 return 0;
681 }
682 }
683
684 UNIMPLEMENTED;
685
686 return 0;
687 }
688
689 DWORD
690 APIENTRY
691 NtUserCallHwndParamLock(
692 HWND hWnd,
693 DWORD Param,
694 DWORD Routine)
695 {
696 DWORD Ret = 0;
697 PWINDOW_OBJECT Window;
698 PWND Wnd;
699 USER_REFERENCE_ENTRY Ref;
700 DECLARE_RETURN(DWORD);
701
702 DPRINT1("Enter NtUserCallHwndParamLock\n");
703 UserEnterExclusive();
704
705 if (!(Window = UserGetWindowObject(hWnd)) || !Window->Wnd)
706 {
707 RETURN( FALSE);
708 }
709 UserRefObjectCo(Window, &Ref);
710
711 Wnd = Window->Wnd;
712
713 switch (Routine)
714 {
715 case TWOPARAM_ROUTINE_VALIDATERGN:
716 Ret = (DWORD)co_UserRedrawWindow( Window, NULL, (HRGN)Param, RDW_VALIDATE);
717 break;
718 }
719
720 UserDerefObjectCo(Window);
721
722 RETURN( Ret);
723
724 CLEANUP:
725 DPRINT1("Leave NtUserCallHwndParamLock, ret=%i\n",_ret_);
726 UserLeave();
727 END_CLEANUP;
728
729 }
730
731 /* EOF */