Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1048 lines
29 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: surfgdi.cxx
  3. *
  4. * This file contains the bitmap creation functions
  5. *
  6. * Created: 14-Jun-1991 17:05:47
  7. * Author: Patrick Haluptzok patrickh
  8. *
  9. * Copyright (c) 1990-1999 Microsoft Corporation
  10. \**************************************************************************/
  11. #include "precomp.hxx"
  12. BOOL bDoGetSetBitmapBits(SURFOBJ *, SURFOBJ *, BOOL);
  13. /******************************Public*Routine******************************\
  14. * HBITMAP GreCreateBitmap
  15. *
  16. * API Entry point to create a bitmap.
  17. *
  18. * Returns: Handle to bitmap for success
  19. *
  20. * History:
  21. * Wed 23-Jan-1991 -by- Patrick Haluptzok [patrickh]
  22. * Wrote it.
  23. \**************************************************************************/
  24. HBITMAP APIENTRY GreCreateBitmap(
  25. int cx,
  26. int cy,
  27. UINT cPlanes,
  28. UINT cBits,
  29. LPBYTE pvBits
  30. )
  31. {
  32. //
  33. // Try to guess what format the user wanted. We will always guarantee
  34. // enough space in the bitmap for the info. Note that if either cPlanes
  35. // or cBits is zero, a monochrome bitmap will be created.
  36. //
  37. ULONG iFormat = cPlanes * cBits;
  38. //
  39. // Validate the width, height, planes, and bits
  40. //
  41. if ((cx <= 0) ||
  42. (cx > MAX_SURF_WIDTH) ||
  43. (cy <= 0) ||
  44. (cPlanes > 32) ||
  45. (cBits > 32) ||
  46. (iFormat > 32))
  47. {
  48. WARNING("GreCreateBitmap failed - parameter too big");
  49. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  50. return((HBITMAP) 0);
  51. }
  52. ULONG cjScanBytes = (((((ULONG) cx * iFormat) + 15) >> 4) << 1);
  53. ULONGLONG cjTotal = (ULONGLONG) cjScanBytes * (ULONGLONG) cy;
  54. // BUGFIX #172774 12-12-2000 bhouse
  55. //
  56. // NOTE: Is there a better way to detect overflow then to use ULONGLONG?
  57. // I vaguely recall that if for unsigned values r = a * b
  58. // then an overflow occured if either r < a || r < b
  59. if(cjTotal > ULONG_MAX)
  60. {
  61. WARNING("GreCreateBitmap failed - size too big");
  62. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  63. return((HBITMAP) 0);
  64. }
  65. //
  66. // This if-else loop can be simplified and made smaller but until we get
  67. // this right let's leave it like this so it's easy to change.
  68. //
  69. DEVBITMAPINFO dbmi;
  70. dbmi.cxBitmap = cx;
  71. dbmi.cyBitmap = cy;
  72. dbmi.hpal = (HPALETTE) 0;
  73. dbmi.fl = BMF_TOPDOWN;
  74. if (iFormat <= 1)
  75. {
  76. //
  77. // A monochrome bitmap has a fixed palette. The 0 (black) is always
  78. // mapped to foreground, the 1 is always mapped to background (white).
  79. //
  80. iFormat = BMF_1BPP;
  81. dbmi.hpal = hpalMono;
  82. }
  83. else if (iFormat <= 4)
  84. {
  85. iFormat = BMF_4BPP;
  86. }
  87. else if (iFormat <= 8)
  88. {
  89. iFormat = BMF_8BPP;
  90. }
  91. else if (iFormat <= 16)
  92. {
  93. iFormat = BMF_16BPP;
  94. }
  95. else if (iFormat <= 24)
  96. {
  97. iFormat = BMF_24BPP;
  98. }
  99. else if (iFormat <= 32)
  100. {
  101. iFormat = BMF_32BPP;
  102. }
  103. else
  104. {
  105. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  106. return((HBITMAP) 0);
  107. }
  108. dbmi.iFormat = iFormat;
  109. SURFMEM SurfDimo;
  110. SurfDimo.bCreateDIB(&dbmi, NULL);
  111. if (!SurfDimo.bValid())
  112. {
  113. WARNING("Failed surface memory alloc in GreCreateBitmap\n");
  114. return((HBITMAP) 0);
  115. }
  116. SurfDimo.ps->vSetApiBitmap();
  117. if (pvBits != (LPBYTE) NULL)
  118. {
  119. //
  120. // Initialize the bitmap.
  121. //
  122. ULONG cColors;
  123. cColors = 0;
  124. GreSetBitmapBits((HBITMAP)SurfDimo.ps->hsurf(), (ULONG) cjTotal,
  125. (PBYTE) pvBits, (LONG *) &cColors);
  126. }
  127. //
  128. // Monochrome bitmaps are not considered to be DDBs:
  129. //
  130. if (iFormat != BMF_1BPP)
  131. {
  132. SurfDimo.ps->vSetDeviceDependentBitmap();
  133. }
  134. SurfDimo.vKeepIt();
  135. GreSetBitmapOwner((HBITMAP) SurfDimo.ps->hsurf(), OBJECT_OWNER_CURRENT);
  136. return((HBITMAP) SurfDimo.ps->hsurf());
  137. }
  138. /******************************Public*Routine******************************\
  139. * HSURF hsurfCreateCompatibleSurface(hdev,cx,cy,bDriver)
  140. *
  141. * Low-level GDI interface for creating a compatible surface, possibly
  142. * hooked by the driver.
  143. *
  144. \**************************************************************************/
  145. HSURF hsurfCreateCompatibleSurface(
  146. HDEV hdev,
  147. ULONG iFormat,
  148. HPALETTE hpal,
  149. int cx,
  150. int cy,
  151. BOOL bDriverCreatible
  152. )
  153. {
  154. PDEVOBJ po(hdev);
  155. po.vAssertDevLock();
  156. //
  157. // Fill in the desired bitmap properties
  158. //
  159. DEVBITMAPINFO dbmi;
  160. dbmi.cxBitmap = cx;
  161. dbmi.cyBitmap = cy;
  162. dbmi.hpal = hpal;
  163. dbmi.iFormat = iFormat;
  164. dbmi.fl = BMF_TOPDOWN;
  165. if (po.bUMPD())
  166. {
  167. dbmi.fl |= UMPD_SURFACE;
  168. }
  169. //
  170. // See if the device driver will manage the bitmap.
  171. //
  172. if ((bDriverCreatible) &&
  173. (PPFNVALID(po,CreateDeviceBitmap)))
  174. {
  175. //
  176. // Ok the device exports the entry point. Let's call him up.
  177. //
  178. HSURF hsurf;
  179. SIZEL sizlTemp;
  180. sizlTemp.cx = cx;
  181. sizlTemp.cy = cy;
  182. hsurf = (HSURF) (*PPFNDRV(po,CreateDeviceBitmap))(po.dhpdev(),
  183. sizlTemp,
  184. dbmi.iFormat);
  185. if (hsurf && (LongToHandle(HandleToLong(hsurf)) != (HANDLE)-1))
  186. {
  187. SURFREF so(hsurf);
  188. ASSERTGDI(so.bValid(), "ERROR device gave back invalid handle");
  189. //
  190. // Device Format Bitmaps (DFBs) are a subset of Device
  191. // Depdendent Bitmaps (DDBs):
  192. //
  193. so.ps->vSetDeviceDependentBitmap();
  194. so.ps->vSetApiBitmap();
  195. //
  196. // DFBs must always be accessed under the devlock, in part
  197. // because they have to be deleted and recreated when a
  198. // dynamic mode change occurs.
  199. //
  200. so.ps->vSetUseDevlock();
  201. if (dbmi.hpal != (HPALETTE) 0)
  202. {
  203. EPALOBJ palSurf(dbmi.hpal);
  204. ASSERTGDI(palSurf.bValid(), "ERROR invalid palette CreateCompatibleBitmap");
  205. //
  206. // Set palette into surface.
  207. //
  208. so.ps->ppal(palSurf.ppalGet());
  209. //
  210. // Reference count it by making sure it is not unlocked.
  211. //
  212. palSurf.ppalSet((PPALETTE) NULL); // It won't be unlocked
  213. }
  214. //
  215. // Zero memory by sending a bitblt command to device
  216. //
  217. RECTL rclDst;
  218. rclDst.left = 0;
  219. rclDst.top = 0;
  220. rclDst.right = cx;
  221. rclDst.bottom = cy;
  222. (*(so.ps->pfnBitBlt()))(
  223. so.pSurfobj(),
  224. (SURFOBJ *)NULL,
  225. (SURFOBJ *)NULL,
  226. (CLIPOBJ *)NULL,
  227. NULL,
  228. &rclDst,
  229. (POINTL *)NULL,
  230. (POINTL *)NULL,
  231. (EBRUSHOBJ *)NULL,
  232. (POINTL *)NULL,
  233. 0x0);
  234. return(hsurf);
  235. }
  236. }
  237. SURFMEM SurfDimo;
  238. SurfDimo.bCreateDIB(&dbmi, (PVOID) NULL);
  239. if (!SurfDimo.bValid())
  240. {
  241. return(0);
  242. }
  243. //
  244. // Mark the bitmap a keeper.
  245. //
  246. SurfDimo.vKeepIt();
  247. SurfDimo.ps->vSetDeviceDependentBitmap();
  248. SurfDimo.ps->vSetApiBitmap();
  249. SurfDimo.ps->hdev(po.hdev());
  250. return(SurfDimo.ps->hsurf());
  251. }
  252. /******************************Public*Routine******************************\
  253. * HBITMAP GreCreateCompatibleBitmap(hdc,cx,cy)
  254. *
  255. * GDI Interface routine to create a bitmap.
  256. *
  257. * History:
  258. * Mon 06-Nov-1995 -by- Tom Zakrajsek [tomzak]
  259. * Add overflow checking for cx*cy.
  260. *
  261. * Mon 01-Jun-1992 -by- Patrick Haluptzok [patrickh]
  262. * Add IC support.
  263. *
  264. * Fri 25-Jan-1991 -by- Patrick Haluptzok [patrickh]
  265. * Wrote it.
  266. \**************************************************************************/
  267. HBITMAP APIENTRY GreCreateCompatibleBitmap(HDC hdc, int cx, int cy)
  268. {
  269. BOOL bDriver;
  270. HSURF hsurf;
  271. HPALETTE hpal;
  272. ULONG iFormat;
  273. bDriver = TRUE;
  274. if (cy & CCB_NOVIDEOMEMORY)
  275. {
  276. cy &= ~CCB_NOVIDEOMEMORY;
  277. bDriver = FALSE;
  278. }
  279. //
  280. // Validate the width and height
  281. //
  282. if ((cx <= 0) || (cy <= 0))
  283. {
  284. WARNING("GreCreateCompatibleBitmap failed - cx or cy was <= 0\n");
  285. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  286. return((HBITMAP) 0);
  287. }
  288. ULONGLONG cjTotal = (ULONGLONG) cx * (ULONGLONG) cy;
  289. //
  290. // Assume worse case (32bpp pixels) and calculate possible overflow condition
  291. //
  292. // BUGFIX #172447 12-12-2000 bhouse
  293. //
  294. // NOTE: Tom Zakrajsek added a fairly restrictive checking of cx/cy in 1995
  295. // and we have modified this check to be less restrictive. It appears the
  296. // check was to avoid potential numeric overflow when cx and cy are multiplied
  297. // together with bytes per pixel. It is kinda goofy to have this check
  298. // here though as the possible overflow does not even occur in this
  299. // routine but farther down in the call stack. We will leave the modified
  300. // check here to avoid introducing a possible regression.
  301. //
  302. if(cjTotal > (ULONG_MAX >> 2))
  303. {
  304. WARNING("GreCreateCompatibleBitmap failed - size too big");
  305. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  306. return((HBITMAP) 0);
  307. }
  308. //
  309. // Without an hdc we create a monochrome bitmap.
  310. //
  311. if (hdc == (HDC) NULL)
  312. return(GreCreateBitmap(cx, cy, 1, 1, (LPBYTE) NULL));
  313. //
  314. // Ok lock down the hdc and the surface.
  315. //
  316. DCOBJ dco(hdc);
  317. if (!dco.bValid())
  318. {
  319. WARNING("CreateCompatibleBitmap failed - invalid hdc\n");
  320. return((HBITMAP) 0);
  321. }
  322. //
  323. // NOTE: Even though we touch the SURFOBJ, we actually aren't going to read
  324. // or write it. We just need some of its information.
  325. //
  326. PDEVOBJ po(dco.hdev());
  327. //
  328. // We must hold a lock to protect against the dynamic mode change
  329. // code and to synchronize access to the drivers.
  330. //
  331. {
  332. DEVLOCKOBJ dlo(po);
  333. PSURFACE pSurf = dco.pSurfaceEff();
  334. hpal = 0;
  335. if (dco.dctp() == DCTYPE_MEMORY)
  336. {
  337. iFormat = pSurf->iFormat();
  338. if (pSurf->ppal() != NULL)
  339. {
  340. hpal = (HPALETTE) pSurf->ppal()->hGet();
  341. }
  342. }
  343. else
  344. {
  345. iFormat = po.iDitherFormat();
  346. if (!po.bIsPalManaged())
  347. {
  348. hpal = (HPALETTE) po.ppalSurf()->hGet();
  349. }
  350. }
  351. hsurf = hsurfCreateCompatibleSurface(dco.hdev(),
  352. iFormat,
  353. hpal,
  354. cx,
  355. cy,
  356. bDriver);
  357. }
  358. GreSetBitmapOwner((HBITMAP) hsurf, OBJECT_OWNER_CURRENT);
  359. return((HBITMAP) hsurf);
  360. }
  361. /******************************Public*Routine******************************\
  362. * GreSetBitmapBits
  363. *
  364. * Does the work for SetBitmapBits.
  365. *
  366. * History:
  367. * 19-Jun-1991 -by- Patrick Haluptzok patrickh
  368. * Wrote it.
  369. \**************************************************************************/
  370. LONG
  371. GreSetBitmapBits(
  372. HBITMAP hbm,
  373. ULONG cjTotal,
  374. PBYTE pjBuffer,
  375. PLONG pOffset
  376. )
  377. {
  378. if (cjTotal == 0)
  379. {
  380. return(0);
  381. }
  382. LONG lReturn = 0;
  383. SURFREF SurfBmo((HSURF) hbm);
  384. SURFMEM SurfDimo;
  385. PSURFACE pSurf;
  386. pSurf = SurfBmo.ps;
  387. if (SurfBmo.bValid() && SurfBmo.ps->bApiBitmap())
  388. {
  389. LONG lInitOffset = *pOffset;
  390. SURFOBJ soTemp;
  391. ERECTL erclDst;
  392. POINTL ptlSrc;
  393. soTemp.dhsurf = 0;
  394. soTemp.hsurf = 0;
  395. soTemp.dhpdev = SurfBmo.ps->dhpdev();
  396. soTemp.hdev = SurfBmo.ps->hdev();
  397. soTemp.sizlBitmap.cx = SurfBmo.ps->sizl().cx;
  398. soTemp.sizlBitmap.cy = SurfBmo.ps->sizl().cy;
  399. soTemp.cjBits = cjTotal;
  400. soTemp.pvBits = pjBuffer;
  401. soTemp.pvScan0 = 0;
  402. soTemp.lDelta = lInitOffset;
  403. soTemp.iUniq = 0;
  404. soTemp.iType = (USHORT) STYPE_BITMAP;
  405. soTemp.fjBitmap = 0;
  406. ptlSrc.x = 0;
  407. ptlSrc.y = 0;
  408. erclDst.left = 0;
  409. erclDst.top = 0;
  410. erclDst.right = SurfBmo.ps->sizl().cx;
  411. erclDst.bottom = SurfBmo.ps->sizl().cy;
  412. HSEMAPHORE hsemDevLock = NULL;
  413. PPDEV ppdev = NULL;
  414. if (SurfBmo.ps->bUseDevlock())
  415. {
  416. PDEVOBJ po(SurfBmo.ps->hdev());
  417. ASSERTGDI(po.bValid(), "PDEV invalid");
  418. hsemDevLock = po.hsemDevLock();
  419. ppdev = po.ppdev;
  420. GreAcquireSemaphoreEx(hsemDevLock, SEMORDER_DEVLOCK, NULL);
  421. GreEnterMonitoredSection(ppdev, WD_DEVLOCK);
  422. }
  423. if (SurfBmo.ps->iType() == STYPE_DEVBITMAP)
  424. {
  425. DEVBITMAPINFO dbmi;
  426. dbmi.iFormat = SurfBmo.ps->iFormat();
  427. dbmi.cxBitmap = SurfBmo.ps->sizl().cx;
  428. dbmi.cyBitmap = SurfBmo.ps->sizl().cy;
  429. dbmi.hpal = 0;
  430. dbmi.fl = SurfBmo.ps->bUMPD() ? UMPD_SURFACE : 0;
  431. //
  432. // Create a DIB (SurfDimo) with the same height,width,
  433. // and BPP as the DEVBITMAP passed in
  434. //
  435. if (!SurfDimo.bCreateDIB(&dbmi,NULL))
  436. {
  437. WARNING("GreSetBitmapBits failed bCreateDIB\n");
  438. lInitOffset = -1; // This is to make us fail the call below.
  439. }
  440. else
  441. {
  442. pSurf = SurfDimo.ps;
  443. //
  444. // We don't need to copy if the offset is 0 because either
  445. // it's a 1 shot set that inits the whole thing, or else
  446. // it's the first of a batch. In either case anything
  447. // that's there before doesn't need to be saved because
  448. // it will all be over-written when we are done.
  449. //
  450. if (lInitOffset != 0)
  451. {
  452. BOOL bCopyRet = EngCopyBits
  453. (
  454. pSurf->pSurfobj(),
  455. SurfBmo.pSurfobj(),
  456. NULL,
  457. NULL,
  458. &erclDst,
  459. &ptlSrc
  460. );
  461. ASSERTGDI(bCopyRet, "ERROR how can this fail ?");
  462. }
  463. }
  464. }
  465. //
  466. // Check for invalid initial offset.
  467. //
  468. if (lInitOffset >= 0)
  469. {
  470. PDEVOBJ po(SurfBmo.ps->hdev());
  471. //
  472. // Inc the target surface uniqueness
  473. //
  474. INC_SURF_UNIQ(SurfBmo.ps);
  475. //
  476. // Copy the buffer to the DIB
  477. //
  478. BOOL bReturn = bDoGetSetBitmapBits(pSurf->pSurfobj(),&soTemp,FALSE);
  479. ASSERTGDI(bReturn, "GreSetBitmapBits failed bDoGetSetBitmapBits\n");
  480. lReturn = soTemp.cjBits;
  481. *pOffset = lInitOffset + lReturn;
  482. if (SurfBmo.ps->iType() == STYPE_DEVBITMAP)
  483. {
  484. //
  485. // Have the driver copy the temp DIB to the DEVBITMAP
  486. //
  487. if (!((*PPFNGET(po,CopyBits,SurfBmo.ps->flags())) (
  488. SurfBmo.pSurfobj(),
  489. pSurf->pSurfobj(),
  490. NULL,
  491. NULL,
  492. &erclDst,
  493. &ptlSrc)))
  494. {
  495. WARNING("GreSetBitmapBits failed copying temp DIB to DFB\n");
  496. lReturn = 0;
  497. }
  498. }
  499. }
  500. if (hsemDevLock)
  501. {
  502. GreExitMonitoredSection(ppdev, WD_DEVLOCK);
  503. GreReleaseSemaphoreEx(hsemDevLock);
  504. }
  505. }
  506. else
  507. {
  508. WARNING("GreSetBitmapBits failed - invalid bitmap handle\n");
  509. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  510. }
  511. return(lReturn);
  512. }
  513. /******************************Public*Routine******************************\
  514. * GreGetBitmapBits
  515. *
  516. * Does the work for GetBitmapBits
  517. *
  518. * Returns: Number of bytes copied, or if pjBuffer is NULL the total size of
  519. * the bitmap.
  520. *
  521. * History:
  522. * Mon 01-Jun-1992 -by- Patrick Haluptzok [patrickh]
  523. * Return bitmap scanlines in BMF_TOPDOWN organization.
  524. *
  525. * 22-Jun-1991 -by- Patrick Haluptzok patrickh
  526. * Wrote it.
  527. \**************************************************************************/
  528. LONG GreGetBitmapBits(HBITMAP hbm, ULONG cjTotal, PBYTE pjBuffer, PLONG pOffset)
  529. {
  530. LONG lReturn = 0;
  531. SURFREF SurfBmo((HSURF) hbm);
  532. if (SurfBmo.bValid() && SurfBmo.ps->bApiBitmap())
  533. {
  534. SURFMEM SurfDimo;
  535. SURFACE *pSurf;
  536. PDEVOBJ pdo(SurfBmo.ps->hdev());
  537. pSurf = SurfBmo.ps;
  538. lReturn = ((((gaulConvert[SurfBmo.ps->iFormat()] * SurfBmo.ps->sizl().cx) + 15) >> 4) << 1) * SurfBmo.ps->sizl().cy;
  539. if (pjBuffer != (PBYTE) NULL)
  540. {
  541. SURFOBJ soTemp;
  542. ERECTL erclDst;
  543. POINTL ptlSrc;
  544. soTemp.dhsurf = 0;
  545. soTemp.hsurf = 0;
  546. soTemp.dhpdev = SurfBmo.ps->dhpdev();
  547. soTemp.hdev = SurfBmo.ps->hdev();
  548. soTemp.sizlBitmap.cx = SurfBmo.ps->sizl().cx;
  549. soTemp.sizlBitmap.cy = SurfBmo.ps->sizl().cy;
  550. soTemp.cjBits = 0;
  551. soTemp.pvBits = 0;
  552. soTemp.pvScan0 = 0;
  553. soTemp.lDelta = 0;
  554. soTemp.iUniq = 0;
  555. soTemp.iType = (USHORT) STYPE_BITMAP;
  556. soTemp.fjBitmap = 0;
  557. ptlSrc.x = 0;
  558. ptlSrc.y = 0;
  559. erclDst.left = 0;
  560. erclDst.top = 0;
  561. erclDst.right = SurfBmo.ps->sizl().cx;
  562. erclDst.bottom = SurfBmo.ps->sizl().cy;
  563. HSEMAPHORE hsemDevLock = NULL;
  564. PPDEV ppdev = NULL;
  565. if (SurfBmo.ps->bUseDevlock())
  566. {
  567. PDEVOBJ po(SurfBmo.ps->hdev());
  568. ASSERTGDI(po.bValid(), "PDEV invalid");
  569. hsemDevLock = po.hsemDevLock();
  570. ppdev = po.ppdev;
  571. GreAcquireSemaphoreEx(hsemDevLock, SEMORDER_DEVLOCK, NULL);
  572. GreEnterMonitoredSection(ppdev, WD_DEVLOCK);
  573. }
  574. if (SurfBmo.ps->iType() == STYPE_DEVBITMAP)
  575. {
  576. //
  577. // Create a DIB (SurfDimo) with the same height,width,
  578. // and BPP as the DEVBITMAP passed in
  579. //
  580. DEVBITMAPINFO dbmi;
  581. dbmi.iFormat = SurfBmo.ps->iFormat();
  582. dbmi.cxBitmap = SurfBmo.ps->sizl().cx;
  583. dbmi.cyBitmap = SurfBmo.ps->sizl().cy;
  584. dbmi.hpal = 0;
  585. dbmi.fl = SurfBmo.ps->bUMPD() ? UMPD_SURFACE : 0;
  586. if (!SurfDimo.bCreateDIB(&dbmi,NULL))
  587. {
  588. WARNING("GreGetBitmapBits failed bCreateDIB\n");
  589. lReturn = 0;
  590. }
  591. else
  592. {
  593. pSurf = SurfDimo.ps;
  594. EngCopyBits(pSurf->pSurfobj(),
  595. SurfBmo.pSurfobj(),
  596. NULL,
  597. NULL,
  598. &erclDst,
  599. &ptlSrc);
  600. }
  601. }
  602. if (lReturn)
  603. {
  604. //
  605. // We know how big the buffer needs to be. Set up the
  606. // soTemp so the driver knows how much to fill in.
  607. //
  608. ULONG cjMaxLength = lReturn;
  609. LONG lInitOffset = *pOffset;
  610. //
  611. // Check for invalid initial offset.
  612. //
  613. if ((lInitOffset >= 0) && ((ULONG)lInitOffset < cjMaxLength))
  614. {
  615. //
  616. // Make cjTotal valid range.
  617. //
  618. if ((lInitOffset + cjTotal) > cjMaxLength)
  619. {
  620. cjTotal = cjMaxLength - lInitOffset;
  621. }
  622. if (cjTotal > 0)
  623. {
  624. //
  625. // Fill in our return values, we know them already.
  626. //
  627. soTemp.cjBits = cjTotal;
  628. soTemp.lDelta = lInitOffset;
  629. soTemp.pvBits = pjBuffer;
  630. BOOL bReturn = bDoGetSetBitmapBits(&soTemp,pSurf->pSurfobj(),TRUE);
  631. ASSERTGDI(bReturn, "GreGetBitmapBits failed bDoGetSetBitmapBits\n");
  632. lReturn = soTemp.cjBits;
  633. *pOffset = lInitOffset + lReturn;
  634. }
  635. else
  636. {
  637. WARNING("GreGetBitmapBits failed cjTotal 0\n");
  638. lReturn = 0;
  639. }
  640. }
  641. else
  642. {
  643. WARNING("GreGetBitmapBits failed lInitOffset invalid\n");
  644. lReturn = 0;
  645. }
  646. }
  647. if (hsemDevLock)
  648. {
  649. GreExitMonitoredSection(ppdev, WD_DEVLOCK);
  650. GreReleaseSemaphoreEx(hsemDevLock);
  651. }
  652. }
  653. }
  654. else
  655. {
  656. WARNING("GreGetBitmapBits failed - invalid bitmap handle\n");
  657. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  658. }
  659. return(lReturn);
  660. }
  661. /******************************Public*Routine******************************\
  662. * bDoGetSetBitmapBits
  663. *
  664. * Does the get or set of bitmap bits for EngCopyBits.
  665. *
  666. * History:
  667. * 16-Mar-1993 -by- Patrick Haluptzok patrickh
  668. * Wrote it.
  669. \**************************************************************************/
  670. BOOL bDoGetSetBitmapBits(SURFOBJ *psoDst, SURFOBJ *psoSrc, BOOL bGetBits)
  671. {
  672. ASSERTGDI(psoDst->iType == STYPE_BITMAP, "ERROR no DIB dst");
  673. ASSERTGDI(psoSrc->iType == STYPE_BITMAP, "ERROR no DIB src");
  674. //
  675. // Synchronize with the device driver before touching the device surface.
  676. //
  677. if (bGetBits)
  678. {
  679. //
  680. // Doing a GetBitmapBits.
  681. //
  682. PSURFACE pSurfSrc = SURFOBJ_TO_SURFACE(psoSrc);
  683. {
  684. PDEVOBJ po(psoSrc->hdev);
  685. po.vSync(psoSrc,NULL,0);
  686. }
  687. if (psoDst->pvBits == NULL)
  688. {
  689. psoDst->cjBits = ((((gaulConvert[psoSrc->iBitmapFormat] * psoSrc->sizlBitmap.cx) + 15) >> 4) << 1) * psoSrc->sizlBitmap.cy;
  690. }
  691. else
  692. {
  693. //
  694. // Initialize temporaries.
  695. //
  696. PBYTE pjBuffer = (PBYTE) psoDst->pvBits;
  697. PBYTE pjBitmap = (PBYTE) psoSrc->pvScan0;
  698. LONG lDeltaBitmap = psoSrc->lDelta;
  699. ULONG cjScanBitmap = pSurfSrc->cjScan();
  700. ASSERTGDI(pjBuffer != NULL, "ERROR pjBuffer is NULL");
  701. ASSERTGDI(pjBitmap != NULL, "ERROR pjBitmap is NULL");
  702. //
  703. // Get the WORD aligned width of the input scanlines.
  704. //
  705. ULONG cjScanInput = ((((gaulConvert[psoSrc->iBitmapFormat] * psoSrc->sizlBitmap.cx) + 15) >> 4) << 1);
  706. ULONG cjMaxLength = cjScanInput * psoSrc->sizlBitmap.cy;
  707. LONG lInitOffset = psoDst->lDelta;
  708. ULONG cjTotal = psoDst->cjBits;
  709. //
  710. // Check for invalid initial offset.
  711. //
  712. if ((lInitOffset < 0) || ((ULONG)lInitOffset >= cjMaxLength))
  713. {
  714. psoDst->cjBits = 0;
  715. return(FALSE);
  716. }
  717. //
  718. // Make cjTotal valid range.
  719. //
  720. if (lInitOffset + cjTotal > cjMaxLength)
  721. {
  722. cjTotal = cjMaxLength - lInitOffset;
  723. }
  724. //
  725. // Fill in our return values.
  726. //
  727. psoDst->cjBits = cjTotal;
  728. //
  729. // Move pointer to current scanline in bitmap.
  730. //
  731. pjBitmap += ((lInitOffset / cjScanInput) * lDeltaBitmap);
  732. ULONG ulTemp,ulCopy;
  733. //
  734. // Move partial scan if necesary.
  735. //
  736. ulTemp = (lInitOffset % cjScanInput);
  737. if (ulTemp)
  738. {
  739. ulCopy = MIN((cjScanInput - ulTemp), cjTotal);
  740. RtlCopyMemory((PVOID) pjBuffer, (PVOID) (pjBitmap + ulTemp), (unsigned int) ulCopy);
  741. pjBuffer += ulCopy;
  742. pjBitmap += lDeltaBitmap;
  743. cjTotal -= ulCopy;
  744. }
  745. //
  746. // Move as many scans that fit.
  747. //
  748. ulTemp = cjTotal / cjScanInput;
  749. cjTotal -= (ulTemp * cjScanInput);
  750. while (ulTemp--)
  751. {
  752. RtlCopyMemory((PVOID) pjBuffer, (PVOID) pjBitmap, (unsigned int) cjScanInput);
  753. pjBuffer += cjScanInput;
  754. pjBitmap += lDeltaBitmap;
  755. }
  756. //
  757. // Move as much of partial scan as possible.
  758. //
  759. if (cjTotal)
  760. {
  761. RtlCopyMemory((PVOID) pjBuffer, (PVOID) pjBitmap, (unsigned int) cjTotal);
  762. }
  763. }
  764. }
  765. else
  766. {
  767. //
  768. // Doing a SetBitmapBits call.
  769. //
  770. PSURFACE pSurfDst = SURFOBJ_TO_SURFACE(psoDst);
  771. {
  772. PDEVOBJ po(psoDst->hdev);
  773. po.vSync(psoDst,NULL,0);
  774. }
  775. //
  776. // Initialize temporaries.
  777. //
  778. PBYTE pjBuffer = (PBYTE) psoSrc->pvBits;
  779. PBYTE pjBitmap = (PBYTE) psoDst->pvScan0;
  780. LONG lDeltaBitmap = psoDst->lDelta;
  781. ULONG cjScanBitmap = pSurfDst->cjScan();
  782. //
  783. // Get the WORD aligned width of the input scanlines.
  784. //
  785. ULONG cjScanInput = ((((gaulConvert[psoDst->iBitmapFormat] * psoDst->sizlBitmap.cx) + 15) >> 4) << 1);
  786. ULONG cjMaxLength = cjScanInput * psoDst->sizlBitmap.cy;
  787. LONG lInitOffset = psoSrc->lDelta;
  788. ULONG cjTotal = psoSrc->cjBits;
  789. //
  790. // Check for invalid initial offset.
  791. //
  792. if ((lInitOffset < 0) || ((ULONG)lInitOffset >= cjMaxLength))
  793. {
  794. psoSrc->cjBits = 0;
  795. return(TRUE);
  796. }
  797. //
  798. // Make cjTotal valid range.
  799. //
  800. if (lInitOffset + cjTotal > cjMaxLength)
  801. {
  802. cjTotal = cjMaxLength - lInitOffset;
  803. }
  804. //
  805. // Fill in our return values, we know them already.
  806. //
  807. psoSrc->cjBits = cjTotal;
  808. //
  809. // Move pointer to current scanline in bitmap.
  810. //
  811. pjBitmap += ((lInitOffset / cjScanInput) * lDeltaBitmap);
  812. ULONG ulTemp,ulCopy;
  813. //
  814. // Move partial scan if necesary.
  815. //
  816. ulTemp = (lInitOffset % cjScanInput);
  817. if (ulTemp)
  818. {
  819. ulCopy = MIN((cjScanInput - ulTemp), cjTotal);
  820. RtlCopyMemory((PVOID) (pjBitmap + ulTemp), (PVOID) pjBuffer, (unsigned int) ulCopy);
  821. pjBuffer += ulCopy;
  822. pjBitmap += lDeltaBitmap;
  823. cjTotal -= ulCopy;
  824. }
  825. //
  826. // Move as many scans that fit.
  827. //
  828. ulTemp = cjTotal / cjScanInput;
  829. cjTotal -= (ulTemp * cjScanInput);
  830. while (ulTemp--)
  831. {
  832. RtlCopyMemory((PVOID) pjBitmap, (PVOID) pjBuffer, (unsigned int) cjScanInput);
  833. pjBuffer += cjScanInput;
  834. pjBitmap += lDeltaBitmap;
  835. }
  836. //
  837. // Move as much of partial scan as possible.
  838. //
  839. if (cjTotal)
  840. {
  841. RtlCopyMemory((PVOID) pjBitmap, (PVOID) pjBuffer, (unsigned int) cjTotal);
  842. }
  843. }
  844. return(TRUE);
  845. }