Fix a typo.
[reactos.git] / reactos / subsys / win32k / objects / dc.c
index dfa539c..e44b5df 100644 (file)
  * DC.C - Device context functions
  *
  */
+
 #include <w32k.h>
 
+#define NDEBUG
+#include <debug.h>
+
 #ifndef OBJ_COLORSPACE
 #define OBJ_COLORSPACE (14)
 #endif
@@ -47,7 +51,7 @@ func_type STDCALL  func_name( HDC hdc ) \
     return 0;                       \
   }                                 \
   ft = dc->dc_field;                \
-  DC_UnlockDc( hdc );                          \
+  DC_UnlockDc(dc);                             \
   return ft;                        \
 }
 
@@ -65,7 +69,7 @@ VOID FASTCALL Int##FuncName ( PDC dc, LP##type pt) \
 } \
 BOOL STDCALL NtGdi##FuncName ( HDC hdc, LP##type pt ) \
 { \
-  NTSTATUS Status; \
+  NTSTATUS Status = STATUS_SUCCESS; \
   type Safept; \
   PDC dc; \
   if(!pt) \
@@ -79,8 +83,19 @@ BOOL STDCALL NtGdi##FuncName ( HDC hdc, LP##type pt ) \
     return FALSE; \
   } \
   Int##FuncName( dc, &Safept); \
-  DC_UnlockDc(hdc); \
-  Status = MmCopyToCaller(pt, &Safept, sizeof( type )); \
+  DC_UnlockDc(dc); \
+  _SEH_TRY \
+  { \
+    ProbeForWrite(pt, \
+                  sizeof( type ), \
+                  1); \
+    *pt = Safept; \
+  } \
+  _SEH_HANDLE \
+  { \
+    Status = _SEH_GetExceptionCode(); \
+  } \
+  _SEH_END; \
   if(!NT_SUCCESS(Status)) \
   { \
     SetLastNtError(Status); \
@@ -107,7 +122,7 @@ INT STDCALL  func_name( HDC hdc, INT mode ) \
   } \
   prevMode = dc->dc_field;                  \
   dc->dc_field = mode;                      \
-  DC_UnlockDc ( hdc );                    \
+  DC_UnlockDc ( dc );                    \
   return prevMode;                          \
 }
 
@@ -124,7 +139,7 @@ NtGdiCancelDC(HDC  hDC)
 }
 
 HDC STDCALL
