[WIN32K:NTUSER] Similarly to what was done in USERSRV for harderrors, introduce the...
[reactos.git] / win32ss / user / ntuser / misc.c
index 2e4519f..83d0ad1 100644 (file)
@@ -9,6 +9,30 @@
 #include <win32k.h>
 DBG_DEFAULT_CHANNEL(UserMisc);
 
+
+/*
+ * NOTE: _scwprintf() is NOT exported by ntoskrnl.exe,
+ * only _vscwprintf() is, so we need to implement it here.
+ * Code comes from sdk/lib/crt/printf/_scwprintf.c .
+ * See also win32ss/user/winsrv/usersrv/harderror.c .
+ */
+int
+__cdecl
+_scwprintf(
+    const wchar_t *format,
+    ...)
+{
+    int len;
+    va_list args;
+
+    va_start(args, format);
+    len = _vscwprintf(format, args);
+    va_end(args);
+
+    return len;
+}
+
+
 /*
  * Test the Thread to verify and validate it. Hard to the core tests are required.
  */
@@ -51,6 +75,22 @@ IntTID2PTI(HANDLE id)
    return pti;
 }
 
+DWORD
+FASTCALL
+UserGetLanguageToggle(VOID)
+{
+    NTSTATUS Status;
+    DWORD dwValue = 0;
+
+    Status = RegReadUserSetting(L"Keyboard Layout\\Toggle", L"Layout Hotkey", REG_SZ, &dwValue, sizeof(dwValue));
+    if (NT_SUCCESS(Status))
+    {
+        dwValue = atoi((char *)&dwValue);
+        TRACE("Layout Hotkey %d\n",dwValue);
+    }
+    return dwValue;
+}
+
 SHORT
 FASTCALL
 UserGetLanguageID(VOID)
@@ -58,7 +98,7 @@ UserGetLanguageID(VOID)
   HANDLE KeyHandle;
   OBJECT_ATTRIBUTES ObAttr;
 //  http://support.microsoft.com/kb/324097
-  ULONG Ret = 0x409; // English
+  ULONG Ret = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
   PKEY_VALUE_PARTIAL_INFORMATION pKeyInfo;
   ULONG Size = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + MAX_PATH*sizeof(WCHAR);
   UNICODE_STRING Language;
@@ -67,10 +107,10 @@ UserGetLanguageID(VOID)
     L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Nls\\Language");
 
   InitializeObjectAttributes( &ObAttr,
-                            &Language,
-                 OBJ_CASE_INSENSITIVE,
-                                 NULL,
-                                 NULL);
+                              &Language,
+                              OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
+                              NULL,
+                              NULL);
 
   if ( NT_SUCCESS(ZwOpenKey(&KeyHandle, KEY_READ, &ObAttr)))
   {
@@ -87,7 +127,10 @@ UserGetLanguageID(VOID)
                                              &Size)) )
       {
         RtlInitUnicodeString(&Language, (PWSTR)pKeyInfo->Data);
-        RtlUnicodeStringToInteger(&Language, 16, &Ret);
+        if (!NT_SUCCESS(RtlUnicodeStringToInteger(&Language, 16, &Ret)))
+        {
+            Ret = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
+        }
       }
       ExFreePoolWithTag(pKeyInfo, TAG_STRING);
     }
