Commit in reactos on MAIN
lib/user32/windows/window.c+2-51.110 -> 1.111
subsys/win32k/ntuser/misc.c+7-51.59 -> 1.60
                    /window.c+213-801.217 -> 1.218
+222-90
3 modified files
rewrote NtUserFindWindowEx() so it works as it's supposed to. This function is currently called from FindWindowEx(), however there should be a usermode implementation of FindWindowEx() that sends WM_GETTEXT messages to windows belonging to the caller's process. This is not done and should not be done from the kernel mode version.

reactos/lib/user32/windows
window.c 1.110 -> 1.111
diff -u -r1.110 -r1.111
--- window.c	13 Apr 2004 16:48:45 -0000	1.110
+++ window.c	14 Apr 2004 23:17:55 -0000	1.111
@@ -1,4 +1,4 @@
-/* $Id: window.c,v 1.110 2004/04/13 16:48:45 weiden Exp $
+/* $Id: window.c,v 1.111 2004/04/14 23:17:55 weiden Exp $
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS user32.dll
@@ -665,7 +665,7 @@
 
 
 /*
- * @unimplemented
+ * @implemented
  */
 HWND STDCALL
 FindWindowExA(HWND hwndParent,
@@ -731,9 +731,6 @@
    {
       RtlInitUnicodeString(&ucClassName, lpszClass);
    }
-
-   // Window names can't be atoms, and if lpszWindow = NULL,
-   // RtlInitUnicodeString will clear it
 	
    RtlInitUnicodeString(&ucWindowName, lpszWindow);
 

reactos/subsys/win32k/ntuser
misc.c 1.59 -> 1.60
diff -u -r1.59 -r1.60
--- misc.c	9 Apr 2004 20:03:19 -0000	1.59
+++ misc.c	14 Apr 2004 23:17:56 -0000	1.60
@@ -1,4 +1,4 @@
-/* $Id: misc.c,v 1.59 2004/04/09 20:03:19 navaraf Exp $
+/* $Id: misc.c,v 1.60 2004/04/14 23:17:56 weiden Exp $
  *
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
@@ -931,17 +931,17 @@
     return Status;
   }
   
-  if(Dest->MaximumLength > 0)
+  if(Dest->Length > 0)
   {
     Src = Dest->Buffer;
     
-    Dest->Buffer = ExAllocatePoolWithTag(NonPagedPool, Dest->MaximumLength, TAG_STRING);
+    Dest->Buffer = ExAllocatePoolWithTag(NonPagedPool, Dest->Length, TAG_STRING);
     if(!Dest->Buffer)
     {
       return STATUS_NO_MEMORY;
     }
     
-    Status = MmCopyFromCaller(Dest->Buffer, Src, Dest->MaximumLength);
+    Status = MmCopyFromCaller(Dest->Buffer, Src, Dest->Length);
     if(!NT_SUCCESS(Status))
     {
       ExFreePool(Dest->Buffer);
@@ -952,6 +952,8 @@
     
     return STATUS_SUCCESS;
   }
-  return STATUS_UNSUCCESSFUL;
+  
+  /* string is empty */
+  return STATUS_SUCCESS;
 }
 

