https://git.reactos.org/?p=reactos.git;a=commitdiff;h=402bc38ba7cabda46e816b9cfa35773922b56d60

commit 402bc38ba7cabda46e816b9cfa35773922b56d60
Author:     Timo Kreuzer <timo.kreu...@reactos.org>
AuthorDate: Wed Sep 4 21:14:31 2024 +0300
Commit:     Timo Kreuzer <timo.kreu...@reactos.org>
CommitDate: Thu Sep 12 15:52:30 2024 +0300

    [NTGDI] Rewrite NtGdiPolyDraw
    
    It is now a wrapper around GdiPolyDraw, which implements the main body of 
the function, while the Nt function only probes and captures the user mode data 
into safe kernel mode buffers.
    Previously some people thought it was a great idea to just wrap the entire 
implementation in SEH, so when something throws an exception somewhere for 
whatever reason, we can just catch it here... and LEAK ALL RESOURCES IN THE 
PROCESS!
    TODO: Rewrite all of this. It's broken everywhere.
---
 win32ss/gdi/ntgdi/line.c | 97 ++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 82 insertions(+), 15 deletions(-)

diff --git a/win32ss/gdi/ntgdi/line.c b/win32ss/gdi/ntgdi/line.c
index 9e3ff20c824..9c4bee2bd13 100644
--- a/win32ss/gdi/ntgdi/line.c
+++ b/win32ss/gdi/ntgdi/line.c
@@ -11,6 +11,8 @@
 #define NDEBUG
 #include <debug.h>
 
+DBG_DEFAULT_CHANNEL(GdiLine);
+
 // Some code from the WINE project source (www.winehq.com)
 
 VOID FASTCALL
@@ -531,9 +533,9 @@ NtGdiLineTo(HDC  hDC,
 }
 
 // FIXME: This function is completely broken
+static
 BOOL
-APIENTRY
-NtGdiPolyDraw(
+GdiPolyDraw(
     IN HDC hdc,
     IN LPPOINT lppt,
     IN LPBYTE lpbTypes,
@@ -567,15 +569,11 @@ NtGdiPolyDraw(
     line_pts_old = NULL;
     bzr_pts = NULL;
 
-    _SEH2_TRY
     {
-        ProbeArrayForRead(lppt, sizeof(POINT), cCount, sizeof(LONG));
-        ProbeArrayForRead(lpbTypes, sizeof(BYTE), cCount, sizeof(BYTE));
-
         if (PATH_IsPathOpen(dc->dclevel))
         {
            result = PATH_PolyDraw(dc, (const POINT *)lppt, (const BYTE 
*)lpbTypes, cCount);
-           _SEH2_LEAVE;
+           goto Cleanup;
         }
 
         /* Check for valid point types */
@@ -595,7 +593,7 @@ NtGdiPolyDraw(
                    break;
                }
            default:
-               _SEH2_LEAVE;
+               goto Cleanup;
            }
         }
 
@@ -604,7 +602,7 @@ NtGdiPolyDraw(
         if (line_pts == NULL)
         {
             result = FALSE;
-            _SEH2_LEAVE;
+            goto Cleanup;
         }
 
         num_pts = 1;
@@ -639,7 +637,7 @@ NtGdiPolyDraw(
                       space = size * 2;
                       line_pts_old = line_pts;
                       line_pts = ExAllocatePoolWithTag(PagedPool, space * 
sizeof(POINT), TAG_SHAPE);
-                      if (!line_pts) _SEH2_LEAVE;
+                      if (!line_pts) goto Cleanup;
                       RtlCopyMemory(line_pts, line_pts_old, space_old * 
sizeof(POINT));
                       ExFreePoolWithTag(line_pts_old, TAG_SHAPE);
                       line_pts_old = NULL;
@@ -659,11 +657,8 @@ NtGdiPolyDraw(
         IntGdiMoveToEx( dc, line_pts[num_pts - 1].x, line_pts[num_pts - 1].y, 
NULL );
         result = TRUE;
     }
-    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-    {
-        SetLastNtError(_SEH2_GetExceptionCode());
-    }
-    _SEH2_END;
+
+Cleanup:
 
     if (line_pts != NULL)
     {
@@ -685,6 +680,78 @@ NtGdiPolyDraw(
     return result;
 }
 
+__kernel_entry
+W32KAPI
+BOOL
+APIENTRY
+NtGdiPolyDraw(
+    _In_ HDC hdc,
+    _In_reads_(cpt) LPPOINT ppt,
+    _In_reads_(cpt) LPBYTE pjAttr,
+    _In_ ULONG cpt)
+{
+    PBYTE pjBuffer;
+    PPOINT pptSafe;
+    PBYTE pjSafe;
+    SIZE_T cjSizePt;
+    BOOL bResult;
+
+    if (cpt == 0)
+    {
+        ERR("cpt is 0\n");
+        return FALSE;
+    }
+
+    /* Validate that cpt isn't too large */
+    if (cpt > ((MAXULONG - cpt) / sizeof(*ppt)))
+    {
+        ERR("cpt is too large\n", cpt);
+        return FALSE;
+    }
+
+    /* Calculate size for a buffer */
+    cjSizePt = cpt * sizeof(*ppt);
+    ASSERT(cjSizePt + cpt > cjSizePt);
+
+    /* Allocate a buffer for all data */
+    pjBuffer = ExAllocatePoolWithTag(PagedPool, cjSizePt + cpt, TAG_SHAPE);
+    if (pjBuffer == NULL)
+    {
+        ERR("Failed to allocate buffer\n");
+        return FALSE;
+    }
+
+    pptSafe = (PPOINT)pjBuffer;
+    pjSafe = pjBuffer + cjSizePt;
+
+    _SEH2_TRY
+    {
+        ProbeArrayForRead(ppt, sizeof(*ppt), cpt, sizeof(ULONG));
+        ProbeArrayForRead(pjAttr, sizeof(*pjAttr), cpt, sizeof(BYTE));
+
+        /* Copy the arrays */
+        RtlCopyMemory(pptSafe, ppt, cjSizePt);
+        RtlCopyMemory(pjSafe, pjAttr, cpt);
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        SetLastNtError(_SEH2_GetExceptionCode());
+        bResult = FALSE;
+        goto Cleanup;
+    }
+    _SEH2_END;
+
+    /* Call the internal function */
+    bResult = GdiPolyDraw(hdc, pptSafe, pjSafe, cpt);
+
+Cleanup:
+
+    /* Free the buffer */
+    ExFreePoolWithTag(pjBuffer, TAG_SHAPE);
+
+    return bResult;
+}
+
 /*
  * @implemented
  */

Reply via email to