- Add message type to debug.
[reactos.git] / reactos / win32ss / user / ntuser / callback.c
index 4653f1e..c0d61a5 100644 (file)
@@ -13,6 +13,7 @@
 #include <win32k.h>
 DBG_DEFAULT_CHANNEL(UserCallback);
 
+
 /* CALLBACK MEMORY MANAGEMENT ************************************************/
 
 typedef struct _INT_CALLBACK_HEADER
@@ -77,7 +78,7 @@ IntCleanupThreadCallbacks(PTHREADINFO W32Thread)
                               ListEntry);
 
       /* Free memory */
-      ExFreePool(Mem);
+      ExFreePoolWithTag(Mem, USERTAG_CALLBACK);
    }
 }
 
@@ -114,9 +115,10 @@ IntRestoreTebWndCallback (HWND hWnd, PWND pWnd, PVOID pActCtx)
 /* FUNCTIONS *****************************************************************/
 
 /* Calls ClientLoadLibrary in user32 */
-HMODULE
-co_IntClientLoadLibrary(PUNICODE_STRING pstrLibName, 
-                        PUNICODE_STRING pstrInitFunc, 
+BOOL
+NTAPI
+co_IntClientLoadLibrary(PUNICODE_STRING pstrLibName,
+                        PUNICODE_STRING pstrInitFunc,
                         BOOL Unload,
                         BOOL ApiHook)
 {
@@ -125,9 +127,12 @@ co_IntClientLoadLibrary(PUNICODE_STRING pstrLibName,
    ULONG ArgumentLength;
    PCLIENT_LOAD_LIBRARY_ARGUMENTS pArguments;
    NTSTATUS Status;
-   HMODULE Result;
+   BOOL bResult;
    ULONG_PTR pLibNameBuffer = 0, pInitFuncBuffer = 0;
 
+   /* Do not allow the desktop thread to do callback to user mode */
+   ASSERT(PsGetCurrentThreadWin32Thread() != gptiDesktopThread);
+
    TRACE("co_IntClientLoadLibrary: %S, %S, %d, %d\n", pstrLibName->Buffer, pstrLibName->Buffer, Unload, ApiHook);
 
    /* Calculate the size of the argument */
@@ -139,7 +144,7 @@ co_IntClientLoadLibrary(PUNICODE_STRING pstrLibName,
    }
    if(pstrInitFunc)
    {
-       pInitFuncBuffer = ArgumentLength; 
+       pInitFuncBuffer = ArgumentLength;
        ArgumentLength += pstrInitFunc->Length + sizeof(WCHAR);
    }
 
@@ -208,17 +213,17 @@ co_IntClientLoadLibrary(PUNICODE_STRING pstrLibName,
 
    _SEH2_TRY
    {
+       /* Probe and copy the usermode result data */
        ProbeForRead(ResultPointer, sizeof(HMODULE), 1);
-       /* Simulate old behaviour: copy into our local buffer */
-       Result = *(HMODULE*)ResultPointer;
+       bResult = *(BOOL*)ResultPointer;
    }
    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
    {
-       Result = 0;
+       bResult = FALSE;
    }
    _SEH2_END;
 
-   return Result;
+   return bResult;
 }
 
 VOID APIENTRY
@@ -234,6 +239,9 @@ co_IntCallSentMessageCallback(SENDASYNCPROC CompletionCallback,
    ULONG ResultLength;
    NTSTATUS Status;
 
+   /* Do not allow the desktop thread to do callback to user mode */
+   ASSERT(PsGetCurrentThreadWin32Thread() != gptiDesktopThread);
+
    Arguments.Callback = CompletionCallback;
    Arguments.Wnd = hWnd;
    Arguments.Msg = Msg;
@@ -279,6 +287,9 @@ co_IntCallWindowProc(WNDPROC Proc,
    ULONG ArgumentLength;
    LRESULT Result;
 
+   /* Do not allow the desktop thread to do callback to user mode */
+   ASSERT(PsGetCurrentThreadWin32Thread() != gptiDesktopThread);
+
    if (0 < lParamBufferSize)
    {
       ArgumentLength = sizeof(WINDOWPROC_CALLBACK_ARGUMENTS) + lParamBufferSize;
@@ -323,7 +334,7 @@ co_IntCallWindowProc(WNDPROC Proc,
    }
    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
    {
-      ERR("Failed to copy result from user mode!\n");
+      ERR("Failed to copy result from user mode Message %d!\n", Message);
       Status = _SEH2_GetExceptionCode();
    }
    _SEH2_END;
@@ -362,13 +373,16 @@ co_IntLoadSysMenuTemplate()
    PVOID ResultPointer;
    ULONG ResultLength;
 
+   /* Do not allow the desktop thread to do callback to user mode */
+   ASSERT(PsGetCurrentThreadWin32Thread() != gptiDesktopThread);
+
    ResultPointer = NULL;
    ResultLength = sizeof(LRESULT);
 
    UserLeaveCo();
 
    Status = KeUserModeCallback(USER32_CALLBACK_LOADSYSMENUTEMPLATE,
-                               NULL,
+                               &ResultPointer,
                                0,
                                &ResultPointer,
                                &ResultLength);
@@ -392,6 +406,8 @@ co_IntLoadSysMenuTemplate()
    return (HMENU)Result;
 }
 
+extern HCURSOR gDesktopCursor;
+
 BOOL APIENTRY
 co_IntLoadDefaultCursors(VOID)
 {
@@ -400,8 +416,11 @@ co_IntLoadDefaultCursors(VOID)
    ULONG ResultLength;
    BOOL DefaultCursor = TRUE;
 
+   /* Do not allow the desktop thread to do callback to user mode */
+   ASSERT(PsGetCurrentThreadWin32Thread() != gptiDesktopThread);
+
    ResultPointer = NULL;
-   ResultLength = sizeof(LRESULT);
+   ResultLength = sizeof(HCURSOR);
 
    UserLeaveCo();
 
@@ -413,6 +432,9 @@ co_IntLoadDefaultCursors(VOID)
 
    UserEnterCo();
 
+   /* HACK: The desktop class doen't have a proper cursor yet, so set it here */
+    gDesktopCursor = *((HCURSOR*)ResultPointer);
+
    if (!NT_SUCCESS(Status))
    {
       return FALSE;
@@ -426,6 +448,8 @@ co_IntCallHookProc(INT HookId,
                    WPARAM wParam,
                    LPARAM lParam,
                    HOOKPROC Proc,
+                   INT Mod,
+                   ULONG_PTR offPfn,
                    BOOLEAN Ansi,
                    PUNICODE_STRING ModuleName)
 {
@@ -443,8 +467,11 @@ co_IntCallHookProc(INT HookId,
    PWND pWnd;
    PMSG pMsg = NULL;
    BOOL Hit = FALSE;
+   UINT lParamSize = 0;
 
    ASSERT(Proc);
+   /* Do not allow the desktop thread to do callback to user mode */
+   ASSERT(PsGetCurrentThreadWin32Thread() != gptiDesktopThread);
 
    pti = PsGetCurrentThreadWin32Thread();
    if (pti->TIF_flags & TIF_INCLEANUP)
@@ -509,11 +536,21 @@ co_IntCallHookProc(INT HookId,
          ArgumentLength += sizeof(MOUSEHOOKSTRUCT);
          break;
      case WH_CALLWNDPROC:
+     {
+         CWPSTRUCT* pCWP = (CWPSTRUCT*) lParam;
          ArgumentLength += sizeof(CWPSTRUCT);
+         lParamSize = lParamMemorySize(pCWP->message, pCWP->wParam, pCWP->lParam);
+         ArgumentLength += lParamSize;
          break;
+      }
       case WH_CALLWNDPROCRET:
+      {
+         CWPRETSTRUCT* pCWPR = (CWPRETSTRUCT*) lParam;
          ArgumentLength += sizeof(CWPRETSTRUCT);
+         lParamSize = lParamMemorySize(pCWPR->message, pCWPR->wParam, pCWPR->lParam);
+         ArgumentLength += lParamSize;
          break;
+      }
       case WH_MSGFILTER:
       case WH_SYSMSGFILTER:
       case WH_GETMESSAGE:
@@ -540,7 +577,11 @@ co_IntCallHookProc(INT HookId,
    Common->wParam = wParam;
    Common->lParam = lParam;
    Common->Proc = Proc;
+   Common->Mod = Mod;
+   Common->offPfn = offPfn;
    Common->Ansi = Ansi;
+   RtlZeroMemory(&Common->ModuleName, sizeof(Common->ModuleName));
+   RtlCopyMemory(&Common->ModuleName, ModuleName->Buffer, ModuleName->Length);
    Extra = (PCHAR) Common + sizeof(HOOKPROC_CALLBACK_ARGUMENTS);
 
    switch(HookId)
@@ -583,12 +624,25 @@ co_IntCallHookProc(INT HookId,
          Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
          break;
       case WH_CALLWNDPROC:
+         /* For CALLWNDPROC and CALLWNDPROCRET, we must be wary of the fact that
+          * lParam could be a pointer to a buffer. This buffer must be exported
+          * to user space too */
          RtlCopyMemory(Extra, (PVOID) lParam, sizeof(CWPSTRUCT));
          Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
+         if(lParamSize)
+         {
+             RtlCopyMemory(Extra + sizeof(CWPSTRUCT), (PVOID)((CWPSTRUCT*)lParam)->lParam, lParamSize);
+             ((CWPSTRUCT*)Extra)->lParam = (LPARAM)lParamSize;
+         }
          break;
       case WH_CALLWNDPROCRET:
          RtlCopyMemory(Extra, (PVOID) lParam, sizeof(CWPRETSTRUCT));
          Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
+         if(lParamSize)
+         {
+             RtlCopyMemory(Extra + sizeof(CWPRETSTRUCT), (PVOID)((CWPRETSTRUCT*)lParam)->lParam, lParamSize);
+             ((CWPRETSTRUCT*)Extra)->lParam = (LPARAM)lParamSize;
+         }
          break;
       case WH_MSGFILTER:
       case WH_SYSMSGFILTER:
@@ -633,7 +687,7 @@ co_IntCallHookProc(INT HookId,
    }
    else
    {
-      ERR("ERROR: Hook ResultPointer 0x%x ResultLength %d\n",ResultPointer,ResultLength);
+      ERR("ERROR: Hook ResultPointer 0x%p ResultLength %u\n",ResultPointer,ResultLength);
    }
 
    if (!NT_SUCCESS(Status))
@@ -808,6 +862,9 @@ co_IntClientThreadSetup(VOID)
    ULONG ArgumentLength, ResultLength;
    PVOID Argument, ResultPointer;
 
+   /* Do not allow the desktop thread to do callback to user mode */
+   ASSERT(PsGetCurrentThreadWin32Thread() != gptiDesktopThread);
+
    ArgumentLength = ResultLength = 0;
    Argument = ResultPointer = NULL;
 
@@ -824,6 +881,58 @@ co_IntClientThreadSetup(VOID)
    return Status;
 }
 
+HANDLE FASTCALL
+co_IntCopyImage(HANDLE hnd, UINT type, INT desiredx, INT desiredy, UINT flags)
+{
+   HANDLE Handle;
+   NTSTATUS Status;
+   ULONG ArgumentLength, ResultLength;
+   PVOID Argument, ResultPointer;
+   PCOPYIMAGE_CALLBACK_ARGUMENTS Common;
+
+   ArgumentLength = ResultLength = 0;
+   Argument = ResultPointer = NULL;
+
+   ArgumentLength = sizeof(COPYIMAGE_CALLBACK_ARGUMENTS);
+
+   Argument = IntCbAllocateMemory(ArgumentLength);
+   if (NULL == Argument)
+   {
+      ERR("CopyImage callback failed: out of memory\n");
+      return 0;
+   }
+   Common = (PCOPYIMAGE_CALLBACK_ARGUMENTS) Argument;
+
+   Common->hImage = hnd;
+   Common->uType = type;
+   Common->cxDesired = desiredx;
+   Common->cyDesired = desiredy;
+   Common->fuFlags = flags;
+
+   UserLeaveCo();
+
+   Status = KeUserModeCallback(USER32_CALLBACK_COPYIMAGE,
+                               Argument,
+                               ArgumentLength,
+                               &ResultPointer,
+                               &ResultLength);
+
+
+   UserEnterCo();
+
+   Handle = *(HANDLE*)ResultPointer;
+
+   IntCbFreeMemory(Argument);
+
+   if (!NT_SUCCESS(Status))
+   {
+      ERR("CopyImage callback failed!\n");
+      return 0;
+   }
+
+   return Handle;
+}
+
 BOOL
 APIENTRY
 co_IntGetCharsetInfo(LCID Locale, PCHARSETINFO pCs)
@@ -883,4 +992,53 @@ co_IntGetCharsetInfo(LCID Locale, PCHARSETINFO pCs)
    return TRUE;
 }
 
+BOOL FASTCALL
+co_IntSetWndIcons(VOID)
+{
+   NTSTATUS Status;
+   ULONG ArgumentLength, ResultLength;
+   PVOID Argument, ResultPointer;
+   PSETWNDICONS_CALLBACK_ARGUMENTS Common;
+
+   ArgumentLength = ResultLength = 0;
+   Argument = ResultPointer = NULL;
+
+   ArgumentLength = sizeof(SETWNDICONS_CALLBACK_ARGUMENTS);
+
+   Argument = IntCbAllocateMemory(ArgumentLength);
+   if (NULL == Argument)
+   {
+      ERR("Set Window Icons callback failed: out of memory\n");
+      return FALSE;
+   }
+   Common = (PSETWNDICONS_CALLBACK_ARGUMENTS) Argument;
+
+   UserLeaveCo();
+
+   Status = KeUserModeCallback(USER32_CALLBACK_SETWNDICONS,
+                               Argument,
+                               ArgumentLength,
+                               &ResultPointer,
+                               &ResultLength);
+
+
+   UserEnterCo();
+
+   /* FIXME: Need to setup Registry System Cursor & Icons via Callbacks at init time! */
+   gpsi->hIconSmWindows = Common->hIconSmWindows;
+   gpsi->hIconWindows   = Common->hIconWindows;
+
+   ERR("hIconSmWindows %p hIconWindows %p \n",gpsi->hIconSmWindows,gpsi->hIconWindows);
+
+   IntCbFreeMemory(Argument);
+
+   if (!NT_SUCCESS(Status))
+   {
+      ERR("Set Window Icons callback failed!\n");
+      return FALSE;
+   }
+
+   return TRUE;
+}
+
 /* EOF */