reactos/subsys/win32k/ntuser
window.c 1.217 -> 1.218
diff -u -r1.217 -r1.218
--- window.c	14 Apr 2004 17:19:38 -0000	1.217
+++ window.c	14 Apr 2004 23:17:56 -0000	1.218
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: window.c,v 1.217 2004/04/14 17:19:38 weiden Exp $
+/* $Id: window.c,v 1.218 2004/04/14 23:17:56 weiden Exp $
  *
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
@@ -2050,6 +2050,60 @@
 }
 
 
+HWND FASTCALL
+IntFindWindow(PWINDOW_OBJECT Parent,
+              PWINDOW_OBJECT ChildAfter,
+              PWNDCLASS_OBJECT ClassObject,
+              PUNICODE_STRING WindowName)
+{
+  BOOL CheckWindowName;
+  HWND *List, *phWnd;
+  HWND Ret = NULL;
+  
+  ASSERT(Parent);
+  
+  CheckWindowName = (WindowName && (WindowName->Length > 0));
+  
+  if((List = IntWinListChildren(Parent)))
+  {
+    phWnd = List;
+    if(ChildAfter)
+    {
+      /* skip handles before and including ChildAfter */
+      while(*phWnd && (*(phWnd++) != ChildAfter->Self));
+    }
+    
+    /* search children */
+    while(*phWnd)
+    {
+      PWINDOW_OBJECT Child;
+      if(!(Child = IntGetWindowObject(*(phWnd++))))
+      {
+        continue;
+      }
+      
+      /* Do not send WM_GETTEXT messages in the kernel mode version!
+         The user mode version however calls GetWindowText() which will
+         send WM_GETTEXT messages to windows belonging to its processes */
+      if(((!CheckWindowName || (CheckWindowName && !RtlCompareUnicodeString(WindowName, &(Child->WindowName), FALSE))) &&
+          (!ClassObject || (ClassObject && (Child->Class == ClassObject))))
+         ||
+         ((!CheckWindowName || (CheckWindowName && !RtlCompareUnicodeString(WindowName, &(Child->WindowName), FALSE))) &&
+          (!ClassObject || (ClassObject && (Child->Class == ClassObject)))))
+      {
+        Ret = Child->Self;
+        IntReleaseWindowObject(Child);
+        break;
+      }
+      
+      IntReleaseWindowObject(Child);
+    }
+    ExFreePool(List);
+  }
+  
+  return Ret;
+}
+
 /*
  * FUNCTION:
  *   Searches a window's children for a window with the specified
@@ -2057,6 +2111,7 @@
  * ARGUMENTS:
  *   hwndParent	    = The window whose childs are to be searched. 
  *					  NULL = desktop
+ *					  HWND_MESSAGE = message-only windows
  *
  *   hwndChildAfter = Search starts after this child window. 
  *					  NULL = start from beginning
@@ -2069,10 +2124,6 @@
  *			  
  * RETURNS:
  *   The HWND of the window if it was found, otherwise NULL
- *
- * FIXME:
- *   Should use MmCopyFromCaller, we don't want an access violation in here
- *	 
  */
 /*
  * @implemented
@@ -2083,97 +2134,179 @@
 		   PUNICODE_STRING ucClassName,
 		   PUNICODE_STRING ucWindowName)
 {
-  NTSTATUS status;
-  HWND windowHandle;
-  PWINDOW_OBJECT ParentWindow, WndChildAfter, WndChild;
-  PWNDCLASS_OBJECT classObject = NULL;
-
-  DPRINT1("NtUserFindWindowEx(%x,%x,%wZ,%wZ)\n",
-     hwndParent, hwndChildAfter, ucClassName, ucWindowName);
+  PWINDOW_OBJECT Parent, ChildAfter;
+  UNICODE_STRING ClassName, WindowName;
+  NTSTATUS Status;
+  HWND Desktop, Ret = NULL;
+  PWNDCLASS_OBJECT ClassObject = NULL;
   
-  // Get a pointer to the class
-  if (ucClassName->Buffer != NULL)
-    {
-      status = ClassReferenceClassByNameOrAtom(&classObject, ucClassName->Buffer);
-      if (!NT_SUCCESS(status))
-        {
-          DPRINT1("Error 1\n");
-          return NULL;
-        }
-    }
+  Desktop = IntGetDesktopWindow();
   
-  // If hwndParent==NULL use the desktop window instead
-  if(!hwndParent)
-      hwndParent = PsGetWin32Thread()->Desktop->DesktopWindow;
-
-  // Get the object
-  ParentWindow = IntGetWindowObject(hwndParent);
-
-  if(!ParentWindow)
-    {
-      if (classObject != NULL)
-        ObmDereferenceObject(classObject);
-      DPRINT1("Error 2\n");
-      return NULL;      
-    }
-
-  IntLockRelatives(ParentWindow);
-
-  if(hwndChildAfter)
+  if(hwndParent == NULL)
+    hwndParent = Desktop;
+  /* FIXME
+  else if(hwndParent == HWND_MESSAGE)
+  {
+    hwndParent = IntGetMessageWindow();
+  }
+  */
+  
+  if(!(Parent = IntGetWindowObject(hwndParent)))
+  {
+    SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
+    return NULL;
+  }
+  
+  ChildAfter = NULL;
+  if(hwndChildAfter && !(ChildAfter = IntGetWindowObject(hwndChildAfter)))
+  {
+    IntReleaseWindowObject(hwndParent);
+    SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
+    return NULL;
+  }
+  
+  /* copy the window name */
+  Status = IntSafeCopyUnicodeString(&WindowName, ucWindowName);
+  if(!NT_SUCCESS(Status))
+  {
+    SetLastNtError(Status);
+    goto Cleanup3;
+  }
+  
+  /* safely copy the class name */
+  Status = MmCopyFromCaller(&ClassName, ucClassName, sizeof(UNICODE_STRING));
+  if(!NT_SUCCESS(Status))
+  {
+    SetLastNtError(Status);
+    goto Cleanup2;
+  }
+  if(ClassName.Length > 0 && ClassName.Buffer)
   {
-    if (!(WndChildAfter = IntGetWindowObject(hwndChildAfter)))
+    WCHAR *buf;
+    /* safely copy the class name string (NULL terminated because class-lookup
+       depends on it... */
+    buf = ExAllocatePoolWithTag(NonPagedPool, ClassName.Length + sizeof(WCHAR), TAG_STRING);
+    if(!buf)
     {
-      SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
-      DPRINT1("Error 3\n");
-      return NULL;
+      SetLastWin32Error(STATUS_INSUFFICIENT_RESOURCES);
+      goto Cleanup2;
     }
-
-    /* must be a direct child (not a decendant child)*/
-    IntLockRelatives(WndChildAfter);
-    if (WndChildAfter->Parent != ParentWindow->Self)
+    Status = MmCopyFromCaller(buf, ClassName.Buffer, ClassName.Length);
+    if(!NT_SUCCESS(Status))
     {
-      DPRINT1("Error 4\n");
-      IntUnLockRelatives(WndChildAfter);
-      SetLastWin32Error(ERROR_INVALID_PARAMETER);
-      return NULL;
+      ExFreePool(buf);
+      SetLastNtError(Status);
+      goto Cleanup2;
     }
-    IntUnLockRelatives(WndChildAfter);
-    
-    WndChild = WndChildAfter->NextSibling;
+    ClassName.Buffer = buf;
+    /* make sure the string is null-terminated */
+    buf += ClassName.Length / sizeof(WCHAR);
+    *buf = L'\0';
   }