-NtGdiCreateCompatableDC(HDC hDC)
+NtGdiCreateCompatibleDC(HDC hDC)
 {
   PDC  NewDC, OrigDC;
   HBITMAP  hBitmap;
@@ -158,7 +173,7 @@ NtGdiCreateCompatableDC(HDC hDC)
 
   if (NULL == hNewDC)
     {
-      DC_UnlockDc(hDC);
+      DC_UnlockDc(OrigDC);
       if (NULL != DisplayDC)
         {
           NtGdiDeleteDC(DisplayDC);
@@ -193,8 +208,8 @@ NtGdiCreateCompatableDC(HDC hDC)
   /* Create default bitmap */
   if (!(hBitmap = NtGdiCreateBitmap( 1, 1, 1, NewDC->w.bitsPerPixel, NULL )))
     {
-      DC_UnlockDc( hDC );
-      DC_UnlockDc( hNewDC );
+      DC_UnlockDc( OrigDC );
+      DC_UnlockDc( NewDC );
       DC_FreeDC( hNewDC );
       if (NULL != DisplayDC)
         {
@@ -213,12 +228,12 @@ NtGdiCreateCompatableDC(HDC hDC)
   NewDC->w.backgroundColor = OrigDC->w.backgroundColor;
   NewDC->w.backgroundMode = OrigDC->w.backgroundMode;
   NewDC->w.ROPmode = OrigDC->w.ROPmode;
-  DC_UnlockDc( hDC );
+  DC_UnlockDc(NewDC);
+  DC_UnlockDc(OrigDC);
   if (NULL != DisplayDC)
     {
       NtGdiDeleteDC(DisplayDC);
     }
-  DC_UnlockDc(hNewDC);
 
   hVisRgn = NtGdiCreateRectRgn(0, 0, 1, 1);
   NtGdiSelectVisRgn(hNewDC, hVisRgn);
@@ -390,7 +405,7 @@ SetupDevMode(PDEVMODEW DevMode, ULONG DisplayNumber)
   if (Valid)
     {
       ProfilePath = ExAllocatePoolWithTag(PagedPool,
-                                          (wcslen(RegistryPath.Buffer) + 
+                                          (wcslen(RegistryPath.Buffer) +
                                            wcslen(Insert) + 1) * sizeof(WCHAR),
                                           TAG_DC);
       if (NULL != ProfilePath)
@@ -646,18 +661,79 @@ IntPrepareDriverIfNeeded()
    return (PrimarySurface.PreparedDriver ? TRUE : IntPrepareDriver());
 }
 
+static BOOL FASTCALL
+PrepareVideoPrt()
+{
+   PIRP Irp;
+   NTSTATUS Status;
+   IO_STATUS_BLOCK Iosb;
+   BOOL Prepare = TRUE;
+   ULONG Length = sizeof(BOOL);
+   PIO_STACK_LOCATION StackPtr;
+   LARGE_INTEGER StartOffset;
+   PFILE_OBJECT FileObject = PrimarySurface.VideoFileObject;
+   PDEVICE_OBJECT DeviceObject = FileObject->DeviceObject;
+
+   DPRINT("PrepareVideoPrt() called\n");
+
+   KeClearEvent(&PrimarySurface.VideoFileObject->Event);
+
+   ObReferenceObjectByPointer(FileObject, 0, IoFileObjectType, KernelMode);
+
+   StartOffset.QuadPart = 0;
+   Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE,
+                                      DeviceObject,
+                                      (PVOID) &Prepare,
+                                      Length,
+                                      &StartOffset,
+                                      NULL,
+                                      &Iosb);
+   if (NULL == Irp)
+   {
+      return FALSE;
+   }
+
+   /* Set up IRP Data */
+   Irp->Tail.Overlay.OriginalFileObject = FileObject;
+   Irp->RequestorMode = KernelMode;
+   Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;
+   Irp->Overlay.AsynchronousParameters.UserApcContext = NULL;
+   Irp->Flags |= IRP_WRITE_OPERATION;
+
+   /* Setup Stack Data */
+   StackPtr = IoGetNextIrpStackLocation(Irp);
+   StackPtr->FileObject = PrimarySurface.VideoFileObject;
+   StackPtr->Parameters.Write.Key = 0;
+
+   Status = IoCallDriver(DeviceObject, Irp);
+
+   if (STATUS_PENDING == Status)
+   {
+      KeWaitForSingleObject(&FileObject->Event, Executive, KernelMode, TRUE, 0);
+      Status = Iosb.Status;
+   }
+
+   return NT_SUCCESS(Status);
+}
+
 BOOL FASTCALL
 IntCreatePrimarySurface()
 {
    SIZEL SurfSize;
    RECTL SurfaceRect;
    SURFOBJ *SurfObj;
-
+   BOOL calledFromUser;
+   
    if (! IntPrepareDriverIfNeeded())
    {
       return FALSE;
    }
 
+   if (! PrepareVideoPrt())
+   {
+      return FALSE;
+   }
+
    DPRINT("calling EnableSurface\n");
    /* Enable the drawing surface */
    PrimarySurface.Handle =
@@ -673,6 +749,11 @@ IntCreatePrimarySurface()
 
    PrimarySurface.DriverFunctions.AssertMode(PrimarySurface.PDev, TRUE);
 
+   calledFromUser = UserIsEntered(); //fixme: possibly upgrade a shared lock
+   if (!calledFromUser){
+      UserEnterExclusive();
+   }
+
    /* attach monitor */
    IntAttachMonitor(&PrimarySurface, PrimarySurface.DisplayNumber);
 
@@ -690,7 +771,11 @@ IntCreatePrimarySurface()
    GDIDEV(SurfObj)->Pointer.Pos.y = (SurfaceRect.bottom - SurfaceRect.top) / 2;
 
    EngUnlockSurface(SurfObj);
-   IntShowDesktop(IntGetActiveDesktop(), SurfSize.cx, SurfSize.cy);
+   co_IntShowDesktop(IntGetActiveDesktop(), SurfSize.cx, SurfSize.cy);
+
+   if (!calledFromUser){
+      UserLeave();
+   }
 
    return TRUE;
 }
@@ -698,11 +783,22 @@ IntCreatePrimarySurface()
 VOID FASTCALL
 IntDestroyPrimarySurface()
   {
+    BOOL calledFromUser; 
+     
     DRIVER_UnreferenceDriver(L"DISPLAY");
 
+    calledFromUser = UserIsEntered();
+    if (!calledFromUser){
+       UserEnterExclusive();
+    }
+
     /* detach monitor */
     IntDetachMonitor(&PrimarySurface);
 
+    if (!calledFromUser){
+       UserLeave();
+    }
+
     /*
      * FIXME: Hide a mouse pointer there. Also because we have to prevent
      * memory leaks with the Eng* mouse routines.
@@ -729,9 +825,9 @@ IntGdiCreateDC(PUNICODE_STRING Driver,
   HDC      hNewDC;
   PDC      NewDC;
   HDC      hDC = NULL;
-  SURFOBJ *SurfObj;
   HRGN     hVisRgn;
   UNICODE_STRING StdDriver;
+  BOOL calledFromUser;
   
   RtlInitUnicodeString(&StdDriver, L"DISPLAY");
 
@@ -745,10 +841,26 @@ IntGdiCreateDC(PUNICODE_STRING Driver,
               return NULL;
             }
         }
-      else if (! IntGraphicsCheck(TRUE))
+      else
         {
-          DPRINT1("Unable to initialize graphics, returning NULL dc\n");
-          return NULL;
+          calledFromUser = UserIsEntered();
+          if (!calledFromUser){
+             UserEnterExclusive();
+          }
+          
+          if (! co_IntGraphicsCheck(TRUE))
+          {
+            if (!calledFromUser){
+               UserLeave();
+            } 
+            DPRINT1("Unable to initialize graphics, returning NULL dc\n");
+            return NULL;
+          }
+          
+          if (!calledFromUser){
+            UserLeave();
+          } 
+          
         }
     }
 
@@ -756,7 +868,7 @@ IntGdiCreateDC(PUNICODE_STRING Driver,
   if ((hNewDC = DC_FindOpenDC(Driver)) != NULL)
   {
     hDC = hNewDC;
-    return  NtGdiCreateCompatableDC(hDC);
+    return  NtGdiCreateCompatibleDC(hDC);
   }
 
   if (Driver != NULL && Driver->Buffer != NULL)
@@ -793,24 +905,13 @@ IntGdiCreateDC(PUNICODE_STRING Driver,
 
   if (! CreateAsIC)
   {
-    SurfObj = EngLockSurface((HSURF)PrimarySurface.Handle);
-    if ( !SurfObj )
-    {
-      DC_UnlockDc ( hNewDC );
-      DC_FreeDC ( hNewDC) ;
-      return NULL;
-    }
-    ASSERT(NewDC->GDIInfo->cBitsPixel * NewDC->GDIInfo->cPlanes == BitsPerFormat(SurfObj->iBitmapFormat));
-    ASSERT(NewDC->GDIInfo->ulHorzRes == SurfObj->sizlBitmap.cx);
-    ASSERT(NewDC->GDIInfo->ulVertRes == SurfObj->sizlBitmap.cy);
-
     NewDC->w.hPalette = NewDC->DevInfo->hpalDefault;
     NewDC->w.ROPmode = R2_COPYPEN;
-  
-    DC_UnlockDc( hNewDC );
 
-    hVisRgn = NtGdiCreateRectRgn(0, 0, SurfObj->sizlBitmap.cx,
-                                 SurfObj->sizlBitmap.cy);
+    DC_UnlockDc( NewDC );
+
+    hVisRgn = NtGdiCreateRectRgn(0, 0, NewDC->GDIInfo->ulHorzRes,
+                                 NewDC->GDIInfo->ulVertRes);
     NtGdiSelectVisRgn(hNewDC, hVisRgn);
     NtGdiDeleteObject(hVisRgn);
 
@@ -820,14 +921,12 @@ IntGdiCreateDC(PUNICODE_STRING Driver,
     NtGdiSetTextAlign(hNewDC, TA_TOP);
     NtGdiSetBkColor(hNewDC, RGB(255, 255, 255));
     NtGdiSetBkMode(hNewDC, OPAQUE);
-
-    EngUnlockSurface(SurfObj);
   }
   else
   {
-    DC_UnlockDc( hNewDC );
+    DC_UnlockDc( NewDC );
   }
-  
+
   return hNewDC;
 }
 
@@ -840,11 +939,25 @@ NtGdiCreateDC(PUNICODE_STRING Driver,
   UNICODE_STRING SafeDriver, SafeDevice;
   DEVMODEW SafeInitData;
   HDC Ret;
-  NTSTATUS Status;
-  
+  NTSTATUS Status = STATUS_SUCCESS;
+
   if(InitData)
   {
-    Status = MmCopyFromCaller(&SafeInitData, InitData, sizeof(DEVMODEW));
+    _SEH_TRY
+    {
+      ProbeForRead(InitData,
+                   sizeof(DEVMODEW),
+                   1);
+      RtlCopyMemory(&SafeInitData,
+                    InitData,
+                    sizeof(DEVMODEW));
+    }
+    _SEH_HANDLE
+    {
+      Status = _SEH_GetExceptionCode();
+    }
+    _SEH_END;
+
     if(!NT_SUCCESS(Status))
     {
       SetLastNtError(Status);
@@ -852,7 +965,7 @@ NtGdiCreateDC(PUNICODE_STRING Driver,
     }
     /* FIXME - InitData can have some more bytes! */
   }
-  
+
   if(Driver)
   {
     Status = IntSafeCopyUnicodeString(&SafeDriver, Driver);
@@ -862,7 +975,7 @@ NtGdiCreateDC(PUNICODE_STRING Driver,
       return NULL;
     }
   }
-  
+
   if(Device)
   {
     Status = IntSafeCopyUnicodeString(&SafeDevice, Device);
@@ -873,9 +986,11 @@ NtGdiCreateDC(PUNICODE_STRING Driver,
       return NULL;
     }
   }
-  
-  Ret = IntGdiCreateDC(&SafeDriver, &SafeDevice, NULL, &SafeInitData, FALSE);
-  
+
+  Ret = IntGdiCreateDC(NULL == Driver ? NULL : &SafeDriver,
+                       NULL == Device ? NULL : &SafeDevice, NULL,
+                       NULL == InitData ? NULL : &SafeInitData, FALSE);
+
   return Ret;
 }
 
@@ -888,11 +1003,24 @@ NtGdiCreateIC(PUNICODE_STRING Driver,
   UNICODE_STRING SafeDriver, SafeDevice;
   DEVMODEW SafeInitData;
   HDC Ret;
-  NTSTATUS Status;
-  
+  NTSTATUS Status = STATUS_SUCCESS;
+
   if(InitData)
   {
-    Status = MmCopyFromCaller(&SafeInitData, InitData, sizeof(DEVMODEW));
+    _SEH_TRY
+    {
+      ProbeForRead(InitData,
+                   sizeof(DEVMODEW),
+                   1);
+      RtlCopyMemory(&SafeInitData,
+                    InitData,
+                    sizeof(DEVMODEW));
+    }
+    _SEH_HANDLE
+    {
+      Status = _SEH_GetExceptionCode();
+    }
+    _SEH_END;
     if(!NT_SUCCESS(Status))
     {
       SetLastNtError(Status);
@@ -900,7 +1028,7 @@ NtGdiCreateIC(PUNICODE_STRING Driver,
     }
     /* FIXME - InitData can have some more bytes! */
   }
-  
+
   if(Driver)
   {
     Status = IntSafeCopyUnicodeString(&SafeDriver, Driver);
@@ -910,7 +1038,7 @@ NtGdiCreateIC(PUNICODE_STRING Driver,
       return NULL;
     }
   }
-  
+
   if(Device)
   {
     Status = IntSafeCopyUnicodeString(&SafeDevice, Device);
@@ -921,11 +1049,11 @@ NtGdiCreateIC(PUNICODE_STRING Driver,
       return NULL;
     }
   }
-  
+
   Ret = IntGdiCreateDC(NULL == Driver ? NULL : &SafeDriver,
                        NULL == Device ? NULL : &SafeDevice, NULL,
                        NULL == InitData ? NULL : &SafeInitData, TRUE);
-  
+
   return Ret;
 }
 
@@ -934,10 +1062,17 @@ NtGdiDeleteDC(HDC  DCHandle)
 {
   PDC  DCToDelete;
 
+  if (!GDIOBJ_OwnedByCurrentProcess(DCHandle))
+    {
+      SetLastWin32Error(ERROR_INVALID_HANDLE);
+      return FALSE;
+    }
+  
   DCToDelete = DC_LockDc(DCHandle);
   if (DCToDelete == NULL)
     {
-      return  FALSE;
+      SetLastWin32Error(ERROR_INVALID_HANDLE);
+      return FALSE;
     }
 
   /*  First delete all saved DCs  */
@@ -954,7 +1089,7 @@ NtGdiDeleteDC(HDC  DCHandle)
     }
     DC_SetNextDC (DCToDelete, DC_GetNextDC (savedDC));
     DCToDelete->saveLevel--;
-    DC_UnlockDc( savedHDC );
+    DC_UnlockDc( savedDC );
     NtGdiDeleteDC (savedHDC);
   }
 
@@ -994,7 +1129,7 @@ NtGdiDeleteDC(HDC  DCHandle)
 #if 0 /* FIXME */
   PATH_DestroyGdiPath (&DCToDelete->w.path);
 #endif
-  DC_UnlockDc( DCHandle );
+  DC_UnlockDc( DCToDelete );
   DC_FreeDC ( DCHandle );
 
   return TRUE;
@@ -1030,13 +1165,13 @@ NtGdiGetCurrentObject(HDC  hDC, UINT  ObjectType)
 {
   HGDIOBJ SelObject;
   DC *dc;
-  
+
   if(!(dc = DC_LockDc(hDC)))
   {
     SetLastWin32Error(ERROR_INVALID_HANDLE);
     return NULL;
   }
-  
+
   switch(ObjectType)
   {
     case OBJ_PEN:
@@ -1064,8 +1199,8 @@ NtGdiGetCurrentObject(HDC  hDC, UINT  ObjectType)
       SetLastWin32Error(ERROR_INVALID_PARAMETER);
       break;
   }
-  
-  DC_UnlockDc(hDC);
+
+  DC_UnlockDc(dc);
   return SelObject;
 }
 
@@ -1076,7 +1211,7 @@ IntGdiGetDCOrgEx(DC *dc, LPPOINT  Point)
 {
   Point->x = dc->w.DCOrgX;
   Point->y = dc->w.DCOrgY;
-  
+
   return  TRUE;
 }
 
@@ -1086,32 +1221,44 @@ NtGdiGetDCOrgEx(HDC  hDC, LPPOINT  Point)
   BOOL Ret;
   DC *dc;
   POINT SafePoint;
-  NTSTATUS Status;
-  
+  NTSTATUS Status = STATUS_SUCCESS;
+
   if(!Point)
   {
     SetLastWin32Error(ERROR_INVALID_PARAMETER);
     return FALSE;
   }
-  
+
   dc = DC_LockDc(hDC);
   if(!dc)
   {
     SetLastWin32Error(ERROR_INVALID_HANDLE);
     return FALSE;
   }
-  
+
   Ret = IntGdiGetDCOrgEx(dc, &SafePoint);
-  
-  Status = MmCopyToCaller(Point, &SafePoint, sizeof(POINT));
+
+  _SEH_TRY
+  {
+    ProbeForWrite(Point,
+                  sizeof(POINT),
+                  1);
+    *Point = SafePoint;
+  }
+  _SEH_HANDLE
+  {
+    Status = _SEH_GetExceptionCode();
+  }
+  _SEH_END;
+
   if(!NT_SUCCESS(Status))
   {
     SetLastNtError(Status);
-    DC_UnlockDc(hDC);
+    DC_UnlockDc(dc);
     return FALSE;
   }
-  
-  DC_UnlockDc(hDC);
+
+  DC_UnlockDc(dc);
   return Ret;
 }
 
@@ -1131,7 +1278,7 @@ NtGdiSetBkColor(HDC hDC, COLORREF color)
   oldColor = dc->w.backgroundColor;
   dc->w.backgroundColor = color;
   hBrush = dc->w.hBrush;
-  DC_UnlockDc ( hDC );
+  DC_UnlockDc(dc);
   NtGdiSelectObject(hDC, hBrush);
   return oldColor;
 }
@@ -1152,7 +1299,7 @@ NtGdiGetDCState(HDC  hDC)
   hnewdc = DC_AllocDC(NULL);
   if (hnewdc == NULL)
   {
-    DC_UnlockDc( hDC );
+    DC_UnlockDc(dc);
     return 0;
   }
   newdc = DC_LockDc( hnewdc );
@@ -1225,8 +1372,8 @@ NtGdiGetDCState(HDC  hDC)
     newdc->w.hClipRgn = NtGdiCreateRectRgn( 0, 0, 0, 0 );
     NtGdiCombineRgn( newdc->w.hClipRgn, dc->w.hClipRgn, 0, RGN_COPY );
   }
-  DC_UnlockDc( hnewdc );
-  DC_UnlockDc( hDC );
+  DC_UnlockDc( newdc );
+  DC_UnlockDc( dc );
   return  hnewdc;
 }
 
