- Turn off debug print outs.
[reactos.git] / reactos / dll / win32 / gdi32 / misc / misc.c
index 9ca6185..3a3ce0a 100644 (file)
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
  *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
-/* $Id$
- *
+/*
  * PROJECT:         ReactOS gdi32.dll
- * FILE:            lib/gdi32/misc/misc.c
+ * FILE:            dll/win32/gdi32/misc/misc.c
  * PURPOSE:         Miscellaneous functions
  * PROGRAMMER:      Thomas Weidenmueller <w3seek@reactos.com>
  * UPDATE HISTORY:
 
 #include "precomp.h"
 
+#define NDEBUG
+#include <debug.h>
+
 PGDI_TABLE_ENTRY GdiHandleTable = NULL;
+PGDI_SHARED_HANDLE_TABLE GdiSharedHandleTable = NULL;
 HANDLE CurrentProcessId = NULL;
 DWORD GDI_BatchLimit = 1;
 
+
+BOOL
+WINAPI
+GdiAlphaBlend(
+            HDC hDCDst,
+            int DstX,
+            int DstY,
+            int DstCx,
+            int DstCy,
+            HDC hDCSrc,
+            int SrcX,
+            int SrcY,
+            int SrcCx,
+            int SrcCy,
+            BLENDFUNCTION BlendFunction
+            )
+{
+   if ( hDCSrc == NULL ) return FALSE;
+
+   if (GDI_HANDLE_GET_TYPE(hDCSrc) == GDI_OBJECT_TYPE_METADC) return FALSE;
+
+   return NtGdiAlphaBlend(
+                      hDCDst,
+                        DstX,
+                        DstY,
+                       DstCx,
+                       DstCy,
+                      hDCSrc,
+                        SrcX,
+                        SrcY,
+                       SrcCx,
+                       SrcCy,
+               BlendFunction,
+                           0 );
+}
+
+/*
+ * @implemented
+ */
+HGDIOBJ
+WINAPI
+GdiFixUpHandle(HGDIOBJ hGdiObj)
+{
+    PGDI_TABLE_ENTRY Entry;
+
+    if (((ULONG_PTR)(hGdiObj)) & GDI_HANDLE_UPPER_MASK )
+    {
+        return hGdiObj;
+    }
+
+    /* FIXME is this right ?? */
+
+    Entry = GdiHandleTable + GDI_HANDLE_GET_INDEX(hGdiObj);
+
+   /* Rebuild handle for Object */
+    return hGdiObj = (HGDIOBJ)(((LONG_PTR)(hGdiObj)) | (Entry->Type << GDI_ENTRY_UPPER_SHIFT));
+}
+
 /*
  * @implemented
  */
 PVOID
