* Sync up to trunk head (r64921).
[reactos.git] / win32ss / user / user32 / windows / class.c
index 8fe3036..b46f3f7 100644 (file)
@@ -39,7 +39,7 @@ ClassNameToVersion(
 {
    NTSTATUS Status;
    UNICODE_STRING SectionName;
-   WCHAR SeactionNameBuf[256] = {0};
+   WCHAR SeactionNameBuf[MAX_PATH] = {0};
    ACTCTX_SECTION_KEYED_DATA KeyedData = { sizeof(KeyedData) };
 
    if (IS_ATOM(lpszClass))
@@ -67,7 +67,7 @@ ClassNameToVersion(
                                                    ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION,
                                                   &SectionName,
                                                   &KeyedData );
+
    if (NT_SUCCESS(Status) && KeyedData.ulDataFormatVersion == 1)
    {
       struct dll_redirect *dll = KeyedData.lpSectionBase;
@@ -113,9 +113,12 @@ ClassNameToVersion(
    return lpszClass;
 }
 
+//
+// Ref: http://yvs-it.blogspot.com/2010/04/initcommoncontrolsex.html
+//
 BOOL
 FASTCALL
-VersionRegisterClass(
+Real_VersionRegisterClass(
   PCWSTR pszClass,
   LPCWSTR lpLibFileName,
   HANDLE Contex,
@@ -125,7 +128,7 @@ VersionRegisterClass(
    HMODULE hLibModule;
    PREGISTERCLASSNAMEW pRegisterClassNameW;
    UNICODE_STRING ClassName;
-   WCHAR ClassNameBuf[256] = {0};
+   WCHAR ClassNameBuf[MAX_PATH] = {0};
    RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame = { sizeof(Frame), 1 };
 
    RtlActivateActivationContextUnsafeFast(&Frame, Contex);
@@ -162,7 +165,7 @@ VersionRegisterClass(
 Error_Exit:
    if ( Ret || !hLibModule )
    {
-      if ( phLibModule ) *phLibModule = hLibModule;  
+      if ( phLibModule ) *phLibModule = hLibModule;
    }
    else
    {
@@ -170,10 +173,120 @@ Error_Exit:
       FreeLibrary(hLibModule);
       SetLastError(save_error);
    }
-                                  
+
    return Ret;
 }
 
+//
+// Use wine hack to process extened context classes.
+//
+/***********************************************************************
+ *           is_comctl32_class
+ */
+static BOOL is_comctl32_class( const WCHAR *name )
+{
+    static const WCHAR classesW[][20] =
+    {
+        {'C','o','m','b','o','B','o','x','E','x','3','2',0},
+        {'m','s','c','t','l','s','_','h','o','t','k','e','y','3','2',0},
+        {'m','s','c','t','l','s','_','p','r','o','g','r','e','s','s','3','2',0},
+        {'m','s','c','t','l','s','_','s','t','a','t','u','s','b','a','r','3','2',0},
+        {'m','s','c','t','l','s','_','t','r','a','c','k','b','a','r','3','2',0},
+        {'m','s','c','t','l','s','_','u','p','d','o','w','n','3','2',0},
+        {'N','a','t','i','v','e','F','o','n','t','C','t','l',0},
+        {'R','e','B','a','r','W','i','n','d','o','w','3','2',0},
+        {'S','y','s','A','n','i','m','a','t','e','3','2',0},
+        {'S','y','s','D','a','t','e','T','i','m','e','P','i','c','k','3','2',0},
+        {'S','y','s','H','e','a','d','e','r','3','2',0},
+        {'S','y','s','I','P','A','d','d','r','e','s','s','3','2',0},
+        {'S','y','s','L','i','s','t','V','i','e','w','3','2',0},
+        {'S','y','s','M','o','n','t','h','C','a','l','3','2',0},
+        {'S','y','s','P','a','g','e','r',0},
+        {'S','y','s','T','a','b','C','o','n','t','r','o','l','3','2',0},
+        {'S','y','s','T','r','e','e','V','i','e','w','3','2',0},
+        {'T','o','o','l','b','a','r','W','i','n','d','o','w','3','2',0},
+        {'t','o','o','l','t','i','p','s','_','c','l','a','s','s','3','2',0},
+    };
+
+    int min = 0, max = (sizeof(classesW) / sizeof(classesW[0])) - 1;
+
+    while (min <= max)
+    {
+        int res, pos = (min + max) / 2;
+        if (!(res = strcmpiW( name, classesW[pos] ))) return TRUE;
+        if (res < 0) max = pos - 1;
+        else min = pos + 1;
+    }
+    return FALSE;
+}
+
+BOOL
+FASTCALL
+VersionRegisterClass(
+  PCWSTR pszClass,
+  LPCWSTR lpLibFileName,
+  HANDLE Contex,
+  HMODULE * phLibModule)
+{
+   // Should be lpLibFileName.....
+   static const WCHAR comctl32W[] = {'c','o','m','c','t','l','3','2','.','d','l','l',0};
+   //
+   PREGISTERCLASSNAMEW pRegisterClassNameW;
+   UNICODE_STRING ClassName;
+   WCHAR ClassNameBuf[MAX_PATH] = {0};
+   BOOL Ret = FALSE;
+   HMODULE hLibModule = NULL;
+
+   if (!IS_ATOM(pszClass) && is_comctl32_class( pszClass ))
+   {
+   _SEH2_TRY
+   {
+      hLibModule = LoadLibraryW(comctl32W);
+      if ( hLibModule )
+      {
+         if ((pRegisterClassNameW = (void*) GetProcAddress(hLibModule, "RegisterClassNameW")))
+         {
+            if (IS_ATOM(pszClass))
+            {
+               ClassName.Buffer = (LPWSTR)&ClassNameBuf;
+               ClassName.MaximumLength = sizeof(ClassNameBuf);
+               if (!NtUserGetAtomName(LOWORD((DWORD_PTR)pszClass), &ClassName))
+               {
+                  ERR("Error while verifying ATOM\n");
+                  _SEH2_YIELD(goto Error_Exit);
+               }
+               pszClass = (PCWSTR)&ClassNameBuf;
+            }
+            Ret = pRegisterClassNameW(pszClass);
+         }
+      }
+   }
+   _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+   {
+   }
+   _SEH2_END
+
+Error_Exit:
+   if ( Ret || !hLibModule )
+   {
+      if ( phLibModule ) *phLibModule = hLibModule;
+   }
+   else
+   {
+      DWORD save_error = GetLastError();
+      FreeLibrary(hLibModule);
+      SetLastError(save_error);
+   }
+      TRACE( "%s retrying after loading comctl32\n", debugstr_w(pszClass) );
+      return Ret;
+   }
+   TRACE("NO ComCtl32 Class %S!\n",pszClass);
+   return FALSE;
+}
+//
+//
+//
+
 /*
  * @implemented
  */
@@ -185,8 +298,10 @@ GetClassInfoExA(
   LPWNDCLASSEXA lpwcx)
 {
     UNICODE_STRING ClassName = {0};
-    BOOL Ret;
     LPCSTR pszMenuName;
+    HMODULE hLibModule = NULL;
+    DWORD save_error;
+    BOOL Ret, ClassFound = FALSE;
 
     TRACE("%p class/atom: %s/%04x %p\n", hInstance,
         IS_ATOM(lpszClass) ? NULL : lpszClass,
@@ -226,15 +341,38 @@ GetClassInfoExA(
 
     if (!RegisterDefaultClasses)
     {
-        ERR("GetClassInfoExA RegisterSystemControls\n");
+        TRACE("RegisterSystemControls\n");
         RegisterSystemControls();
     }
 
-    Ret = NtUserGetClassInfo(hInstance,
-                             &ClassName,
-                             (LPWNDCLASSEXW)lpwcx,
-                             (LPWSTR *)&pszMenuName,
-                             TRUE);
+    for(;;)
+    {
+       Ret = NtUserGetClassInfo( hInstance,
+                                &ClassName,
+                                (LPWNDCLASSEXW)lpwcx,
+                                (LPWSTR *)&pszMenuName,
+                                 TRUE);
+       if (Ret) break;
+       if (!ClassFound)
+       {
+          save_error = GetLastError();
+          if ( save_error == ERROR_CANNOT_FIND_WND_CLASS ||
+               save_error == ERROR_CLASS_DOES_NOT_EXIST )
+          {
+              ClassFound = VersionRegisterClass(ClassName.Buffer, NULL, NULL, &hLibModule);
+              if (ClassFound) continue;
+          }
+       }
+       if (hLibModule)
+       {
+          save_error = GetLastError();
+          FreeLibrary(hLibModule);
+          SetLastError(save_error);
+          hLibModule = 0;
+       }
+       break;
+    }
+
     if (Ret)
     {
        lpwcx->lpszClassName = lpszClass;
@@ -261,8 +399,10 @@ GetClassInfoExW(
   LPWNDCLASSEXW lpwcx)
 {
     UNICODE_STRING ClassName = {0};
-    BOOL Ret;
     LPWSTR pszMenuName;
+    HMODULE hLibModule = NULL;
+    DWORD save_error;
+    BOOL Ret, ClassFound = FALSE;
 
     TRACE("%p class/atom: %S/%04x %p\n", hInstance,
         IS_ATOM(lpszClass) ? NULL : lpszClass,
@@ -301,15 +441,38 @@ GetClassInfoExW(
 
     if (!RegisterDefaultClasses)
     {
-       ERR("GetClassInfoExW RegisterSystemControls\n");
+       TRACE("RegisterSystemControls\n");
        RegisterSystemControls();
     }
 
-    Ret = NtUserGetClassInfo( hInstance,
-                              &ClassName,
-                              lpwcx,
-                              &pszMenuName,
-                              FALSE);
+    for(;;)
+    {
+       Ret = NtUserGetClassInfo( hInstance,
+                                &ClassName,
+                                 lpwcx,
+                                &pszMenuName,
+                                 FALSE);
+       if (Ret) break;
+       if (!ClassFound)
+       {
+          save_error = GetLastError();
+          if ( save_error == ERROR_CANNOT_FIND_WND_CLASS ||
+               save_error == ERROR_CLASS_DOES_NOT_EXIST )
+          {
+              ClassFound = VersionRegisterClass(ClassName.Buffer, NULL, NULL, &hLibModule);
+              if (ClassFound) continue;
+          }
+       }
+       if (hLibModule)
+       {
+          save_error = GetLastError();
+          FreeLibrary(hLibModule);
+          SetLastError(save_error);
+          hLibModule = 0;
+       }
+       break;
+    }
+
     if (Ret)
     {
        lpwcx->lpszClassName = lpszClass;
@@ -549,7 +712,19 @@ IntGetClassLongA(PWND Wnd, PCLS Class, int nIndex)
             case GCW_ATOM:
                 Ret = (ULONG_PTR)Class->atomClassName;
                 break;
+#ifdef NEW_CURSORICON
+            case GCLP_HCURSOR:
+                Ret = Class->spcur ? (ULONG_PTR)((PPROCMARKHEAD)SharedPtrToUser(Class->spcur))->h : 0;
+                break;
+
+            case GCLP_HICON:
+                Ret = Class->spicn ? (ULONG_PTR)((PPROCMARKHEAD)SharedPtrToUser(Class->spicn))->h : 0;
+                break;
 
+            case GCLP_HICONSM:
+                Ret = Class->spicnSm ? (ULONG_PTR)((PPROCMARKHEAD)SharedPtrToUser(Class->spicnSm))->h : 0;
+                break;
+#else
             case GCLP_HCURSOR:
                 /* FIXME - get handle from pointer to CURSOR object */
                 Ret = (ULONG_PTR)Class->hCursor;
@@ -562,8 +737,9 @@ IntGetClassLongA(PWND Wnd, PCLS Class, int nIndex)
 
             case GCLP_HICONSM:
                 /* FIXME - get handle from pointer to ICON object */
-                Ret = (ULONG_PTR)Class->hIconSm;
+                Ret = (ULONG_PTR)(Class->hIconSm ? Class->hIconSm : Class->hIconSmIntern);
                 break;
+#endif
 
             case GCLP_WNDPROC:
                 Ret = IntGetClsWndProc(Wnd, Class, TRUE);
@@ -627,6 +803,19 @@ IntGetClassLongW (PWND Wnd, PCLS Class, int nIndex)
                 Ret = (ULONG_PTR)Class->atomClassName;
                 break;
 
+#ifdef NEW_CURSORICON
+            case GCLP_HCURSOR:
+                Ret = Class->spcur ? (ULONG_PTR)((PPROCMARKHEAD)SharedPtrToUser(Class->spcur))->h : 0;
+                break;
+
+            case GCLP_HICON:
+                Ret = Class->spicn ? (ULONG_PTR)((PPROCMARKHEAD)SharedPtrToUser(Class->spicn))->h : 0;
+                break;
+
+            case GCLP_HICONSM:
+                Ret = Class->spicnSm ? (ULONG_PTR)((PPROCMARKHEAD)SharedPtrToUser(Class->spicnSm))->h : 0;
+                break;
+#else
             case GCLP_HCURSOR:
                 /* FIXME - get handle from pointer to CURSOR object */
                 Ret = (ULONG_PTR)Class->hCursor;
@@ -639,8 +828,9 @@ IntGetClassLongW (PWND Wnd, PCLS Class, int nIndex)
 
             case GCLP_HICONSM:
                 /* FIXME - get handle from pointer to ICON object */
-                Ret = (ULONG_PTR)Class->hIconSm;
+                Ret = (ULONG_PTR)(Class->hIconSm ? Class->hIconSm : Class->hIconSmIntern);
                 break;
+#endif
 
             case GCLP_WNDPROC:
                 Ret = IntGetClsWndProc(Wnd, Class, FALSE);
@@ -859,7 +1049,7 @@ GetClassNameA(
 {
     WCHAR tmpbuf[MAX_ATOM_LEN + 1];
     int len;
-  
+
     if (nMaxCount <= 0) return 0;
     if (!GetClassNameW( hWnd, tmpbuf, sizeof(tmpbuf)/sizeof(WCHAR) )) return 0;
     RtlUnicodeToMultiByteN( lpClassName, nMaxCount - 1, (PULONG)&len, tmpbuf, strlenW(tmpbuf) * sizeof(WCHAR) );
@@ -1093,7 +1283,7 @@ RealGetWindowClassA(
 {
     WCHAR tmpbuf[MAX_ATOM_LEN + 1];
     UINT len;
-  
+
     if ((INT)cchType <= 0) return 0;
     if (!RealGetWindowClassW( hwnd, tmpbuf, sizeof(tmpbuf)/sizeof(WCHAR) )) return 0;
     RtlUnicodeToMultiByteN( pszType, cchType - 1, (PULONG)&len, tmpbuf, strlenW(tmpbuf) * sizeof(WCHAR) );
@@ -1104,6 +1294,7 @@ RealGetWindowClassA(
 /*
  * Create a small icon based on a standard icon
  */
+#if 0 // Keep vintage code from revision 18764 by GvG!
 static HICON
 CreateSmallIcon(HICON StdIcon)
 {
@@ -1249,7 +1440,7 @@ cleanup:
 
    return SmallIcon;
 }
-
+#endif
 
 ATOM WINAPI
 RegisterClassExWOWW(WNDCLASSEXW *lpwcx,
@@ -1264,6 +1455,9 @@ RegisterClassExWOWW(WNDCLASSEXW *lpwcx,
    UNICODE_STRING MenuName = {0};
    CLSMENUNAME clsMenuName;
    ANSI_STRING AnsiMenuName;
+   HMODULE hLibModule = NULL;
+   DWORD save_error;
+   BOOL ClassFound = FALSE;
 
    if (lpwcx == NULL || lpwcx->cbSize != sizeof(WNDCLASSEXW) ||
        lpwcx->cbClsExtra < 0 || lpwcx->cbWndExtra < 0 ||
@@ -1299,12 +1493,13 @@ RegisterClassExWOWW(WNDCLASSEXW *lpwcx,
       ((WNDCLASSEXW*)lpwcx)->hInstance = GetModuleHandleW(NULL);
 
    RtlCopyMemory(&WndClass, lpwcx, sizeof(WNDCLASSEXW));
-
+/*
    if (NULL == WndClass.hIconSm)
    {
       WndClass.hIconSm = CreateSmallIcon(WndClass.hIcon);
    }
-
+*/
+   RtlInitEmptyAnsiString(&AnsiMenuName, NULL, 0);
    if (WndClass.lpszMenuName != NULL)
    {
       if (!IS_INTRESOURCE(WndClass.lpszMenuName))
@@ -1337,13 +1532,36 @@ RegisterClassExWOWW(WNDCLASSEXW *lpwcx,
    clsMenuName.pwszClientUnicodeMenuName = MenuName.Buffer;
    clsMenuName.pusMenuName = &MenuName;
 
-   Atom = NtUserRegisterClassExWOW( &WndClass,
-                                    &ClassName,
-                                     NULL, //PUNICODE_STRING ClsNVersion,
-                                    &clsMenuName,
-                                     fnID,
-                                     dwFlags,
-                                     pdwWowData);
+   for(;;)
+   {
+       Atom = NtUserRegisterClassExWOW( &WndClass,
+                                        &ClassName,
+                                         NULL, //PUNICODE_STRING ClsNVersion,
+                                        &clsMenuName,
+                                         fnID,
+                                         dwFlags,
+                                         pdwWowData);
+
+       if (Atom) break;
+       if (!ClassFound)
+       {
+          save_error = GetLastError();
+          if ( save_error == ERROR_CANNOT_FIND_WND_CLASS ||
+               save_error == ERROR_CLASS_DOES_NOT_EXIST )
+          {
+              ClassFound = VersionRegisterClass(ClassName.Buffer, NULL, NULL, &hLibModule);
+              if (ClassFound) continue;
+          }
+       }
+       if (hLibModule)
+       {
+          save_error = GetLastError();
+          FreeLibrary(hLibModule);
+          SetLastError(save_error);
+          hLibModule = 0;
+       }
+       break;
+   }
 
    TRACE("atom=%04x wndproc=%p hinst=%p bg=%p style=%08x clsExt=%d winExt=%d class=%p\n",
           Atom, lpwcx->lpfnWndProc, lpwcx->hInstance, lpwcx->hbrBackground,
@@ -1642,6 +1860,7 @@ SetWindowWord ( HWND hWnd,int nIndex,WORD wNewWord )
  */
 LONG
 WINAPI
+DECLSPEC_HOTPATCH
 SetWindowLongA(
   HWND hWnd,
   int nIndex,
@@ -1719,8 +1938,8 @@ UnregisterClassA(
         ClassName.Buffer = (PWSTR)((ULONG_PTR)lpClassName);
 
     Ret = NtUserUnregisterClass(&ClassName,
-                                hInstance,
-                                0);
+                                 hInstance,
+                                 0);
 
     if (!IS_ATOM(lpClassName))
         RtlFreeUnicodeString(&ClassName);