-  else
+  
+  /* find the class object */
+  if(ClassName.Buffer)
   {
-    WndChild = ParentWindow->FirstChild;
+    /* this expects the string in ClassName to be NULL-terminated! */
+    Status = ClassReferenceClassByNameOrAtom(&ClassObject, ClassName.Buffer);
+    if(!NT_SUCCESS(Status))
+    {
+      DPRINT1("Window class not found\n");
+      /* windows returns ERROR_FILE_NOT_FOUND !? */
+      SetLastWin32Error(ERROR_FILE_NOT_FOUND);
+      goto Cleanup;
+    }
   }
-
-  while (WndChild)
+  
+  if(Parent->Self == Desktop)
   {
-    if ((classObject == NULL || classObject == WndChild->Class) &&
-        (ucWindowName->Buffer==NULL || 
-        RtlCompareUnicodeString (ucWindowName, &WndChild->WindowName, TRUE) == 0))
+    HWND *List, *phWnd;
+    PWINDOW_OBJECT TopLevelWindow;
+    BOOL CheckWindowName;
+    
+    /* windows searches through all top-level windows if the parent is the desktop
+       window */
+    
+    if((List = IntWinListChildren(Parent)))
     {
-      windowHandle = WndChild->Self;
-
-      IntUnLockRelatives(ParentWindow);
-      IntReleaseWindowObject(ParentWindow);
-      if (classObject != NULL)
-        ObmDereferenceObject (classObject);
+      phWnd = List;
+      
+      if(ChildAfter)
+      {
+        /* skip handles before and including ChildAfter */
+        while(*phWnd && (*(phWnd++) != ChildAfter->Self));
+      }
+      
+      CheckWindowName = WindowName.Length > 0;
       
-      DPRINT1("Success: %x\n", windowHandle);
-      return windowHandle;
+      /* search children */
+      while(*phWnd)
+      {
+        if(!(TopLevelWindow = IntGetWindowObject(*(phWnd++))))
+        {
+          continue;
+        }
+        
+        /* Do not send WM_GETTEXT messages in the kernel mode version!
+           The user mode version however calls GetWindowText() which will
+           send WM_GETTEXT messages to windows belonging to its processes */
+        if(((!CheckWindowName || (CheckWindowName && !RtlCompareUnicodeString(&WindowName, &(TopLevelWindow->WindowName), FALSE))) &&
+            (!ClassObject || (ClassObject && (TopLevelWindow->Class == ClassObject))))
+           ||
+           ((!CheckWindowName || (CheckWindowName && !RtlCompareUnicodeString(&WindowName, &(TopLevelWindow->WindowName), FALSE))) &&
+            (!ClassObject || (ClassObject && (TopLevelWindow->Class == ClassObject)))))
+        {
+          Ret = TopLevelWindow->Self;
+          IntReleaseWindowObject(TopLevelWindow);
+          break;
+        }
+        
+        if(IntFindWindow(TopLevelWindow, NULL, ClassObject, &WindowName))
+        {
+          /* window returns the handle of the top-level window, in case it found
+             the child window */
+          Ret = TopLevelWindow->Self;
+          IntReleaseWindowObject(TopLevelWindow);
+          break;
+        }
+        
+        IntReleaseWindowObject(TopLevelWindow);
+      }
+      ExFreePool(List);
     }
+  }
+  else
+    Ret = IntFindWindow(Parent, ChildAfter, ClassObject, &WindowName);
+  
+#if 0
+  if(Ret == NULL && hwndParent == NULL && hwndChildAfter == NULL)
+  {
+    /* FIXME - if both hwndParent and hwndChildAfter are NULL, we also should
+               search the message-only windows. Should this also be done if
+               Parent is the desktop window??? */
+    PWINDOW_OBJECT MsgWindows;
     
-    WndChild = WndChild->NextSibling;
+    if((MsgWindows = IntGetWindowObject(IntGetMessageWindow())))
+    {
+      Ret = IntFindWindow(MsgWindows, ChildAfter, ClassObject, &WindowName);
+      IntReleaseWindowObject(MsgWindows);
+    }
   }
-
-  IntUnLockRelatives(ParentWindow);
-
-  IntReleaseWindowObject(ParentWindow);
-  if (classObject != NULL)
-    ObmDereferenceObject (classObject);
-
-  DPRINT1("Not found\n");
-  return  NULL;
+#endif
+  
+  Cleanup:
+  if(ClassName.Length > 0 && ClassName.Buffer)
+    ExFreePool(ClassName.Buffer);
+  
+  Cleanup2:
+  RtlFreeUnicodeString(&WindowName);
+  
+  Cleanup3:
+  if(ChildAfter)
+    IntReleaseWindowObject(ChildAfter);
+  IntReleaseWindowObject(Parent);
+  
+  return Ret;
 }
 
 
CVSspam 0.2.8