-STDCALL
+WINAPI
 GdiQueryTable(VOID)
 {
   return (PVOID)GdiHandleTable;
@@ -45,7 +106,11 @@ GdiQueryTable(VOID)
 BOOL GdiIsHandleValid(HGDIOBJ hGdiObj)
 {
   PGDI_TABLE_ENTRY Entry = GdiHandleTable + GDI_HANDLE_GET_INDEX(hGdiObj);
-  if(Entry->KernelData != NULL && (Entry->Type & GDI_HANDLE_TYPE_MASK) == (LONG)GDI_HANDLE_GET_TYPE(hGdiObj))
+// We are only looking for TYPE not the rest here, and why is FullUnique filled up with CRAP!?
+// DPRINT1("FullUnique -> %x\n", Entry->FullUnique);
+  if((Entry->Type & GDI_ENTRY_BASETYPE_MASK) != 0 &&
+     ( (Entry->Type << GDI_ENTRY_UPPER_SHIFT) & GDI_HANDLE_TYPE_MASK ) == 
+                                                                   GDI_HANDLE_GET_TYPE(hGdiObj))
   {
     HANDLE pid = (HANDLE)((ULONG_PTR)Entry->ProcessId & ~0x1);
     if(pid == NULL || pid == CurrentProcessId)
@@ -56,31 +121,112 @@ BOOL GdiIsHandleValid(HGDIOBJ hGdiObj)
   return FALSE;
 }
 
-BOOL GdiGetHandleUserData(HGDIOBJ hGdiObj, PVOID *UserData)
+BOOL GdiGetHandleUserData(HGDIOBJ hGdiObj, DWORD ObjectType, PVOID *UserData)
 {
   PGDI_TABLE_ENTRY Entry = GdiHandleTable + GDI_HANDLE_GET_INDEX(hGdiObj);
-  if(Entry->KernelData != NULL && (Entry->Type & GDI_HANDLE_TYPE_MASK) == (LONG)GDI_HANDLE_GET_TYPE(hGdiObj))
+  if((Entry->Type & GDI_ENTRY_BASETYPE_MASK) == ObjectType &&
+    ( (Entry->Type << GDI_ENTRY_UPPER_SHIFT) & GDI_HANDLE_TYPE_MASK ) == 
+                                                                GDI_HANDLE_GET_TYPE(hGdiObj))
   {
     HANDLE pid = (HANDLE)((ULONG_PTR)Entry->ProcessId & ~0x1);
     if(pid == NULL || pid == CurrentProcessId)
     {
-      *UserData = Entry->UserData;
-      return TRUE;
+    //
+    // Need to test if we have Read & Write access to the VM address space.
+    //
+      BOOL Result = TRUE;
+      if(Entry->UserData)
+      {
+         volatile CHAR *Current = (volatile CHAR*)Entry->UserData;
+         _SEH2_TRY
+         {
+           *Current = *Current;
+         }
+         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+         {
+           Result = FALSE;
+         }
+         _SEH2_END
+      }
+      else
+         Result = FALSE; // Can not be zero.
+      if (Result) *UserData = Entry->UserData;
+      return Result;
     }
   }
+  SetLastError(ERROR_INVALID_PARAMETER);
   return FALSE;
 }
 
+PLDC
+FASTCALL
+GdiGetLDC(HDC hDC)
+{
+  PDC_ATTR Dc_Attr;
+  PGDI_TABLE_ENTRY Entry = GdiHandleTable + GDI_HANDLE_GET_INDEX((HGDIOBJ) hDC);
+  HANDLE pid = (HANDLE)((ULONG_PTR)Entry->ProcessId & ~0x1);
+  // Don't check the mask, just the object type.
+  if ( Entry->ObjectType == GDIObjType_DC_TYPE &&
+       (pid == NULL || pid == CurrentProcessId) )
+  {
+     BOOL Result = TRUE;
+     if (Entry->UserData)
+     {
+        volatile CHAR *Current = (volatile CHAR*)Entry->UserData;
+        _SEH2_TRY
+        {
+          *Current = *Current;
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+          Result = FALSE;
+        }
+        _SEH2_END
+     }
+     else
+        Result = FALSE;
+
+     if (Result)
+     {
+        Dc_Attr = (PDC_ATTR)Entry->UserData;
+        return Dc_Attr->pvLDC;
+     }
+  }
+  return NULL;
+}
+
+VOID GdiSAPCallback(PLDC pldc)
+{
+    DWORD Time, NewTime = GetTickCount();
+
+    Time = NewTime - pldc->CallBackTick;
+
+    if ( Time < SAPCALLBACKDELAY) return;
+
+    pldc->CallBackTick = NewTime;
+
+    if ( !pldc->pAbortProc(pldc->hDC, 0) )
+    {
+       CancelDC(pldc->hDC);
+       AbortDoc(pldc->hDC);
+    }
+}
 
 /*
  * @implemented
  */
 DWORD
-STDCALL
+WINAPI
 GdiSetBatchLimit(DWORD Limit)
 {
-  DWORD OldLimit = GDI_BatchLimit;
-    if ((!Limit) || (Limit > GDI_BATCH_LIMIT)) return Limit;
+    DWORD OldLimit = GDI_BatchLimit;
+
+    if ( (!Limit) ||
+         (Limit >= GDI_BATCH_LIMIT))
+    {
+        return Limit;
+    }
+
     GdiFlush();
     GDI_BatchLimit = Limit;
     return OldLimit;
@@ -91,8 +237,92 @@ GdiSetBatchLimit(DWORD      Limit)
  * @implemented
  */
 DWORD
-STDCALL
+WINAPI
 GdiGetBatchLimit()
 {
     return GDI_BatchLimit;
 }
+
+/*
+ * @unimplemented
+ */
+BOOL
+WINAPI
+GdiReleaseDC(HDC hdc)
+{
+    return 0;
+}
+
+INT
+WINAPI
+ExtEscape(HDC hDC,
+          int nEscape,
+          int cbInput,
+          LPCSTR lpszInData,
+          int cbOutput,
+          LPSTR lpszOutData)
+{
+    return NtGdiExtEscape(hDC, NULL, 0, nEscape, cbInput, (LPSTR)lpszInData, cbOutput, lpszOutData);
+}
+
+/*
+ * @implemented
+ */
+VOID
+WINAPI
+GdiSetLastError(DWORD dwErrCode)
+{
+    NtCurrentTeb()->LastErrorValue = (ULONG) dwErrCode;
+}
+
+BOOL
+WINAPI
+GdiAddGlsBounds(HDC hdc,LPRECT prc)
+{
+    //FIXME: Lookup what 0x8000 means
+    return NtGdiSetBoundsRect(hdc, prc, 0x8000 |  DCB_ACCUMULATE ) ? TRUE : FALSE;
+}
+
+extern PGDIHANDLECACHE GdiHandleCache;
+
+HGDIOBJ
+FASTCALL
+hGetPEBHandle(HANDLECACHETYPE Type, COLORREF cr)
+{
+   int Number;
+   HANDLE Lock;
+   HGDIOBJ Handle = NULL;
+
+   Lock = InterlockedCompareExchangePointer( (PVOID*)&GdiHandleCache->ulLock,
+                                              NtCurrentTeb(),
+                                              NULL );
+   
+   if (Lock) return Handle;
+
+   Number = GdiHandleCache->ulNumHandles[Type];
+
+   if ( Number && Number <= CACHE_REGION_ENTRIES )
+   {
+      if ( Type == hctRegionHandle)
+      {
+         PRGN_ATTR pRgn_Attr;
+         HGDIOBJ *hPtr;
+         hPtr = GdiHandleCache->Handle + CACHE_BRUSH_ENTRIES+CACHE_PEN_ENTRIES;
+         Handle = hPtr[Number - 1];
+
+         if (GdiGetHandleUserData( Handle, GDI_OBJECT_TYPE_REGION, (PVOID) &pRgn_Attr))
+         {
+            if (pRgn_Attr->AttrFlags & ATTR_CACHED)
+            {
+               DPRINT("Get Handle! Count %d PEB 0x%x\n", GdiHandleCache->ulNumHandles[Type], NtCurrentTeb()->ProcessEnvironmentBlock);
+               pRgn_Attr->AttrFlags &= ~ATTR_CACHED;
+               hPtr[Number - 1] = NULL;
+               GdiHandleCache->ulNumHandles[Type]--;
+            }
+         }
+      }
+   }
+   (void)InterlockedExchangePointer((PVOID*)&GdiHandleCache->ulLock, Lock);
+   return Handle;
+}
+