ReactOS  0.4.14-dev-77-gd9e7c48
shutdown.c
Go to the documentation of this file.
1 /*
2  * COPYRIGHT: See COPYING in the top level directory
3  * PROJECT: ReactOS User API Server DLL
4  * FILE: win32ss/user/winsrv/usersrv/shutdown.c
5  * PURPOSE: Logout/shutdown
6  * PROGRAMMERS:
7  */
8 
9 /* INCLUDES *******************************************************************/
10 
11 #include "usersrv.h"
12 
13 #include <commctrl.h>
14 #include <psapi.h>
15 
16 #include "resource.h"
17 
18 #define NDEBUG
19 #include <debug.h>
20 
21 /* GLOBALS ********************************************************************/
22 
23 // Those flags (that are used for CsrProcess->ShutdownFlags) are named
24 // in accordance to the only public one: SHUTDOWN_NORETRY used for the
25 // SetProcessShutdownParameters API.
26 #if !defined(SHUTDOWN_SYSTEMCONTEXT) && !defined(SHUTDOWN_OTHERCONTEXT)
27 #define SHUTDOWN_SYSTEMCONTEXT CsrShutdownSystem
28 #define SHUTDOWN_OTHERCONTEXT CsrShutdownOther
29 #endif
30 
31 // The DPRINTs that need to really be removed as soon as everything works.
32 #define MY_DPRINT DPRINT1
33 #define MY_DPRINT2 DPRINT
34 
35 typedef struct tagNOTIFY_CONTEXT
36 {
40  // HDESK Desktop;
41  // HDESK OldDesktop;
51 
52 #define QUERY_RESULT_ABORT 0
53 #define QUERY_RESULT_CONTINUE 1
54 #define QUERY_RESULT_TIMEOUT 2
55 #define QUERY_RESULT_ERROR 3
56 #define QUERY_RESULT_FORCE 4
57 
59 
60 typedef struct tagMESSAGE_CONTEXT
61 {
68 
69 
70 /* FUNCTIONS ******************************************************************/
71 
73 
74 static VOID
76 {
77  static BOOL Initialized = FALSE;
78  INITCOMMONCONTROLS_PROC InitProc;
79 
80  if (Initialized) return;
81 
82  hComCtl32Lib = LoadLibraryW(L"COMCTL32.DLL");
83  if (hComCtl32Lib == NULL) return;
84 
85  InitProc = (INITCOMMONCONTROLS_PROC)GetProcAddress(hComCtl32Lib, "InitCommonControls");
86  if (InitProc == NULL) return;
87 
88  (*InitProc)();
89 
90  Initialized = TRUE;
91 }
92 
93 static VOID FASTCALL
94 UpdateProgressBar(HWND ProgressBar, PNOTIFY_CONTEXT NotifyContext)
95 {
96  DWORD Passed;
97 
98  Passed = GetTickCount() - NotifyContext->StartTime;
99  Passed -= NotifyContext->ShutdownSettings->HungAppTimeout;
100  if (NotifyContext->ShutdownSettings->WaitToKillAppTimeout < Passed)
101  {
102  Passed = NotifyContext->ShutdownSettings->WaitToKillAppTimeout;
103  }
104  SendMessageW(ProgressBar, PBM_SETPOS, Passed / 2, 0);
105 }
106 
107 static INT_PTR CALLBACK
109 {
110  INT_PTR Result;
111  PNOTIFY_CONTEXT NotifyContext;
112  HWND ProgressBar;
113  DWORD TitleLength;
114  int Len;
115  LPWSTR Title;
116 
117  switch(Msg)
118  {
119  case WM_INITDIALOG:
120  NotifyContext = (PNOTIFY_CONTEXT)lParam;
121  NotifyContext->EndNowResult = QUERY_RESULT_ABORT;
123  TitleLength = SendMessageW(NotifyContext->WndClient, WM_GETTEXTLENGTH,
124  0, 0) +
126  Title = HeapAlloc(UserServerHeap, 0, (TitleLength + 1) * sizeof(WCHAR));
127  if (Title)
128  {
129  Len = GetWindowTextW(Dlg, Title, TitleLength + 1);
130  SendMessageW(NotifyContext->WndClient, WM_GETTEXT,
131  TitleLength + 1 - Len, (LPARAM)(Title + Len));
132  SetWindowTextW(Dlg, Title);
134  }
135  ProgressBar = GetDlgItem(Dlg, IDC_PROGRESS);
136  SendMessageW(ProgressBar, PBM_SETRANGE32, 0,
137  NotifyContext->ShutdownSettings->WaitToKillAppTimeout / 2);
138  UpdateProgressBar(ProgressBar, NotifyContext);
139  SetTimer(Dlg, 0, 200, NULL);
140  Result = FALSE;
141  break;
142 
143  case WM_TIMER:
144  NotifyContext = (PNOTIFY_CONTEXT)GetWindowLongPtrW(Dlg, DWLP_USER);
145  ProgressBar = GetDlgItem(Dlg, IDC_PROGRESS);
146  UpdateProgressBar(ProgressBar, NotifyContext);
147  Result = TRUE;
148  break;
149 
150  case WM_COMMAND:
152  {
153  NotifyContext = (PNOTIFY_CONTEXT)GetWindowLongPtrW(Dlg, DWLP_USER);
154  NotifyContext->EndNowResult = QUERY_RESULT_FORCE;
155  MY_DPRINT("Closing progress dlg by hand\n");
156  SendMessageW(Dlg, WM_CLOSE, 0, 0);
157  Result = TRUE;
158  }
159  else
160  {
161  Result = FALSE;
162  }
163  break;
164 
165  case WM_CLOSE:
166  MY_DPRINT("WM_CLOSE\n");
167  DestroyWindow(Dlg);
168  Result = TRUE;
169  break;
170 
171  case WM_DESTROY:
172  MY_DPRINT("WM_DESTROY\n");
173  NotifyContext = (PNOTIFY_CONTEXT)GetWindowLongPtrW(Dlg, DWLP_USER);
174  NotifyContext->Dlg = NULL;
175  KillTimer(Dlg, 0);
176  PostQuitMessage(NotifyContext->EndNowResult);
177  Result = TRUE;
178  break;
179 
180  default:
181  Result = FALSE;
182  break;
183  }
184 
185  return Result;
186 }
187 
188 static DWORD WINAPI
190 {
191  PNOTIFY_CONTEXT NotifyContext = (PNOTIFY_CONTEXT)Parameter;
192  MSG Msg;
193 
194 #if 0
195  SetThreadDesktop(NotifyContext->Desktop);
196  SwitchDesktop(NotifyContext->Desktop);
197 #else
198  /* For now show the end task dialog in the active desktop */
201  NULL,
202  0);
203 #endif
204 
208  EndNowDlgProc, (LPARAM)NotifyContext);
209  if (NotifyContext->Dlg == NULL)
210  return 0;
211 
212  ShowWindow(NotifyContext->Dlg, SW_SHOWNORMAL);
213 
214  while (GetMessageW(&Msg, NULL, 0, 0))
215  {
216  if (!IsDialogMessage(NotifyContext->Dlg, &Msg))
217  {
220  }
221  }
222 
223  return Msg.wParam;
224 }
225 
226 static DWORD WINAPI
228 {
231 
232  /* If the shutdown is aborted, just notify the process, there is no need to wait */
233  if ((Context->wParam & (MCS_QUERYENDSESSION | MCS_ENDSESSION)) == 0)
234  {
235  DPRINT("Called WM_CLIENTSHUTDOWN with wParam == 0 ...\n");
237  Context->wParam, Context->lParam);
238  return QUERY_RESULT_CONTINUE;
239  }
240 
242  Context->wParam, Context->lParam,
243  SMTO_NORMAL, Context->Timeout, &Result))
244  {
245  DWORD Ret;
246 
247  if (Context->wParam & MCS_QUERYENDSESSION)
248  {
249  /* WM_QUERYENDSESSION case */
250  switch (Result)
251  {
252  case MCSR_DONOTSHUTDOWN:
253  Ret = QUERY_RESULT_ABORT;
254  break;
255 
258  default:
259  Ret = QUERY_RESULT_CONTINUE;
260  }
261  }
262  else
263  {
264  /* WM_ENDSESSION case */
265  Ret = QUERY_RESULT_CONTINUE;
266  }
267 
268  DPRINT("SendClientShutdown -- Return == %s\n",
269  Ret == QUERY_RESULT_CONTINUE ? "Continue" : "Abort");
270  return Ret;
271  }
272 
273  DPRINT1("SendClientShutdown -- Error == %s\n",
274  GetLastError() == 0 ? "Timeout" : "error");
275 
277 }
278 
279 static BOOL
281 {
282  MESSAGE_CONTEXT MessageContext;
283  DWORD Now, Passed;
284  DWORD Timeout, WaitStatus;
285  HANDLE MessageThread;
286  HANDLE Threads[2];
287 
288  SetForegroundWindow(Wnd);
289 
290  Now = GetTickCount();
291  if (NotifyContext->StartTime == 0)
292  NotifyContext->StartTime = Now;
293 
294  /*
295  * Note: Passed is computed correctly even when GetTickCount()
296  * wraps due to unsigned arithmetic.
297  */
298  Passed = Now - NotifyContext->StartTime;
299  MessageContext.Wnd = Wnd;
300  MessageContext.Msg = NotifyContext->Msg;
301  MessageContext.wParam = NotifyContext->wParam;
302  MessageContext.lParam = NotifyContext->lParam;
303  MessageContext.Timeout = NotifyContext->ShutdownSettings->HungAppTimeout;
304  if (!NotifyContext->ShutdownSettings->AutoEndTasks)
305  {
306  MessageContext.Timeout += NotifyContext->ShutdownSettings->WaitToKillAppTimeout;
307  }
308  if (Passed < MessageContext.Timeout)
309  {
310  MessageContext.Timeout -= Passed;
311  MessageThread = CreateThread(NULL, 0, SendClientShutdown,
312  (LPVOID)&MessageContext, 0, NULL);
313  if (MessageThread == NULL)
314  {
315  NotifyContext->QueryResult = QUERY_RESULT_ERROR;
316  return FALSE;
317  }
318  Timeout = NotifyContext->ShutdownSettings->HungAppTimeout;
319  if (Passed < Timeout)
320  {
321  Timeout -= Passed;
322  WaitStatus = WaitForSingleObjectEx(MessageThread, Timeout, FALSE);
323  }
324  else
325  {
326  WaitStatus = WAIT_TIMEOUT;
327  }
328  if (WAIT_TIMEOUT == WaitStatus)
329  {
330  NotifyContext->WndClient = Wnd;
331  if (NotifyContext->UIThread == NULL && NotifyContext->ShowUI)
332  {
333  NotifyContext->UIThread = CreateThread(NULL, 0,
335  (LPVOID)NotifyContext,
336  0, NULL);
337  }
338  Threads[0] = MessageThread;
339  Threads[1] = NotifyContext->UIThread;
340  WaitStatus = WaitForMultipleObjectsEx(NotifyContext->UIThread == NULL ?
341  1 : 2,
342  Threads, FALSE, INFINITE,
343  FALSE);
344  if (WaitStatus == WAIT_OBJECT_0)
345  {
346  if (!GetExitCodeThread(MessageThread, &NotifyContext->QueryResult))
347  {
348  NotifyContext->QueryResult = QUERY_RESULT_ERROR;
349  }
350  }
351  else if (WaitStatus == WAIT_OBJECT_0 + 1)
352  {
353  if (!GetExitCodeThread(NotifyContext->UIThread,
354  &NotifyContext->QueryResult))
355  {
356  NotifyContext->QueryResult = QUERY_RESULT_ERROR;
357  }
358  }
359  else
360  {
361  NotifyContext->QueryResult = QUERY_RESULT_ERROR;
362  }
363  if (WaitStatus != WAIT_OBJECT_0)
364  {
365  TerminateThread(MessageThread, QUERY_RESULT_TIMEOUT);
366  }
367  }
368  else if (WaitStatus == WAIT_OBJECT_0)
369  {
370  if (!GetExitCodeThread(MessageThread,
371  &NotifyContext->QueryResult))
372  {
373  NotifyContext->QueryResult = QUERY_RESULT_ERROR;
374  }
375  }
376  else
377  {
378  NotifyContext->QueryResult = QUERY_RESULT_ERROR;
379  }
380  CloseHandle(MessageThread);
381  }
382  else
383  {
384  NotifyContext->QueryResult = QUERY_RESULT_TIMEOUT;
385  }
386 
387  DPRINT("NotifyContext->QueryResult == %d\n", NotifyContext->QueryResult);
388  return (NotifyContext->QueryResult == QUERY_RESULT_CONTINUE);
389 }
390 
391 static BOOLEAN
393 {
395 }
396 
397 /************************************************/
398 
399 
400 static BOOL
402  IN ULONG Flags,
403  IN ULONG Flags2,
405 {
406  HWND TopWnd = NULL;
407 
408  EnumThreadWindows(HandleToUlong(CsrThread->ClientId.UniqueThread),
409  FindTopLevelWnd, (LPARAM)&TopWnd);
410  if (TopWnd)
411  {
412  HWND hWndOwner;
413 
414  /*** FOR TESTING PURPOSES ONLY!! ***/
415  HWND tmpWnd;
416  tmpWnd = TopWnd;
417  /***********************************/
418 
419  while ((hWndOwner = GetWindow(TopWnd, GW_OWNER)) != NULL)
420  {
421  MY_DPRINT("GetWindow(TopWnd, GW_OWNER) not returned NULL...\n");
422  TopWnd = hWndOwner;
423  }
424  if (TopWnd != tmpWnd) MY_DPRINT("(TopWnd = %x) != (tmpWnd = %x)\n", TopWnd, tmpWnd);
425  }
426  else
427  {
428  return FALSE;
429  }
430 
431  Context->wParam = Flags2;
432  Context->lParam = (0 != (Flags & EWX_CALLER_WINLOGON_LOGOFF) ?
433  ENDSESSION_LOGOFF : 0);
434 
435  Context->StartTime = 0;
436  Context->UIThread = NULL;
438  Context->Dlg = NULL;
439 
440 #if 0 // Obviously, switching desktops like that from within WINSRV doesn't work...
441  {
442  BOOL Success;
444  // Context->Desktop = GetThreadDesktop(HandleToUlong(CsrThread->ClientId.UniqueThread));
446  MY_DPRINT("Last error = %d\n", GetLastError());
447  MY_DPRINT("Before switching to desktop 0x%x\n", Context->Desktop);
448  Success = SwitchDesktop(Context->Desktop);
449  MY_DPRINT("After switching to desktop (Success = %s ; last error = %d); going to notify top-level...\n",
450  Success ? "TRUE" : "FALSE", GetLastError());
451  }
452 #endif
453 
454  NotifyTopLevelWindow(TopWnd, Context);
455 
456 /******************************************************************************/
457 #if 1
458  if (Context->UIThread)
459  {
460  MY_DPRINT("Context->UIThread != NULL\n");
461  if (Context->Dlg)
462  {
463  MY_DPRINT("Sending WM_CLOSE because Dlg is != NULL\n");
464  SendMessageW(Context->Dlg, WM_CLOSE, 0, 0);
465  }
466  else
467  {
468  MY_DPRINT("Terminating UIThread thread with QUERY_RESULT_ERROR\n");
470  }
471  CloseHandle(Context->UIThread);
472  Context->UIThread = NULL;
473  Context->Dlg = NULL;
474  }
475 #endif
476 /******************************************************************************/
477 
478 #if 0
479  MY_DPRINT("Switch back to old desktop 0x%x\n", Context->OldDesktop);
480  SwitchDesktop(Context->OldDesktop);
481  MY_DPRINT("Switched back ok\n");
482 #endif
483 
484  return TRUE;
485 }
486 
487 static ULONG
490  UINT Flags)
491 {
492  DWORD QueryResult = QUERY_RESULT_CONTINUE;
495  PLIST_ENTRY NextEntry;
497  BOOL FoundWindows = FALSE;
498 
499  /* In case we make a forced shutdown, just kill the process */
500  if (Flags & EWX_FORCE)
501  return CsrShutdownCsrProcess;
502 
503  Context.ShutdownSettings = ShutdownSettings;
504  Context.QueryResult = QUERY_RESULT_CONTINUE; // We continue shutdown by default.
505 
506  /* Lock the process */
508 
509  /* Send first the QUERYENDSESSION messages to all the threads of the process */
510  MY_DPRINT2("Sending the QUERYENDSESSION messages...\n");
511 
512  NextEntry = CsrProcess->ThreadList.Flink;
513  while (NextEntry != &CsrProcess->ThreadList)
514  {
515  /* Get the current thread entry */
516  Thread = CONTAINING_RECORD(NextEntry, CSR_THREAD, Link);
517 
518  /* Move to the next entry */
519  NextEntry = NextEntry->Flink;
520 
521  /* If the thread is being terminated, just skip it */
522  if (Thread->Flags & CsrThreadTerminated) continue;
523 
524  /* Reference the thread and temporarily unlock the process */
527 
528  Context.QueryResult = QUERY_RESULT_CONTINUE;
530  {
531  FoundWindows = TRUE;
532  }
533 
534  /* Lock the process again and dereference the thread */
537 
538  // FIXME: Analyze Context.QueryResult !!
539  if (Context.QueryResult == QUERY_RESULT_ABORT) goto Quit;
540  }
541 
542  if (!FoundWindows)
543  {
544  /* We looped all threads but no top level window was found so we didn't send any message */
545  /* Let the console server run the generic process shutdown handler */
548  }
549 
550  QueryResult = Context.QueryResult;
551  MY_DPRINT2("QueryResult = %s\n",
552  QueryResult == QUERY_RESULT_ABORT ? "Abort" : "Continue");
553 
554  /* Now send the ENDSESSION messages to the threads */
555  MY_DPRINT2("Now sending the ENDSESSION messages...\n");
556 
557  NextEntry = CsrProcess->ThreadList.Flink;
558  while (NextEntry != &CsrProcess->ThreadList)
559  {
560  /* Get the current thread entry */
561  Thread = CONTAINING_RECORD(NextEntry, CSR_THREAD, Link);
562 
563  /* Move to the next entry */
564  NextEntry = NextEntry->Flink;
565 
566  /* If the thread is being terminated, just skip it */
567  if (Thread->Flags & CsrThreadTerminated) continue;
568 
569  /* Reference the thread and temporarily unlock the process */
572 
573  Context.QueryResult = QUERY_RESULT_CONTINUE;
575  (QUERY_RESULT_ABORT != QueryResult) ? MCS_ENDSESSION : 0,
576  &Context);
577 
578  /* Lock the process again and dereference the thread */
581  }
582 
583 Quit:
584  /* Unlock the process */
586 
587 #if 0
588  if (Context.UIThread)
589  {
590  if (Context.Dlg)
591  {
592  SendMessageW(Context.Dlg, WM_CLOSE, 0, 0);
593  }
594  else
595  {
597  }
598  CloseHandle(Context.UIThread);
599  }
600 #endif
601 
602  /* Kill the process unless we abort shutdown */
603  if (QueryResult == QUERY_RESULT_ABORT)
604  return CsrShutdownCancelled;
605 
606  return CsrShutdownCsrProcess;
607 }
608 
609 static NTSTATUS FASTCALL
611 {
613  LUID CallerLuid;
614 
616  DWORD ThreadId = HandleToUlong(CsrThread->ClientId.UniqueThread);
617 
618  DPRINT1("SrvExitWindowsEx(ClientId: %lx.%lx, Flags: 0x%x)\n",
619  ProcessId, ThreadId, Flags);
620 
621  /*
622  * Check for flags validity
623  */
624 
626  {
627  /* Only Winlogon can call this */
628  if (ProcessId != LogonProcessId)
629  {
630  DPRINT1("SrvExitWindowsEx call not from Winlogon\n");
631  return STATUS_ACCESS_DENIED;
632  }
633  }
634 
635  /* Implicitely add the shutdown flag when we poweroff or reboot */
636  if (Flags & (EWX_POWEROFF | EWX_REBOOT))
637  Flags |= EWX_SHUTDOWN;
638 
639  /*
640  * Impersonate and retrieve the caller's LUID so that
641  * we can only shutdown processes in its context.
642  */
645 
646  Status = CsrGetProcessLuid(NULL, &CallerLuid);
647  if (!NT_SUCCESS(Status))
648  {
649  DPRINT1("Unable to get caller LUID, Status = 0x%08x\n", Status);
650  goto Quit;
651  }
652 
653  DPRINT("Caller LUID is: %lx.%lx\n", CallerLuid.HighPart, CallerLuid.LowPart);
654 
655  /* Shutdown loop */
656  while (TRUE)
657  {
658  /* Notify Win32k and potentially Winlogon of the shutdown */
661  &Flags, sizeof(Flags));
662  DPRINT("Win32k says: %lx\n", Status);
663  switch (Status)
664  {
665  /* We cannot wait here, the caller should start a new thread */
666  case STATUS_CANT_WAIT:
667  DPRINT1("NtUserSetInformationThread returned STATUS_CANT_WAIT\n");
668  goto Quit;
669 
670  /* Shutdown is in progress */
671  case STATUS_PENDING:
672  DPRINT1("NtUserSetInformationThread returned STATUS_PENDING\n");
673  goto Quit;
674 
675  /* Abort */
676  case STATUS_RETRY:
677  {
678  DPRINT1("NtUserSetInformationThread returned STATUS_RETRY\n");
680  continue;
681  }
682 
683  default:
684  {
685  if (!NT_SUCCESS(Status))
686  {
687  // FIXME: Use some UserSetLastNTError or SetLastNtError
688  // that we have defined for user32 or win32k usage only...
690  goto Quit;
691  }
692  }
693  }
694 
695  /* All good */
696  break;
697  }
698 
699  /*
700  * OK we can continue. Now magic happens:
701  *
702  * Terminate all Win32 processes, stop if we find one kicking
703  * and screaming it doesn't want to die.
704  *
705  * This function calls the ShutdownProcessCallback callback of
706  * each CSR server for each Win32 process.
707  */
708  Status = CsrShutdownProcesses(&CallerLuid, Flags);
709  if (!NT_SUCCESS(Status))
710  {
711  DPRINT1("Failed to shutdown processes, Status = 0x%08x\n", Status);
712  }
713 
714  // FIXME: If Status == STATUS_CANCELLED, call RecordShutdownReason
715 
716  /* Tell Win32k and potentially Winlogon that we're done */
719  &Status, sizeof(Status));
720 
721  DPRINT("SrvExitWindowsEx returned 0x%08x\n", Status);
722 
723 Quit:
724  /* We are done */
725  CsrRevertToSelf();
726  return Status;
727 }
728 
729 
730 ULONG
731 NTAPI
733  IN ULONG Flags,
734  IN BOOLEAN FirstPhase)
735 {
736  ULONG result;
737 
738  DPRINT("UserClientShutdown(0x%p, 0x%x, %s) - [0x%x, 0x%x], ShutdownFlags: %lu\n",
739  CsrProcess, Flags, FirstPhase ? "FirstPhase" : "LastPhase",
740  CsrProcess->ClientId.UniqueProcess, CsrProcess->ClientId.UniqueThread,
741  CsrProcess->ShutdownFlags);
742 
743  /*
744  * Check for process validity
745  */
746 
747  /* Do not kill system processes when a user is logging off */
748  if ((Flags & EWX_SHUTDOWN) == EWX_LOGOFF &&
749  (CsrProcess->ShutdownFlags & (SHUTDOWN_OTHERCONTEXT | SHUTDOWN_SYSTEMCONTEXT)))
750  {
751  DPRINT("Do not kill a system process in a logoff request!\n");
753  }
754 
755  /* Do not kill Winlogon */
756  if (CsrProcess->ClientId.UniqueProcess == UlongToHandle(LogonProcessId))
757  {
758  DPRINT("Not killing Winlogon; CsrProcess->ShutdownFlags = %lu\n",
759  CsrProcess->ShutdownFlags);
760 
761  /* Returning CsrShutdownCsrProcess means that we handled this process by doing nothing */
762  /* This will mark winlogon as processed so consrv won't be notified again for it */
763  CsrDereferenceProcess(CsrProcess);
764  return CsrShutdownCsrProcess;
765  }
766 
767  /* Notify the process for shutdown if needed */
770  {
772  DPRINT1("Process 0x%x aborted shutdown\n", CsrProcess->ClientId.UniqueProcess);
773  return result;
774  }
775 
776  /* Terminate this process */
777 #if DBG
778  {
780  if (!GetProcessImageFileNameW(CsrProcess->ProcessHandle, buffer, MAX_PATH))
781  {
782  DPRINT1("Terminating process %x\n", CsrProcess->ClientId.UniqueProcess);
783  }
784  else
785  {
786  DPRINT1("Terminating process %x (%S)\n", CsrProcess->ClientId.UniqueProcess, buffer);
787  }
788  }
789 #endif
790  NtTerminateProcess(CsrProcess->ProcessHandle, 0);
791 
793 
794  /* We are done */
795  CsrDereferenceProcess(CsrProcess);
796  return CsrShutdownCsrProcess;
797 }
798 
799 
800 /* PUBLIC SERVER APIS *********************************************************/
801 
802 CSR_API(SrvExitWindowsEx)
803 {
805  PUSER_EXIT_REACTOS ExitReactOSRequest = &((PUSER_API_MESSAGE)ApiMessage)->Data.ExitReactOSRequest;
806 
809  NULL,
810  0);
811  if (!NT_SUCCESS(Status))
812  {
813  DPRINT1("Failed to set thread desktop!\n");
814  return Status;
815  }
816 
817  Status = UserExitReactOS(CsrGetClientThread(), ExitReactOSRequest->Flags);
818  ExitReactOSRequest->Success = NT_SUCCESS(Status);
819  ExitReactOSRequest->LastError = GetLastError();
820 
822 
823  return Status;
824 }
825 
826 CSR_API(SrvEndTask)
827 {
828  PUSER_END_TASK EndTaskRequest = &((PUSER_API_MESSAGE)ApiMessage)->Data.EndTaskRequest;
830 
831  // FIXME: This is HACK-plemented!!
832  DPRINT1("SrvEndTask is HACKPLEMENTED!!\n");
833 
836  NULL,
837  0);
838  if (!NT_SUCCESS(Status))
839  {
840  DPRINT1("Failed to set thread desktop!\n");
841  return Status;
842  }
843 
844  SendMessageW(EndTaskRequest->WndHandle, WM_CLOSE, 0, 0);
845  // PostMessageW(EndTaskRequest->WndHandle, WM_CLOSE, 0, 0);
846 
847  if (IsWindow(EndTaskRequest->WndHandle))
848  {
849  if (EndTaskRequest->Force)
850  {
851  EndTaskRequest->Success = DestroyWindow(EndTaskRequest->WndHandle);
852  EndTaskRequest->LastError = GetLastError();
853  }
854  else
855  {
856  EndTaskRequest->Success = FALSE;
857  }
858  }
859  else
860  {
861  EndTaskRequest->Success = TRUE;
862  EndTaskRequest->LastError = ERROR_SUCCESS;
863  }
864 
866 
867  return STATUS_SUCCESS;
868 }
869 
870 CSR_API(SrvRecordShutdownReason)
871 {
872  DPRINT1("%s not yet implemented\n", __FUNCTION__);
873  return STATUS_NOT_IMPLEMENTED;
874 }
875 
876 /* EOF */
#define WM_GETTEXTLENGTH
Definition: winuser.h:1601
#define SHUTDOWN_OTHERCONTEXT
Definition: shutdown.c:28
static BOOLEAN IsConsoleMode(VOID)
Definition: shutdown.c:392
#define MCSR_GOODFORSHUTDOWN
Definition: undocuser.h:106
#define EWX_FORCE
Definition: winuser.h:630
DWORD WINAPI WaitForSingleObjectEx(IN HANDLE hHandle, IN DWORD dwMilliseconds, IN BOOL bAlertable)
Definition: synch.c:94
#define MAKEINTRESOURCE
Definition: winuser.h:591
#define IN
Definition: typedefs.h:38
CSR_API(SrvExitWindowsEx)
Definition: shutdown.c:802
#define CsrGetClientThread()
Definition: csrsrv.h:77
IN PLARGE_INTEGER IN PLARGE_INTEGER PEPROCESS ProcessId
Definition: fatprocs.h:2697
BOOL WINAPI TranslateMessage(_In_ const MSG *)
#define MCSR_DONOTSHUTDOWN
Definition: undocuser.h:108
#define PBM_SETRANGE32
Definition: commctrl.h:2160
#define TRUE
Definition: types.h:120
#define CloseHandle
Definition: compat.h:398
#define STATUS_BAD_IMPERSONATION_LEVEL
Definition: ntstatus.h:387
BOOL Force
Definition: winmsg.h:59
static ULONG NotifyUserProcessForShutdown(PCSR_PROCESS CsrProcess, PSHUTDOWN_SETTINGS ShutdownSettings, UINT Flags)
Definition: shutdown.c:488
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
#define ERROR_SUCCESS
Definition: deptool.c:10
BOOL WINAPI TerminateThread(IN HANDLE hThread, IN DWORD dwExitCode)
Definition: thread.c:586
static BOOL ThreadShutdownNotify(IN PCSR_THREAD CsrThread, IN ULONG Flags, IN ULONG Flags2, IN PNOTIFY_CONTEXT Context)
Definition: shutdown.c:401
BOOL WINAPI IsWindow(_In_opt_ HWND)
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:225
ULONG HungAppTimeout
Definition: winsrv.h:49
DWORD LastError
Definition: winmsg.h:50
#define WM_CLIENTSHUTDOWN
Definition: undocuser.h:35
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1827
#define WM_GETTEXT
Definition: winuser.h:1600
LONG NTSTATUS
Definition: precomp.h:26
#define HandleToUlong(h)
Definition: basetsd.h:79
#define CALLBACK
Definition: compat.h:27
#define NtCurrentThread()
HDESK WINAPI GetThreadDesktop(_In_ DWORD)
DWORD WINAPI GetTickCount(VOID)
Definition: time.c:445
BOOLEAN NTAPI CsrRevertToSelf(VOID)
Definition: procsup.c:1048
#define IDD_END_NOW
Definition: resource.h:10
BOOL WINAPI EnumThreadWindows(_In_ DWORD, _In_ WNDENUMPROC, _In_ LPARAM)
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
GLuint buffer
Definition: glext.h:5915
#define PBM_SETPOS
Definition: commctrl.h:2156
BOOL Success
Definition: winmsg.h:60
VOID NTAPI CsrDereferenceProcess(IN PCSR_PROCESS CsrProcess)
Definition: procsup.c:690
BOOL CALLBACK FindTopLevelWnd(IN HWND hWnd, IN LPARAM lParam)
Definition: init.c:94
HWND WndHandle
Definition: winmsg.h:58
BOOL WINAPI SetWindowTextW(_In_ HWND, _In_opt_ LPCWSTR)
UINT_PTR WPARAM
Definition: windef.h:207
ULONG NTAPI UserClientShutdown(IN PCSR_PROCESS CsrProcess, IN ULONG Flags, IN BOOLEAN FirstPhase)
Definition: shutdown.c:732
DWORD EndNowResult
Definition: shutdown.c:45
VOID NTAPI CsrDereferenceThread(IN PCSR_THREAD CsrThread)
Definition: thredsup.c:775
#define GetWindowLongPtrW
Definition: winuser.h:4730
BOOL WINAPI ShowWindow(_In_ HWND, _In_ int)
_In_ PVOID Parameter
Definition: ldrtypes.h:241
int32_t INT_PTR
Definition: typedefs.h:62
#define EWX_REBOOT
Definition: winuser.h:633
#define IsDialogMessage
Definition: winuser.h:5710
HANDLE UniqueProcess
Definition: compat.h:474
#define FASTCALL
Definition: nt_native.h:50
BOOL WINAPI DestroyWindow(_In_ HWND)
static NTSTATUS FASTCALL UserExitReactOS(PCSR_THREAD CsrThread, UINT Flags)
Definition: shutdown.c:610
static int Link(const char **args)
Definition: vfdcmd.c:2414
WPARAM wParam
Definition: combotst.c:138
#define EWX_LOGOFF
Definition: winuser.h:631
#define SMTO_NORMAL
Definition: winuser.h:1211
#define EWX_CALLER_WINLOGON
Definition: undocuser.h:127
BOOL WINAPI SetThreadDesktop(_In_ HDESK)
#define QUERY_RESULT_ABORT
Definition: shutdown.c:52
#define IDC_PROGRESS
Definition: resource.h:13
BOOL WINAPI GetExitCodeThread(IN HANDLE hThread, OUT LPDWORD lpExitCode)
Definition: thread.c:540
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
static VOID FASTCALL UpdateProgressBar(HWND ProgressBar, PNOTIFY_CONTEXT NotifyContext)
Definition: shutdown.c:94
NTSTATUS NTAPI NtUserSetInformationThread(IN HANDLE ThreadHandle, IN USERTHREADINFOCLASS ThreadInformationClass, IN PVOID ThreadInformation, IN ULONG ThreadInformationLength)
Definition: ntstubs.c:699
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
struct tagNOTIFY_CONTEXT NOTIFY_CONTEXT
struct @1576 Msg[]
static INT_PTR CALLBACK EndNowDlgProc(HWND Dlg, UINT Msg, WPARAM wParam, LPARAM lParam)
Definition: shutdown.c:108
BOOL WINAPI SendNotifyMessageW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
void(WINAPI * INITCOMMONCONTROLS_PROC)(void)
Definition: shutdown.c:58
#define EWX_SHUTDOWN
Definition: winuser.h:634
LRESULT WINAPI DispatchMessageW(_In_ const MSG *)
unsigned int BOOL
Definition: ntddk_ex.h:94
DWORD QueryResult
Definition: shutdown.c:43
NTSTATUS NTAPI CsrShutdownProcesses(IN PLUID CallerLuid, IN ULONG Flags)
Definition: procsup.c:1268
#define QUERY_RESULT_ERROR
Definition: shutdown.c:55
#define QUERY_RESULT_TIMEOUT
Definition: shutdown.c:54
DWORD WINAPI GetWindowThreadProcessId(HWND, PDWORD)
ULONG ProcessTerminateTimeout
Definition: winsrv.h:52
unsigned char BOOLEAN
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:136
#define LoadLibraryW(x)
Definition: compat.h:404
smooth NULL
Definition: ftsmooth.c:416
ULONG_PTR LogonProcessId
Definition: register.c:21
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
LONG_PTR LPARAM
Definition: windef.h:208
NTSTATUS NTAPI CsrLockProcessByClientId(IN HANDLE Pid, OUT PCSR_PROCESS *CsrProcess OPTIONAL)
void DPRINT(...)
Definition: polytest.cpp:61
#define SHUTDOWN_SYSTEMCONTEXT
Definition: shutdown.c:27
CLIENT_ID ClientId
Definition: csrsrv.h:38
#define MY_DPRINT2
Definition: shutdown.c:33
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
DWORD WINAPI GetCurrentThreadId(VOID)
Definition: thread.c:458
UINT_PTR WINAPI SetTimer(_In_opt_ HWND, _In_ UINT_PTR, _In_ UINT, _In_opt_ TIMERPROC)
struct tagMESSAGE_CONTEXT * PMESSAGE_CONTEXT
#define WM_DESTROY
Definition: winuser.h:1591
#define EWX_POWEROFF
Definition: winuser.h:632
static DWORD WINAPI EndNowThreadProc(LPVOID Parameter)
Definition: shutdown.c:189
struct tagMESSAGE_CONTEXT MESSAGE_CONTEXT
VOID NTAPI CsrReferenceThread(IN PCSR_THREAD CsrThread)
Definition: thredsup.c:1042
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
PSHUTDOWN_SETTINGS ShutdownSettings
Definition: shutdown.c:49
struct tagNOTIFY_CONTEXT * PNOTIFY_CONTEXT
#define WAIT_OBJECT_0
Definition: winbase.h:387
static const WCHAR Title[]
Definition: oid.c:1259
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
HWND WINAPI GetDlgItem(_In_opt_ HWND, _In_ int)
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
CLIENT_ID ClientId
Definition: csrsrv.h:68
DWORD LowPart
DWORD WINAPI WaitForMultipleObjectsEx(IN DWORD nCount, IN CONST HANDLE *lpHandles, IN BOOL bWaitAll, IN DWORD dwMilliseconds, IN BOOL bAlertable)
Definition: synch.c:169
#define UlongToHandle(ul)
Definition: basetsd.h:97
#define WM_TIMER
Definition: winuser.h:1724
#define WM_CLOSE
Definition: winuser.h:1603
#define MAX_PATH
Definition: compat.h:26
int WINAPI GetWindowTextLengthW(_In_ HWND)
#define WINAPI
Definition: msvc.h:8
#define QUERY_RESULT_FORCE
Definition: shutdown.c:56
#define BN_CLICKED
Definition: winuser.h:1907
unsigned long DWORD
Definition: ntddk_ex.h:95
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
#define Len
Definition: deflate.h:82
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define SetLastError(x)
Definition: compat.h:409
BOOL WINAPI SwitchDesktop(_In_ HDESK)
struct _USER_API_MESSAGE * PUSER_API_MESSAGE
#define WAIT_TIMEOUT
Definition: dderror.h:14
#define QUERY_RESULT_CONTINUE
Definition: shutdown.c:53
HANDLE UniqueThread
Definition: compat.h:475
HANDLE ThreadHandle
Definition: csrsrv.h:71
BOOL WINAPI KillTimer(_In_opt_ HWND, _In_ UINT_PTR)
HWND WINAPI GetWindow(_In_ HWND, _In_ UINT)
static const WCHAR L[]
Definition: oid.c:1250
LONG HighPart
#define DWLP_USER
Definition: winuser.h:866
struct tm * Now
Definition: output.c:19
#define MCSR_SHUTDOWNFINISHED
Definition: undocuser.h:107
#define MCS_ENDSESSION
Definition: undocuser.h:103
ULONG WaitToKillAppTimeout
Definition: winsrv.h:50
Definition: typedefs.h:117
#define WM_COMMAND
Definition: winuser.h:1722
uint32_t DWORD_PTR
Definition: typedefs.h:63
HINSTANCE UserServerDllInstance
Definition: init.c:21
DWORD_PTR NTAPI NtUserCallNoParam(DWORD Routine)
Definition: simplecall.c:59
Status
Definition: gdiplustypes.h:24
NTSYSAPI ULONG WINAPI RtlNtStatusToDosError(NTSTATUS)
HANDLE UIThread
Definition: shutdown.c:47
#define SW_SHOWNORMAL
Definition: winuser.h:764
SHUTDOWN_SETTINGS ShutdownSettings
Definition: init.c:24
static ULONG Timeout
Definition: ping.c:61
static BOOL NotifyTopLevelWindow(HWND Wnd, PNOTIFY_CONTEXT NotifyContext)
Definition: shutdown.c:280
NTSTATUS NTAPI CsrGetProcessLuid(IN HANDLE hProcess OPTIONAL, OUT PLUID Luid)
Definition: procsup.c:827
int WINAPI GetWindowTextW(HWND hWnd, LPWSTR lpString, int nMaxCount)
Definition: window.c:1408
LIST_ENTRY ThreadList
Definition: csrsrv.h:40
LRESULT WINAPI SendMessageW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
unsigned int UINT
Definition: ndis.h:50
static VOID CallInitCommonControls(VOID)
Definition: shutdown.c:75
#define GW_OWNER
Definition: winuser.h:761
BOOL WINAPI GetMessageW(_Out_ LPMSG, _In_opt_ HWND, _In_ UINT, _In_ UINT)
LRESULT WINAPI SendMessageTimeoutW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM, _In_ UINT, _In_ UINT, _Out_opt_ PDWORD_PTR)
#define DPRINT1
Definition: precomp.h:8
#define STATUS_RETRY
Definition: udferr_usr.h:182
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
DWORD WINAPI GetProcessImageFileNameW(HANDLE hProcess, LPWSTR lpImageFileName, DWORD nSize)
Definition: psapi.c:1179
DWORD LastError
Definition: winmsg.h:57
struct tagContext Context
Definition: acpixf.h:1024
#define HIWORD(l)
Definition: typedefs.h:246
unsigned int ULONG
Definition: retypes.h:1
BOOL WINAPI SetForegroundWindow(_In_ HWND)
#define UNIMPLEMENTED
Definition: debug.h:114
BOOLEAN NTAPI CsrImpersonateClient(IN PCSR_THREAD CsrThread)
Definition: procsup.c:925
NTSTATUS NTAPI NtTerminateProcess(HANDLE ProcessHandle, LONG ExitStatus)
#define EWX_CALLER_WINLOGON_LOGOFF
Definition: undocuser.h:128
#define GetProcAddress(x, y)
Definition: compat.h:410
#define NOPARAM_ROUTINE_ISCONSOLEMODE
Definition: ntuser.h:3537
#define SetWindowLongPtrW
Definition: winuser.h:5247
HANDLE UserServerHeap
Definition: init.c:31
#define MY_DPRINT
Definition: shutdown.c:32
WCHAR * LPWSTR
Definition: xmlstorage.h:184
#define INFINITE
Definition: serial.h:102
localAdvHdr Flags2
Definition: fsrtlfuncs.h:1692
return STATUS_SUCCESS
Definition: btrfs.c:2966
#define IDC_END_NOW
Definition: resource.h:16
#define __FUNCTION__
Definition: types.h:112
GLuint64EXT * result
Definition: glext.h:11304
#define WM_INITDIALOG
Definition: winuser.h:1721
NTSTATUS NTAPI CsrUnlockProcess(IN PCSR_PROCESS CsrProcess)
Definition: procsup.c:1398
LPARAM lParam
Definition: combotst.c:139
#define LOWORD(l)
Definition: pedump.c:82
static HMODULE hComCtl32Lib
Definition: shutdown.c:72
#define HeapFree(x, y, z)
Definition: compat.h:394
__analysis_noreturn void WINAPI PostQuitMessage(_In_ int)
#define MCS_QUERYENDSESSION
Definition: undocuser.h:104
static DWORD WINAPI SendClientShutdown(LPVOID Parameter)
Definition: shutdown.c:227
#define STATUS_CANT_WAIT
Definition: ntstatus.h:438
#define CreateDialogParam
Definition: winuser.h:5653