@@ -1322,9 +1469,9 @@ NtGdiSetDCState ( HDC hDC, HDC hDCSave )
                res = CLIPPING_UpdateGCRegion( dc );
                ASSERT ( res != ERROR );
        }
-       DC_UnlockDc ( hDC );
+       DC_UnlockDc ( dc );
 #else
-       DC_UnlockDc ( hDC );
+       DC_UnlockDc ( dc );
        NtGdiSelectClipRgn(hDC, dcs->w.hClipRgn);
 #endif
 
@@ -1341,11 +1488,11 @@ NtGdiSetDCState ( HDC hDC, HDC hDCSave )
        GDISelectPalette16( hDC, dcs->w.hPalette, FALSE );
 #endif
       } else {
-       DC_UnlockDc(hDC);
+       DC_UnlockDc(dc);
       }
-      DC_UnlockDc ( hDCSave );
+      DC_UnlockDc ( dcs );
     } else {
-      DC_UnlockDc ( hDC );
+      DC_UnlockDc ( dc );
       SetLastWin32Error(ERROR_INVALID_HANDLE);
     }
   }
@@ -1356,7 +1503,7 @@ NtGdiSetDCState ( HDC hDC, HDC hDCSave )
 INT FASTCALL
 IntGdiGetDeviceCaps(PDC dc, INT Index)
 {
-  INT ret;
+  INT ret = 0;
   POINT  pt;
 
   /* Retrieve capability */
@@ -1566,7 +1713,7 @@ NtGdiGetDeviceCaps(HDC  hDC,
 
   DPRINT("(%04x,%d): returning %d\n", hDC, Index, ret);
 
-  DC_UnlockDc( hDC );
+  DC_UnlockDc( dc );
   return ret;
 }
 
@@ -1586,7 +1733,7 @@ IntGdiGetObject(HANDLE Handle, INT Count, LPVOID Buffer)
       SetLastWin32Error(ERROR_INVALID_HANDLE);
       return 0;
     }
