diff --git a/reactos/boot/bootdata/packages/reactos.dff b/reactos/boot/bootdata/packages/reactos.dff index c5e998d4b36..f08fb2489c0 100644 --- a/reactos/boot/bootdata/packages/reactos.dff +++ b/reactos/boot/bootdata/packages/reactos.dff @@ -456,6 +456,7 @@ dll\win32\uxtheme\uxtheme.dll 1 dll\win32\vdmdbg\vdmdbg.dll 1 dll\win32\version\version.dll 1 dll\win32\wdmaud.drv\wdmaud.drv 1 +dll\win32\wer\wer.dll 1 dll\win32\windowscodecs\windowscodecs.dll 1 dll\win32\winemp3.acm\winemp3.acm 1 dll\win32\winfax\winfax.dll 1 diff --git a/reactos/dll/win32/gdiplus/brush.c b/reactos/dll/win32/gdiplus/brush.c index b46bdc559b8..74dc833d88d 100644 --- a/reactos/dll/win32/gdiplus/brush.c +++ b/reactos/dll/win32/gdiplus/brush.c @@ -352,6 +352,9 @@ GpStatus WINGDIPAPI GdipCreateLineBrush(GDIPCONST GpPointF* startpoint, if(!line || !startpoint || !endpoint || wrap == WrapModeClamp) return InvalidParameter; + if (startpoint->X == endpoint->X && startpoint->Y == endpoint->Y) + return OutOfMemory; + *line = GdipAlloc(sizeof(GpLineGradient)); if(!*line) return OutOfMemory; @@ -428,7 +431,7 @@ GpStatus WINGDIPAPI GdipCreateLineBrushI(GDIPCONST GpPoint* startpoint, stF.X = (REAL)startpoint->X; stF.Y = (REAL)startpoint->Y; endF.X = (REAL)endpoint->X; - endF.X = (REAL)endpoint->Y; + endF.Y = (REAL)endpoint->Y; return GdipCreateLineBrush(&stF, &endF, startcolor, endcolor, wrap, line); } @@ -1494,6 +1497,19 @@ GpStatus WINGDIPAPI GdipSetPathGradientBlend(GpPathGradient *brush, GDIPCONST RE return NotImplemented; } +GpStatus WINGDIPAPI GdipSetPathGradientLinearBlend(GpPathGradient *brush, + REAL focus, REAL scale) +{ + static int calls; + + TRACE("(%p,%0.2f,%0.2f)\n", brush, focus, scale); + + if(!(calls++)) + FIXME("not implemented\n"); + + return NotImplemented; +} + GpStatus WINGDIPAPI GdipSetPathGradientPresetBlend(GpPathGradient *brush, GDIPCONST ARGB *blend, GDIPCONST REAL *pos, INT count) { @@ -1501,6 +1517,20 @@ GpStatus WINGDIPAPI GdipSetPathGradientPresetBlend(GpPathGradient *brush, return NotImplemented; } +GpStatus WINGDIPAPI GdipGetPathGradientPresetBlend(GpPathGradient *brush, + ARGB *blend, REAL *pos, INT count) +{ + FIXME("(%p,%p,%p,%i): stub\n", brush, blend, pos, count); + return NotImplemented; +} + +GpStatus WINGDIPAPI GdipGetPathGradientPresetBlendCount(GpPathGradient *brush, + INT *count) +{ + FIXME("(%p,%p): stub\n", brush, count); + return NotImplemented; +} + GpStatus WINGDIPAPI GdipSetPathGradientCenterColor(GpPathGradient *grad, ARGB argb) { @@ -1621,6 +1651,84 @@ GpStatus WINGDIPAPI GdipSetPathGradientWrapMode(GpPathGradient *grad, return Ok; } +GpStatus WINGDIPAPI GdipSetPathGradientTransform(GpPathGradient *grad, + GpMatrix *matrix) +{ + static int calls; + + TRACE("(%p,%p)\n", grad, matrix); + + if(!(calls++)) + FIXME("not implemented\n"); + + return NotImplemented; +} + +GpStatus WINGDIPAPI GdipGetPathGradientTransform(GpPathGradient *grad, + GpMatrix *matrix) +{ + static int calls; + + TRACE("(%p,%p)\n", grad, matrix); + + if(!(calls++)) + FIXME("not implemented\n"); + + return NotImplemented; +} + +GpStatus WINGDIPAPI GdipMultiplyPathGradientTransform(GpPathGradient *grad, + GDIPCONST GpMatrix *matrix, GpMatrixOrder order) +{ + static int calls; + + TRACE("(%p,%p,%i)\n", grad, matrix, order); + + if(!(calls++)) + FIXME("not implemented\n"); + + return NotImplemented; +} + +GpStatus WINGDIPAPI GdipRotatePathGradientTransform(GpPathGradient *grad, + REAL angle, GpMatrixOrder order) +{ + static int calls; + + TRACE("(%p,%0.2f,%i)\n", grad, angle, order); + + if(!(calls++)) + FIXME("not implemented\n"); + + return NotImplemented; +} + +GpStatus WINGDIPAPI GdipScalePathGradientTransform(GpPathGradient *grad, + REAL sx, REAL sy, GpMatrixOrder order) +{ + static int calls; + + TRACE("(%p,%0.2f,%0.2f,%i)\n", grad, sx, sy, order); + + if(!(calls++)) + FIXME("not implemented\n"); + + return NotImplemented; +} + +GpStatus WINGDIPAPI GdipTranslatePathGradientTransform(GpPathGradient *grad, + REAL dx, REAL dy, GpMatrixOrder order) +{ + static int calls; + + TRACE("(%p,%0.2f,%0.2f,%i)\n", grad, dx, dy, order); + + if(!(calls++)) + FIXME("not implemented\n"); + + return NotImplemented; +} + GpStatus WINGDIPAPI GdipSetSolidFillColor(GpSolidFill *sf, ARGB argb) { TRACE("(%p, %x)\n", sf, argb); diff --git a/reactos/dll/win32/gdiplus/font.c b/reactos/dll/win32/gdiplus/font.c index 2670e8175dc..843cfb52683 100644 --- a/reactos/dll/win32/gdiplus/font.c +++ b/reactos/dll/win32/gdiplus/font.c @@ -452,12 +452,16 @@ GpStatus WINGDIPAPI GdipGetFontHeight(GDIPCONST GpFont *font, GDIPCONST GpGraphics *graphics, REAL *height) { REAL dpi; + GpStatus stat; TRACE("%p %p %p\n", font, graphics, height); - dpi = GetDeviceCaps(graphics->hdc, LOGPIXELSY); + stat = GdipGetDpiY((GpGraphics*)graphics, &dpi); - return GdipGetFontHeightGivenDPI(font, dpi, height); + if (stat == Ok) + stat = GdipGetFontHeightGivenDPI(font, dpi, height); + + return stat; } /******************************************************************************* diff --git a/reactos/dll/win32/gdiplus/gdiplus.c b/reactos/dll/win32/gdiplus/gdiplus.c index 383f53621fb..fb159be55b2 100644 --- a/reactos/dll/win32/gdiplus/gdiplus.c +++ b/reactos/dll/win32/gdiplus/gdiplus.c @@ -121,6 +121,14 @@ void WINAPI GdiplusShutdown(ULONG_PTR token) /* FIXME: no object tracking */ } +/* "bricksntiles" expects a return value of 0, which native coincidentally gives */ +ULONG WINAPI GdiplusShutdown_wrapper(ULONG_PTR token) +{ + GdiplusShutdown(token); + + return 0; +} + /***************************************************** * GdipAlloc [GDIPLUS.@] */ @@ -314,18 +322,18 @@ GpStatus hresult_to_status(HRESULT res) } /* converts a given unit to its value in pixels */ -REAL convert_unit(HDC hdc, GpUnit unit) +REAL convert_unit(REAL logpixels, GpUnit unit) { switch(unit) { case UnitInch: - return (REAL) GetDeviceCaps(hdc, LOGPIXELSX); + return logpixels; case UnitPoint: - return ((REAL)GetDeviceCaps(hdc, LOGPIXELSX)) / 72.0; + return logpixels / 72.0; case UnitDocument: - return ((REAL)GetDeviceCaps(hdc, LOGPIXELSX)) / 300.0; + return logpixels / 300.0; case UnitMillimeter: - return ((REAL)GetDeviceCaps(hdc, LOGPIXELSX)) / 25.4; + return logpixels / 25.4; case UnitWorld: ERR("cannot convert UnitWorld\n"); return 0.0; diff --git a/reactos/dll/win32/gdiplus/gdiplus.spec b/reactos/dll/win32/gdiplus/gdiplus.spec index bf0de649289..4cf15ab4d5e 100644 --- a/reactos/dll/win32/gdiplus/gdiplus.spec +++ b/reactos/dll/win32/gdiplus/gdiplus.spec @@ -67,7 +67,7 @@ @ stdcall GdipCombineRegionRegion(ptr ptr long) @ stdcall GdipComment(ptr long ptr) @ stdcall GdipConvertToEmfPlus(ptr ptr ptr long ptr ptr) -@ stub GdipConvertToEmfPlusToFile +@ stdcall GdipConvertToEmfPlusToFile(ptr ptr ptr ptr long ptr ptr) @ stub GdipConvertToEmfPlusToStream @ stdcall GdipCreateAdjustableArrowCap(long long long ptr) @ stub GdipCreateBitmapFromDirectDrawSurface @@ -215,8 +215,8 @@ @ stub GdipEnumerateMetafileSrcRectDestRectI @ stdcall GdipFillClosedCurve2(ptr ptr ptr long long long) @ stdcall GdipFillClosedCurve2I(ptr ptr ptr long long long) -@ stub GdipFillClosedCurve -@ stub GdipFillClosedCurveI +@ stdcall GdipFillClosedCurve(ptr ptr ptr long) +@ stdcall GdipFillClosedCurveI(ptr ptr ptr long) @ stdcall GdipFillEllipse(ptr ptr long long long long) @ stdcall GdipFillEllipseI(ptr ptr long long long long) @ stdcall GdipFillPath(ptr ptr ptr) @@ -315,10 +315,10 @@ @ stdcall GdipGetLogFontW(ptr ptr ptr) @ stdcall GdipGetMatrixElements(ptr ptr) @ stub GdipGetMetafileDownLevelRasterizationLimit -@ stub GdipGetMetafileHeaderFromEmf -@ stub GdipGetMetafileHeaderFromFile +@ stdcall GdipGetMetafileHeaderFromEmf(ptr ptr) +@ stdcall GdipGetMetafileHeaderFromFile(wstr ptr) @ stdcall GdipGetMetafileHeaderFromMetafile(ptr ptr) -@ stub GdipGetMetafileHeaderFromStream +@ stdcall GdipGetMetafileHeaderFromStream(ptr ptr) @ stub GdipGetMetafileHeaderFromWmf @ stdcall GdipGetNearestColor(ptr ptr) @ stdcall GdipGetPageScale(ptr ptr) @@ -334,13 +334,13 @@ @ stdcall GdipGetPathGradientGammaCorrection(ptr ptr) @ stub GdipGetPathGradientPath @ stdcall GdipGetPathGradientPointCount(ptr ptr) -@ stub GdipGetPathGradientPresetBlend -@ stub GdipGetPathGradientPresetBlendCount +@ stdcall GdipGetPathGradientPresetBlend(ptr ptr ptr long) +@ stdcall GdipGetPathGradientPresetBlendCount(ptr ptr) @ stdcall GdipGetPathGradientRect(ptr ptr) @ stdcall GdipGetPathGradientRectI(ptr ptr) @ stdcall GdipGetPathGradientSurroundColorCount(ptr ptr) @ stdcall GdipGetPathGradientSurroundColorsWithCount(ptr ptr ptr) -@ stub GdipGetPathGradientTransform +@ stdcall GdipGetPathGradientTransform(ptr ptr) @ stdcall GdipGetPathGradientWrapMode(ptr ptr) @ stdcall GdipGetPathLastPoint(ptr ptr) @ stdcall GdipGetPathPoints(ptr ptr long) @@ -351,7 +351,7 @@ @ stdcall GdipGetPenBrushFill(ptr ptr) @ stdcall GdipGetPenColor(ptr ptr) @ stub GdipGetPenCompoundArray -@ stub GdipGetPenCompoundCount +@ stdcall GdipGetPenCompoundCount(ptr ptr) @ stdcall GdipGetPenCustomEndCap(ptr ptr) @ stdcall GdipGetPenCustomStartCap(ptr ptr) @ stdcall GdipGetPenDashArray(ptr ptr long) @@ -365,7 +365,7 @@ @ stdcall GdipGetPenMiterLimit(ptr ptr) @ stdcall GdipGetPenMode(ptr ptr) @ stdcall GdipGetPenStartCap(ptr ptr) -@ stub GdipGetPenTransform +@ stdcall GdipGetPenTransform(ptr ptr) @ stdcall GdipGetPenUnit(ptr ptr) @ stdcall GdipGetPenWidth(ptr ptr) @ stdcall GdipGetPixelOffsetMode(ptr ptr) @@ -380,9 +380,9 @@ @ stdcall GdipGetRegionData(ptr ptr long ptr) @ stdcall GdipGetRegionDataSize(ptr ptr) @ stdcall GdipGetRegionHRgn(ptr ptr ptr) -@ stub GdipGetRegionScans +@ stdcall GdipGetRegionScans(ptr ptr ptr ptr) @ stdcall GdipGetRegionScansCount(ptr ptr ptr) -@ stub GdipGetRegionScansI +@ stdcall GdipGetRegionScansI(ptr ptr ptr ptr) @ stdcall GdipGetRenderingOrigin(ptr ptr ptr) @ stdcall GdipGetSmoothingMode(ptr ptr) @ stdcall GdipGetSolidFillColor(ptr ptr) @@ -444,8 +444,8 @@ @ stdcall GdipMeasureString(ptr wstr long ptr ptr ptr ptr ptr ptr) @ stdcall GdipMultiplyLineTransform(ptr ptr long) @ stdcall GdipMultiplyMatrix(ptr ptr long) -@ stub GdipMultiplyPathGradientTransform -@ stub GdipMultiplyPenTransform +@ stdcall GdipMultiplyPathGradientTransform(ptr ptr long) +@ stdcall GdipMultiplyPenTransform(ptr ptr long) @ stdcall GdipMultiplyTextureTransform(ptr ptr long) @ stdcall GdipMultiplyWorldTransform(ptr ptr long) @ stdcall GdipNewInstalledFontCollection(ptr) @@ -466,11 +466,11 @@ @ stub GdipPlayTSClientRecord @ stdcall GdipPrivateAddFontFile(ptr wstr) @ stdcall GdipPrivateAddMemoryFont(ptr ptr long) -@ stub GdipRecordMetafile +@ stdcall GdipRecordMetafile(long long ptr long wstr ptr) @ stdcall GdipRecordMetafileFileName(wstr long long ptr long wstr ptr) @ stdcall GdipRecordMetafileFileNameI(wstr long long ptr long wstr ptr) @ stdcall GdipRecordMetafileI(long long ptr long wstr ptr) -@ stub GdipRecordMetafileStream +@ stdcall GdipRecordMetafileStream(ptr long long ptr long wstr ptr) @ stub GdipRecordMetafileStreamI @ stdcall GdipReleaseDC(ptr ptr) @ stdcall GdipRemovePropertyItem(ptr long) @@ -487,8 +487,8 @@ @ stdcall GdipReversePath(ptr) @ stdcall GdipRotateLineTransform(ptr long long) @ stdcall GdipRotateMatrix(ptr long long) -@ stub GdipRotatePathGradientTransform -@ stub GdipRotatePenTransform +@ stdcall GdipRotatePathGradientTransform(ptr long long) +@ stdcall GdipRotatePenTransform(ptr long long) @ stdcall GdipRotateTextureTransform(ptr long long) @ stdcall GdipRotateWorldTransform(ptr long long) @ stub GdipSaveAdd @@ -498,7 +498,7 @@ @ stdcall GdipSaveImageToStream(ptr ptr ptr ptr) @ stdcall GdipScaleLineTransform(ptr long long long) @ stdcall GdipScaleMatrix(ptr long long long) -@ stub GdipScalePathGradientTransform +@ stdcall GdipScalePathGradientTransform(ptr long long long) @ stdcall GdipScalePenTransform(ptr long long long) @ stdcall GdipScaleTextureTransform(ptr long long long) @ stdcall GdipScaleWorldTransform(ptr long long long) @@ -554,12 +554,12 @@ @ stdcall GdipSetPathGradientCenterPointI(ptr ptr) @ stdcall GdipSetPathGradientFocusScales(ptr long long) @ stdcall GdipSetPathGradientGammaCorrection(ptr long) -@ stub GdipSetPathGradientLinearBlend +@ stdcall GdipSetPathGradientLinearBlend(ptr long long) @ stub GdipSetPathGradientPath @ stdcall GdipSetPathGradientPresetBlend(ptr ptr ptr long) @ stdcall GdipSetPathGradientSigmaBlend(ptr long long) @ stdcall GdipSetPathGradientSurroundColorsWithCount(ptr ptr ptr) -@ stub GdipSetPathGradientTransform +@ stdcall GdipSetPathGradientTransform(ptr ptr) @ stdcall GdipSetPathGradientWrapMode(ptr long) @ stdcall GdipSetPathMarker(ptr) @ stdcall GdipSetPenBrushFill(ptr ptr) @@ -577,7 +577,7 @@ @ stdcall GdipSetPenMiterLimit(ptr long) @ stdcall GdipSetPenMode(ptr long) @ stdcall GdipSetPenStartCap(ptr long) -@ stub GdipSetPenTransform +@ stdcall GdipSetPenTransform(ptr ptr) @ stub GdipSetPenUnit @ stdcall GdipSetPenWidth(ptr long) @ stdcall GdipSetPixelOffsetMode(ptr long) @@ -613,8 +613,8 @@ @ stdcall GdipTranslateClipI(ptr long long) @ stdcall GdipTranslateLineTransform(ptr long long long) @ stdcall GdipTranslateMatrix(ptr long long long) -@ stub GdipTranslatePathGradientTransform -@ stub GdipTranslatePenTransform +@ stdcall GdipTranslatePathGradientTransform(ptr long long long) +@ stdcall GdipTranslatePenTransform(ptr long long long) @ stdcall GdipTranslateRegion(ptr long long) @ stdcall GdipTranslateRegionI(ptr long long) @ stdcall GdipTranslateTextureTransform(ptr long long long) @@ -623,8 +623,8 @@ @ stdcall GdipVectorTransformMatrixPointsI(ptr ptr long) @ stdcall GdipWarpPath(ptr ptr ptr long long long long long long long) @ stdcall GdipWidenPath(ptr ptr ptr long) -@ stub GdipWindingModeOutline +@ stdcall GdipWindingModeOutline(ptr ptr long) @ stdcall GdiplusNotificationHook(ptr) @ stdcall GdiplusNotificationUnhook(ptr) -@ stdcall GdiplusShutdown(ptr) +@ stdcall GdiplusShutdown(ptr) GdiplusShutdown_wrapper @ stdcall GdiplusStartup(ptr ptr ptr) diff --git a/reactos/dll/win32/gdiplus/gdiplus_private.h b/reactos/dll/win32/gdiplus/gdiplus_private.h index eafed7c820e..b78e459a3ce 100644 --- a/reactos/dll/win32/gdiplus/gdiplus_private.h +++ b/reactos/dll/win32/gdiplus/gdiplus_private.h @@ -47,7 +47,9 @@ extern INT arc2polybezier(GpPointF * points, REAL x1, REAL y1, REAL x2, REAL y2, REAL startAngle, REAL sweepAngle); extern REAL gdiplus_atan2(REAL dy, REAL dx); extern GpStatus hresult_to_status(HRESULT res); -extern REAL convert_unit(HDC hdc, GpUnit unit); +extern REAL convert_unit(REAL logpixels, GpUnit unit); + +extern GpStatus graphics_from_image(GpImage *image, GpGraphics **graphics); extern void calc_curve_bezier(CONST GpPointF *pts, REAL tension, REAL *x1, REAL *y1, REAL *x2, REAL *y2); @@ -150,6 +152,12 @@ struct GpGraphics{ UINT textcontrast; /* not used yet. get/set only */ struct list containers; GraphicsContainer contid; /* last-issued container ID */ + /* For giving the caller an HDC when we technically can't: */ + HBITMAP temp_hbitmap; + int temp_hbitmap_width; + int temp_hbitmap_height; + BYTE *temp_bits; + HDC temp_hdc; }; struct GpBrush{ @@ -269,6 +277,7 @@ struct GpBitmap{ HDC hdc; BYTE *bits; /* actual image bits if this is a DIB */ INT stride; /* stride of bits if this is a DIB */ + BYTE *own_bits; /* image bits that need to be freed with this object */ }; struct GpCachedBitmap{ diff --git a/reactos/dll/win32/gdiplus/graphics.c b/reactos/dll/win32/gdiplus/graphics.c index 2d512abdc6c..e85a8ba3614 100644 --- a/reactos/dll/win32/gdiplus/graphics.c +++ b/reactos/dll/win32/gdiplus/graphics.c @@ -84,14 +84,22 @@ static BYTE convert_path_point_type(BYTE type) return ret; } +static REAL graphics_res(GpGraphics *graphics) +{ + if (graphics->image) return graphics->image->xres; + else return (REAL)GetDeviceCaps(graphics->hdc, LOGPIXELSX); +} + static INT prepare_dc(GpGraphics *graphics, GpPen *pen) { HPEN gdipen; REAL width; - INT save_state = SaveDC(graphics->hdc), i, numdashes; + INT save_state, i, numdashes; GpPointF pt[2]; DWORD dash_array[MAX_DASHLEN]; + save_state = SaveDC(graphics->hdc); + EndPath(graphics->hdc); if(pen->unit == UnitPixel){ @@ -108,7 +116,7 @@ static INT prepare_dc(GpGraphics *graphics, GpPen *pen) width = sqrt((pt[1].X - pt[0].X) * (pt[1].X - pt[0].X) + (pt[1].Y - pt[0].Y) * (pt[1].Y - pt[0].Y)) / sqrt(2.0); - width *= pen->width * convert_unit(graphics->hdc, + width *= pen->width * convert_unit(graphics_res(graphics), pen->unit == UnitWorld ? graphics->unit : pen->unit); } @@ -156,7 +164,7 @@ static void transform_and_round_points(GpGraphics *graphics, POINT *pti, GpMatrix *matrix; int i; - unitscale = convert_unit(graphics->hdc, graphics->unit); + unitscale = convert_unit(graphics_res(graphics), graphics->unit); /* apply page scale */ if(graphics->unit != UnitDisplay) @@ -1131,6 +1139,8 @@ static GpStatus restore_container(GpGraphics* graphics, static GpStatus get_graphics_bounds(GpGraphics* graphics, GpRectF* rect) { RECT wnd_rect; + GpStatus stat=Ok; + GpUnit unit; if(graphics->hwnd) { if(!GetClientRect(graphics->hwnd, &wnd_rect)) @@ -1140,6 +1150,10 @@ static GpStatus get_graphics_bounds(GpGraphics* graphics, GpRectF* rect) rect->Y = wnd_rect.top; rect->Width = wnd_rect.right - wnd_rect.left; rect->Height = wnd_rect.bottom - wnd_rect.top; + }else if (graphics->image){ + stat = GdipGetImageBounds(graphics->image, rect, &unit); + if (stat == Ok && unit != UnitPixel) + FIXME("need to convert from unit %i\n", unit); }else{ rect->X = 0; rect->Y = 0; @@ -1147,7 +1161,7 @@ static GpStatus get_graphics_bounds(GpGraphics* graphics, GpRectF* rect) rect->Height = GetDeviceCaps(graphics->hdc, VERTRES); } - return Ok; + return stat; } /* on success, rgn will contain the region of the graphics object which @@ -1235,6 +1249,45 @@ GpStatus WINGDIPAPI GdipCreateFromHDC2(HDC hdc, HANDLE hDevice, GpGraphics **gra return Ok; } +GpStatus graphics_from_image(GpImage *image, GpGraphics **graphics) +{ + GpStatus retval; + + *graphics = GdipAlloc(sizeof(GpGraphics)); + if(!*graphics) return OutOfMemory; + + if((retval = GdipCreateMatrix(&(*graphics)->worldtrans)) != Ok){ + GdipFree(*graphics); + return retval; + } + + if((retval = GdipCreateRegion(&(*graphics)->clip)) != Ok){ + GdipFree((*graphics)->worldtrans); + GdipFree(*graphics); + return retval; + } + + (*graphics)->hdc = NULL; + (*graphics)->hwnd = NULL; + (*graphics)->owndc = FALSE; + (*graphics)->image = image; + (*graphics)->smoothing = SmoothingModeDefault; + (*graphics)->compqual = CompositingQualityDefault; + (*graphics)->interpolation = InterpolationModeDefault; + (*graphics)->pixeloffset = PixelOffsetModeDefault; + (*graphics)->compmode = CompositingModeSourceOver; + (*graphics)->unit = UnitDisplay; + (*graphics)->scale = 1.0; + (*graphics)->busy = FALSE; + (*graphics)->textcontrast = 4; + list_init(&(*graphics)->containers); + (*graphics)->contid = 0; + + TRACE("<-- %p\n", *graphics); + + return Ok; +} + GpStatus WINGDIPAPI GdipCreateFromHWND(HWND hwnd, GpGraphics **graphics) { GpStatus ret; @@ -1446,6 +1499,12 @@ GpStatus WINGDIPAPI GdipDrawArc(GpGraphics *graphics, GpPen *pen, REAL x, if(graphics->busy) return ObjectBusy; + if (!graphics->hdc) + { + FIXME("graphics object has no HDC\n"); + return Ok; + } + num_pts = arc2polybezier(points, x, y, width, height, startAngle, sweepAngle); save_state = prepare_dc(graphics, pen); @@ -1482,6 +1541,12 @@ GpStatus WINGDIPAPI GdipDrawBezier(GpGraphics *graphics, GpPen *pen, REAL x1, if(graphics->busy) return ObjectBusy; + if (!graphics->hdc) + { + FIXME("graphics object has no HDC\n"); + return Ok; + } + pt[0].X = x1; pt[0].Y = y1; pt[1].X = x2; @@ -1516,6 +1581,12 @@ GpStatus WINGDIPAPI GdipDrawBezierI(GpGraphics *graphics, GpPen *pen, INT x1, if(graphics->busy) return ObjectBusy; + if (!graphics->hdc) + { + FIXME("graphics object has no HDC\n"); + return Ok; + } + pt[0].X = x1; pt[0].Y = y1; pt[1].X = x2; @@ -1722,6 +1793,12 @@ GpStatus WINGDIPAPI GdipDrawCurve2(GpGraphics *graphics, GpPen *pen, if(count < 2) return InvalidParameter; + if (!graphics->hdc) + { + FIXME("graphics object has no HDC\n"); + return Ok; + } + pt = GdipAlloc(len_pt * sizeof(GpPointF)); if(!pt) return OutOfMemory; @@ -1837,6 +1914,12 @@ GpStatus WINGDIPAPI GdipDrawEllipse(GpGraphics *graphics, GpPen *pen, REAL x, if(graphics->busy) return ObjectBusy; + if (!graphics->hdc) + { + FIXME("graphics object has no HDC\n"); + return Ok; + } + ptf[0].X = x; ptf[0].Y = y; ptf[1].X = x + width; @@ -1961,6 +2044,11 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image if (image->picture) { + if (!graphics->hdc) + { + FIXME("graphics object has no HDC\n"); + } + /* FIXME: partially implemented (only works for rectangular parallelograms) */ if(srcUnit == UnitInch) dx = dy = (REAL) INCH_HIMETRIC; @@ -1983,7 +2071,7 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image return GenericError; } } - else if (image->type == ImageTypeBitmap && ((GpBitmap*)image)->hbitmap) + else if (image->type == ImageTypeBitmap) { GpBitmap* bitmap = (GpBitmap*)image; int use_software=0; @@ -1997,6 +2085,7 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image if (imageAttributes || (graphics->image && graphics->image->type == ImageTypeBitmap) || + !((GpBitmap*)image)->hbitmap || ptf[1].Y != ptf[0].Y || ptf[2].X != ptf[0].X) use_software = 1; @@ -2383,6 +2472,12 @@ GpStatus WINGDIPAPI GdipDrawLine(GpGraphics *graphics, GpPen *pen, REAL x1, if(graphics->busy) return ObjectBusy; + if (!graphics->hdc) + { + FIXME("graphics object has no HDC\n"); + return Ok; + } + pt[0].X = x1; pt[0].Y = y1; pt[1].X = x2; @@ -2412,6 +2507,12 @@ GpStatus WINGDIPAPI GdipDrawLineI(GpGraphics *graphics, GpPen *pen, INT x1, if(graphics->busy) return ObjectBusy; + if (!graphics->hdc) + { + FIXME("graphics object has no HDC\n"); + return Ok; + } + pt[0].X = (REAL)x1; pt[0].Y = (REAL)y1; pt[1].X = (REAL)x2; @@ -2440,6 +2541,12 @@ GpStatus WINGDIPAPI GdipDrawLines(GpGraphics *graphics, GpPen *pen, GDIPCONST if(graphics->busy) return ObjectBusy; + if (!graphics->hdc) + { + FIXME("graphics object has no HDC\n"); + return Ok; + } + save_state = prepare_dc(graphics, pen); retval = draw_polyline(graphics, pen, points, count, TRUE); @@ -2465,6 +2572,12 @@ GpStatus WINGDIPAPI GdipDrawLinesI(GpGraphics *graphics, GpPen *pen, GDIPCONST if(graphics->busy) return ObjectBusy; + if (!graphics->hdc) + { + FIXME("graphics object has no HDC\n"); + return Ok; + } + ptf = GdipAlloc(count * sizeof(GpPointF)); if(!ptf) return OutOfMemory; @@ -2496,6 +2609,12 @@ GpStatus WINGDIPAPI GdipDrawPath(GpGraphics *graphics, GpPen *pen, GpPath *path) if(graphics->busy) return ObjectBusy; + if (!graphics->hdc) + { + FIXME("graphics object has no HDC\n"); + return Ok; + } + save_state = prepare_dc(graphics, pen); retval = draw_poly(graphics, pen, path->pathdata.Points, @@ -2520,6 +2639,12 @@ GpStatus WINGDIPAPI GdipDrawPie(GpGraphics *graphics, GpPen *pen, REAL x, if(graphics->busy) return ObjectBusy; + if (!graphics->hdc) + { + FIXME("graphics object has no HDC\n"); + return Ok; + } + save_state = prepare_dc(graphics, pen); SelectObject(graphics->hdc, GetStockObject(NULL_BRUSH)); @@ -2554,6 +2679,12 @@ GpStatus WINGDIPAPI GdipDrawRectangle(GpGraphics *graphics, GpPen *pen, REAL x, if(graphics->busy) return ObjectBusy; + if (!graphics->hdc) + { + FIXME("graphics object has no HDC\n"); + return Ok; + } + ptf[0].X = x; ptf[0].Y = y; ptf[1].X = x + width; @@ -2597,6 +2728,12 @@ GpStatus WINGDIPAPI GdipDrawRectangles(GpGraphics *graphics, GpPen *pen, if(graphics->busy) return ObjectBusy; + if (!graphics->hdc) + { + FIXME("graphics object has no HDC\n"); + return Ok; + } + ptf = GdipAlloc(4 * count * sizeof(GpPointF)); pti = GdipAlloc(4 * count * sizeof(POINT)); @@ -2673,6 +2810,9 @@ GpStatus WINGDIPAPI GdipFillClosedCurve2(GpGraphics *graphics, GpBrush *brush, if(graphics->busy) return ObjectBusy; + if(count == 1) /* Do nothing */ + return Ok; + stat = GdipCreatePath(fill, &path); if(stat != Ok) return stat; @@ -2704,9 +2844,12 @@ GpStatus WINGDIPAPI GdipFillClosedCurve2I(GpGraphics *graphics, GpBrush *brush, TRACE("(%p, %p, %p, %d, %.2f, %d)\n", graphics, brush, points, count, tension, fill); - if(!points || count <= 0) + if(!points || count == 0) return InvalidParameter; + if(count == 1) /* Do nothing */ + return Ok; + ptf = GdipAlloc(sizeof(GpPointF)*count); if(!ptf) return OutOfMemory; @@ -2723,6 +2866,22 @@ GpStatus WINGDIPAPI GdipFillClosedCurve2I(GpGraphics *graphics, GpBrush *brush, return stat; } +GpStatus WINGDIPAPI GdipFillClosedCurve(GpGraphics *graphics, GpBrush *brush, + GDIPCONST GpPointF *points, INT count) +{ + TRACE("(%p, %p, %p, %d)\n", graphics, brush, points, count); + return GdipFillClosedCurve2(graphics, brush, points, count, + 0.5f, FillModeAlternate); +} + +GpStatus WINGDIPAPI GdipFillClosedCurveI(GpGraphics *graphics, GpBrush *brush, + GDIPCONST GpPoint *points, INT count) +{ + TRACE("(%p, %p, %p, %d)\n", graphics, brush, points, count); + return GdipFillClosedCurve2I(graphics, brush, points, count, + 0.5f, FillModeAlternate); +} + GpStatus WINGDIPAPI GdipFillEllipse(GpGraphics *graphics, GpBrush *brush, REAL x, REAL y, REAL width, REAL height) { @@ -2738,6 +2897,12 @@ GpStatus WINGDIPAPI GdipFillEllipse(GpGraphics *graphics, GpBrush *brush, REAL x if(graphics->busy) return ObjectBusy; + if(!graphics->hdc) + { + FIXME("graphics object has no HDC\n"); + return Ok; + } + ptf[0].X = x; ptf[0].Y = y; ptf[1].X = x + width; @@ -2780,6 +2945,12 @@ GpStatus WINGDIPAPI GdipFillPath(GpGraphics *graphics, GpBrush *brush, GpPath *p if(graphics->busy) return ObjectBusy; + if(!graphics->hdc) + { + FIXME("graphics object has no HDC\n"); + return Ok; + } + save_state = SaveDC(graphics->hdc); EndPath(graphics->hdc); SetPolyFillMode(graphics->hdc, (path->fill == FillModeAlternate ? ALTERNATE @@ -2817,6 +2988,12 @@ GpStatus WINGDIPAPI GdipFillPie(GpGraphics *graphics, GpBrush *brush, REAL x, if(graphics->busy) return ObjectBusy; + if(!graphics->hdc) + { + FIXME("graphics object has no HDC\n"); + return Ok; + } + save_state = SaveDC(graphics->hdc); EndPath(graphics->hdc); @@ -2856,6 +3033,12 @@ GpStatus WINGDIPAPI GdipFillPolygon(GpGraphics *graphics, GpBrush *brush, if(graphics->busy) return ObjectBusy; + if(!graphics->hdc) + { + FIXME("graphics object has no HDC\n"); + return Ok; + } + ptf = GdipAlloc(count * sizeof(GpPointF)); pti = GdipAlloc(count * sizeof(POINT)); if(!ptf || !pti){ @@ -2903,6 +3086,12 @@ GpStatus WINGDIPAPI GdipFillPolygonI(GpGraphics *graphics, GpBrush *brush, if(graphics->busy) return ObjectBusy; + if(!graphics->hdc) + { + FIXME("graphics object has no HDC\n"); + return Ok; + } + ptf = GdipAlloc(count * sizeof(GpPointF)); pti = GdipAlloc(count * sizeof(POINT)); if(!ptf || !pti){ @@ -2968,6 +3157,12 @@ GpStatus WINGDIPAPI GdipFillRectangle(GpGraphics *graphics, GpBrush *brush, if(graphics->busy) return ObjectBusy; + if(!graphics->hdc) + { + FIXME("graphics object has no HDC\n"); + return Ok; + } + ptf[0].X = x; ptf[0].Y = y; ptf[1].X = x + width; @@ -3008,6 +3203,12 @@ GpStatus WINGDIPAPI GdipFillRectangleI(GpGraphics *graphics, GpBrush *brush, if(graphics->busy) return ObjectBusy; + if(!graphics->hdc) + { + FIXME("graphics object has no HDC\n"); + return Ok; + } + ptf[0].X = x; ptf[0].Y = y; ptf[1].X = x + width; @@ -3100,6 +3301,12 @@ GpStatus WINGDIPAPI GdipFillRegion(GpGraphics* graphics, GpBrush* brush, if(graphics->busy) return ObjectBusy; + if(!graphics->hdc) + { + FIXME("graphics object has no HDC\n"); + return Ok; + } + status = GdipGetRegionHRgn(region, graphics, &hrgn); if(status != Ok) return status; @@ -3700,6 +3907,7 @@ GpStatus WINGDIPAPI GdipMeasureCharacterRanges(GpGraphics* graphics, int i; HFONT oldfont; struct measure_ranges_args args; + HDC temp_hdc=NULL; TRACE("(%p %s %d %p %s %p %d %p)\n", graphics, debugstr_w(string), length, font, debugstr_rectf(layoutRect), stringFormat, regionCount, regions); @@ -3710,6 +3918,12 @@ GpStatus WINGDIPAPI GdipMeasureCharacterRanges(GpGraphics* graphics, if (regionCount < stringFormat->range_count) return InvalidParameter; + if(!graphics->hdc) + { + temp_hdc = graphics->hdc = CreateCompatibleDC(0); + if (!temp_hdc) return OutOfMemory; + } + if (stringFormat->attr) TRACE("may be ignoring some format flags: attr %x\n", stringFormat->attr); @@ -3729,6 +3943,12 @@ GpStatus WINGDIPAPI GdipMeasureCharacterRanges(GpGraphics* graphics, DeleteObject(SelectObject(graphics->hdc, oldfont)); + if (temp_hdc) + { + graphics->hdc = NULL; + DeleteDC(temp_hdc); + } + return stat; } @@ -3771,6 +3991,7 @@ GpStatus WINGDIPAPI GdipMeasureString(GpGraphics *graphics, { HFONT oldfont; struct measure_string_args args; + HDC temp_hdc=NULL; TRACE("(%p, %s, %i, %p, %s, %p, %p, %p, %p)\n", graphics, debugstr_wn(string, length), length, font, debugstr_rectf(rect), format, @@ -3779,6 +4000,12 @@ GpStatus WINGDIPAPI GdipMeasureString(GpGraphics *graphics, if(!graphics || !string || !font || !rect || !bounds) return InvalidParameter; + if(!graphics->hdc) + { + temp_hdc = graphics->hdc = CreateCompatibleDC(0); + if (!temp_hdc) return OutOfMemory; + } + if(linesfilled) *linesfilled = 0; if(codepointsfitted) *codepointsfitted = 0; @@ -3801,6 +4028,12 @@ GpStatus WINGDIPAPI GdipMeasureString(GpGraphics *graphics, DeleteObject(SelectObject(graphics->hdc, oldfont)); + if (temp_hdc) + { + graphics->hdc = NULL; + DeleteDC(temp_hdc); + } + return Ok; } @@ -3852,6 +4085,12 @@ GpStatus WINGDIPAPI GdipDrawString(GpGraphics *graphics, GDIPCONST WCHAR *string return NotImplemented; } + if(!graphics->hdc) + { + FIXME("graphics object has no HDC\n"); + return Ok; + } + if(format){ TRACE("may be ignoring some format flags: attr %x\n", format->attr); @@ -4415,6 +4654,12 @@ GpStatus WINGDIPAPI GdipDrawPolygon(GpGraphics *graphics,GpPen *pen,GDIPCONST Gp if(graphics->busy) return ObjectBusy; + if (!graphics->hdc) + { + FIXME("graphics object has no HDC\n"); + return Ok; + } + pti = GdipAlloc(sizeof(POINT) * count); save_state = prepare_dc(graphics, pen); @@ -4462,7 +4707,10 @@ GpStatus WINGDIPAPI GdipGetDpiX(GpGraphics *graphics, REAL* dpi) if(graphics->busy) return ObjectBusy; - *dpi = (REAL)GetDeviceCaps(graphics->hdc, LOGPIXELSX); + if (graphics->image) + *dpi = graphics->image->xres; + else + *dpi = (REAL)GetDeviceCaps(graphics->hdc, LOGPIXELSX); return Ok; } @@ -4477,7 +4725,10 @@ GpStatus WINGDIPAPI GdipGetDpiY(GpGraphics *graphics, REAL* dpi) if(graphics->busy) return ObjectBusy; - *dpi = (REAL)GetDeviceCaps(graphics->hdc, LOGPIXELSY); + if (graphics->image) + *dpi = graphics->image->yres; + else + *dpi = (REAL)GetDeviceCaps(graphics->hdc, LOGPIXELSY); return Ok; } @@ -4505,6 +4756,9 @@ GpStatus WINGDIPAPI GdipMultiplyWorldTransform(GpGraphics *graphics, GDIPCONST G return ret; } +/* Color used to fill bitmaps so we can tell which parts have been drawn over by gdi32. */ +static const COLORREF DC_BACKGROUND_KEY = 0x0c0b0d; + GpStatus WINGDIPAPI GdipGetDC(GpGraphics *graphics, HDC *hdc) { TRACE("(%p, %p)\n", graphics, hdc); @@ -4515,7 +4769,61 @@ GpStatus WINGDIPAPI GdipGetDC(GpGraphics *graphics, HDC *hdc) if(graphics->busy) return ObjectBusy; - *hdc = graphics->hdc; + if (!graphics->hdc || + (graphics->image && graphics->image->type == ImageTypeBitmap && ((GpBitmap*)graphics->image)->format & PixelFormatAlpha)) + { + /* Create a fake HDC and fill it with a constant color. */ + HDC temp_hdc; + HBITMAP hbitmap; + GpStatus stat; + GpRectF bounds; + BITMAPINFOHEADER bmih; + int i; + + stat = get_graphics_bounds(graphics, &bounds); + if (stat != Ok) + return stat; + + graphics->temp_hbitmap_width = bounds.Width; + graphics->temp_hbitmap_height = bounds.Height; + + bmih.biSize = sizeof(bmih); + bmih.biWidth = graphics->temp_hbitmap_width; + bmih.biHeight = -graphics->temp_hbitmap_height; + bmih.biPlanes = 1; + bmih.biBitCount = 32; + bmih.biCompression = BI_RGB; + bmih.biSizeImage = 0; + bmih.biXPelsPerMeter = 0; + bmih.biYPelsPerMeter = 0; + bmih.biClrUsed = 0; + bmih.biClrImportant = 0; + + hbitmap = CreateDIBSection(NULL, (BITMAPINFO*)&bmih, DIB_RGB_COLORS, + (void**)&graphics->temp_bits, NULL, 0); + if (!hbitmap) + return GenericError; + + temp_hdc = CreateCompatibleDC(0); + if (!temp_hdc) + { + DeleteObject(hbitmap); + return GenericError; + } + + for (i=0; i<(graphics->temp_hbitmap_width * graphics->temp_hbitmap_height); i++) + ((DWORD*)graphics->temp_bits)[i] = DC_BACKGROUND_KEY; + + SelectObject(temp_hdc, hbitmap); + + graphics->temp_hbitmap = hbitmap; + *hdc = graphics->temp_hdc = temp_hdc; + } + else + { + *hdc = graphics->hdc; + } + graphics->busy = TRUE; return Ok; @@ -4525,12 +4833,40 @@ GpStatus WINGDIPAPI GdipReleaseDC(GpGraphics *graphics, HDC hdc) { TRACE("(%p, %p)\n", graphics, hdc); - if(!graphics) + if(!graphics || !hdc) return InvalidParameter; - if(graphics->hdc != hdc || !(graphics->busy)) + if((graphics->hdc != hdc && graphics->temp_hdc != hdc) || !(graphics->busy)) return InvalidParameter; + if (graphics->temp_hdc == hdc) + { + DWORD* pos; + int i; + + /* Find the pixels that have changed, and mark them as opaque. */ + pos = (DWORD*)graphics->temp_bits; + for (i=0; i<(graphics->temp_hbitmap_width * graphics->temp_hbitmap_height); i++) + { + if (*pos != DC_BACKGROUND_KEY) + { + *pos |= 0xff000000; + } + pos++; + } + + /* Write the changed pixels to the real target. */ + alpha_blend_pixels(graphics, 0, 0, graphics->temp_bits, + graphics->temp_hbitmap_width, graphics->temp_hbitmap_height, + graphics->temp_hbitmap_width * 4); + + /* Clean up. */ + DeleteDC(graphics->temp_hdc); + DeleteObject(graphics->temp_hbitmap); + graphics->temp_hdc = NULL; + graphics->temp_hbitmap = NULL; + } + graphics->busy = FALSE; return Ok; @@ -4580,7 +4916,7 @@ GpStatus WINGDIPAPI GdipTransformPoints(GpGraphics *graphics, GpCoordinateSpace stat = GdipCreateMatrix(&matrix); if (stat == Ok) { - unitscale = convert_unit(graphics->hdc, graphics->unit); + unitscale = convert_unit(graphics_res(graphics), graphics->unit); if(graphics->unit != UnitDisplay) unitscale *= graphics->scale; diff --git a/reactos/dll/win32/gdiplus/graphicspath.c b/reactos/dll/win32/gdiplus/graphicspath.c index 60ddda1d7b5..983ead95008 100644 --- a/reactos/dll/win32/gdiplus/graphicspath.c +++ b/reactos/dll/win32/gdiplus/graphicspath.c @@ -364,7 +364,7 @@ GpStatus WINGDIPAPI GdipAddPathClosedCurve2(GpPath *path, GDIPCONST GpPointF *po } /* points [len_pt-2] and [0] are calculated - separetely to connect splines properly */ + separately to connect splines properly */ pts[0] = points[count-1]; pts[1] = points[0]; /* equals to start and end of a resulting path */ pts[2] = points[1]; @@ -1653,3 +1653,9 @@ GpStatus WINGDIPAPI GdipClearPathMarkers(GpPath* path) return Ok; } + +GpStatus WINGDIPAPI GdipWindingModeOutline(GpPath *path, GpMatrix *matrix, REAL flatness) +{ + FIXME("stub: %p, %p, %.2f\n", path, matrix, flatness); + return NotImplemented; +} diff --git a/reactos/dll/win32/gdiplus/image.c b/reactos/dll/win32/gdiplus/image.c index d72ae8d3775..69f58659a28 100644 --- a/reactos/dll/win32/gdiplus/image.c +++ b/reactos/dll/win32/gdiplus/image.c @@ -1626,11 +1626,10 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT width, INT height, INT stride, PixelFormat format, BYTE* scan0, GpBitmap** bitmap) { BITMAPINFO* pbmi; - HBITMAP hbitmap; + HBITMAP hbitmap=NULL; INT row_size, dib_stride; HDC hdc; - BYTE *bits; - int i; + BYTE *bits=NULL, *own_bits=NULL; REAL xres, yres; GpStatus stat; @@ -1655,46 +1654,62 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT width, INT height, INT stride, if(stride == 0) stride = dib_stride; - pbmi = GdipAlloc(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); - if (!pbmi) - return OutOfMemory; + if (format & PixelFormatGDI && !(format & (PixelFormatAlpha|PixelFormatIndexed)) && !scan0) + { + pbmi = GdipAlloc(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); + if (!pbmi) + return OutOfMemory; - pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - pbmi->bmiHeader.biWidth = width; - pbmi->bmiHeader.biHeight = -height; - pbmi->bmiHeader.biPlanes = 1; - /* FIXME: use the rest of the data from format */ - pbmi->bmiHeader.biBitCount = PIXELFORMATBPP(format); - pbmi->bmiHeader.biCompression = BI_RGB; - pbmi->bmiHeader.biSizeImage = 0; - pbmi->bmiHeader.biXPelsPerMeter = 0; - pbmi->bmiHeader.biYPelsPerMeter = 0; - pbmi->bmiHeader.biClrUsed = 0; - pbmi->bmiHeader.biClrImportant = 0; + pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + pbmi->bmiHeader.biWidth = width; + pbmi->bmiHeader.biHeight = -height; + pbmi->bmiHeader.biPlanes = 1; + /* FIXME: use the rest of the data from format */ + pbmi->bmiHeader.biBitCount = PIXELFORMATBPP(format); + pbmi->bmiHeader.biCompression = BI_RGB; + pbmi->bmiHeader.biSizeImage = 0; + pbmi->bmiHeader.biXPelsPerMeter = 0; + pbmi->bmiHeader.biYPelsPerMeter = 0; + pbmi->bmiHeader.biClrUsed = 0; + pbmi->bmiHeader.biClrImportant = 0; - hdc = CreateCompatibleDC(NULL); - if (!hdc) { + hdc = CreateCompatibleDC(NULL); + if (!hdc) { + GdipFree(pbmi); + return GenericError; + } + + hbitmap = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0); + + DeleteDC(hdc); GdipFree(pbmi); - return GenericError; + + if (!hbitmap) return GenericError; + + stride = dib_stride; } + else + { + /* Not a GDI format; don't try to make an HBITMAP. */ + if (scan0) + bits = scan0; + else + { + INT size = abs(stride) * height; - hbitmap = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0); + own_bits = bits = GdipAlloc(size); + if (!own_bits) return OutOfMemory; - DeleteDC(hdc); - GdipFree(pbmi); - - if (!hbitmap) return GenericError; - - /* copy bits to the dib if necessary */ - /* FIXME: should reference the bits instead of copying them */ - if (scan0) - for (i=0; ihbitmap = hbitmap; (*bitmap)->hdc = NULL; (*bitmap)->bits = bits; - (*bitmap)->stride = dib_stride; + (*bitmap)->stride = stride; + (*bitmap)->own_bits = own_bits; + + /* set format-related flags */ + if (format & (PixelFormatAlpha|PixelFormatPAlpha|PixelFormatIndexed)) + (*bitmap)->image.flags |= ImageFlagsHasAlpha; if (format == PixelFormat1bppIndexed || format == PixelFormat4bppIndexed || @@ -1916,6 +1936,7 @@ static void move_bitmap(GpBitmap *dst, GpBitmap *src, BOOL clobber_palette) dst->hdc = src->hdc; dst->bits = src->bits; dst->stride = src->stride; + dst->own_bits = src->own_bits; GdipFree(src); } @@ -1927,15 +1948,22 @@ GpStatus WINGDIPAPI GdipDisposeImage(GpImage *image) if(!image) return InvalidParameter; - if (image->picture) - IPicture_Release(image->picture); if (image->type == ImageTypeBitmap) { GdipFree(((GpBitmap*)image)->bitmapbits); + GdipFree(((GpBitmap*)image)->own_bits); DeleteDC(((GpBitmap*)image)->hdc); DeleteObject(((GpBitmap*)image)->hbitmap); } + else if (image->type != ImageTypeMetafile) + { + WARN("invalid image: %p\n", image); + return ObjectBusy; + } + if (image->picture) + IPicture_Release(image->picture); GdipFree(image->palette_entries); + image->type = ~0; GdipFree(image); return Ok; @@ -2008,14 +2036,15 @@ GpStatus WINGDIPAPI GdipGetImageDimension(GpImage *image, REAL *width, if(image->type == ImageTypeMetafile){ HDC hdc = GetDC(0); - - *height = convert_unit(hdc, ((GpMetafile*)image)->unit) * - ((GpMetafile*)image)->bounds.Height; - - *width = convert_unit(hdc, ((GpMetafile*)image)->unit) * - ((GpMetafile*)image)->bounds.Width; + REAL res = (REAL)GetDeviceCaps(hdc, LOGPIXELSX); ReleaseDC(0, hdc); + + *height = convert_unit(res, ((GpMetafile*)image)->unit) * + ((GpMetafile*)image)->bounds.Height; + + *width = convert_unit(res, ((GpMetafile*)image)->unit) * + ((GpMetafile*)image)->bounds.Width; } else if(image->type == ImageTypeBitmap){ @@ -2047,18 +2076,23 @@ GpStatus WINGDIPAPI GdipGetImageGraphicsContext(GpImage *image, return NotImplemented; } - hdc = ((GpBitmap*)image)->hdc; + if (((GpBitmap*)image)->hbitmap) + { + hdc = ((GpBitmap*)image)->hdc; - if(!hdc){ - hdc = CreateCompatibleDC(0); - SelectObject(hdc, ((GpBitmap*)image)->hbitmap); - ((GpBitmap*)image)->hdc = hdc; + if(!hdc){ + hdc = CreateCompatibleDC(0); + SelectObject(hdc, ((GpBitmap*)image)->hbitmap); + ((GpBitmap*)image)->hdc = hdc; + } + + stat = GdipCreateFromHDC(hdc, graphics); + + if (stat == Ok) + (*graphics)->image = image; } - - stat = GdipCreateFromHDC(hdc, graphics); - - if (stat == Ok) - (*graphics)->image = image; + else + stat = graphics_from_image(image, graphics); return stat; } @@ -2072,11 +2106,12 @@ GpStatus WINGDIPAPI GdipGetImageHeight(GpImage *image, UINT *height) if(image->type == ImageTypeMetafile){ HDC hdc = GetDC(0); - - *height = roundr(convert_unit(hdc, ((GpMetafile*)image)->unit) * - ((GpMetafile*)image)->bounds.Height); + REAL res = (REAL)GetDeviceCaps(hdc, LOGPIXELSX); ReleaseDC(0, hdc); + + *height = roundr(convert_unit(res, ((GpMetafile*)image)->unit) * + ((GpMetafile*)image)->bounds.Height); } else if(image->type == ImageTypeBitmap) *height = ((GpBitmap*)image)->height; @@ -2178,11 +2213,12 @@ GpStatus WINGDIPAPI GdipGetImageWidth(GpImage *image, UINT *width) if(image->type == ImageTypeMetafile){ HDC hdc = GetDC(0); - - *width = roundr(convert_unit(hdc, ((GpMetafile*)image)->unit) * - ((GpMetafile*)image)->bounds.Width); + REAL res = (REAL)GetDeviceCaps(hdc, LOGPIXELSX); ReleaseDC(0, hdc); + + *width = roundr(convert_unit(res, ((GpMetafile*)image)->unit) * + ((GpMetafile*)image)->bounds.Width); } else if(image->type == ImageTypeBitmap) *width = ((GpBitmap*)image)->width; @@ -2566,6 +2602,18 @@ static GpStatus decode_image_wic(IStream* stream, REFCLSID clsid, GpImage **imag *image = NULL; GdipDisposeImage((GpImage*)bitmap); } + + if (SUCCEEDED(hr) && status == Ok) + { + double dpix, dpiy; + hr = IWICBitmapSource_GetResolution(source, &dpix, &dpiy); + if (SUCCEEDED(hr)) + { + bitmap->image.xres = dpix; + bitmap->image.yres = dpiy; + } + hr = S_OK; + } } IWICBitmapSource_Release(source); @@ -2581,6 +2629,12 @@ end: if (FAILED(hr) && status == Ok) status = hresult_to_status(hr); + if (status == Ok) + { + /* Native GDI+ used to be smarter, but since Win7 it just sets these flags. */ + bitmap->image.flags |= ImageFlagsReadOnly|ImageFlagsHasRealPixelSize|ImageFlagsHasRealDPI|ImageFlagsColorSpaceRGB; + } + return status; } @@ -3756,3 +3810,16 @@ GpStatus WINGDIPAPI GdipImageRotateFlip(GpImage *image, RotateFlipType type) return stat; } + +/***************************************************************************** + * GdipConvertToEmfPlusToFile [GDIPLUS.@] + */ + +GpStatus WINGDIPAPI GdipConvertToEmfPlusToFile(const GpGraphics* refGraphics, + GpMetafile* metafile, BOOL* conversionSuccess, + const WCHAR* filename, EmfType emfType, + const WCHAR* description, GpMetafile** out_metafile) +{ + FIXME("stub: %p, %p, %p, %p, %u, %p, %p\n", refGraphics, metafile, conversionSuccess, filename, emfType, description, out_metafile); + return NotImplemented; +} diff --git a/reactos/dll/win32/gdiplus/pen.c b/reactos/dll/win32/gdiplus/pen.c index 53e47f08f77..a022cfb64e0 100644 --- a/reactos/dll/win32/gdiplus/pen.c +++ b/reactos/dll/win32/gdiplus/pen.c @@ -404,6 +404,51 @@ GpStatus WINGDIPAPI GdipResetPenTransform(GpPen *pen) return NotImplemented; } +GpStatus WINGDIPAPI GdipSetPenTransform(GpPen *pen, GpMatrix *matrix) +{ + static int calls; + + TRACE("(%p,%p)\n", pen, matrix); + + if(!pen || !matrix) + return InvalidParameter; + + if(!(calls++)) + FIXME("not implemented\n"); + + return NotImplemented; +} + +GpStatus WINGDIPAPI GdipGetPenTransform(GpPen *pen, GpMatrix *matrix) +{ + static int calls; + + TRACE("(%p,%p)\n", pen, matrix); + + if(!pen || !matrix) + return InvalidParameter; + + if(!(calls++)) + FIXME("not implemented\n"); + + return NotImplemented; +} + +GpStatus WINGDIPAPI GdipTranslatePenTransform(GpPen *pen, REAL dx, REAL dy, GpMatrixOrder order) +{ + static int calls; + + TRACE("(%p,%0.2f,%0.2f,%u)\n", pen, dx, dy, order); + + if(!pen) + return InvalidParameter; + + if(!(calls++)) + FIXME("not implemented\n"); + + return NotImplemented; +} + GpStatus WINGDIPAPI GdipScalePenTransform(GpPen *pen, REAL sx, REAL sy, GpMatrixOrder order) { static int calls; @@ -419,6 +464,21 @@ GpStatus WINGDIPAPI GdipScalePenTransform(GpPen *pen, REAL sx, REAL sy, GpMatrix return NotImplemented; } +GpStatus WINGDIPAPI GdipRotatePenTransform(GpPen *pen, REAL angle, GpMatrixOrder order) +{ + static int calls; + + TRACE("(%p,%0.2f,%u)\n", pen, angle, order); + + if(!pen) + return InvalidParameter; + + if(!(calls++)) + FIXME("not implemented\n"); + + return NotImplemented; +} + GpStatus WINGDIPAPI GdipMultiplyPenTransform(GpPen *pen, GDIPCONST GpMatrix *matrix, GpMatrixOrder order) { diff --git a/reactos/dll/win32/gdiplus/region.c b/reactos/dll/win32/gdiplus/region.c index decaaf9e837..f11f3ca3669 100644 --- a/reactos/dll/win32/gdiplus/region.c +++ b/reactos/dll/win32/gdiplus/region.c @@ -884,6 +884,7 @@ GpStatus WINGDIPAPI GdipGetRegionDataSize(GpRegion *region, UINT *needed) static GpStatus get_path_hrgn(GpPath *path, GpGraphics *graphics, HRGN *hrgn) { HDC new_hdc=NULL; + GpGraphics *new_graphics=NULL; GpStatus stat; INT save_state; @@ -893,13 +894,20 @@ static GpStatus get_path_hrgn(GpPath *path, GpGraphics *graphics, HRGN *hrgn) if (!new_hdc) return OutOfMemory; - stat = GdipCreateFromHDC(new_hdc, &graphics); + stat = GdipCreateFromHDC(new_hdc, &new_graphics); + graphics = new_graphics; if (stat != Ok) { ReleaseDC(0, new_hdc); return stat; } } + else if (!graphics->hdc) + { + graphics->hdc = new_hdc = GetDC(0); + if (!new_hdc) + return OutOfMemory; + } save_state = SaveDC(graphics->hdc); EndPath(graphics->hdc); @@ -918,7 +926,10 @@ static GpStatus get_path_hrgn(GpPath *path, GpGraphics *graphics, HRGN *hrgn) if (new_hdc) { ReleaseDC(0, new_hdc); - GdipDeleteGraphics(graphics); + if (new_graphics) + GdipDeleteGraphics(new_graphics); + else + graphics->hdc = NULL; } return stat; @@ -1248,11 +1259,66 @@ GpStatus WINGDIPAPI GdipSetInfinite(GpRegion *region) return stat; } +/* Transforms GpRegion elements with given matrix */ +static GpStatus transform_region_element(region_element* element, GpMatrix *matrix) +{ + GpStatus stat; + + switch(element->type) + { + case RegionDataEmptyRect: + case RegionDataInfiniteRect: + return Ok; + case RegionDataRect: + { + /* We can't transform a rectangle, so convert it to a path. */ + GpRegion *new_region; + GpPath *path; + + stat = GdipCreatePath(FillModeAlternate, &path); + if (stat == Ok) + { + stat = GdipAddPathRectangle(path, + element->elementdata.rect.X, element->elementdata.rect.Y, + element->elementdata.rect.Width, element->elementdata.rect.Height); + + if (stat == Ok) + stat = GdipCreateRegionPath(path, &new_region); + + GdipDeletePath(path); + } + + if (stat == Ok) + { + /* Steal the element from the created region. */ + memcpy(element, &new_region->node, sizeof(region_element)); + HeapFree(GetProcessHeap(), 0, new_region); + } + else + return stat; + } + /* Fall-through to do the actual conversion. */ + case RegionDataPath: + stat = GdipTransformMatrixPoints(matrix, + element->elementdata.pathdata.path->pathdata.Points, + element->elementdata.pathdata.path->pathdata.Count); + return stat; + default: + stat = transform_region_element(element->elementdata.combine.left, matrix); + if (stat == Ok) + stat = transform_region_element(element->elementdata.combine.right, matrix); + return stat; + } +} + GpStatus WINGDIPAPI GdipTransformRegion(GpRegion *region, GpMatrix *matrix) { - FIXME("(%p, %p): stub\n", region, matrix); + TRACE("(%p, %p)\n", region, matrix); - return NotImplemented; + if (!region || !matrix) + return InvalidParameter; + + return transform_region_element(®ion->node, matrix); } /* Translates GpRegion elements with specified offsets */ @@ -1307,14 +1373,150 @@ GpStatus WINGDIPAPI GdipTranslateRegionI(GpRegion *region, INT dx, INT dy) return GdipTranslateRegion(region, (REAL)dx, (REAL)dy); } +static GpStatus get_region_scans_data(GpRegion *region, GpMatrix *matrix, LPRGNDATA *data) +{ + GpRegion *region_copy; + GpStatus stat; + HRGN hrgn; + DWORD data_size; + + stat = GdipCloneRegion(region, ®ion_copy); + + if (stat == Ok) + { + stat = GdipTransformRegion(region_copy, matrix); + + if (stat == Ok) + stat = GdipGetRegionHRgn(region_copy, NULL, &hrgn); + + if (stat == Ok) + { + if (hrgn) + { + data_size = GetRegionData(hrgn, 0, NULL); + + *data = GdipAlloc(data_size); + + if (*data) + GetRegionData(hrgn, data_size, *data); + else + stat = OutOfMemory; + + DeleteObject(hrgn); + } + else + { + data_size = sizeof(RGNDATAHEADER) + sizeof(RECT); + + *data = GdipAlloc(data_size); + + if (*data) + { + (*data)->rdh.dwSize = sizeof(RGNDATAHEADER); + (*data)->rdh.iType = RDH_RECTANGLES; + (*data)->rdh.nCount = 1; + (*data)->rdh.nRgnSize = sizeof(RECT); + (*data)->rdh.rcBound.left = (*data)->rdh.rcBound.top = -0x400000; + (*data)->rdh.rcBound.right = (*data)->rdh.rcBound.bottom = 0x400000; + + memcpy(&(*data)->Buffer, &(*data)->rdh.rcBound, sizeof(RECT)); + } + else + stat = OutOfMemory; + } + } + + GdipDeleteRegion(region_copy); + } + + return stat; +} + GpStatus WINGDIPAPI GdipGetRegionScansCount(GpRegion *region, UINT *count, GpMatrix *matrix) { - static int calls; + GpStatus stat; + LPRGNDATA data; TRACE("(%p, %p, %p)\n", region, count, matrix); - if (!(calls++)) - FIXME("not implemented\n"); + if (!region || !count || !matrix) + return InvalidParameter; - return NotImplemented; + stat = get_region_scans_data(region, matrix, &data); + + if (stat == Ok) + { + *count = data->rdh.nCount; + GdipFree(data); + } + + return stat; +} + +GpStatus WINGDIPAPI GdipGetRegionScansI(GpRegion *region, GpRect *scans, INT *count, GpMatrix *matrix) +{ + GpStatus stat; + INT i; + LPRGNDATA data; + RECT *rects; + + if (!region || !count || !matrix) + return InvalidParameter; + + stat = get_region_scans_data(region, matrix, &data); + + if (stat == Ok) + { + *count = data->rdh.nCount; + rects = (RECT*)&data->Buffer; + + if (scans) + { + for (i=0; irdh.nCount; i++) + { + scans[i].X = rects[i].left; + scans[i].Y = rects[i].top; + scans[i].Width = rects[i].right - rects[i].left; + scans[i].Height = rects[i].bottom - rects[i].top; + } + } + + GdipFree(data); + } + + return Ok; +} + +GpStatus WINGDIPAPI GdipGetRegionScans(GpRegion *region, GpRectF *scans, INT *count, GpMatrix *matrix) +{ + GpStatus stat; + INT i; + LPRGNDATA data; + RECT *rects; + + if (!region || !count || !matrix) + return InvalidParameter; + + stat = get_region_scans_data(region, matrix, &data); + + if (stat == Ok) + { + *count = data->rdh.nCount; + rects = (RECT*)&data->Buffer; + + if (scans) + { + for (i=0; irdh.nCount; i++) + { + scans[i].X = rects[i].left; + scans[i].Y = rects[i].top; + scans[i].Width = rects[i].right - rects[i].left; + scans[i].Height = rects[i].bottom - rects[i].top; + } + } + + GdipFree(data); + } + + return Ok; } diff --git a/reactos/dll/win32/wer/main.c b/reactos/dll/win32/wer/main.c new file mode 100644 index 00000000000..585ac91a30b --- /dev/null +++ b/reactos/dll/win32/wer/main.c @@ -0,0 +1,321 @@ +/* + * Copyright 2010 Louis Lenders + * Copyright 2010 Detlef Riekenberg + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" + +#include + +#include "windef.h" +#include "winbase.h" +#include "winreg.h" +#include "werapi.h" +#include "wine/list.h" +#include "wine/unicode.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(wer); + +typedef struct { + struct list entry; + WER_REPORT_INFORMATION info; + WER_REPORT_TYPE reporttype; + WCHAR eventtype[1]; +} report_t; + + +static CRITICAL_SECTION report_table_cs; +static CRITICAL_SECTION_DEBUG report_table_cs_debug = +{ + 0, 0, &report_table_cs, + { &report_table_cs_debug.ProcessLocksList, &report_table_cs_debug.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": report_table_cs") } +}; +static CRITICAL_SECTION report_table_cs = { &report_table_cs_debug, -1, 0, 0, 0, 0 }; + +static struct list report_table = LIST_INIT(report_table); + +static WCHAR regpath_exclude[] = {'S','o','f','t','w','a','r','e','\\', + 'M','i','c','r','o','s','o','f','t','\\', + 'W','i','n','d','o','w','s',' ','E','r','r','o','r',' ','R','e','p','o','r','t','i','n','g','\\', + 'E','x','c','l','u','d','e','d','A','p','p','l','i','c','a','t','i','o','n','s',0}; + +/*********************************************************************** + * Memory alloccation helper + */ + +static inline void * __WINE_ALLOC_SIZE(1) heap_alloc_zero(size_t len) +{ + return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len); +} + +static inline BOOL heap_free(void *mem) +{ + return HeapFree(GetProcessHeap(), 0, mem); +} + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + TRACE("(0x%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved); + + switch (fdwReason) + { + case DLL_WINE_PREATTACH: + return FALSE; /* prefer native version */ + case DLL_PROCESS_ATTACH: + DisableThreadLibraryCalls(hinstDLL); + break; + case DLL_PROCESS_DETACH: + break; + } + + return TRUE; +} + +/*********************************************************************** + * WerAddExcludedApplication (wer.@) + * + * Add an application to the user specific or the system wide exclusion list + * + * PARAMS + * exeName [i] The application name + * allUsers [i] for all users (TRUE) or for the current user (FALSE) + * + * RETURNS + * Success: S_OK + * Faulure: A HRESULT error code + * + */ +HRESULT WINAPI WerAddExcludedApplication(PCWSTR exeName, BOOL allUsers) +{ + HKEY hkey; + DWORD value = 1; + LPWSTR bs; + + TRACE("(%s, %d)\n",debugstr_w(exeName), allUsers); + if (!exeName || !exeName[0]) + return E_INVALIDARG; + + bs = strrchrW(exeName, '\\'); + if (bs) { + bs++; /* skip the backslash */ + if (!bs[0]) { + return E_INVALIDARG; + } + } else + bs = (LPWSTR) exeName; + + if (!RegCreateKeyW(allUsers ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER, regpath_exclude, &hkey)) { + RegSetValueExW(hkey, bs, 0, REG_DWORD, (LPBYTE)&value, sizeof(DWORD)); + RegCloseKey(hkey); + return S_OK; + } + return E_ACCESSDENIED; +} + +/*********************************************************************** + * WerRemoveExcludedApplication (wer.@) + * + * remove an application from the exclusion list + * + * PARAMS + * exeName [i] The application name + * allUsers [i] for all users (TRUE) or for the current user (FALSE) + * + * RETURNS + * Success: S_OK + * Faulure: A HRESULT error code + * + */ +HRESULT WINAPI WerRemoveExcludedApplication(PCWSTR exeName, BOOL allUsers) +{ + HKEY hkey; + LPWSTR bs; + LONG lres; + + TRACE("(%s, %d)\n",debugstr_w(exeName), allUsers); + if (!exeName || !exeName[0]) + return E_INVALIDARG; + + bs = strrchrW(exeName, '\\'); + if (bs) { + bs++; /* skip the backslash */ + if (!bs[0]) { + return E_INVALIDARG; + } + } else + bs = (LPWSTR) exeName; + + if (!RegCreateKeyW(allUsers ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER, regpath_exclude, &hkey)) { + lres = RegDeleteValueW(hkey, bs); + RegCloseKey(hkey); + return lres ? __HRESULT_FROM_WIN32(ERROR_ENVVAR_NOT_FOUND) : S_OK; + } + return E_ACCESSDENIED; +} + +/*********************************************************************** + * WerReportCloseHandle (wer.@) + * + * Close an error reporting handle and free associated resources + * + * PARAMS + * hreport [i] error reporting handle to close + * + * RETURNS + * Success: S_OK + * Failure: A HRESULT error code + * + */ +HRESULT WINAPI WerReportCloseHandle(HREPORT hreport) +{ + report_t * report = (report_t *) hreport; + report_t * cursor; + BOOL found = FALSE; + + TRACE("(%p)\n", hreport); + EnterCriticalSection(&report_table_cs); + if (report) { + LIST_FOR_EACH_ENTRY(cursor, &report_table, report_t, entry) + { + if (cursor == report) { + found = TRUE; + list_remove(&report->entry); + break; + } + } + } + LeaveCriticalSection(&report_table_cs); + if (!found) + return E_INVALIDARG; + + heap_free(report); + + return S_OK; +} + +/*********************************************************************** + * WerReportCreate (wer.@) + * + * Create an error report in memory and return a related HANDLE + * + * PARAMS + * eventtype [i] a name for the event type + * reporttype [i] what type of report should be created + * reportinfo [i] NULL or a ptr to a struct with some detailed information + * phandle [o] ptr, where the resulting handle should be saved + * + * RETURNS + * Success: S_OK + * Failure: A HRESULT error code + * + * NOTES + * The event type must be registered at microsoft. Predefined types are + * "APPCRASH" as the default on Windows, "Crash32" and "Crash64" + * + */ +HRESULT WINAPI WerReportCreate(PCWSTR eventtype, WER_REPORT_TYPE reporttype, PWER_REPORT_INFORMATION reportinfo, HREPORT *phandle) +{ + report_t *report; + DWORD len; + + TRACE("(%s, %d, %p, %p)\n", debugstr_w(eventtype), reporttype, reportinfo, phandle); + if (reportinfo) { + TRACE(".wzFriendlyEventName: %s\n", debugstr_w(reportinfo->wzFriendlyEventName)); + TRACE(".wzApplicationName: %s\n", debugstr_w(reportinfo->wzApplicationName)); + } + + if (phandle) *phandle = NULL; + if (!eventtype || !eventtype[0] || !phandle) { + return E_INVALIDARG; + } + + len = lstrlenW(eventtype) + 1; + + report = heap_alloc_zero(len * sizeof(WCHAR) + sizeof(report_t)); + if (!report) + return __HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY); + + lstrcpyW(report->eventtype, eventtype); + report->reporttype = reporttype; + + if (reportinfo) { + report->info = *reportinfo; + } else { + FIXME("build report information from scratch for %p\n", report); + } + + EnterCriticalSection(&report_table_cs); + list_add_head(&report_table, &report->entry); + LeaveCriticalSection(&report_table_cs); + + *phandle = report; + TRACE("=> %p\n", report); + return S_OK; +} + +/*********************************************************************** + * WerReportSetParameter (wer.@) + * + * Set one of 10 parameter / value pairs for a report handle + * + * PARAMS + * hreport [i] error reporting handle to add the parameter + * id [i] parameter to set (WER_P0 upto WER_P9) + * name [i] optional name of the parameter + * value [i] value of the parameter + * + * RETURNS + * Success: S_OK + * Failure: A HRESULT error code + * + */ +HRESULT WINAPI WerReportSetParameter(HREPORT hreport, DWORD id, PCWSTR name, PCWSTR value) +{ + FIXME("(%p, %d, %s, %s) :stub\n", hreport, id, debugstr_w(name), debugstr_w(value)); + + return E_NOTIMPL; +} + +/*********************************************************************** + * WerReportSubmit (wer.@) + * + * Ask the user for permission and send the error report + * then kill or restart the application, when requested + * + * PARAMS + * hreport [i] error reporting handle to send + * consent [i] current transmit permission + * flags [i] flag to select dialog, transmission snd restart options + * presult [o] ptr, where the transmission result should be saved + * + * RETURNS + * Success: S_OK + * Failure: A HRESULT error code + * + */ +HRESULT WINAPI WerReportSubmit(HREPORT hreport, WER_CONSENT consent, DWORD flags, PWER_SUBMIT_RESULT presult) +{ + FIXME("(%p, %d, 0x%x, %p) :stub\n", hreport, consent, flags, presult); + + if(!presult) + return E_INVALIDARG; + + *presult = WerDisabled; + return E_NOTIMPL; +} diff --git a/reactos/dll/win32/wer/wer.rbuild b/reactos/dll/win32/wer/wer.rbuild new file mode 100644 index 00000000000..852102966ba --- /dev/null +++ b/reactos/dll/win32/wer/wer.rbuild @@ -0,0 +1,11 @@ + + + + + . + include/reactos/wine + + advapi32 + wine + main.c + diff --git a/reactos/dll/win32/wer/wer.spec b/reactos/dll/win32/wer/wer.spec new file mode 100644 index 00000000000..4303c204b7e --- /dev/null +++ b/reactos/dll/win32/wer/wer.spec @@ -0,0 +1,77 @@ +@ stub WerSysprepCleanup +@ stub WerSysprepGeneralize +@ stub WerSysprepSpecialize +@ stub WerUnattendedSetup +@ stub WerpAddAppCompatData +@ stub WerpAddFile +@ stub WerpAddMemoryBlock +@ stub WerpAddRegisteredDataToReport +@ stub WerpAddSecondaryParameter +@ stub WerpAddTextToReport +@ stub WerpArchiveReport +@ stub WerpCancelResponseDownload +@ stub WerpCancelUpload +@ stub WerpCloseStore +@ stub WerpCreateMachineStore +@ stub WerpDeleteReport +@ stub WerpDestroyWerString +@ stub WerpDownloadResponse +@ stub WerpDownloadResponseTemplate +@ stub WerpEnumerateStoreNext +@ stub WerpEnumerateStoreStart +@ stub WerpExtractReportFiles +@ stub WerpGetBucketId +@ stub WerpGetDynamicParameter +@ stub WerpGetEventType +@ stub WerpGetFileByIndex +@ stub WerpGetFilePathByIndex +@ stub WerpGetNumFiles +@ stub WerpGetNumSecParams +@ stub WerpGetNumSigParams +@ stub WerpGetReportFinalConsent +@ stub WerpGetReportFlags +@ stub WerpGetReportInformation +@ stub WerpGetReportTime +@ stub WerpGetReportType +@ stub WerpGetResponseId +@ stub WerpGetResponseUrl +@ stub WerpGetSecParamByIndex +@ stub WerpGetSigParamByIndex +@ stub WerpGetStoreLocation +@ stub WerpGetStoreType +@ stub WerpGetTextFromReport +@ stub WerpGetUIParamByIndex +@ stub WerpGetUploadTime +@ stub WerpGetWerStringData +@ stub WerpIsTransportAvailable +@ stub WerpLoadReport +@ stub WerpOpenMachineArchive +@ stub WerpOpenMachineQueue +@ stub WerpOpenUserArchive +@ stub WerpReportCancel +@ stub WerpRestartApplication +@ stub WerpSetDynamicParameter +@ stub WerpSetEventName +@ stub WerpSetReportFlags +@ stub WerpSetReportInformation +@ stub WerpSetReportTime +@ stub WerpSetReportUploadContextToken +@ stub WerpShowNXNotification +@ stub WerpShowSecondLevelConsent +@ stub WerpShowUpsellUI +@ stub WerpSubmitReportFromStore +@ stub WerpSvcReportFromMachineQueue +@ stdcall WerAddExcludedApplication(wstr long) +@ stdcall WerRemoveExcludedApplication(wstr long) +@ stub WerReportAddDump +@ stub WerReportAddFile +@ stdcall WerReportCloseHandle(ptr) +@ stdcall WerReportCreate(wstr long ptr ptr) +@ stdcall WerReportSetParameter(ptr long wstr wstr) +@ stub WerReportSetUIOption +@ stdcall WerReportSubmit(ptr long long ptr) +@ stub WerpGetReportConsent +@ stub WerpIsDisabled +@ stub WerpOpenUserQueue +@ stub WerpPromtUser +@ stub WerpSetCallBack diff --git a/reactos/dll/win32/win32.rbuild b/reactos/dll/win32/win32.rbuild index 5cd3d741736..30dbf94704c 100644 --- a/reactos/dll/win32/win32.rbuild +++ b/reactos/dll/win32/win32.rbuild @@ -595,6 +595,9 @@ + + + diff --git a/reactos/include/psdk/werapi.h b/reactos/include/psdk/werapi.h new file mode 100644 index 00000000000..4b79c041787 --- /dev/null +++ b/reactos/include/psdk/werapi.h @@ -0,0 +1,127 @@ +/* + * Windows Error Reporing definitions + * + * Copyright (C) 2010 Louis Lenders + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __WINE_WERAPI_H +#define __WINE_WERAPI_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Only 10 parameter are allowed in WerReportSetParameter */ +#define WER_MAX_PARAM_COUNT 10 +#define WER_P0 0 +#define WER_P1 1 +#define WER_P2 2 +#define WER_P3 3 +#define WER_P4 4 +#define WER_P5 5 +#define WER_P6 6 +#define WER_P7 7 +#define WER_P8 8 +#define WER_P9 9 + +/* Flags for WerReportSubmit */ +#define WER_SUBMIT_HONOR_RECOVERY 0x0001 +#define WER_SUBMIT_HONOR_RESTART 0x0002 +#define WER_SUBMIT_QUEUE 0x0004 +#define WER_SUBMIT_SHOW_DEBUG 0x0008 +#define WER_SUBMIT_ADD_REGISTERED_DATA 0x0010 +#define WER_SUBMIT_OUTOFPROCESS 0x0020 +#define WER_SUBMIT_NO_CLOSE_UI 0x0040 +#define WER_SUBMIT_NO_QUEUE 0x0080 +#define WER_SUBMIT_NO_ARCHIVE 0x0100 +#define WER_SUBMIT_START_MINIMIZED 0x0200 +#define WER_SUBMIT_OUTOFPROCESS_ASYNC 0x0400 +#define WER_SUBMIT_BYPASS_DATA_THROTTLING 0x0800 +#define WER_SUBMIT_ARCHIVE_PARAMETERS_ONLY 0x1000 +#define WER_SUBMIT_REPORT_MACHINE_ID 0x2000 + +/* #### */ + +typedef HANDLE HREPORT; + +typedef enum _WER_CONSENT +{ + WerConsentNotAsked = 1, + WerConsentApproved, + WerConsentDenied, + WerConsentAlwaysPrompt, + WerConsentMax +} WER_CONSENT; + +typedef enum _WER_REGISTER_FILE_TYPE +{ + WerRegFileTypeUserDocument = 1, + WerRegFileTypeOther = 2, + WerRegFileTypeMax +} WER_REGISTER_FILE_TYPE; + +typedef struct _WER_REPORT_INFORMATION +{ + DWORD dwSize; + HANDLE hProcess; + WCHAR wzConsentKey[64]; + WCHAR wzFriendlyEventName[128]; + WCHAR wzApplicationName[128]; + WCHAR wzApplicationPath[MAX_PATH]; + WCHAR wzDescription[512]; + HWND hwndParent; +} WER_REPORT_INFORMATION, *PWER_REPORT_INFORMATION; + + +typedef enum _WER_REPORT_TYPE +{ + WerReportNonCritical = 0, + WerReportCritical, + WerReportApplicationCrash, + WerReportApplicationHang, + WerReportKernel, + WerReportInvalid +} WER_REPORT_TYPE; + +typedef enum _WER_SUBMIT_RESULT +{ + WerReportQueued = 1, + WerReportUploaded, + WerReportDebug, + WerReportFailed, + WerDisabled, + WerReportCancelled, + WerDisabledQueue, + WerReportAsync, + WerCustomAction +} WER_SUBMIT_RESULT, *PWER_SUBMIT_RESULT; + +/* #### */ + +HRESULT WINAPI WerAddExcludedApplication(PCWSTR, BOOL); +HRESULT WINAPI WerRegisterFile(PCWSTR file, WER_REGISTER_FILE_TYPE regfiletype, DWORD flags); +HRESULT WINAPI WerRemoveExcludedApplication(PCWSTR, BOOL); +HRESULT WINAPI WerReportCloseHandle(HREPORT); +HRESULT WINAPI WerReportCreate(PCWSTR, WER_REPORT_TYPE, PWER_REPORT_INFORMATION, HREPORT*); +HRESULT WINAPI WerReportSetParameter(HREPORT, DWORD, PCWSTR, PCWSTR); +HRESULT WINAPI WerReportSubmit(HREPORT, WER_CONSENT, DWORD, PWER_SUBMIT_RESULT); + +#ifdef __cplusplus +} +#endif + +#endif /* __WINE_WERAPI_H */ diff --git a/reactos/media/doc/README.WINE b/reactos/media/doc/README.WINE index d03bb636129..0937d63e64b 100644 --- a/reactos/media/doc/README.WINE +++ b/reactos/media/doc/README.WINE @@ -167,6 +167,7 @@ reactos/dll/win32/urlmon # Autosync reactos/dll/win32/usp10 # Autosync reactos/dll/win32/uxtheme # Autosync reactos/dll/win32/version # Autosync +reactos/dll/win32/wer # Autosync reactos/dll/win32/windowscodecs # Autosync reactos/dll/win32/winemp3.acm # Autosync reactos/dll/win32/wininet # Autosync