@@ -223,9 +266,9 @@ NtUserGetThreadState(
          break;
       case THREADSTATE_INSENDMESSAGE:
          {
-           PUSER_SENT_MESSAGE Message = 
+           PUSER_SENT_MESSAGE Message =
                 ((PTHREADINFO)PsGetCurrentThreadWin32Thread())->pusmCurrent;
-           ERR("THREADSTATE_INSENDMESSAGE\n");
+           TRACE("THREADSTATE_INSENDMESSAGE\n");
 
            ret = ISMEX_NOSEND;
            if (Message)
@@ -243,7 +286,7 @@ NtUserGetThreadState(
              if (Message->QS_Flags & QS_SMRESULT) ret |= ISMEX_REPLIED;
            }
 
-           break;         
+           break;
          }
       case THREADSTATE_GETMESSAGETIME:
          ret = ((PTHREADINFO)PsGetCurrentThreadWin32Thread())->timeLast;
@@ -271,9 +314,12 @@ NtUserGetThreadState(
          ret = (DWORD_PTR) (GetW32ThreadInfo()->MessageQueue->CursorObject ?
                             UserHMGetHandle(GetW32ThreadInfo()->MessageQueue->CursorObject) : 0);
          break;
+      case THREADSTATE_GETMESSAGEEXTRAINFO:
+         ret = (DWORD_PTR)MsqGetMessageExtraInfo();
+        break;
    }
 
-   TRACE("Leave NtUserGetThreadState, ret=%i\n", ret);
+   TRACE("Leave NtUserGetThreadState, ret=%lu\n", ret);
    UserLeave();
 
    return ret;
@@ -289,7 +335,7 @@ NtUserSetThreadState(
    DWORD Ret = 0;
    // Test the only flags user can change.
    if (Set & ~(QF_FF10STATUS|QF_DIALOGACTIVE|QF_TABSWITCHING|QF_FMENUSTATUS|QF_FMENUSTATUSBREAK)) return 0;
-   if (Flags & ~(QF_FF10STATUS|QF_DIALOGACTIVE|QF_TABSWITCHING|QF_FMENUSTATUS|QF_FMENUSTATUSBREAK)) return 0;   
+   if (Flags & ~(QF_FF10STATUS|QF_DIALOGACTIVE|QF_TABSWITCHING|QF_FMENUSTATUS|QF_FMENUSTATUSBREAK)) return 0;
    UserEnterExclusive();
    pti = PsGetCurrentThreadWin32Thread();
    if (pti->MessageQueue)
@@ -318,7 +364,7 @@ NtUserGetDoubleClickTime(VOID)
    // FIXME: Check if this works on non-interactive winsta
    Result = gspv.iDblClickTime;
 
-   TRACE("Leave NtUserGetDoubleClickTime, ret=%i\n", Result);
+   TRACE("Leave NtUserGetDoubleClickTime, ret=%u\n", Result);
    UserLeave();
    return Result;
 }
@@ -365,32 +411,58 @@ NtUserGetGUIThreadInfo(
       }
       W32Thread = (PTHREADINFO)Thread->Tcb.Win32Thread;
       Desktop = W32Thread->rpdesk;
+
+      if (!Thread || !Desktop )
+      {
+        if(Thread)
+           ObDereferenceObject(Thread);
+        EngSetLastError(ERROR_ACCESS_DENIED);
+        RETURN( FALSE);
+      }
+      
+      if ( W32Thread->MessageQueue )
+        MsgQueue = W32Thread->MessageQueue;
+      else
+      {
+        if ( Desktop ) MsgQueue = Desktop->ActiveMessageQueue;
+      }
    }
    else
    {  /* Get the foreground thread */
-      Thread = PsGetCurrentThread();
-      W32Thread = (PTHREADINFO)Thread->Tcb.Win32Thread;
-      Desktop = W32Thread->rpdesk;
+      /* FIXME: Handle NULL queue properly? */
+      MsgQueue = IntGetFocusMessageQueue();
+      if(!MsgQueue)
+      {
+        EngSetLastError(ERROR_ACCESS_DENIED);
+        RETURN( FALSE);
+      }
    }
 
-   if (!Thread || !Desktop )
-   {
-      if(idThread && Thread)
-         ObDereferenceObject(Thread);
-      EngSetLastError(ERROR_ACCESS_DENIED);
-      RETURN( FALSE);
-   }
+   CaretInfo = &MsgQueue->CaretInfo;
 
-   if ( W32Thread->MessageQueue )
-      MsgQueue = W32Thread->MessageQueue;
-   else
+   SafeGui.flags = (CaretInfo->Visible ? GUI_CARETBLINKING : 0);
+/*
+   if (W32Thread->pMenuState->pGlobalPopupMenu)
    {
-      if ( Desktop ) MsgQueue = Desktop->ActiveMessageQueue;
+       SafeGui.flags |= GUI_INMENUMODE;
+
+       if (W32Thread->pMenuState->pGlobalPopupMenu->spwndNotify)
+          SafeGui.hwndMenuOwner = UserHMGetHandle(W32Thread->pMenuState->pGlobalPopupMenu->spwndNotify);
+
+       if (W32Thread->pMenuState->pGlobalPopupMenu->fHasMenuBar)
+       {
+          if (W32Thread->pMenuState->pGlobalPopupMenu->fIsSysMenu)
+          {
+             SafeGui.flags |= GUI_SYSTEMMENUMODE;
+          }
+       }
+       else
+       {
+          SafeGui.flags |= GUI_POPUPMENUMODE;
+       }
    }
-
-   CaretInfo = MsgQueue->CaretInfo;
-
-   SafeGui.flags = (CaretInfo->Visible ? GUI_CARETBLINKING : 0);
+ */
+   SafeGui.hwndMenuOwner = MsgQueue->MenuOwner;
 
    if (MsgQueue->MenuOwner)
       SafeGui.flags |= GUI_INMENUMODE | MsgQueue->MenuState;