-  
+
   ObjectType = GDIOBJ_GetObjectType(Handle);
   switch (ObjectType)
     {
@@ -1621,7 +1768,7 @@ IntGdiGetObject(HANDLE Handle, INT Count, LPVOID Buffer)
         break;
     }
 
-  GDIOBJ_UnlockObj(Handle);
+  GDIOBJ_UnlockObjByPtr(GdiObject);
 
   return Result;
 }
@@ -1631,23 +1778,53 @@ NtGdiGetObject(HANDLE handle, INT count, LPVOID buffer)
 {
   INT Ret;
   LPVOID SafeBuf;
-  NTSTATUS Status;
+  NTSTATUS Status = STATUS_SUCCESS;
 
   if (count <= 0)
   {
     return 0;
   }
   
+  _SEH_TRY
+  {
+    ProbeForWrite(buffer,
+                  count,
+                  1);
+  }
+  _SEH_HANDLE
+  {
+    Status = _SEH_GetExceptionCode();
+  }
+  _SEH_END;
+  
+  if(!NT_SUCCESS(Status))
+  {
+    SetLastNtError(Status);
+    return 0;
+  }
+
   SafeBuf = ExAllocatePoolWithTag(PagedPool, count, TAG_GDIOBJ);
   if(!SafeBuf)
   {
     SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
     return 0;
   }
-  
+
   Ret = IntGdiGetObject(handle, count, SafeBuf);
-  
-  Status = MmCopyToCaller(buffer, SafeBuf, count);
+
+  _SEH_TRY
+  {
+    /* pointer already probed! */
+    RtlCopyMemory(buffer,
+                  SafeBuf,
+                  count);
+  }
+  _SEH_HANDLE
+  {
+    Status = _SEH_GetExceptionCode();
+  }
+  _SEH_END;
+
   ExFreePool(SafeBuf);
   if(!NT_SUCCESS(Status))
   {
@@ -1720,7 +1897,7 @@ NtGdiGetObjectType(HANDLE handle)
       result = 0;
       break;
   }
-  GDIOBJ_UnlockObj(handle);
+  GDIOBJ_UnlockObjByPtr(ptr);
   return result;
 }
 
