ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

dibobj.c
Go to the documentation of this file.
00001 /*
00002  * PROJECT:         ReactOS win32 kernel mode subsystem
00003  * LICENSE:         GPL - See COPYING in the top level directory
00004  * FILE:            subsystems/win32/win32k/objects/dibobj.c
00005  * PURPOSE:         Dib object functions
00006  * PROGRAMMER:
00007  */
00008 
00009 #include <win32k.h>
00010 
00011 #define NDEBUG
00012 #include <debug.h>
00013 
00014 static const RGBQUAD EGAColorsQuads[16] =
00015 {
00016     /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
00017     { 0x00, 0x00, 0x00, 0x00 },
00018     { 0x00, 0x00, 0x80, 0x00 },
00019     { 0x00, 0x80, 0x00, 0x00 },
00020     { 0x00, 0x80, 0x80, 0x00 },
00021     { 0x80, 0x00, 0x00, 0x00 },
00022     { 0x80, 0x00, 0x80, 0x00 },
00023     { 0x80, 0x80, 0x00, 0x00 },
00024     { 0x80, 0x80, 0x80, 0x00 },
00025     { 0xc0, 0xc0, 0xc0, 0x00 },
00026     { 0x00, 0x00, 0xff, 0x00 },
00027     { 0x00, 0xff, 0x00, 0x00 },
00028     { 0x00, 0xff, 0xff, 0x00 },
00029     { 0xff, 0x00, 0x00, 0x00 },
00030     { 0xff, 0x00, 0xff, 0x00 },
00031     { 0xff, 0xff, 0x00, 0x00 },
00032     { 0xff, 0xff, 0xff, 0x00 }
00033 };
00034 
00035 static const RGBTRIPLE EGAColorsTriples[16] =
00036 {
00037     /* rgbBlue, rgbGreen, rgbRed */
00038     { 0x00, 0x00, 0x00 },
00039     { 0x00, 0x00, 0x80 },
00040     { 0x00, 0x80, 0x00 },
00041     { 0x00, 0x80, 0x80 },
00042     { 0x80, 0x00, 0x00 },
00043     { 0x80, 0x00, 0x80 },
00044     { 0x80, 0x80, 0x00 },
00045     { 0x80, 0x80, 0x80 },
00046     { 0xc0, 0xc0, 0xc0 },
00047     { 0x00, 0x00, 0xff },
00048     { 0x00, 0xff, 0x00 },
00049     { 0x00, 0xff, 0xff },
00050     { 0xff, 0x00, 0x00 },
00051     { 0xff, 0x00, 0xff },
00052     { 0xff, 0xff, 0x00 },
00053     { 0xff, 0xff, 0xff }
00054 };
00055 
00056 static const RGBQUAD DefLogPaletteQuads[20] =   /* Copy of Default Logical Palette */
00057 {
00058     /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
00059     { 0x00, 0x00, 0x00, 0x00 },
00060     { 0x00, 0x00, 0x80, 0x00 },
00061     { 0x00, 0x80, 0x00, 0x00 },
00062     { 0x00, 0x80, 0x80, 0x00 },
00063     { 0x80, 0x00, 0x00, 0x00 },
00064     { 0x80, 0x00, 0x80, 0x00 },
00065     { 0x80, 0x80, 0x00, 0x00 },
00066     { 0xc0, 0xc0, 0xc0, 0x00 },
00067     { 0xc0, 0xdc, 0xc0, 0x00 },
00068     { 0xf0, 0xca, 0xa6, 0x00 },
00069     { 0xf0, 0xfb, 0xff, 0x00 },
00070     { 0xa4, 0xa0, 0xa0, 0x00 },
00071     { 0x80, 0x80, 0x80, 0x00 },
00072     { 0x00, 0x00, 0xf0, 0x00 },
00073     { 0x00, 0xff, 0x00, 0x00 },
00074     { 0x00, 0xff, 0xff, 0x00 },
00075     { 0xff, 0x00, 0x00, 0x00 },
00076     { 0xff, 0x00, 0xff, 0x00 },
00077     { 0xff, 0xff, 0x00, 0x00 },
00078     { 0xff, 0xff, 0xff, 0x00 }
00079 };
00080 
00081 static const RGBQUAD DefLogPaletteTriples[20] =   /* Copy of Default Logical Palette */
00082 {
00083     /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
00084     { 0x00, 0x00, 0x00 },
00085     { 0x00, 0x00, 0x80 },
00086     { 0x00, 0x80, 0x00 },
00087     { 0x00, 0x80, 0x80 },
00088     { 0x80, 0x00, 0x00 },
00089     { 0x80, 0x00, 0x80 },
00090     { 0x80, 0x80, 0x00 },
00091     { 0xc0, 0xc0, 0xc0 },
00092     { 0xc0, 0xdc, 0xc0 },
00093     { 0xf0, 0xca, 0xa6 },
00094     { 0xf0, 0xfb, 0xff },
00095     { 0xa4, 0xa0, 0xa0 },
00096     { 0x80, 0x80, 0x80 },
00097     { 0x00, 0x00, 0xf0 },
00098     { 0x00, 0xff, 0x00 },
00099     { 0x00, 0xff, 0xff },
00100     { 0xff, 0x00, 0x00 },
00101     { 0xff, 0x00, 0xff },
00102     { 0xff, 0xff, 0x00 },
00103     { 0xff, 0xff, 0xff }
00104 };
00105 
00106 PPALETTE
00107 NTAPI
00108 CreateDIBPalette(
00109     _In_ const BITMAPINFO *pbmi,
00110     _In_ PDC pdc,
00111     _In_ ULONG iUsage)
00112 {
00113     PPALETTE ppal;
00114     ULONG i, cBitsPixel, cColors;
00115 
00116     if (pbmi->bmiHeader.biSize < sizeof(BITMAPINFOHEADER))
00117     {
00118         PBITMAPCOREINFO pbci = (PBITMAPCOREINFO)pbmi;
00119         cBitsPixel = pbci->bmciHeader.bcBitCount;
00120     }
00121     else
00122     {
00123         cBitsPixel = pbmi->bmiHeader.biBitCount;
00124     }
00125 
00126     /* Check if the colors are indexed */
00127     if (cBitsPixel <= 8)
00128     {
00129         /* We create a "full" palette */
00130         cColors = 1 << cBitsPixel;
00131 
00132         /* Allocate the palette */
00133         ppal = PALETTE_AllocPalette(PAL_INDEXED,
00134                                     cColors,
00135                                     NULL,
00136                                     0,
00137                                     0,
00138                                     0);
00139 
00140         /* Check if the BITMAPINFO specifies how many colors to use */
00141         if ((pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
00142             (pbmi->bmiHeader.biClrUsed != 0))
00143         {
00144             /* This is how many colors we can actually process */
00145             cColors = min(cColors, pbmi->bmiHeader.biClrUsed);
00146         }
00147 
00148         /* Check how to use the colors */
00149         if (iUsage == DIB_PAL_COLORS)
00150         {
00151             COLORREF crColor;
00152 
00153             /* The colors are an array of WORD indices into the DC palette */
00154             PWORD pwColors = (PWORD)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
00155 
00156             /* Use the DCs palette or, if no DC is given, the default one */
00157             PPALETTE ppalDC = pdc ? pdc->dclevel.ppal : gppalDefault;
00158 
00159             /* Loop all color indices in the DIB */
00160             for (i = 0; i < cColors; i++)
00161             {
00162                 /* Get the palette index and handle wraparound when exceeding
00163                    the number of colors in the DC palette */
00164                 WORD wIndex = pwColors[i] % ppalDC->NumColors;
00165 
00166                 /* USe the RGB value from the DC palette */
00167                 crColor = PALETTE_ulGetRGBColorFromIndex(ppalDC, wIndex);
00168                 PALETTE_vSetRGBColorForIndex(ppal, i, crColor);
00169             }
00170         }
00171         else if (iUsage == DIB_PAL_BRUSHHACK)
00172         {
00173             /* The colors are an array of WORD indices into the DC palette */
00174             PWORD pwColors = (PWORD)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
00175 
00176             /* Loop all color indices in the DIB */
00177             for (i = 0; i < cColors; i++)
00178             {
00179                 /* Set the index directly as the RGB color, the real palette
00180                    containing RGB values will be calculated when the brush is
00181                    realized */
00182                 PALETTE_vSetRGBColorForIndex(ppal, i, pwColors[i]);
00183             }
00184 
00185             /* Mark the palette as a brush hack palette */
00186             ppal->flFlags |= PAL_BRUSHHACK;
00187         }
00188 //        else if (iUsage == 2)
00189 //        {
00190             // FIXME: this one is undocumented
00191 //            ASSERT(FALSE);
00192 //        }
00193         else if (pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER))
00194         {
00195             /* The colors are an array of RGBQUAD values */
00196             RGBQUAD *prgb = (RGBQUAD*)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
00197 
00198             // FIXME: do we need to handle PALETTEINDEX / PALETTERGB macro?
00199 
00200             /* Loop all color indices in the DIB */
00201             for (i = 0; i < cColors; i++)
00202             {
00203                 /* Get the color value and translate it to a COLORREF */
00204                 RGBQUAD rgb = prgb[i];
00205                 COLORREF crColor = RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
00206 
00207                 /* Set the RGB value in the palette */
00208                 PALETTE_vSetRGBColorForIndex(ppal, i, crColor);
00209             }
00210         }
00211         else
00212         {
00213             /* The colors are an array of RGBTRIPLE values */
00214             RGBTRIPLE *prgb = (RGBTRIPLE*)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
00215 
00216             /* Loop all color indices in the DIB */
00217             for (i = 0; i < cColors; i++)
00218             {
00219                 /* Get the color value and translate it to a COLORREF */
00220                 RGBTRIPLE rgb = prgb[i];
00221                 COLORREF crColor = RGB(rgb.rgbtRed, rgb.rgbtGreen, rgb.rgbtBlue);
00222 
00223                 /* Set the RGB value in the palette */
00224                 PALETTE_vSetRGBColorForIndex(ppal, i, crColor);
00225             }
00226         }
00227     }
00228     else
00229     {
00230         /* This is a bitfield / RGB palette */
00231         ULONG flRedMask, flGreenMask, flBlueMask;
00232 
00233         /* Check if the DIB contains bitfield values */
00234         if ((pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
00235             (pbmi->bmiHeader.biCompression == BI_BITFIELDS))
00236         {
00237             /* Check if we have a v4/v5 header */
00238             if (pbmi->bmiHeader.biSize >= sizeof(BITMAPV4HEADER))
00239             {
00240                 /* The masks are dedicated fields in the header */
00241                 PBITMAPV4HEADER pbmV4Header = (PBITMAPV4HEADER)&pbmi->bmiHeader;
00242                 flRedMask = pbmV4Header->bV4RedMask;
00243                 flGreenMask = pbmV4Header->bV4GreenMask;
00244                 flBlueMask = pbmV4Header->bV4BlueMask;
00245             }
00246             else
00247             {
00248                 /* The masks are the first 3 values in the DIB color table */
00249                 PDWORD pdwColors = (PVOID)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
00250                 flRedMask = pdwColors[0];
00251                 flGreenMask = pdwColors[1];
00252                 flBlueMask = pdwColors[2];
00253             }
00254         }
00255         else
00256         {
00257             /* Check what bit depth we have. Note: optimization flags are
00258                calculated in PALETTE_AllocPalette()  */
00259             if (cBitsPixel == 16)
00260             {
00261                 /* This is an RGB 555 palette */
00262                 flRedMask = 0x7C00;
00263                 flGreenMask = 0x03E0;
00264                 flBlueMask = 0x001F;
00265             }
00266             else
00267             {
00268                 /* This is an RGB 888 palette */
00269                 flRedMask = 0xFF0000;
00270                 flGreenMask = 0x00FF00;
00271                 flBlueMask = 0x0000FF;
00272             }
00273         }
00274 
00275         /* Allocate the bitfield palette */
00276         ppal = PALETTE_AllocPalette(PAL_BITFIELDS,
00277                                     0,
00278                                     NULL,
00279                                     flRedMask,
00280                                     flGreenMask,
00281                                     flBlueMask);
00282     }
00283 
00284     /* We're done, return the palette */
00285     return ppal;
00286 }
00287 
00288 // Converts a DIB to a device-dependent bitmap
00289 static INT
00290 FASTCALL
00291 IntSetDIBits(
00292     PDC   DC,
00293     HBITMAP  hBitmap,
00294     UINT  StartScan,
00295     UINT  ScanLines,
00296     CONST VOID  *Bits,
00297     CONST BITMAPINFO  *bmi,
00298     UINT  ColorUse)
00299 {
00300     HBITMAP     SourceBitmap;
00301     PSURFACE    psurfDst, psurfSrc;
00302     INT         result = 0;
00303     RECT        rcDst;
00304     POINTL      ptSrc;
00305     EXLATEOBJ   exlo;
00306     PPALETTE    ppalDIB = 0;
00307 
00308     if (!bmi) return 0;
00309 
00310     SourceBitmap = GreCreateBitmapEx(bmi->bmiHeader.biWidth,
00311                                      ScanLines,
00312                                      0,
00313                                      BitmapFormat(bmi->bmiHeader.biBitCount,
00314                                                   bmi->bmiHeader.biCompression),
00315                                      bmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
00316                                      bmi->bmiHeader.biSizeImage,
00317                                      (PVOID)Bits,
00318                                      0);
00319     if (!SourceBitmap)
00320     {
00321         DPRINT1("Error: Could not create a bitmap.\n");
00322         EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
00323         return 0;
00324     }
00325 
00326     psurfDst = SURFACE_ShareLockSurface(hBitmap);
00327     psurfSrc = SURFACE_ShareLockSurface(SourceBitmap);
00328 
00329     if(!(psurfSrc && psurfDst))
00330     {
00331         DPRINT1("Error: Could not lock surfaces\n");
00332         goto cleanup;
00333     }
00334 
00335     /* Create a palette for the DIB */
00336     ppalDIB = CreateDIBPalette(bmi, DC, ColorUse);
00337     if (!ppalDIB)
00338     {
00339         EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
00340         goto cleanup;
00341     }
00342 
00343     /* Initialize EXLATEOBJ */
00344     EXLATEOBJ_vInitialize(&exlo,
00345                           ppalDIB,
00346                           psurfDst->ppal,
00347                           RGB(0xff, 0xff, 0xff),
00348                           RGB(0xff, 0xff, 0xff), //DC->pdcattr->crBackgroundClr,
00349                           0); // DC->pdcattr->crForegroundClr);
00350 
00351     rcDst.top = StartScan;
00352     rcDst.left = 0;
00353     rcDst.bottom = rcDst.top + ScanLines;
00354     rcDst.right = psurfDst->SurfObj.sizlBitmap.cx;
00355     ptSrc.x = 0;
00356     ptSrc.y = 0;
00357 
00358     result = IntEngCopyBits(&psurfDst->SurfObj,
00359                             &psurfSrc->SurfObj,
00360                             NULL,
00361                             &exlo.xlo,
00362                             &rcDst,
00363                             &ptSrc);
00364     if(result)
00365         result = ScanLines;
00366 
00367     EXLATEOBJ_vCleanup(&exlo);
00368 
00369 cleanup:
00370     if (ppalDIB) PALETTE_ShareUnlockPalette(ppalDIB);
00371     if(psurfSrc) SURFACE_ShareUnlockSurface(psurfSrc);
00372     if(psurfDst) SURFACE_ShareUnlockSurface(psurfDst);
00373     GreDeleteObject(SourceBitmap);
00374 
00375     return result;
00376 }
00377 
00378 W32KAPI
00379 INT
00380 APIENTRY
00381 NtGdiSetDIBitsToDeviceInternal(
00382     IN HDC hDC,
00383     IN INT XDest,
00384     IN INT YDest,
00385     IN DWORD Width,
00386     IN DWORD Height,
00387     IN INT XSrc,
00388     IN INT YSrc,
00389     IN DWORD StartScan,
00390     IN DWORD ScanLines,
00391     IN LPBYTE Bits,
00392     IN LPBITMAPINFO bmi,
00393     IN DWORD ColorUse,
00394     IN UINT cjMaxBits,
00395     IN UINT cjMaxInfo,
00396     IN BOOL bTransformCoordinates,
00397     IN OPTIONAL HANDLE hcmXform)
00398 {
00399     INT ret = 0;
00400     NTSTATUS Status = STATUS_SUCCESS;
00401     PDC pDC;
00402     HBITMAP hSourceBitmap = NULL;
00403     SURFOBJ *pDestSurf, *pSourceSurf = NULL;
00404     SURFACE *pSurf;
00405     RECTL rcDest;
00406     POINTL ptSource;
00407     //INT DIBWidth;
00408     SIZEL SourceSize;
00409     EXLATEOBJ exlo;
00410     PPALETTE ppalDIB = NULL;
00411     LPBITMAPINFO pbmiSafe;
00412 
00413     if (!Bits) return 0;
00414 
00415     pbmiSafe = ExAllocatePoolWithTag(PagedPool, cjMaxInfo, 'pmTG');
00416     if (!pbmiSafe) return 0;
00417 
00418     _SEH2_TRY
00419     {
00420         ProbeForRead(bmi, cjMaxInfo, 1);
00421         ProbeForRead(Bits, cjMaxBits, 1);
00422         RtlCopyMemory(pbmiSafe, bmi, cjMaxInfo);
00423         bmi = pbmiSafe;
00424     }
00425     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00426     {
00427         Status = _SEH2_GetExceptionCode();
00428     }
00429     _SEH2_END
00430 
00431     if (!NT_SUCCESS(Status))
00432     {
00433         goto Exit2;
00434     }
00435 
00436     pDC = DC_LockDc(hDC);
00437     if (!pDC)
00438     {
00439         EngSetLastError(ERROR_INVALID_HANDLE);
00440         goto Exit2;
00441     }
00442     if (pDC->dctype == DC_TYPE_INFO)
00443     {
00444         DC_UnlockDc(pDC);
00445         goto Exit2;
00446     }
00447 
00448     pSurf = pDC->dclevel.pSurface;
00449 
00450     pDestSurf = pSurf ? &pSurf->SurfObj : NULL;
00451 
00452     ScanLines = min(ScanLines, abs(bmi->bmiHeader.biHeight) - StartScan);
00453 
00454     rcDest.left = XDest;
00455     rcDest.top = YDest;
00456     if (bTransformCoordinates)
00457     {
00458         IntLPtoDP(pDC, (LPPOINT)&rcDest, 2);
00459     }
00460     rcDest.left += pDC->ptlDCOrig.x;
00461     rcDest.top += pDC->ptlDCOrig.y;
00462     rcDest.right = rcDest.left + Width;
00463     rcDest.bottom = rcDest.top + Height;
00464     rcDest.top += StartScan;
00465 
00466     ptSource.x = XSrc;
00467     ptSource.y = YSrc;
00468 
00469     SourceSize.cx = bmi->bmiHeader.biWidth;
00470     SourceSize.cy = ScanLines;
00471 
00472     //DIBWidth = WIDTH_BYTES_ALIGN32(SourceSize.cx, bmi->bmiHeader.biBitCount);
00473 
00474     hSourceBitmap = GreCreateBitmapEx(bmi->bmiHeader.biWidth,
00475                                       ScanLines,
00476                                       0,
00477                                       BitmapFormat(bmi->bmiHeader.biBitCount,
00478                                                    bmi->bmiHeader.biCompression),
00479                                       bmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
00480                                       bmi->bmiHeader.biSizeImage,
00481                                       Bits,
00482                                       0);
00483 
00484     if (!hSourceBitmap)
00485     {
00486         EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
00487         Status = STATUS_NO_MEMORY;
00488         goto Exit;
00489     }
00490 
00491     pSourceSurf = EngLockSurface((HSURF)hSourceBitmap);
00492     if (!pSourceSurf)
00493     {
00494         Status = STATUS_UNSUCCESSFUL;
00495         goto Exit;
00496     }
00497 
00498     ASSERT(pSurf->ppal);
00499 
00500     /* Create a palette for the DIB */
00501     ppalDIB = CreateDIBPalette(bmi, pDC, ColorUse);
00502     if (!ppalDIB)
00503     {
00504         EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
00505         Status = STATUS_NO_MEMORY;
00506         goto Exit;
00507     }
00508 
00509     /* Initialize EXLATEOBJ */
00510     EXLATEOBJ_vInitialize(&exlo,
00511                           ppalDIB,
00512                           pSurf->ppal,
00513                           RGB(0xff, 0xff, 0xff),
00514                           pDC->pdcattr->crBackgroundClr,
00515                           pDC->pdcattr->crForegroundClr);
00516 
00517     /* Copy the bits */
00518     DPRINT("BitsToDev with dstsurf=(%d|%d) (%d|%d), src=(%d|%d) w=%d h=%d\n",
00519            rcDest.left, rcDest.top, rcDest.right, rcDest.bottom,
00520            ptSource.x, ptSource.y, SourceSize.cx, SourceSize.cy);
00521     Status = IntEngBitBlt(pDestSurf,
00522                           pSourceSurf,
00523                           NULL,
00524                           pDC->rosdc.CombinedClip,
00525                           &exlo.xlo,
00526                           &rcDest,
00527                           &ptSource,
00528                           NULL,
00529                           NULL,
00530                           NULL,
00531                           ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY));
00532 
00533     /* Cleanup EXLATEOBJ */
00534     EXLATEOBJ_vCleanup(&exlo);
00535 
00536 Exit:
00537     if (NT_SUCCESS(Status))
00538     {
00539         ret = ScanLines;
00540     }
00541 
00542     if (ppalDIB) PALETTE_ShareUnlockPalette(ppalDIB);
00543 
00544     if (pSourceSurf) EngUnlockSurface(pSourceSurf);
00545     if (hSourceBitmap) EngDeleteSurface((HSURF)hSourceBitmap);
00546     DC_UnlockDc(pDC);
00547 Exit2:
00548     ExFreePool(pbmiSafe);
00549     return ret;
00550 }
00551 
00552 
00553 /* Converts a device-dependent bitmap to a DIB */
00554 INT
00555 APIENTRY
00556 NtGdiGetDIBitsInternal(
00557     HDC hDC,
00558     HBITMAP hBitmap,
00559     UINT StartScan,
00560     UINT ScanLines,
00561     LPBYTE Bits,
00562     LPBITMAPINFO Info,
00563     UINT Usage,
00564     UINT MaxBits,
00565     UINT MaxInfo)
00566 {
00567     BITMAPCOREINFO* pbmci = NULL;
00568     PSURFACE psurf = NULL;
00569     PDC pDC;
00570     LONG width, height;
00571     WORD planes, bpp;
00572     DWORD compr, size ;
00573     USHORT i;
00574     int bitmap_type;
00575     RGBTRIPLE* rgbTriples;
00576     RGBQUAD* rgbQuads;
00577     VOID* colorPtr;
00578     NTSTATUS Status = STATUS_SUCCESS;
00579 
00580     DPRINT("Entered NtGdiGetDIBitsInternal()\n");
00581 
00582     if ((Usage && Usage != DIB_PAL_COLORS) || !Info || !hBitmap)
00583         return 0;
00584 
00585     _SEH2_TRY
00586     {
00587         /* Probe for read and write */
00588         ProbeForRead(Info, MaxInfo, 1);
00589         ProbeForWrite(Info, MaxInfo, 1);
00590         if (Bits) ProbeForWrite(Bits, MaxBits, 1);
00591     }
00592     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00593     {
00594         Status = _SEH2_GetExceptionCode();
00595     }
00596     _SEH2_END
00597 
00598     if (!NT_SUCCESS(Status))
00599     {
00600         return 0;
00601     }
00602 
00603     colorPtr = (LPBYTE)Info + Info->bmiHeader.biSize;
00604     rgbTriples = colorPtr;
00605     rgbQuads = colorPtr;
00606 
00607     bitmap_type = DIB_GetBitmapInfo(&Info->bmiHeader,
00608                                     &width,
00609                                     &height,
00610                                     &planes,
00611                                     &bpp,
00612                                     &compr,
00613                                     &size);
00614     if(bitmap_type == -1)
00615     {
00616         DPRINT("Wrong bitmap format\n");
00617         EngSetLastError(ERROR_INVALID_PARAMETER);
00618         return 0;
00619     }
00620     else if(bitmap_type == 0)
00621     {
00622         /* We need a BITMAPINFO to create a DIB, but we have to fill
00623          * the BITMAPCOREINFO we're provided */
00624         pbmci = (BITMAPCOREINFO*)Info;
00625         Info = DIB_ConvertBitmapInfo((BITMAPINFO*)pbmci, Usage);
00626         if(Info == NULL)
00627         {
00628             DPRINT1("Error, could not convert the BITMAPCOREINFO!\n");
00629             return 0;
00630         }
00631         rgbQuads = Info->bmiColors;
00632     }
00633 
00634     pDC = DC_LockDc(hDC);
00635     if (pDC == NULL || pDC->dctype == DC_TYPE_INFO)
00636     {
00637         ScanLines = 0;
00638         goto done;
00639     }
00640 
00641     /* Get a pointer to the source bitmap object */
00642     psurf = SURFACE_ShareLockSurface(hBitmap);
00643     if (psurf == NULL)
00644     {
00645         ScanLines = 0;
00646         goto done;
00647     }
00648 
00649     /* Fill in the structure */
00650     switch(bpp)
00651     {
00652     case 0: /* Only info */
00653         if(pbmci)
00654         {
00655             pbmci->bmciHeader.bcWidth = (WORD)psurf->SurfObj.sizlBitmap.cx;
00656             pbmci->bmciHeader.bcHeight = (WORD)((psurf->SurfObj.fjBitmap & BMF_TOPDOWN) ?
00657                                          -psurf->SurfObj.sizlBitmap.cy :
00658                                          psurf->SurfObj.sizlBitmap.cy);
00659             pbmci->bmciHeader.bcPlanes = 1;
00660             pbmci->bmciHeader.bcBitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
00661         }
00662         Info->bmiHeader.biWidth = psurf->SurfObj.sizlBitmap.cx;
00663         Info->bmiHeader.biHeight = (psurf->SurfObj.fjBitmap & BMF_TOPDOWN) ?
00664                                    -psurf->SurfObj.sizlBitmap.cy :
00665                                    psurf->SurfObj.sizlBitmap.cy;;
00666         Info->bmiHeader.biPlanes = 1;
00667         Info->bmiHeader.biBitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
00668         Info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( Info->bmiHeader.biWidth,
00669                                       Info->bmiHeader.biHeight,
00670                                       Info->bmiHeader.biBitCount);
00671         if(psurf->hSecure)
00672         {
00673             switch(Info->bmiHeader.biBitCount)
00674             {
00675             case 16:
00676             case 32:
00677                 Info->bmiHeader.biCompression = BI_BITFIELDS;
00678                 break;
00679             default:
00680                 Info->bmiHeader.biCompression = BI_RGB;
00681                 break;
00682             }
00683         }
00684         else if(Info->bmiHeader.biBitCount > 8)
00685         {
00686             Info->bmiHeader.biCompression = BI_BITFIELDS;
00687         }
00688         else
00689         {
00690             Info->bmiHeader.biCompression = BI_RGB;
00691         }
00692         Info->bmiHeader.biXPelsPerMeter = 0;
00693         Info->bmiHeader.biYPelsPerMeter = 0;
00694         Info->bmiHeader.biClrUsed = 0;
00695         Info->bmiHeader.biClrImportant = 0;
00696         ScanLines = abs(Info->bmiHeader.biHeight);
00697         goto done;
00698 
00699     case 1:
00700     case 4:
00701     case 8:
00702         Info->bmiHeader.biClrUsed = 0;
00703 
00704         /* If the bitmap if a DIB section and has the same format than what
00705          * we're asked, go ahead! */
00706         if((psurf->hSecure) &&
00707                 (BitsPerFormat(psurf->SurfObj.iBitmapFormat) == bpp))
00708         {
00709             if(Usage == DIB_RGB_COLORS)
00710             {
00711                 ULONG colors = min(psurf->ppal->NumColors, 256);
00712 
00713                 if(pbmci)
00714                 {
00715                     for(i = 0; i < colors; i++)
00716                     {
00717                         rgbTriples[i].rgbtRed = psurf->ppal->IndexedColors[i].peRed;
00718                         rgbTriples[i].rgbtGreen = psurf->ppal->IndexedColors[i].peGreen;
00719                         rgbTriples[i].rgbtBlue = psurf->ppal->IndexedColors[i].peBlue;
00720                     }
00721                 }
00722                 if(colors != 256) Info->bmiHeader.biClrUsed = colors;
00723                 for(i = 0; i < colors; i++)
00724                 {
00725                     rgbQuads[i].rgbRed = psurf->ppal->IndexedColors[i].peRed;
00726                     rgbQuads[i].rgbGreen = psurf->ppal->IndexedColors[i].peGreen;
00727                     rgbQuads[i].rgbBlue = psurf->ppal->IndexedColors[i].peBlue;
00728                 }
00729             }
00730             else
00731             {
00732                 for(i = 0; i < 256; i++)
00733                 {
00734                     if(pbmci) ((WORD*)rgbTriples)[i] = i;
00735                     ((WORD*)rgbQuads)[i] = i;
00736                 }
00737             }
00738         }
00739         else
00740         {
00741             if(Usage == DIB_PAL_COLORS)
00742             {
00743                 for(i = 0; i < 256; i++)
00744                 {
00745                     if(pbmci) ((WORD*)rgbTriples)[i] = i;
00746                     ((WORD*)rgbQuads)[i] = i;
00747                 }
00748             }
00749             else if(bpp > 1 && bpp == BitsPerFormat(psurf->SurfObj.iBitmapFormat))
00750             {
00751                 /* For color DDBs in native depth (mono DDBs always have
00752                    a black/white palette):
00753                    Generate the color map from the selected palette */
00754                 PPALETTE pDcPal = PALETTE_ShareLockPalette(pDC->dclevel.hpal);
00755                 if(!pDcPal)
00756                 {
00757                     ScanLines = 0 ;
00758                     goto done ;
00759                 }
00760                 for (i = 0; i < pDcPal->NumColors; i++)
00761                 {
00762                     if (pbmci)
00763                     {
00764                         rgbTriples[i].rgbtRed   = pDcPal->IndexedColors[i].peRed;
00765                         rgbTriples[i].rgbtGreen = pDcPal->IndexedColors[i].peGreen;
00766                         rgbTriples[i].rgbtBlue  = pDcPal->IndexedColors[i].peBlue;
00767                     }
00768 
00769                     rgbQuads[i].rgbRed      = pDcPal->IndexedColors[i].peRed;
00770                     rgbQuads[i].rgbGreen    = pDcPal->IndexedColors[i].peGreen;
00771                     rgbQuads[i].rgbBlue     = pDcPal->IndexedColors[i].peBlue;
00772                     rgbQuads[i].rgbReserved = 0;
00773                 }
00774                 PALETTE_ShareUnlockPalette(pDcPal);
00775             }
00776             else
00777             {
00778                 switch (bpp)
00779                 {
00780                 case 1:
00781                     if (pbmci)
00782                     {
00783                         rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen =
00784                                                     rgbTriples[0].rgbtBlue = 0;
00785                         rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen =
00786                                                     rgbTriples[1].rgbtBlue = 0xff;
00787                     }
00788                     rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen =
00789                                              rgbQuads[0].rgbBlue = 0;
00790                     rgbQuads[0].rgbReserved = 0;
00791                     rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen =
00792                                              rgbQuads[1].rgbBlue = 0xff;
00793                     rgbQuads[1].rgbReserved = 0;
00794                     break;
00795 
00796                 case 4:
00797                     if (pbmci)
00798                         RtlCopyMemory(rgbTriples, EGAColorsTriples, sizeof(EGAColorsTriples));
00799                     RtlCopyMemory(rgbQuads, EGAColorsQuads, sizeof(EGAColorsQuads));
00800 
00801                     break;
00802 
00803                 case 8:
00804                 {
00805                     INT r, g, b;
00806                     RGBQUAD *color;
00807                     if (pbmci)
00808                     {
00809                         RGBTRIPLE *colorTriple;
00810 
00811                         RtlCopyMemory(rgbTriples, DefLogPaletteTriples,
00812                                       10 * sizeof(RGBTRIPLE));
00813                         RtlCopyMemory(rgbTriples + 246, DefLogPaletteTriples + 10,
00814                                       10 * sizeof(RGBTRIPLE));
00815                         colorTriple = rgbTriples + 10;
00816                         for(r = 0; r <= 5; r++) /* FIXME */
00817                         {
00818                             for(g = 0; g <= 5; g++)
00819                             {
00820                                 for(b = 0; b <= 5; b++)
00821                                 {
00822                                     colorTriple->rgbtRed =   (r * 0xff) / 5;
00823                                     colorTriple->rgbtGreen = (g * 0xff) / 5;
00824                                     colorTriple->rgbtBlue =  (b * 0xff) / 5;
00825                                     color++;
00826                                 }
00827                             }
00828                         }
00829                     }
00830                     memcpy(rgbQuads, DefLogPaletteQuads,
00831                            10 * sizeof(RGBQUAD));
00832                     memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
00833                            10 * sizeof(RGBQUAD));
00834                     color = rgbQuads + 10;
00835                     for(r = 0; r <= 5; r++) /* FIXME */
00836                     {
00837                         for(g = 0; g <= 5; g++)
00838                         {
00839                             for(b = 0; b <= 5; b++)
00840                             {
00841                                 color->rgbRed =   (r * 0xff) / 5;
00842                                 color->rgbGreen = (g * 0xff) / 5;
00843                                 color->rgbBlue =  (b * 0xff) / 5;
00844                                 color->rgbReserved = 0;
00845                                 color++;
00846                             }
00847                         }
00848                     }
00849                 }
00850                 }
00851             }
00852         }
00853         break;
00854 
00855     case 15:
00856         if (Info->bmiHeader.biCompression == BI_BITFIELDS)
00857         {
00858             ((PDWORD)Info->bmiColors)[0] = 0x7c00;
00859             ((PDWORD)Info->bmiColors)[1] = 0x03e0;
00860             ((PDWORD)Info->bmiColors)[2] = 0x001f;
00861         }
00862         break;
00863 
00864     case 16:
00865         if (Info->bmiHeader.biCompression == BI_BITFIELDS)
00866         {
00867             if (psurf->hSecure)
00868             {
00869                 ((PDWORD)Info->bmiColors)[0] = psurf->ppal->RedMask;
00870                 ((PDWORD)Info->bmiColors)[1] = psurf->ppal->GreenMask;
00871                 ((PDWORD)Info->bmiColors)[2] = psurf->ppal->BlueMask;
00872             }
00873             else
00874             {
00875                 ((PDWORD)Info->bmiColors)[0] = 0xf800;
00876                 ((PDWORD)Info->bmiColors)[1] = 0x07e0;
00877                 ((PDWORD)Info->bmiColors)[2] = 0x001f;
00878             }
00879         }
00880         break;
00881 
00882     case 24:
00883     case 32:
00884         if (Info->bmiHeader.biCompression == BI_BITFIELDS)
00885         {
00886             if (psurf->hSecure)
00887             {
00888                 ((PDWORD)Info->bmiColors)[0] = psurf->ppal->RedMask;
00889                 ((PDWORD)Info->bmiColors)[1] = psurf->ppal->GreenMask;
00890                 ((PDWORD)Info->bmiColors)[2] = psurf->ppal->BlueMask;
00891             }
00892             else
00893             {
00894                 ((PDWORD)Info->bmiColors)[0] = 0xff0000;
00895                 ((PDWORD)Info->bmiColors)[1] = 0x00ff00;
00896                 ((PDWORD)Info->bmiColors)[2] = 0x0000ff;
00897             }
00898         }
00899         break;
00900     }
00901     Info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(width, height, bpp);
00902 
00903     if(Bits && ScanLines)
00904     {
00905         /* Create a DIBSECTION, blt it, profit */
00906         PVOID pDIBits ;
00907         HBITMAP hBmpDest;
00908         PSURFACE psurfDest;
00909         EXLATEOBJ exlo;
00910         RECT rcDest;
00911         POINTL srcPoint;
00912         BOOL ret ;
00913 
00914         if (StartScan > (ULONG)psurf->SurfObj.sizlBitmap.cy)
00915         {
00916             ScanLines = 0;
00917             goto done;
00918         }
00919         else
00920         {
00921             ScanLines = min(ScanLines, psurf->SurfObj.sizlBitmap.cy - StartScan);
00922         }
00923 
00924         /* Fixup values */
00925         Info->bmiHeader.biWidth = psurf->SurfObj.sizlBitmap.cx;
00926         Info->bmiHeader.biHeight = (height < 0) ?
00927                                    -(LONG)ScanLines : ScanLines;
00928         /* Create the DIB */
00929         hBmpDest = DIB_CreateDIBSection(pDC, Info, Usage, &pDIBits, NULL, 0, 0);
00930         /* Restore them */
00931         Info->bmiHeader.biWidth = width;
00932         Info->bmiHeader.biHeight = height;
00933 
00934         if(!hBmpDest)
00935         {
00936             DPRINT1("Unable to create a DIB Section!\n");
00937             EngSetLastError(ERROR_INVALID_PARAMETER);
00938             ScanLines = 0;
00939             goto done ;
00940         }
00941 
00942         psurfDest = SURFACE_ShareLockSurface(hBmpDest);
00943 
00944         rcDest.left = 0;
00945         rcDest.top = 0;
00946         rcDest.bottom = ScanLines;
00947         rcDest.right = psurf->SurfObj.sizlBitmap.cx;
00948 
00949         srcPoint.x = 0;
00950 
00951         if(height < 0)
00952         {
00953             srcPoint.y = 0;
00954 
00955             if(ScanLines <= StartScan)
00956             {
00957                 ScanLines = 1;
00958                 SURFACE_ShareUnlockSurface(psurfDest);
00959                 GreDeleteObject(hBmpDest);
00960                 goto done;
00961             }
00962 
00963             ScanLines -= StartScan;
00964         }
00965         else
00966         {
00967             srcPoint.y = StartScan;
00968         }
00969 
00970         EXLATEOBJ_vInitialize(&exlo, psurf->ppal, psurfDest->ppal, 0xffffff, 0xffffff, 0);
00971 
00972         ret = IntEngCopyBits(&psurfDest->SurfObj,
00973                              &psurf->SurfObj,
00974                              NULL,
00975                              &exlo.xlo,
00976                              &rcDest,
00977                              &srcPoint);
00978 
00979         SURFACE_ShareUnlockSurface(psurfDest);
00980 
00981         if(!ret)
00982             ScanLines = 0;
00983         else
00984         {
00985             Status = STATUS_SUCCESS;
00986             _SEH2_TRY
00987             {
00988                 RtlCopyMemory(Bits, pDIBits, DIB_GetDIBImageBytes (width, ScanLines, bpp));
00989             }
00990             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00991             {
00992                 Status = _SEH2_GetExceptionCode();
00993             }
00994             _SEH2_END
00995 
00996             if(!NT_SUCCESS(Status))
00997             {
00998                 DPRINT1("Unable to copy bits to the user provided pointer\n");
00999                 ScanLines = 0;
01000             }
01001         }
01002 
01003         GreDeleteObject(hBmpDest);
01004         EXLATEOBJ_vCleanup(&exlo);
01005     }
01006     else ScanLines = abs(height);
01007 
01008 done:
01009 
01010     if(pDC) DC_UnlockDc(pDC);
01011     if(psurf) SURFACE_ShareUnlockSurface(psurf);
01012     if(pbmci) DIB_FreeConvertedBitmapInfo(Info, (BITMAPINFO*)pbmci);
01013 
01014     return ScanLines;
01015 }
01016 
01017 #define ROP_TO_ROP4(Rop) ((Rop) >> 16)
01018 
01019 W32KAPI
01020 INT
01021 APIENTRY
01022 NtGdiStretchDIBitsInternal(
01023     IN HDC hdc,
01024     IN INT xDst,
01025     IN INT yDst,
01026     IN INT cxDst,
01027     IN INT cyDst,
01028     IN INT xSrc,
01029     IN INT ySrc,
01030     IN INT cxSrc,
01031     IN INT cySrc,
01032     IN OPTIONAL LPBYTE pjInit,
01033     IN LPBITMAPINFO pbmi,
01034     IN DWORD dwUsage,
01035     IN DWORD dwRop, // MS ntgdi.h says dwRop4(?)
01036     IN UINT cjMaxInfo,
01037     IN UINT cjMaxBits,
01038     IN HANDLE hcmXform)
01039 {
01040     BOOL bResult = FALSE;
01041     SIZEL sizel;
01042     RECTL rcSrc, rcDst;
01043     PDC pdc;
01044     HBITMAP hbmTmp = 0;
01045     PSURFACE psurfTmp = 0, psurfDst = 0;
01046     PPALETTE ppalDIB = 0;
01047     EXLATEOBJ exlo;
01048     PVOID pvBits;
01049 
01050     if (!(pdc = DC_LockDc(hdc)))
01051     {
01052         EngSetLastError(ERROR_INVALID_HANDLE);
01053         return 0;
01054     }
01055 
01056     /* Transform dest size */
01057     sizel.cx = cxDst;
01058     sizel.cy = cyDst;
01059     IntLPtoDP(pdc, (POINTL*)&sizel, 1);
01060     DC_UnlockDc(pdc);
01061 
01062     /* Check if we can use NtGdiSetDIBitsToDeviceInternal */
01063     if (sizel.cx == cxSrc && sizel.cy == cySrc && dwRop == SRCCOPY)
01064     {
01065         /* Yes, we can! */
01066         return NtGdiSetDIBitsToDeviceInternal(hdc,
01067                                               xDst,
01068                                               yDst,
01069                                               cxDst,
01070                                               cyDst,
01071                                               xSrc,
01072                                               ySrc,
01073                                               0,
01074                                               cySrc,
01075                                               pjInit,
01076                                               pbmi,
01077                                               dwUsage,
01078                                               cjMaxBits,
01079                                               cjMaxInfo,
01080                                               TRUE,
01081                                               hcmXform);
01082     }
01083 
01084     pvBits = ExAllocatePoolWithTag(PagedPool, cjMaxBits, 'pmeT');
01085     if (!pvBits)
01086     {
01087         return 0;
01088     }
01089 
01090     _SEH2_TRY
01091     {
01092         ProbeForRead(pjInit, cjMaxBits, 1);
01093         RtlCopyMemory(pvBits, pjInit, cjMaxBits);
01094     }
01095     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
01096     {
01097         _SEH2_YIELD(return 0);
01098     }
01099     _SEH2_END
01100 
01101     /* FIXME: Locking twice is cheesy, coord tranlation in UM will fix it */
01102     if (!(pdc = DC_LockDc(hdc)))
01103     {
01104         DPRINT1("Could not lock dc\n");
01105         EngSetLastError(ERROR_INVALID_HANDLE);
01106         goto cleanup;
01107     }
01108 
01109     psurfDst = pdc->dclevel.pSurface;
01110     if (!psurfDst)
01111     {
01112         // CHECKME
01113         bResult = TRUE;
01114         goto cleanup;
01115     }
01116 
01117     /* Calculate source and destination rect */
01118     rcSrc.left = xSrc;
01119     rcSrc.top = ySrc;
01120     rcSrc.right = xSrc + abs(cxSrc);
01121     rcSrc.bottom = ySrc + abs(cySrc);
01122     rcDst.left = xDst;
01123     rcDst.top = yDst;
01124     rcDst.right = rcDst.left + cxDst;
01125     rcDst.bottom = rcDst.top + cyDst;
01126     IntLPtoDP(pdc, (POINTL*)&rcDst, 2);
01127     RECTL_vOffsetRect(&rcDst, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y);
01128 
01129     hbmTmp = GreCreateBitmapEx(pbmi->bmiHeader.biWidth,
01130                                pbmi->bmiHeader.biHeight,
01131                                0,
01132                                BitmapFormat(pbmi->bmiHeader.biBitCount,
01133                                             pbmi->bmiHeader.biCompression),
01134                                pbmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
01135                                pbmi->bmiHeader.biSizeImage,
01136                                pvBits,
01137                                0);
01138 
01139     if (!hbmTmp)
01140     {
01141         bResult = FALSE;
01142         goto cleanup;
01143     }
01144 
01145     psurfTmp = SURFACE_ShareLockSurface(hbmTmp);
01146     if (!psurfTmp)
01147     {
01148         bResult = FALSE;
01149         goto cleanup;
01150     }
01151 
01152     /* Create a palette for the DIB */
01153     ppalDIB = CreateDIBPalette(pbmi, pdc, dwUsage);
01154     if (!ppalDIB)
01155     {
01156         bResult = FALSE;
01157         goto cleanup;
01158     }
01159 
01160     /* Initialize XLATEOBJ */
01161     EXLATEOBJ_vInitialize(&exlo,
01162                           ppalDIB,
01163                           psurfDst->ppal,
01164                           RGB(0xff, 0xff, 0xff),
01165                           pdc->pdcattr->crBackgroundClr,
01166                           pdc->pdcattr->crForegroundClr);
01167 
01168     /* Prepare DC for blit */
01169     DC_vPrepareDCsForBlit(pdc, rcDst, NULL, rcSrc);
01170 
01171     /* Perform the stretch operation */
01172     bResult = IntEngStretchBlt(&psurfDst->SurfObj,
01173                                &psurfTmp->SurfObj,
01174                                NULL,
01175                                pdc->rosdc.CombinedClip,
01176                                &exlo.xlo,
01177                                &rcDst,
01178                                &rcSrc,
01179                                NULL,
01180                                &pdc->eboFill.BrushObject,
01181                                NULL,
01182                                ROP_TO_ROP4(dwRop));
01183 
01184     /* Cleanup */
01185     DC_vFinishBlit(pdc, NULL);
01186     EXLATEOBJ_vCleanup(&exlo);
01187 cleanup:
01188     if (ppalDIB) PALETTE_ShareUnlockPalette(ppalDIB);
01189     if (psurfTmp) SURFACE_ShareUnlockSurface(psurfTmp);
01190     if (hbmTmp) GreDeleteObject(hbmTmp);
01191     if (pdc) DC_UnlockDc(pdc);
01192     ExFreePoolWithTag(pvBits, 'pmeT');
01193 
01194     return bResult;
01195 }
01196 
01197 
01198 HBITMAP
01199 FASTCALL
01200 IntCreateDIBitmap(
01201     PDC Dc,
01202     INT width,
01203     INT height,
01204     UINT bpp,
01205     DWORD init,
01206     LPBYTE bits,
01207     PBITMAPINFO data,
01208     DWORD coloruse)
01209 {
01210     HBITMAP handle;
01211     BOOL fColor;
01212 
01213     // Check if we should create a monochrome or color bitmap. We create a monochrome bitmap only if it has exactly 2
01214     // colors, which are black followed by white, nothing else. In all other cases, we create a color bitmap.
01215 
01216     if (bpp != 1) fColor = TRUE;
01217     else if ((coloruse != DIB_RGB_COLORS) || (init != CBM_INIT) || !data) fColor = FALSE;
01218     else
01219     {
01220         const RGBQUAD *rgb = (RGBQUAD*)((PBYTE)data + data->bmiHeader.biSize);
01221         DWORD col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
01222 
01223         // Check if the first color of the colormap is black
01224         if ((col == RGB(0, 0, 0)))
01225         {
01226             rgb++;
01227             col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
01228 
01229             // If the second color is white, create a monochrome bitmap
01230             fColor = (col != RGB(0xff,0xff,0xff));
01231         }
01232         else fColor = TRUE;
01233     }
01234 
01235     // Now create the bitmap
01236     if (fColor)
01237     {
01238         handle = IntCreateCompatibleBitmap(Dc, width, height);
01239     }
01240     else
01241     {
01242         handle = GreCreateBitmap(width,
01243                                  height,
01244                                  1,
01245                                  1,
01246                                  NULL);
01247     }
01248 
01249     if (height < 0)
01250         height = -height;
01251 
01252     if (NULL != handle && CBM_INIT == init)
01253     {
01254         IntSetDIBits(Dc, handle, 0, height, bits, data, coloruse);
01255     }
01256 
01257     return handle;
01258 }
01259 
01260 // The CreateDIBitmap function creates a device-dependent bitmap (DDB) from a DIB and, optionally, sets the bitmap bits
01261 // The DDB that is created will be whatever bit depth your reference DC is
01262 HBITMAP
01263 APIENTRY
01264 NtGdiCreateDIBitmapInternal(
01265     IN HDC hDc,
01266     IN INT cx,
01267     IN INT cy,
01268     IN DWORD fInit,
01269     IN OPTIONAL LPBYTE pjInit,
01270     IN OPTIONAL LPBITMAPINFO pbmi,
01271     IN DWORD iUsage,
01272     IN UINT cjMaxInitInfo,
01273     IN UINT cjMaxBits,
01274     IN FLONG fl,
01275     IN HANDLE hcmXform)
01276 {
01277     NTSTATUS Status = STATUS_SUCCESS;
01278     PBYTE safeBits = NULL;
01279     HBITMAP hbmResult = NULL;
01280 
01281     if(pjInit && (fInit == CBM_INIT))
01282     {
01283         if (cjMaxBits == 0) return NULL;
01284         safeBits = ExAllocatePoolWithTag(PagedPool, cjMaxBits, TAG_DIB);
01285         if(!safeBits)
01286         {
01287             EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
01288             return NULL;
01289         }
01290     }
01291 
01292     _SEH2_TRY
01293     {
01294         if(pbmi) ProbeForRead(pbmi, cjMaxInitInfo, 1);
01295         if(pjInit && (fInit == CBM_INIT))
01296         {
01297             ProbeForRead(pjInit, cjMaxBits, 1);
01298             RtlCopyMemory(safeBits, pjInit, cjMaxBits);
01299         }
01300     }
01301     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
01302     {
01303         Status = _SEH2_GetExceptionCode();
01304     }
01305     _SEH2_END
01306 
01307     if(!NT_SUCCESS(Status))
01308     {
01309         SetLastNtError(Status);
01310         goto cleanup;
01311     }
01312 
01313     hbmResult =  GreCreateDIBitmapInternal(hDc,
01314                                            cx,
01315                                            cy,
01316                                            fInit,
01317                                            safeBits,
01318                                            pbmi,
01319                                            iUsage,
01320                                            fl,
01321                                            cjMaxBits,
01322                                            hcmXform);
01323 
01324 cleanup:
01325     if (safeBits) ExFreePoolWithTag(safeBits, TAG_DIB);
01326     return hbmResult;
01327 }
01328 
01329 HBITMAP
01330 NTAPI
01331 GreCreateDIBitmapInternal(
01332     IN HDC hDc,
01333     IN INT cx,
01334     IN INT cy,
01335     IN DWORD fInit,
01336     IN OPTIONAL LPBYTE pjInit,
01337     IN OPTIONAL PBITMAPINFO pbmi,
01338     IN DWORD iUsage,
01339     IN FLONG fl,
01340     IN UINT cjMaxBits,
01341     IN HANDLE hcmXform)
01342 {
01343     PDC Dc;
01344     HBITMAP Bmp;
01345     WORD bpp;
01346     HDC hdcDest;
01347 
01348     if (!hDc) /* 1bpp monochrome bitmap */
01349     {
01350         // Should use System Bitmap DC hSystemBM, with CreateCompatibleDC for this.
01351         hdcDest = NtGdiCreateCompatibleDC(0);
01352         if(!hdcDest)
01353         {
01354             return NULL;
01355         }
01356     }
01357     else
01358     {
01359         hdcDest = hDc;
01360     }
01361 
01362     Dc = DC_LockDc(hdcDest);
01363     if (!Dc)
01364     {
01365         EngSetLastError(ERROR_INVALID_HANDLE);
01366         return NULL;
01367     }
01368     /* It's OK to set bpp=0 here, as IntCreateDIBitmap will create a compatible Bitmap
01369      * if bpp != 1 and ignore the real value that was passed */
01370     if (pbmi)
01371         bpp = pbmi->bmiHeader.biBitCount;
01372     else
01373         bpp = 0;
01374     Bmp = IntCreateDIBitmap(Dc, cx, cy, bpp, fInit, pjInit, pbmi, iUsage);
01375     DC_UnlockDc(Dc);
01376 
01377     if(!hDc)
01378     {
01379         NtGdiDeleteObjectApp(hdcDest);
01380     }
01381     return Bmp;
01382 }
01383 
01384 
01385 HBITMAP
01386 APIENTRY
01387 NtGdiCreateDIBSection(
01388     IN HDC hDC,
01389     IN OPTIONAL HANDLE hSection,
01390     IN DWORD dwOffset,
01391     IN BITMAPINFO* bmi,
01392     IN DWORD Usage,
01393     IN UINT cjHeader,
01394     IN FLONG fl,
01395     IN ULONG_PTR dwColorSpace,
01396     OUT PVOID *Bits)
01397 {
01398     HBITMAP hbitmap = 0;
01399     DC *dc;
01400     BOOL bDesktopDC = FALSE;
01401     NTSTATUS Status = STATUS_SUCCESS;
01402 
01403     if (!bmi) return hbitmap; // Make sure.
01404 
01405     _SEH2_TRY
01406     {
01407         ProbeForRead(&bmi->bmiHeader.biSize, sizeof(DWORD), 1);
01408         ProbeForRead(bmi, bmi->bmiHeader.biSize, 1);
01409         ProbeForRead(bmi, DIB_BitmapInfoSize(bmi, (WORD)Usage), 1);
01410     }
01411     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
01412     {
01413         Status = _SEH2_GetExceptionCode();
01414     }
01415     _SEH2_END
01416 
01417     if(!NT_SUCCESS(Status))
01418     {
01419         SetLastNtError(Status);
01420         return NULL;
01421     }
01422 
01423     // If the reference hdc is null, take the desktop dc
01424     if (hDC == 0)
01425     {
01426         hDC = NtGdiCreateCompatibleDC(0);
01427         bDesktopDC = TRUE;
01428     }
01429 
01430     if ((dc = DC_LockDc(hDC)))
01431     {
01432         hbitmap = DIB_CreateDIBSection(dc,
01433                                        bmi,
01434                                        Usage,
01435                                        Bits,
01436                                        hSection,
01437                                        dwOffset,
01438                                        0);
01439         DC_UnlockDc(dc);
01440     }
01441     else
01442     {
01443         EngSetLastError(ERROR_INVALID_HANDLE);
01444     }
01445 
01446     if (bDesktopDC)
01447         NtGdiDeleteObjectApp(hDC);
01448 
01449     return hbitmap;
01450 }
01451 
01452 HBITMAP
01453 APIENTRY
01454 DIB_CreateDIBSection(
01455     PDC dc,
01456     CONST BITMAPINFO *bmi,
01457     UINT usage,
01458     LPVOID *bits,
01459     HANDLE section,
01460     DWORD offset,
01461     DWORD ovr_pitch)
01462 {
01463     HBITMAP res = 0;
01464     SURFACE *bmp = NULL;
01465     void *mapBits = NULL;
01466     PPALETTE ppalDIB;
01467 
01468     // Fill BITMAP32 structure with DIB data
01469     CONST BITMAPINFOHEADER *bi = &bmi->bmiHeader;
01470     INT effHeight;
01471     ULONG totalSize;
01472     BITMAP bm;
01473     //SIZEL Size;
01474     HANDLE hSecure;
01475 
01476     DPRINT("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
01477            bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
01478            bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
01479 
01480     /* CreateDIBSection should fail for compressed formats */
01481     if (bi->biCompression == BI_RLE4 || bi->biCompression == BI_RLE8)
01482     {
01483         DPRINT1("no compressed format allowed\n");
01484         return (HBITMAP)NULL;
01485     }
01486 
01487     effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
01488     bm.bmType = 0;
01489     bm.bmWidth = bi->biWidth;
01490     bm.bmHeight = effHeight;
01491     bm.bmWidthBytes = ovr_pitch ? ovr_pitch : WIDTH_BYTES_ALIGN32(bm.bmWidth, bi->biBitCount);
01492 
01493     bm.bmPlanes = bi->biPlanes;
01494     bm.bmBitsPixel = bi->biBitCount;
01495     bm.bmBits = NULL;
01496 
01497     // Get storage location for DIB bits.  Only use biSizeImage if it's valid and
01498     // we're dealing with a compressed bitmap.  Otherwise, use width * height.
01499     totalSize = bi->biSizeImage && bi->biCompression != BI_RGB && bi->biCompression != BI_BITFIELDS
01500                 ? bi->biSizeImage : (ULONG)(bm.bmWidthBytes * effHeight);
01501 
01502     if (section)
01503     {
01504         SYSTEM_BASIC_INFORMATION Sbi;
01505         NTSTATUS Status;
01506         DWORD mapOffset;
01507         LARGE_INTEGER SectionOffset;
01508         SIZE_T mapSize;
01509 
01510         Status = ZwQuerySystemInformation(SystemBasicInformation,
01511                                           &Sbi,
01512                                           sizeof Sbi,
01513                                           0);
01514         if (!NT_SUCCESS(Status))
01515         {
01516             DPRINT1("ZwQuerySystemInformation failed (0x%lx)\n", Status);
01517             return NULL;
01518         }
01519 
01520         mapOffset = offset - (offset % Sbi.AllocationGranularity);
01521         mapSize = bi->biSizeImage + (offset - mapOffset);
01522 
01523         SectionOffset.LowPart  = mapOffset;
01524         SectionOffset.HighPart = 0;
01525 
01526         Status = ZwMapViewOfSection(section,
01527                                     NtCurrentProcess(),
01528                                     &mapBits,
01529                                     0,
01530                                     0,
01531                                     &SectionOffset,
01532                                     &mapSize,
01533                                     ViewShare,
01534                                     0,
01535                                     PAGE_READWRITE);
01536         if (!NT_SUCCESS(Status))
01537         {
01538             DPRINT1("ZwMapViewOfSection failed (0x%lx)\n", Status);
01539             EngSetLastError(ERROR_INVALID_PARAMETER);
01540             return NULL;
01541         }
01542 
01543         if (mapBits) bm.bmBits = (char *)mapBits + (offset - mapOffset);
01544     }
01545     else if (ovr_pitch && offset)
01546         bm.bmBits = (LPVOID) offset;
01547     else
01548     {
01549         offset = 0;
01550         bm.bmBits = EngAllocUserMem(totalSize, 0);
01551         if(!bm.bmBits)
01552         {
01553             DPRINT1("Failed to allocate memory\n");
01554             goto cleanup;
01555         }
01556     }
01557 
01558 //  hSecure = MmSecureVirtualMemory(bm.bmBits, totalSize, PAGE_READWRITE);
01559     hSecure = (HANDLE)0x1; // HACK OF UNIMPLEMENTED KERNEL STUFF !!!!
01560 
01561 
01562     // Create Device Dependent Bitmap and add DIB pointer
01563     //Size.cx = bm.bmWidth;
01564     //Size.cy = abs(bm.bmHeight);
01565     res = GreCreateBitmapEx(bm.bmWidth,
01566                             abs(bm.bmHeight),
01567                             bm.bmWidthBytes,
01568                             BitmapFormat(bi->biBitCount * bi->biPlanes, bi->biCompression),
01569                             BMF_DONTCACHE | BMF_USERMEM | BMF_NOZEROINIT |
01570                             ((bi->biHeight < 0) ? BMF_TOPDOWN : 0),
01571                             bi->biSizeImage,
01572                             bm.bmBits,
01573                             0);
01574     if (!res)
01575     {
01576         DPRINT1("GreCreateBitmapEx failed\n");
01577         EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
01578         goto cleanup;
01579     }
01580     bmp = SURFACE_ShareLockSurface(res); // HACK
01581     if (NULL == bmp)
01582     {
01583         DPRINT1("SURFACE_LockSurface failed\n");
01584         EngSetLastError(ERROR_INVALID_HANDLE);
01585         goto cleanup;
01586     }
01587 
01588     /* WINE NOTE: WINE makes use of a colormap, which is a color translation
01589                   table between the DIB and the X physical device. Obviously,
01590                   this is left out of the ReactOS implementation. Instead,
01591                   we call NtGdiSetDIBColorTable. */
01592     bmp->hDIBSection = section;
01593     bmp->hSecure = hSecure;
01594     bmp->dwOffset = offset;
01595     bmp->flags = API_BITMAP;
01596     bmp->biClrImportant = bi->biClrImportant;
01597 
01598     /* Create a palette for the DIB */
01599     ppalDIB = CreateDIBPalette(bmi, dc, usage);
01600     if (ppalDIB)
01601     {
01602         if (bmp->ppal) PALETTE_ShareUnlockPalette(bmp->ppal);
01603         bmp->ppal = ppalDIB;
01604     }
01605 
01606     // Clean up in case of errors
01607 cleanup:
01608     if (!res || !bmp || !bm.bmBits)
01609     {
01610         DPRINT("Got an error res=%08x, bmp=%p, bm.bmBits=%p\n", res, bmp, bm.bmBits);
01611         if (bm.bmBits)
01612         {
01613             // MmUnsecureVirtualMemory(hSecure); // FIXME: Implement this!
01614             if (section)
01615             {
01616                 ZwUnmapViewOfSection(NtCurrentProcess(), mapBits);
01617                 bm.bmBits = NULL;
01618             }
01619             else if (!offset)
01620                 EngFreeUserMem(bm.bmBits), bm.bmBits = NULL;
01621         }
01622 
01623         if (bmp)
01624             bmp = NULL;
01625 
01626         if (res)
01627         {
01628             GreDeleteObject(res);
01629             res = 0;
01630         }
01631     }
01632 
01633     if (bmp)
01634     {
01635         SURFACE_ShareUnlockSurface(bmp);
01636     }
01637 
01638     // Return BITMAP handle and storage location
01639     if (NULL != bm.bmBits && NULL != bits)
01640     {
01641         *bits = bm.bmBits;
01642     }
01643 
01644     return res;
01645 }
01646 
01647 /***********************************************************************
01648  *           DIB_GetBitmapInfo
01649  *
01650  * Get the info from a bitmap header.
01651  * Return 0 for COREHEADER, 1 for INFOHEADER, -1 for error.
01652  */
01653 int
01654 FASTCALL
01655 DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
01656                    LONG *height, WORD *planes, WORD *bpp, DWORD *compr, DWORD *size )
01657 {
01658     if (header->biSize == sizeof(BITMAPCOREHEADER))
01659     {
01660         const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header;
01661         *width  = core->bcWidth;
01662         *height = core->bcHeight;
01663         *planes = core->bcPlanes;
01664         *bpp    = core->bcBitCount;
01665         *compr  = BI_RGB;
01666         *size   = 0;
01667         return 0;
01668     }
01669     if (header->biSize >= sizeof(BITMAPINFOHEADER)) /* Assume BITMAPINFOHEADER */
01670     {
01671         *width  = header->biWidth;
01672         *height = header->biHeight;
01673         *planes = header->biPlanes;
01674         *bpp    = header->biBitCount;
01675         *compr  = header->biCompression;
01676         *size   = header->biSizeImage;
01677         return 1;
01678     }
01679     DPRINT1("(%d): unknown/wrong size for header\n", header->biSize );
01680     return -1;
01681 }
01682 
01683 /***********************************************************************
01684  *           DIB_GetDIBImageBytes
01685  *
01686  * Return the number of bytes used to hold the image in a DIB bitmap.
01687  * 11/16/1999 (RJJ) lifted from wine
01688  */
01689 
01690 INT APIENTRY DIB_GetDIBImageBytes(INT  width, INT height, INT depth)
01691 {
01692     return WIDTH_BYTES_ALIGN32(width, depth) * (height < 0 ? -height : height);
01693 }
01694 
01695 /***********************************************************************
01696  *           DIB_BitmapInfoSize
01697  *
01698  * Return the size of the bitmap info structure including color table.
01699  * 11/16/1999 (RJJ) lifted from wine
01700  */
01701 
01702 INT FASTCALL DIB_BitmapInfoSize(const BITMAPINFO * info, WORD coloruse)
01703 {
01704     unsigned int colors, size, masks = 0;
01705 
01706     if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
01707     {
01708         const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
01709         colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
01710         return sizeof(BITMAPCOREHEADER) + colors *
01711                ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
01712     }
01713     else  /* Assume BITMAPINFOHEADER */
01714     {
01715         colors = info->bmiHeader.biClrUsed;
01716         if (colors > 256) colors = 256;
01717         if (!colors && (info->bmiHeader.biBitCount <= 8))
01718             colors = 1 << info->bmiHeader.biBitCount;
01719         if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
01720         size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
01721         return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
01722     }
01723 }
01724 
01725 HPALETTE
01726 FASTCALL
01727 DIB_MapPaletteColors(PPALETTE ppalDc, CONST BITMAPINFO* lpbmi)
01728 {
01729     PPALETTE ppalNew;
01730     ULONG nNumColors,i;
01731     USHORT *lpIndex;
01732     HPALETTE hpal;
01733 
01734     if (!(ppalDc->flFlags & PAL_INDEXED))
01735     {
01736         return NULL;
01737     }
01738 
01739     nNumColors = 1 << lpbmi->bmiHeader.biBitCount;
01740     if (lpbmi->bmiHeader.biClrUsed)
01741     {
01742         nNumColors = min(nNumColors, lpbmi->bmiHeader.biClrUsed);
01743     }
01744 
01745     ppalNew = PALETTE_AllocPalWithHandle(PAL_INDEXED, nNumColors, NULL, 0, 0, 0);
01746     if (ppalNew == NULL)
01747     {
01748         DPRINT1("Could not allocate palette\n");
01749         return NULL;
01750     }
01751 
01752     lpIndex = (USHORT *)((PBYTE)lpbmi + lpbmi->bmiHeader.biSize);
01753 
01754     for (i = 0; i < nNumColors; i++)
01755     {
01756         ULONG iColorIndex = *lpIndex % ppalDc->NumColors;
01757         ppalNew->IndexedColors[i] = ppalDc->IndexedColors[iColorIndex];
01758         lpIndex++;
01759     }
01760 
01761     hpal = ppalNew->BaseObject.hHmgr;
01762     PALETTE_UnlockPalette(ppalNew);
01763 
01764     return hpal;
01765 }
01766 
01767 /* Converts a BITMAPCOREINFO to a BITMAPINFO structure,
01768  * or does nothing if it's already a BITMAPINFO (or V4 or V5) */
01769 BITMAPINFO*
01770 FASTCALL
01771 DIB_ConvertBitmapInfo (CONST BITMAPINFO* pbmi, DWORD Usage)
01772 {
01773     CONST BITMAPCOREINFO* pbmci = (BITMAPCOREINFO*)pbmi;
01774     BITMAPINFO* pNewBmi ;
01775     UINT numColors = 0, ColorsSize = 0;
01776 
01777     if(pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) return (BITMAPINFO*)pbmi;
01778     if(pbmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) return NULL;
01779 
01780     if(pbmci->bmciHeader.bcBitCount <= 8)
01781     {
01782         numColors = 1 << pbmci->bmciHeader.bcBitCount;
01783         if(Usage == DIB_PAL_COLORS)
01784         {
01785             ColorsSize = numColors * sizeof(WORD);
01786         }
01787         else
01788         {
01789             ColorsSize = numColors * sizeof(RGBQUAD);
01790         }
01791     }
01792     else if (Usage == DIB_PAL_COLORS)
01793     {
01794         /* Invalid at high-res */
01795         return NULL;
01796     }
01797 
01798     pNewBmi = ExAllocatePoolWithTag(PagedPool, sizeof(BITMAPINFOHEADER) + ColorsSize, TAG_DIB);
01799     if(!pNewBmi) return NULL;
01800 
01801     RtlZeroMemory(pNewBmi, sizeof(BITMAPINFOHEADER) + ColorsSize);
01802 
01803     pNewBmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
01804     pNewBmi->bmiHeader.biBitCount = pbmci->bmciHeader.bcBitCount;
01805     pNewBmi->bmiHeader.biWidth = pbmci->bmciHeader.bcWidth;
01806     pNewBmi->bmiHeader.biHeight = pbmci->bmciHeader.bcHeight;
01807     pNewBmi->bmiHeader.biPlanes = pbmci->bmciHeader.bcPlanes;
01808     pNewBmi->bmiHeader.biCompression = BI_RGB ;
01809     pNewBmi->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(pNewBmi->bmiHeader.biWidth,
01810                                      pNewBmi->bmiHeader.biHeight,
01811                                      pNewBmi->bmiHeader.biBitCount);
01812 
01813     if(Usage == DIB_PAL_COLORS)
01814     {
01815         RtlCopyMemory(pNewBmi->bmiColors, pbmci->bmciColors, ColorsSize);
01816     }
01817     else
01818     {
01819         UINT i;
01820         for(i=0; i<numColors; i++)
01821         {
01822             pNewBmi->bmiColors[i].rgbRed = pbmci->bmciColors[i].rgbtRed;
01823             pNewBmi->bmiColors[i].rgbGreen = pbmci->bmciColors[i].rgbtGreen;
01824             pNewBmi->bmiColors[i].rgbBlue = pbmci->bmciColors[i].rgbtBlue;
01825         }
01826     }
01827 
01828     return pNewBmi ;
01829 }
01830 
01831 /* Frees a BITMAPINFO created with DIB_ConvertBitmapInfo */
01832 VOID
01833 FASTCALL
01834 DIB_FreeConvertedBitmapInfo(BITMAPINFO* converted, BITMAPINFO* orig)
01835 {
01836     if(converted != orig)
01837         ExFreePoolWithTag(converted, TAG_DIB);
01838 }
01839 
01840 /* EOF */

Generated on Sun May 27 2012 04:38:25 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.