@@ -403,7 +475,6 @@ NtUserGetGUIThreadInfo(
    SafeGui.hwndActive = MsgQueue->spwndActive ? UserHMGetHandle(MsgQueue->spwndActive) : 0;
    SafeGui.hwndFocus = MsgQueue->spwndFocus ? UserHMGetHandle(MsgQueue->spwndFocus) : 0;
    SafeGui.hwndCapture = MsgQueue->spwndCapture ? UserHMGetHandle(MsgQueue->spwndCapture) : 0;
-   SafeGui.hwndMenuOwner = MsgQueue->MenuOwner;
    SafeGui.hwndMoveSize = MsgQueue->MoveSize;
    SafeGui.hwndCaret = CaretInfo->hWnd;
 
@@ -425,7 +496,7 @@ NtUserGetGUIThreadInfo(
    RETURN( TRUE);
 
 CLEANUP:
-   TRACE("Leave NtUserGetGUIThreadInfo, ret=%i\n",_ret_);
+   TRACE("Leave NtUserGetGUIThreadInfo, ret=%u\n",_ret_);
    UserLeave();
    END_CLEANUP;
 }
@@ -448,7 +519,7 @@ NtUserGetGuiResources(
 
    Status = ObReferenceObjectByHandle(hProcess,
                                       PROCESS_QUERY_INFORMATION,
-                                      PsProcessType,
+                                      *PsProcessType,
                                       ExGetPreviousMode(),
                                       (PVOID*)&Process,
                                       NULL);
@@ -491,7 +562,7 @@ NtUserGetGuiResources(
    RETURN( Ret);
 
 CLEANUP:
-   TRACE("Leave NtUserGetGuiResources, ret=%i\n",_ret_);
+   TRACE("Leave NtUserGetGuiResources, ret=%lu\n",_ret_);
    UserLeave();
    END_CLEANUP;
 }
@@ -656,14 +727,19 @@ void UserDbgAssertThreadInfo(BOOL showCaller)
     ASSERT(pci->ulClientDelta == DesktopHeapGetUserDelta());
     if (pti->pcti && pci->pDeskInfo)
         ASSERT(pci->pClientThreadInfo == (PVOID)((ULONG_PTR)pti->pcti - pci->ulClientDelta));
-    if (pti->KeyboardLayout) 
+    if (pti->pcti && IsListEmpty(&pti->SentMessagesListHead))
+        ASSERT((pti->pcti->fsChangeBits & QS_SENDMESSAGE) == 0);
+    if (pti->KeyboardLayout)
         ASSERT(pci->hKL == pti->KeyboardLayout->hkl);
     if(pti->rpdesk != NULL)
         ASSERT(pti->pDeskInfo == pti->rpdesk->pDeskInfo);
 
     /*too bad we still get this assertion*/
+
+    // Why? Not all flags are passed to the user and doing so could crash the system........
+
     /* ASSERT(pci->dwTIFlags == pti->TIF_flags); */
-    if(pci->dwTIFlags != pti->TIF_flags)
+/*    if(pci->dwTIFlags != pti->TIF_flags)
     {
         ERR("pci->dwTIFlags(0x%x) doesn't match pti->TIF_flags(0x%x)\n", pci->dwTIFlags, pti->TIF_flags);
         if(showCaller)
@@ -673,6 +749,7 @@ void UserDbgAssertThreadInfo(BOOL showCaller)
         }
         pci->dwTIFlags = pti->TIF_flags;
     }
+*/
 }
 
 void
@@ -688,7 +765,7 @@ UserDbgPostServiceHook(ULONG ulSyscallId, ULONG_PTR ulResult)
 {
     /* Make sure that the first syscall is NtUserInitialize */
     /* too bad this fails */
-    //ASSERT(gbInitialized);
+    // ASSERT(gpepCSRSS);
 
     UserDbgAssertThreadInfo(TRUE);
 
@@ -709,4 +786,55 @@ GetW32ThreadInfo(VOID)
     return (PTHREADINFO)PsGetCurrentThreadWin32Thread();
 }
 
+
+NTSTATUS
+GetProcessLuid(
+    IN PETHREAD Thread OPTIONAL,
+    IN PEPROCESS Process OPTIONAL,
+    OUT PLUID Luid)
+{
+    NTSTATUS Status;
+    PACCESS_TOKEN Token = NULL;
+    SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
+    BOOLEAN CopyOnOpen, EffectiveOnly;
+
+    if (Thread && Process)
+        return STATUS_INVALID_PARAMETER;
+
+    /* If nothing has been specified, use the current thread */
+    if (!Thread && !Process)
+        Thread = PsGetCurrentThread();
+
+    if (Thread)
+    {
+        /* Use a thread token */
+        ASSERT(!Process);
+        Token = PsReferenceImpersonationToken(Thread,
+                                              &CopyOnOpen,
+                                              &EffectiveOnly,
+                                              &ImpersonationLevel);
+
+        /* If we don't have a thread token, use a process token */
+        if (!Token)
+            Process = PsGetThreadProcess(Thread);
+    }
+    if (!Token && Process)
+    {
+        /* Use a process token */
+        Token = PsReferencePrimaryToken(Process);
+
+        /* If we don't have a token, fail */
+        if (!Token)
+            return STATUS_NO_TOKEN;
+    }
+    ASSERT(Token);
+
+    /* Query the LUID */
+    Status = SeQueryAuthenticationIdToken(Token, Luid);
+
+    /* Get rid of the token and return */
+    ObDereferenceObject(Token);
+    return Status;
+}
+
 /* EOF */