@@ -1761,7 +1938,7 @@ NtGdiRestoreDC(HDC  hDC, INT  SaveLevel)
 
   if ((SaveLevel < 1) || (SaveLevel > dc->saveLevel))
   {
-    DC_UnlockDc(hDC);
+    DC_UnlockDc(dc);
     return FALSE;
   }
 
@@ -1773,14 +1950,14 @@ NtGdiRestoreDC(HDC  hDC, INT  SaveLevel)
     dcs = DC_LockDc (hdcs);
     if (dcs == NULL)
     {
-      DC_UnlockDc(hDC);
+      DC_UnlockDc(dc);
       return FALSE;
     }
     DC_SetNextDC (dcs, DC_GetNextDC (dcs));
     if (--dc->saveLevel < SaveLevel)
       {
-       DC_UnlockDc( hDC );
-        DC_UnlockDc( hdcs );
+       DC_UnlockDc( dc );
+        DC_UnlockDc( dcs );
         NtGdiSetDCState(hDC, hdcs);
 #if 0
         if (!PATH_AssignGdiPath( &dc->w.path, &dcs->w.path ))
@@ -1798,11 +1975,11 @@ NtGdiRestoreDC(HDC  hDC, INT  SaveLevel)
       }
     else
       {
-      DC_UnlockDc( hdcs );
+      DC_UnlockDc( dcs );
       }
     NtGdiDeleteDC (hdcs);
   }
-  DC_UnlockDc( hDC );
+  DC_UnlockDc( dc );
   return  success;
 }
 
@@ -1829,7 +2006,7 @@ NtGdiSaveDC(HDC  hDC)
   dc = DC_LockDc (hDC);
   if (dc == NULL)
   {
-    DC_UnlockDc(hdcs);
+    DC_UnlockDc(dcs);
     SetLastWin32Error(ERROR_INVALID_HANDLE);
     return 0;
   }
@@ -1851,8 +2028,8 @@ NtGdiSaveDC(HDC  hDC)
   DC_SetNextDC (dcs, DC_GetNextDC (dc));
   DC_SetNextDC (dc, hdcs);
   ret = ++dc->saveLevel;
-  DC_UnlockDc( hdcs );
-  DC_UnlockDc( hDC );
+  DC_UnlockDc( dcs );
+  DC_UnlockDc( dc );
 
   return  ret;
 }
@@ -1872,7 +2049,7 @@ NtGdiSelectObject(HDC  hDC, HGDIOBJ  hGDIObj)
   BOOLEAN Failed;
 
   if(!hDC || !hGDIObj) return NULL;
-  
+
   dc = DC_LockDc(hDC);
   if (NULL == dc)
     {
@@ -1893,7 +2070,7 @@ NtGdiSelectObject(HDC  hDC, HGDIOBJ  hGDIObj)
       }
 
       XlateObj = IntGdiCreateBrushXlate(dc, pen, &Failed);
-      PENOBJ_UnlockPen(hGDIObj);
+      PENOBJ_UnlockPen(pen);
       if (Failed)
       {
         SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
@@ -1916,7 +2093,7 @@ NtGdiSelectObject(HDC  hDC, HGDIOBJ  hGDIObj)
       }
 
       XlateObj = IntGdiCreateBrushXlate(dc, brush, &Failed);
-      BRUSHOBJ_UnlockBrush(hGDIObj);
+      BRUSHOBJ_UnlockBrush(brush);
       if (Failed)
       {
         SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
@@ -1942,14 +2119,14 @@ NtGdiSelectObject(HDC  hDC, HGDIOBJ  hGDIObj)
       // must be memory dc to select bitmap
       if (!(dc->w.flags & DC_MEMORY))
         {
-          DC_UnlockDc(hDC);
+          DC_UnlockDc(dc);
           return NULL;
         }
       pb = BITMAPOBJ_LockBitmap(hGDIObj);
       if (NULL == pb)
        {
          SetLastWin32Error(ERROR_INVALID_HANDLE);
-          DC_UnlockDc(hDC);
+          DC_UnlockDc(dc);
          return NULL;
        }
       objOrg = (HGDIOBJ)dc->w.hBitmap;
@@ -1973,16 +2150,16 @@ NtGdiSelectObject(HDC  hDC, HGDIOBJ  hGDIObj)
       NtGdiSelectObject ( hDC, dc->w.hBrush );
       NtGdiSelectObject ( hDC, dc->w.hPen );
 
-      DC_UnlockDc ( hDC );
+      DC_UnlockDc ( dc );
       hVisRgn = NtGdiCreateRectRgn ( 0, 0, pb->SurfObj.sizlBitmap.cx, pb->SurfObj.sizlBitmap.cy );
-      BITMAPOBJ_UnlockBitmap( hGDIObj );
+      BITMAPOBJ_UnlockBitmap( pb );
       NtGdiSelectVisRgn ( hDC, hVisRgn );
       NtGdiDeleteObject ( hVisRgn );
 
       return objOrg;
 
     case GDI_OBJECT_TYPE_REGION:
-      DC_UnlockDc (hDC);
+      DC_UnlockDc (dc);
       /*
        * The return value is one of the following values:
        *  SIMPLEREGION
@@ -1994,7 +2171,7 @@ NtGdiSelectObject(HDC  hDC, HGDIOBJ  hGDIObj)
     default:
       break;
   }
-  DC_UnlockDc( hDC );
+  DC_UnlockDc( dc );
   return objOrg;
 }
 
@@ -2026,7 +2203,7 @@ NtGdiSetHookFlags(HDC hDC, WORD Flags)
       dc->w.flags &= ~DC_DIRTY;
     }
 
-  DC_UnlockDc(hDC);
+  DC_UnlockDc(dc);
 
   return wRet;
 }
@@ -2045,7 +2222,7 @@ DC_AllocDC(PUNICODE_STRING Driver)
   PDC  NewDC;
   HDC  hDC;
   PWSTR Buf = NULL;
-  
+
   if (Driver != NULL)
   {
     Buf = ExAllocatePoolWithTag(PagedPool, Driver->MaximumLength, TAG_DC);
@@ -2068,7 +2245,7 @@ DC_AllocDC(PUNICODE_STRING Driver)
 
   NewDC = DC_LockDc(hDC);
   /* FIXME - Handle NewDC == NULL! */
-  
+
   if (Driver != NULL)
   {
     RtlCopyMemory(&NewDC->DriverName, Driver, sizeof(UNICODE_STRING));
@@ -2097,7 +2274,7 @@ DC_AllocDC(PUNICODE_STRING Driver)
 
   NewDC->w.hPalette = NtGdiGetStockObject(DEFAULT_PALETTE);
 
-  DC_UnlockDc(hDC);
+  DC_UnlockDc(NewDC);
 
   return  hDC;
 }
@@ -2224,7 +2401,7 @@ DC_SetOwnership(HDC hDC, PEPROCESS Owner)
         {
           GDIOBJ_CopyOwnership(hDC, DC->w.hGCClipRgn);
         }
-      DC_UnlockDc(hDC);
+      DC_UnlockDc(DC);
     }
 }
 
@@ -2297,9 +2474,9 @@ IntEnumDisplaySettings(
   DEVMODEW DevMode;
   INT Size, OldSize;
   ULONG DisplayNumber = 0; /* only default display supported */
-  
-  DPRINT1("DevMode->dmSize = %d\n", pDevMode->dmSize);
-  DPRINT1("DevMode->dmExtraSize = %d\n", pDevMode->dmDriverExtra);
+
+  DPRINT("DevMode->dmSize = %d\n", pDevMode->dmSize);
+  DPRINT("DevMode->dmExtraSize = %d\n", pDevMode->dmDriverExtra);
   if (pDevMode->dmSize != SIZEOF_DEVMODEW_300 &&
       pDevMode->dmSize != SIZEOF_DEVMODEW_400 &&
       pDevMode->dmSize != SIZEOF_DEVMODEW_500)
@@ -2310,7 +2487,7 @@ IntEnumDisplaySettings(
 
   if (iModeNum == ENUM_CURRENT_SETTINGS)
   {
-    CachedMode = &PrimarySurface.DMW;    
+    CachedMode = &PrimarySurface.DMW;
     ASSERT(CachedMode->dmSize > 0);
   }
   else if (iModeNum == ENUM_REGISTRY_SETTINGS)
@@ -2337,7 +2514,7 @@ IntEnumDisplaySettings(
       UNICODE_STRING DriverFileNames;
       LPWSTR CurrentName;
       DRVENABLEDATA DrvEnableData;
-  
+
       /* Retrieve DDI driver names from registry */
       RtlInitUnicodeString(&DriverFileNames, NULL);
       if (!FindDriverFileNames(&DriverFileNames, DisplayNumber))
@@ -2345,13 +2522,13 @@ IntEnumDisplaySettings(
         DPRINT1("FindDriverFileNames failed\n");
         return FALSE;
       }
-      
+
       if (!HalQueryDisplayOwnership())
       {
         IntCreatePrimarySurface();
         PrimarySurfaceCreated = TRUE;
       }
-  
+
       /*
        * DriverFileNames may be a list of drivers in REG_SZ_MULTI format,
        * scan all of them until a good one found.
@@ -2362,7 +2539,7 @@ IntEnumDisplaySettings(
       {
         INT i;
         PGD_ENABLEDRIVER GDEnableDriver;
-  
+
         /* Get the DDI driver's entry point */
         GDEnableDriver = DRIVER_FindDDIDriver(CurrentName);
         if (NULL == GDEnableDriver)
@@ -2370,30 +2547,30 @@ IntEnumDisplaySettings(
           DPRINT("FindDDIDriver failed for %S\n", CurrentName);
           continue;
         }
-  
+
         /*  Call DDI driver's EnableDriver function  */
         RtlZeroMemory(&DrvEnableData, sizeof (DrvEnableData));
-  
+
         if (!GDEnableDriver(DDI_DRIVER_VERSION_NT5_01, sizeof (DrvEnableData), &DrvEnableData))
         {
           DPRINT("DrvEnableDriver failed for %S\n", CurrentName);
           continue;
         }
-        
+
         CachedDevModesEnd = CachedDevModes;
-        
+
         /* find DrvGetModes function */
         for (i = 0; i < DrvEnableData.c; i++)
         {
           PDRVFN DrvFn = DrvEnableData.pdrvfn + i;
           PGD_GETMODES GetModes;
           INT SizeNeeded, SizeUsed;
-  
+
           if (DrvFn->iFunc != INDEX_DrvGetModes)
             continue;
-  
+
           GetModes = (PGD_GETMODES)DrvFn->pfn;
-  
+
           /* make sure we have enough memory to hold the modes */
           SizeNeeded = GetModes((HANDLE)(PrimarySurface.VideoFileObject->DeviceObject), 0, NULL);
           if (SizeNeeded <= 0)
@@ -2401,12 +2578,12 @@ IntEnumDisplaySettings(
             DPRINT("DrvGetModes failed for %S\n", CurrentName);
             break;
           }
-          
+
           SizeUsed = CachedDevModesEnd - CachedDevModes;
           if (SizeOfCachedDevModes - SizeUsed < SizeNeeded)
           {
             PVOID NewBuffer;
-            
+
             SizeOfCachedDevModes += SizeNeeded;
             NewBuffer = ExAllocatePool(PagedPool, SizeOfCachedDevModes);
             if (NewBuffer == NULL)
@@ -2431,7 +2608,7 @@ IntEnumDisplaySettings(
             CachedDevModes = NewBuffer;
             CachedDevModesEnd = (DEVMODEW *)((PCHAR)NewBuffer + SizeUsed);
           }
-  
+
           /* query modes */
           SizeNeeded = GetModes((HANDLE)(PrimarySurface.VideoFileObject->DeviceObject),
                                 SizeOfCachedDevModes - SizeUsed,
@@ -2447,12 +2624,12 @@ IntEnumDisplaySettings(
           break;
         }
       }
-      
+
       if (PrimarySurfaceCreated)
       {
         IntDestroyPrimarySurface();
       }
-  
+
       RtlFreeUnicodeString(&DriverFileNames);
     }
 
@@ -2483,7 +2660,7 @@ IntEnumDisplaySettings(
   RtlCopyMemory(pDevMode, CachedMode, Size);
   RtlZeroMemory((PCHAR)pDevMode + Size, OldSize - Size);
   pDevMode->dmSize = OldSize;
-  
+
   Size = OldSize = pDevMode->dmDriverExtra;
   if (Size > CachedMode->dmDriverExtra)
     Size = CachedMode->dmDriverExtra;
@@ -2494,7 +2671,6 @@ IntEnumDisplaySettings(
 
   return TRUE;
 }
-
 LONG
 FASTCALL
 IntChangeDisplaySettings(
@@ -2507,7 +2683,10 @@ IntChangeDisplaySettings(
   BOOLEAN NoReset = FALSE;
   BOOLEAN Reset = FALSE;
   BOOLEAN SetPrimary = FALSE;
-  LONG Ret;
+  LONG Ret=0;
+  NTSTATUS Status ;
+
+  DPRINT1("display flag : %x\n",dwflags);
 
   if ((dwflags & CDS_UPDATEREGISTRY) == CDS_UPDATEREGISTRY)
   {
@@ -2527,50 +2706,102 @@ IntChangeDisplaySettings(
   if (Reset && NoReset)
     return DISP_CHANGE_BADFLAGS;
 
-  switch (dwflags)
-  {
-  case 0: /* Dynamically change graphics mode */
-    Ret = DISP_CHANGE_FAILED;
-    break;
-    
-  case CDS_FULLSCREEN: /* Given mode is temporary */
-    Ret = DISP_CHANGE_FAILED;
-    break;
-    
-  case CDS_UPDATEREGISTRY:
-    {
+  if (dwflags == 0)
+  {
+   /* Dynamically change graphics mode */
+   DPRINT1("flag 0 UNIMPLEMENT \n");
+   return DISP_CHANGE_FAILED;
+  }
+
+  if ((dwflags & CDS_TEST) == CDS_TEST)
+  {
+   /* Test reslution */
+   dwflags &= ~CDS_TEST;
+   DPRINT1("flag CDS_TEST UNIMPLEMENT");
+   Ret = DISP_CHANGE_FAILED;
+  }
+  
+  if ((dwflags & CDS_FULLSCREEN) == CDS_FULLSCREEN)
+  {
+   DEVMODE lpDevMode;
+   /* Full Screen */
+   dwflags &= ~CDS_FULLSCREEN;
+   DPRINT1("flag CDS_FULLSCREEN partially implemented");
+   Ret = DISP_CHANGE_FAILED;
+
+   lpDevMode.dmBitsPerPel =0;
+   lpDevMode.dmPelsWidth  =0;
+   lpDevMode.dmPelsHeight =0;
+   lpDevMode.dmDriverExtra =0;
+
+   lpDevMode.dmSize = sizeof(DEVMODE);
+   Status = IntEnumDisplaySettings(pDeviceName,  ENUM_CURRENT_SETTINGS, &lpDevMode, 0);
+   if (!NT_SUCCESS(Status)) return DISP_CHANGE_FAILED;
+
+   DPRINT1("Req Mode     : %d x %d x %d\n", DevMode->dmPelsWidth,DevMode->dmPelsHeight,DevMode->dmBitsPerPel);
+   DPRINT1("Current Mode : %d x %d x %d\n", lpDevMode.dmPelsWidth,lpDevMode.dmPelsHeight, lpDevMode.dmBitsPerPel);
+
+
+   if ((lpDevMode.dmBitsPerPel == DevMode->dmBitsPerPel) &&
+       (lpDevMode.dmPelsWidth  == DevMode->dmPelsWidth) &&
+       (lpDevMode.dmPelsHeight == DevMode->dmPelsHeight))
+          Ret = DISP_CHANGE_SUCCESSFUL; 
+  }
+
+  if ((dwflags & CDS_VIDEOPARAMETERS) == CDS_VIDEOPARAMETERS)
+  {  
+    dwflags &= ~CDS_VIDEOPARAMETERS;
+    if (lParam == NULL) Ret=DISP_CHANGE_BADPARAM;
+       else
+       {
+               DPRINT1("flag CDS_VIDEOPARAMETERS UNIMPLEMENT");
+               Ret = DISP_CHANGE_FAILED;
+       }
+
+  }    
+
+  if ((dwflags & CDS_UPDATEREGISTRY) == CDS_UPDATEREGISTRY)
+  {  
+  
                UNICODE_STRING ObjectName;
                UNICODE_STRING KernelModeName;
                WCHAR KernelModeNameBuffer[256];
                UNICODE_STRING RegistryKey;
                WCHAR RegistryKeyBuffer[512];
-               PDEVICE_OBJECT DeviceObject;
-               NTSTATUS Status;
+               PDEVICE_OBJECT DeviceObject;            
                ULONG LastSlash;
                OBJECT_ATTRIBUTES ObjectAttributes;
                HANDLE DevInstRegKey;
                ULONG NewValue;
                
+
+               DPRINT1("set CDS_UPDATEREGISTRY \n");
+               
+               dwflags &= ~CDS_UPDATEREGISTRY; 
+
                /* Get device name (pDeviceName is "\.\xxx") */
                for (LastSlash = pDeviceName->Length / sizeof(WCHAR); LastSlash > 0; LastSlash--)
                {
                        if (pDeviceName->Buffer[LastSlash - 1] == L'\\')
                                break;
                }
-               if (LastSlash == 0) return DISP_CHANGE_FAILED;
+               
+               if (LastSlash == 0) return DISP_CHANGE_RESTART;
                ObjectName = *pDeviceName;
                ObjectName.Length -= LastSlash * sizeof(WCHAR);
                ObjectName.MaximumLength -= LastSlash * sizeof(WCHAR);
                ObjectName.Buffer += LastSlash;
-               
+
                KernelModeName.Length = 0;
                KernelModeName.MaximumLength = sizeof(KernelModeNameBuffer);
                KernelModeName.Buffer = KernelModeNameBuffer;
-               
+
                /* Open \??\xxx (ex: "\??\DISPLAY1") */
                Status = RtlAppendUnicodeToString(&KernelModeName, L"\\??\\");
+               
                if (!NT_SUCCESS(Status)) return DISP_CHANGE_FAILED;
                Status = RtlAppendUnicodeStringToString(&KernelModeName, &ObjectName);
+               
                if (!NT_SUCCESS(Status)) return DISP_CHANGE_FAILED;
                Status = ObReferenceObjectByName(
                        &KernelModeName,
@@ -2581,6 +2812,7 @@ IntChangeDisplaySettings(
                        KernelMode,
                        NULL,
                        (PVOID*)&DeviceObject);
+
                if (!NT_SUCCESS(Status)) return DISP_CHANGE_FAILED;
                /* Get associated driver name (ex: "VBE") */
                for (LastSlash = DeviceObject->DriverObject->DriverName.Length / sizeof(WCHAR); LastSlash > 0; LastSlash--)
@@ -2588,79 +2820,70 @@ IntChangeDisplaySettings(
                        if (DeviceObject->DriverObject->DriverName.Buffer[LastSlash - 1] == L'\\')
                                break;
                }
+
                if (LastSlash == 0) { ObDereferenceObject(DeviceObject); return DISP_CHANGE_FAILED; }
                ObjectName = DeviceObject->DriverObject->DriverName;
                ObjectName.Length -= LastSlash * sizeof(WCHAR);
                ObjectName.MaximumLength -= LastSlash * sizeof(WCHAR);
                ObjectName.Buffer += LastSlash;
-               
+
                RegistryKey.Length = 0;
                RegistryKey.MaximumLength = sizeof(RegistryKeyBuffer);
                RegistryKey.Buffer = RegistryKeyBuffer;
-               
+
                /* Open registry key */
                Status = RtlAppendUnicodeToString(&RegistryKey,
                        L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Hardware Profiles\\Current\\System\\CurrentControlSet\\Services\\");
+               
                if (!NT_SUCCESS(Status)) { ObDereferenceObject(DeviceObject); return DISP_CHANGE_FAILED; }
                Status = RtlAppendUnicodeStringToString(&RegistryKey, &ObjectName);
+
                if (!NT_SUCCESS(Status)) { ObDereferenceObject(DeviceObject); return DISP_CHANGE_FAILED; }
                Status = RtlAppendUnicodeToString(&RegistryKey,
                        L"\\Device0");
+
                if (!NT_SUCCESS(Status)) { ObDereferenceObject(DeviceObject); return DISP_CHANGE_FAILED; }
-               
+
                InitializeObjectAttributes(&ObjectAttributes, &RegistryKey,
                        OBJ_CASE_INSENSITIVE, NULL, NULL);
                Status = ZwOpenKey(&DevInstRegKey, GENERIC_READ | GENERIC_WRITE, &ObjectAttributes);
                ObDereferenceObject(DeviceObject);
                if (!NT_SUCCESS(Status)) return DISP_CHANGE_FAILED;
-               
+
                /* Update needed fields */
                if (NT_SUCCESS(Status) && DevMode->dmFields & DM_BITSPERPEL)
                {
                        RtlInitUnicodeString(&RegistryKey, L"DefaultSettings.BitsPerPel");
                        NewValue = DevMode->dmBitsPerPel;
-                       Status = ZwSetValueKey(DevInstRegKey, &RegistryKey, 0, REG_DWORD, &NewValue, sizeof(NewValue));
+                       Status = ZwSetValueKey(DevInstRegKey, &RegistryKey, 0, REG_DWORD, &NewValue, sizeof(NewValue));                 
                }
-               
+
                if (NT_SUCCESS(Status) && DevMode->dmFields & DM_PELSWIDTH)
                {
                        RtlInitUnicodeString(&RegistryKey, L"DefaultSettings.XResolution");
-                       NewValue = DevMode->dmPelsWidth;
-                       Status = ZwSetValueKey(DevInstRegKey, &RegistryKey, 0, REG_DWORD, &NewValue, sizeof(NewValue));
+                       NewValue = DevMode->dmPelsWidth;                        
+                       Status = ZwSetValueKey(DevInstRegKey, &RegistryKey, 0, REG_DWORD, &NewValue, sizeof(NewValue));                 
                }
-               
+
                if (NT_SUCCESS(Status) && DevMode->dmFields & DM_PELSHEIGHT)
                {
                        RtlInitUnicodeString(&RegistryKey, L"DefaultSettings.YResolution");
                        NewValue = DevMode->dmPelsHeight;
-                       Status = ZwSetValueKey(DevInstRegKey, &RegistryKey, 0, REG_DWORD, &NewValue, sizeof(NewValue));
+                       Status = ZwSetValueKey(DevInstRegKey, &RegistryKey, 0, REG_DWORD, &NewValue, sizeof(NewValue));                 
                }
-               
+
                ZwClose(DevInstRegKey);
                if (NT_SUCCESS(Status))
                        Ret = DISP_CHANGE_RESTART;
                else
-                       Ret = DISP_CHANGE_FAILED;
-               break;
+                       /* return DISP_CHANGE_NOTUPDATED when we can save to reg only vaild for NT */ 
+                       Ret = DISP_CHANGE_NOTUPDATED;
+               
     }
-     
-  case CDS_TEST: /* Test if the mode could be set */
-    Ret = DISP_CHANGE_FAILED;
-    break;
-    
-#ifdef CDS_VIDEOPARAMETERS
-  case CDS_VIDEOPARAMETERS:
-    if (lParam == NULL)
-      return DISP_CHANGE_BADPARAM;
-    Ret = DISP_CHANGE_FAILED;
-    break;
-#endif
-    
-  default:
+ if (dwflags != 0)  
     Ret = DISP_CHANGE_BADFLAGS;
-    break;
-  }
-  
+
   return Ret;
 }