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.

1254 lines
37 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: surfobj.cxx
  3. *
  4. * Surface user objects.
  5. *
  6. * Copyright (c) 1990-1999 Microsoft Corporation
  7. \**************************************************************************/
  8. #include "precomp.hxx"
  9. #ifdef _HYDRA_
  10. #include "muclean.hxx"
  11. #endif
  12. extern BOOL G_fConsole;
  13. // Global surface uniqueness -- incremented every time a surface is created.
  14. ULONG _ulGlobalSurfaceUnique;
  15. // The following declarations are required by the native c8 compiler.
  16. PSURFACE SURFACE::pdibDefault; // The default bitmap pointer
  17. SIZE_T SURFACE::tSize = sizeof(SURFACE);
  18. #if TRACE_SURFACE_ALLOCS
  19. TRACED_SURFACE::SurfaceTraceStatus TRACED_SURFACE::eTraceStatus = SURFACE_TRACING_UNINITIALIZED;
  20. #if TRACE_SURFACE_USER_CHAIN_IN_UM
  21. TRACED_SURFACE::SurfaceTraceStatus TRACED_SURFACE::eUMTraceStatus = SURFACE_TRACING_UNINITIALIZED;
  22. #endif
  23. #endif
  24. // By default, EngCreateBitmap allocations larger than 260k will be
  25. // allocated as a section:
  26. #define KM_SIZE_MAX 0x40000
  27. /******************************Public*Routine******************************\
  28. * GreMarkUndeletableBitmap -- a USER callable API to mark a surface as
  29. * undeletable. Currently this is used to make sure applications
  30. * cannot delete redirection bitmaps.
  31. *
  32. * Arguments:
  33. *
  34. * hbm -- handle to bitmap to be marked undeletable
  35. *
  36. * Return Value:
  37. *
  38. * TRUE upon success, FALSE otherwise.
  39. *
  40. * History:
  41. *
  42. * 2-Nov-1998 -by- Ori Gershony [orig]
  43. *
  44. \**************************************************************************/
  45. BOOL
  46. GreMarkUndeletableBitmap(
  47. HBITMAP hbm
  48. )
  49. {
  50. return (HmgMarkUndeletable((HOBJ) hbm, SURF_TYPE));
  51. }
  52. /******************************Public*Routine******************************\
  53. * GreMarkDeletableBitmap -- a USER callable API to mark a surface as
  54. * deletable. Currently this is used by USER just before deleting
  55. * a redirection bitmap.
  56. *
  57. * Arguments:
  58. *
  59. * hbm -- handle to bitmap to be marked deletable
  60. *
  61. * Return Value:
  62. *
  63. * TRUE upon success, FALSE otherwise.
  64. *
  65. * History:
  66. *
  67. * 2-Nov-1998 -by- Ori Gershony [orig]
  68. *
  69. \**************************************************************************/
  70. BOOL
  71. GreMarkDeletableBitmap(
  72. HBITMAP hbm
  73. )
  74. {
  75. return (HmgMarkDeletable((HOBJ) hbm, SURF_TYPE));
  76. }
  77. /******************************Public*Routine******************************\
  78. * pvAllocateKernelSection - Allocate kernel mode section
  79. *
  80. * Arguments:
  81. *
  82. * AllocationSize - size in bytes of requested memory
  83. *
  84. * Return Value:
  85. *
  86. * Pointer to memory or NULL
  87. *
  88. * History:
  89. *
  90. * 22-May-1996 -by- Mark Enstrom [marke]
  91. *
  92. \**************************************************************************/
  93. PVOID
  94. pvAllocateKernelSection(
  95. ULONGSIZE_T AllocationSize,
  96. ULONG Tag
  97. )
  98. {
  99. NTSTATUS Status;
  100. OBJECT_ATTRIBUTES ObjectAttributes;
  101. LARGE_INTEGER MaximumSize;
  102. PVOID pvAlloc = NULL;
  103. PVOID pvRet = NULL;
  104. //
  105. // Create km section
  106. //
  107. ACCESS_MASK DesiredAccess = SECTION_MAP_READ |
  108. SECTION_MAP_WRITE;
  109. ULONG SectionPageProtection = PAGE_READWRITE;
  110. ULONG AllocationAttributes = SEC_COMMIT |
  111. SEC_NO_CHANGE;
  112. MaximumSize.HighPart = 0;
  113. MaximumSize.LowPart = AllocationSize + sizeof(KMSECTIONHEADER);
  114. PVOID pHandleSection;
  115. //
  116. // map a copy of this section into kernel address space
  117. // Lets use the Section tagging code.
  118. //
  119. Status = Win32CreateSection(&pHandleSection,
  120. DesiredAccess,
  121. NULL,
  122. &MaximumSize,
  123. SectionPageProtection,
  124. AllocationAttributes,
  125. NULL,
  126. NULL,
  127. TAG_SECTION_DIB);
  128. if (!NT_SUCCESS(Status))
  129. {
  130. WARNING1("pvAllocateKernelSection: ObReferenceObjectByHandle failed\n");
  131. }
  132. else
  133. {
  134. SIZE_T ViewSize = 0;
  135. #ifdef _HYDRA_
  136. // MmMapViewInSessionSpace is internally promoted to
  137. // MmMapViewInSystemSpace on non-Hydra systems.
  138. Status = Win32MapViewInSessionSpace(
  139. pHandleSection,
  140. (PVOID*)&pvAlloc,
  141. &ViewSize);
  142. #else
  143. Status = MmMapViewInSystemSpace(
  144. pHandleSection,
  145. (PVOID*)&pvAlloc,
  146. &ViewSize);
  147. #endif
  148. if (!NT_SUCCESS(Status))
  149. {
  150. //
  151. // free section
  152. //
  153. WARNING1("pvAllocateKernelSection: MmMapViewInSystemSpace failed\n");
  154. Win32DestroySection(pHandleSection);
  155. }
  156. else
  157. {
  158. #ifdef _HYDRA_
  159. #if DBG
  160. if (!G_fConsole)
  161. {
  162. DebugGreTrackAddMapView(pvAlloc);
  163. }
  164. #endif
  165. #endif
  166. ((PKMSECTIONHEADER)pvAlloc)->Tag = Tag;
  167. ((PKMSECTIONHEADER)pvAlloc)->pSection = pHandleSection;
  168. pvRet = (PVOID)(((PUCHAR)pvAlloc)+sizeof(KMSECTIONHEADER));
  169. }
  170. }
  171. return(pvRet);
  172. }
  173. /******************************Public*Routine******************************\
  174. * vFreeKernelSection: Free kernel mode section
  175. *
  176. * Arguments:
  177. *
  178. * pvMem - Kernel mode section pointer
  179. *
  180. * Return Value:
  181. *
  182. * None
  183. *
  184. * History:
  185. *
  186. * 22-May-1996 -by- Mark Enstrom [marke]
  187. *
  188. \**************************************************************************/
  189. VOID
  190. vFreeKernelSection(
  191. PVOID pvMem
  192. )
  193. {
  194. NTSTATUS Status;
  195. PVOID pHandleSection;
  196. if (pvMem != NULL)
  197. {
  198. PKMSECTIONHEADER pvHeader = (PKMSECTIONHEADER)((PUCHAR)pvMem - sizeof(KMSECTIONHEADER));
  199. pHandleSection = pvHeader->pSection;
  200. //
  201. // Temporary code to catch stress failure (bug #263678)
  202. // We want to fail before the page is unmapped, instead of
  203. // afterwards
  204. //
  205. if (!pHandleSection)
  206. {
  207. KeBugCheckEx(PAGE_FAULT_IN_NONPAGED_AREA,
  208. (LONG_PTR) pHandleSection,
  209. (LONG_PTR) pvHeader->pSection,
  210. (LONG) pvHeader->Tag,
  211. 0);
  212. }
  213. //
  214. // unmap kernel mode view
  215. //
  216. #ifdef _HYDRA_
  217. // MmUnmapViewInSessionSpace is internally promoted to
  218. // MmUnmapViewInSystemSpace on non-Hydra systems.
  219. Status = Win32UnmapViewInSessionSpace((PVOID)pvHeader);
  220. #else
  221. Status = MmUnmapViewInSystemSpace((PVOID)pvHeader);
  222. #endif
  223. if (!NT_SUCCESS(Status))
  224. {
  225. WARNING1("vFreeKernelSection: MmUnmapViewInSystemSpace failed\n");
  226. }
  227. else
  228. {
  229. #ifdef _HYDRA_
  230. #if DBG
  231. if (!G_fConsole)
  232. {
  233. DebugGreTrackRemoveMapView(pvHeader);
  234. }
  235. #endif
  236. #endif
  237. //
  238. // delete reference to section
  239. //
  240. Win32DestroySection(pHandleSection);
  241. }
  242. }
  243. else
  244. {
  245. WARNING("vFreeKernelSection called with NULL pvMem\n");
  246. }
  247. }
  248. /******************************Public*Routine******************************\
  249. * SURFACE::bDeleteSurface()
  250. *
  251. * Delete the surface. Make sure it is not selected into a DC if it is
  252. * a bitmap. We do under cover of multi-lock to ensure no one will select
  253. * the bitmap into a DC after we checked cRef.
  254. *
  255. * History:
  256. * Mon 17-Feb-1992 -by- Patrick Haluptzok [patrickh]
  257. * Add support for closing journal file.
  258. *
  259. * Fri 22-Feb-1991 -by- Patrick Haluptzok [patrickh]
  260. * Wrote it.
  261. \**************************************************************************/
  262. BOOL
  263. SURFACE::bDeleteSurface(CLEANUPTYPE cutype)
  264. {
  265. GDIFunctionID(SURFACE::bDeleteSurface);
  266. BOOL bRet = TRUE;
  267. if (!bIsDefault() && bValid())
  268. {
  269. HANDLE hSecure = NULL;
  270. HANDLE hDibSection = NULL;
  271. PVOID pvBitsBaseOld = NULL;
  272. if (iType() == STYPE_BITMAP)
  273. {
  274. hSecure = DIB.hSecure;
  275. hDibSection = DIB.hDIBSection;
  276. pvBitsBaseOld = pvBitsBase();
  277. }
  278. PDEVOBJ pdo(hdev());
  279. ULONG iTypeOld = iType();
  280. DHSURF dhsurfOld = dhsurf();
  281. PPALETTE ppalOld = ppal();
  282. EWNDOBJ *pwoDelete = pwo();
  283. PVOID pvBitsOld = pvBits();
  284. FLONG fl = fjBitmap();
  285. //
  286. // If the surface is a bitmap, ensure it is not selected into a DC.
  287. // Also make sure we are the only one with it locked down. These are
  288. // both tested at once with HmgRemoveObject, because we increment
  289. // and decrement the alt lock count at the same time we increment
  290. // and decrement the cRef count on selection and deselection into
  291. // DCs. Note that surfaces can also be locked for GetDIBits with no
  292. // DC involvement, so the alt lock count may be higher than the
  293. // reference count.
  294. //
  295. ASSERTGDI(HmgQueryLock((HOBJ) hGet()) == 0,
  296. "ERROR cLock != 0");
  297. //
  298. // If it's a device bitmap, acquire the devlock to protect against
  299. // dynamic mode and driver changes.
  300. //
  301. DEVLOCKOBJ dlo;
  302. if (bEngCreateDeviceBitmap() && pdo.bValid())
  303. {
  304. dlo.vLock(pdo);
  305. }
  306. else
  307. {
  308. dlo.vInit();
  309. }
  310. #if TRACE_SURFACE_ALLOCS
  311. #if TRACE_SURFACE_USER_CHAIN_IN_UM
  312. PVOID pvUserMem = NULL;
  313. if (TRACED_SURFACE::bEnabled())
  314. {
  315. TRACED_SURFACE *pts = (TRACED_SURFACE *)this;
  316. UINT uiIndex = (UINT) HmgIfromH(hGet());
  317. if (pts->Trace.UserChainAllocated &&
  318. uiIndex < gcMaxHmgr)
  319. {
  320. pvUserMem = gpentHmgr[uiIndex].pUser;
  321. ASSERTGDI(pvUserMem == NULL ||
  322. OBJECTOWNER_PID(gpentHmgr[uiIndex].ObjectOwner) == W32GetCurrentPID(),
  323. "Unowned SURFACE still has User Memory.");
  324. }
  325. }
  326. #endif
  327. #endif
  328. //
  329. // Remove undeletable surfaces only during session cleanup.
  330. //
  331. if (HmgRemoveObject((HOBJ) hGet(), 0, 1, (cutype == CLEANUP_SESSION),
  332. SURF_TYPE))
  333. {
  334. #if TRACE_SURFACE_ALLOCS
  335. #if TRACE_SURFACE_USER_CHAIN_IN_UM
  336. EngFreeUserMem(pvUserMem);
  337. #endif
  338. #endif
  339. //
  340. // If this bitmap was created by EngCreateDeviceBitmap, we have
  341. // to call DrvDeleteDeviceBitmap to clean it up. Note that we
  342. // can't simply check for STYPE_DEVBITMAP, since EngModifySurface
  343. // may have changed the type to STYPE_BITMAP.
  344. //
  345. if (bEngCreateDeviceBitmap() && (dhsurfOld != NULL))
  346. {
  347. //
  348. // In UMPD, a bad driver/app(ntcrash) can create a dev bitmap by
  349. // EngCreateDeviceBitmap. But hdev could be null if
  350. // EngAssociateSurface is not called.
  351. //
  352. if (pdo.bValid() && PPFNVALID(pdo, DeleteDeviceBitmap))
  353. {
  354. #if defined(_GDIPLUS_)
  355. (*PPFNDRV(pdo,DeleteDeviceBitmap))(dhsurfOld);
  356. #else // !_GDIPLUS_
  357. if (bUMPD())
  358. {
  359. //
  360. // Do not callout to user-mode driver if the
  361. // user-mode process is gone (i.e., during
  362. // session or process cleanup).
  363. //
  364. if (cutype == CLEANUP_NONE)
  365. {
  366. UMPDDrvDeleteDeviceBitmap(pdo.dhpdev(), dhsurfOld);
  367. }
  368. }
  369. else
  370. {
  371. (*PPFNDRV(pdo,DeleteDeviceBitmap))(dhsurfOld);
  372. }
  373. #endif // !_GDIPLUS_
  374. }
  375. }
  376. FREEOBJ(this, SURF_TYPE);
  377. //
  378. // Note, 'this' not set to NULL
  379. //
  380. //
  381. // For kernel mode, we must unlock the section memory,
  382. // then free the memory. If the section handle is NULL
  383. // then we just use NtVirtualFree, otherwise we must
  384. // use NtUnmapViewOfSection
  385. //
  386. if (hSecure != NULL)
  387. {
  388. MmUnsecureVirtualMemory(hSecure);
  389. if (pvBitsOld == NULL)
  390. {
  391. WARNING("deleting DIB but hSecure or pvBitsOld == NULL");
  392. }
  393. else
  394. {
  395. if (hDibSection != NULL)
  396. {
  397. ZwUnmapViewOfSection(NtCurrentProcess(), pvBitsBaseOld);
  398. }
  399. else
  400. {
  401. SIZE_T ViewSize = 0;
  402. ZwFreeVirtualMemory(
  403. NtCurrentProcess(),
  404. &pvBitsOld,
  405. &ViewSize,
  406. MEM_RELEASE);
  407. }
  408. }
  409. }
  410. else if (fl & BMF_USERMEM)
  411. {
  412. #if defined(_WIN64)
  413. if (fl & BMF_UMPDMEM)
  414. UMPDEngFreeUserMem(pvBitsOld);
  415. else
  416. #endif
  417. EngFreeUserMem(pvBitsOld);
  418. }
  419. else if (fl & BMF_KMSECTION)
  420. {
  421. vFreeKernelSection(pvBitsOld);
  422. }
  423. //
  424. // This DC is going away, the associated WNDOBJ should be deleted.
  425. // The WNDOBJs for memory bitmap and printer surface are deleted here.
  426. // The WNDOBJs for display DCs are deleted in DestroyWindow.
  427. //
  428. if (pwoDelete)
  429. {
  430. GreDeleteWnd((PVOID) pwoDelete);
  431. }
  432. if (ppalOld != NULL)
  433. {
  434. XEPALOBJ pal(ppalOld);
  435. pal.vUnrefPalette();
  436. }
  437. }
  438. else
  439. {
  440. //
  441. // if we can't remove it because it's an application's bitmap
  442. // and is currently selected, mark it for lazy deletion
  443. //
  444. if (HmgQueryAltLock((HOBJ)hGet()) != 1)
  445. {
  446. if (hdc() != NULL || bStockSurface())
  447. {
  448. //
  449. // The surface is currently selected into a DC, so we can't
  450. // simply delete it. Instead, mark it to be deleted when
  451. // the DC is destroyed, or a new surface is selected into
  452. // the DC.
  453. //
  454. vLazyDelete();
  455. bRet = TRUE;
  456. //
  457. // Because we're returning TRUE, the caller will expect
  458. // that the deletion succeeded and so will not unlock the
  459. // object. But since it wasn't truly deleted, we have
  460. // to keep the lock count consistent with the number of DC
  461. // references. We account for the fact that the caller
  462. // won't do the unlock by doing it here:
  463. //
  464. DEC_SHARE_REF_CNT(this);
  465. }
  466. else
  467. {
  468. WARNING("LIKELY MEMORY LEAK IN DRIVER OR GDI!");
  469. RIP("active locks prevented surface deletion");
  470. bRet = FALSE;
  471. }
  472. }
  473. else
  474. {
  475. RIP("failed, handle busy\n");
  476. SAVE_ERROR_CODE(ERROR_BUSY);
  477. bRet = FALSE;
  478. }
  479. }
  480. }
  481. return(bRet);
  482. }
  483. /******************************Public*Routine******************************\
  484. * SURFMEM::bCreateDIB
  485. *
  486. * Constructor for device independent bitmap memory object
  487. *
  488. * History:
  489. * Mon 18-May-1992 -by- Patrick Haluptzok [patrickh]
  490. * return BOOL
  491. *
  492. * 28-Jan-1991 -by- Patrick Haluptzok patrickh
  493. * Wrote it.
  494. \**************************************************************************/
  495. BOOL
  496. SURFMEM::bCreateDIB(
  497. PDEVBITMAPINFO pdbmi,
  498. PVOID pvBitsIn,
  499. HANDLE hDIBSection,
  500. DWORD dsOffset,
  501. HANDLE hSecure,
  502. ULONG_PTR dwColorSpace
  503. )
  504. {
  505. GDIFunctionID(SURFMEM::bCreateDIB);
  506. BOOL bRet = TRUE;
  507. AllocationFlags = SURFACE_DIB;
  508. ps = (PSURFACE) NULL;
  509. FLONG flAllocateSection = 0;
  510. BOOL bCompressed = FALSE;
  511. //
  512. // Figure out the length of a scanline taking arithmetic overflows into account.
  513. //
  514. ULONG cjScanTemp;
  515. switch(pdbmi->iFormat)
  516. {
  517. case BMF_1BPP:
  518. cjScanTemp = ((pdbmi->cxBitmap + 31) & ~31);
  519. if(cjScanTemp < pdbmi->cxBitmap)
  520. return(FALSE);
  521. cjScanTemp >>= 3;
  522. break;
  523. case BMF_4BPP:
  524. cjScanTemp = ((pdbmi->cxBitmap + 7) & ~7);
  525. if (cjScanTemp < pdbmi->cxBitmap)
  526. return(FALSE);
  527. cjScanTemp >>= 1;
  528. break;
  529. case BMF_8BPP:
  530. cjScanTemp = (pdbmi->cxBitmap + 3) & ~3;
  531. if (cjScanTemp < pdbmi->cxBitmap)
  532. return(FALSE);
  533. break;
  534. case BMF_16BPP:
  535. cjScanTemp = ((pdbmi->cxBitmap + 1) & ~1) << 1;
  536. if (cjScanTemp < pdbmi->cxBitmap)
  537. return(FALSE);
  538. break;
  539. case BMF_24BPP:
  540. if ((pdbmi->cxBitmap * 3 < pdbmi->cxBitmap) ||
  541. ((cjScanTemp = ((pdbmi->cxBitmap * 3) + 3) & ~3) < pdbmi->cxBitmap))
  542. return(FALSE);
  543. break;
  544. case BMF_32BPP:
  545. cjScanTemp = pdbmi->cxBitmap << 2;
  546. if (cjScanTemp < pdbmi->cxBitmap)
  547. return(FALSE);
  548. break;
  549. case BMF_8RLE:
  550. case BMF_4RLE:
  551. case BMF_JPEG:
  552. case BMF_PNG:
  553. bCompressed = TRUE;
  554. break;
  555. default:
  556. WARNING("ERROR: failed INVALID BITMAP FORMAT \n");
  557. return(FALSE);
  558. }
  559. //
  560. // If we are given a pointer to bits, then only allocate a DIB header.
  561. // Otherwise allocate space for the header and the required bits.
  562. //
  563. ULONGSIZE_T size = (ULONGSIZE_T) SURFACE::tSizeOf();
  564. FSHORT fsAlloc = HMGR_ALLOC_ALT_LOCK|HMGR_NO_ZERO_INIT;
  565. if (pvBitsIn == (PVOID) NULL)
  566. {
  567. LONGLONG eq;
  568. if (bCompressed)
  569. eq = (LONGLONG)(ULONGLONG) pdbmi->cjBits;
  570. else
  571. eq = Int32x32To64(pdbmi->cyBitmap, cjScanTemp);
  572. eq += (LONGLONG)(ULONGLONG) size;
  573. if (eq > LONG_MAX)
  574. {
  575. WARNING("Attempting to allocate > 4Gb\n");
  576. return(FALSE);
  577. }
  578. //
  579. // if it is UMPD and size > PAGE_SIZE, we always allocate in user memory
  580. //
  581. //
  582. // make sure no one will change KM_SIZE_MAX later and mess things up
  583. //
  584. ASSERTGDI(PAGE_SIZE < KM_SIZE_MAX, "bad KM_SIZE_MAX\n");
  585. if ((pdbmi->fl & UMPD_SURFACE) && (eq > PAGE_SIZE))
  586. pdbmi->fl |= BMF_USERMEM;
  587. // see if we need to allocate the bits out of USER memory
  588. if (pdbmi->fl & BMF_USERMEM)
  589. {
  590. pvBitsIn = EngAllocUserMem((LONG) eq,'mbuG'); //Gubm
  591. if (pvBitsIn == NULL)
  592. return(FALSE);
  593. }
  594. else if ((pdbmi->fl & BMF_KMSECTION) || (eq > KM_SIZE_MAX))
  595. {
  596. //
  597. // Kernel-mode pool is limited in size and prone to fragmentation.
  598. // For this reason, we will automatically allocate 'large' bitmaps
  599. // as sections, which will not be charged against kernel-mode
  600. // pool.
  601. //
  602. // We also allow the driver to specify BMF_KMSECTION -- this is
  603. // specifically for the ModeX driver to allow it to map its shadow
  604. // buffer into user-mode.
  605. //
  606. //
  607. //Sundown, change from SIZE_T to LONG, we return false earlier if > 4GB
  608. //
  609. pvBitsIn = pvAllocateKernelSection((LONG)eq,'mbkG');
  610. if (pvBitsIn != NULL)
  611. {
  612. //
  613. // mark surface as KM SECTION
  614. //
  615. flAllocateSection = BMF_KMSECTION;
  616. }
  617. }
  618. //
  619. // combine size and allocate from pool
  620. //
  621. if (pvBitsIn == NULL)
  622. {
  623. size = (ULONGSIZE_T) eq;
  624. if ((pdbmi->fl & BMF_NOZEROINIT) == 0)
  625. {
  626. fsAlloc = HMGR_ALLOC_ALT_LOCK;
  627. }
  628. }
  629. }
  630. else
  631. {
  632. ASSERTGDI(!(pdbmi->fl & BMF_USERMEM),"flags error\n");
  633. }
  634. ps = (PSURFACE)ALLOCOBJ(size,SURF_TYPE,!(fsAlloc & HMGR_NO_ZERO_INIT));
  635. if (ps == NULL)
  636. {
  637. WARNING("failed memory alloc\n");
  638. bRet = FALSE;
  639. }
  640. else
  641. {
  642. //
  643. // Initialize the surf fields
  644. //
  645. SIZEL sizlTemp;
  646. sizlTemp.cx = pdbmi->cxBitmap;
  647. sizlTemp.cy = pdbmi->cyBitmap;
  648. ps->sizl(sizlTemp);
  649. ps->iType(STYPE_BITMAP);
  650. ps->hSecureUMPD = 0;
  651. if (pdbmi->hpal != (HPALETTE) 0)
  652. {
  653. EPALOBJ palSurf(pdbmi->hpal);
  654. ASSERTGDI(palSurf.bValid(), "ERROR invalid palette");
  655. //
  656. // Set palette into surface.
  657. //
  658. ps->ppal(palSurf.ppalGet());
  659. //
  660. // Reference count it by making sure it is not unlocked.
  661. //
  662. palSurf.ppalSet((PPALETTE) NULL); // It won't be unlocked
  663. }
  664. else
  665. {
  666. ps->ppal((PPALETTE) NULL);
  667. }
  668. //
  669. // Initialize the BITMAP fields
  670. //
  671. ps->iFormat(pdbmi->iFormat);
  672. ps->fjBitmap(((pdbmi->fl) & (BMF_TOPDOWN | BMF_USERMEM)) |
  673. (flAllocateSection));
  674. ps->DIB.hDIBSection = hDIBSection;
  675. ps->DIB.dwOffset = dsOffset;
  676. ps->DIB.hSecure = hSecure;
  677. ps->DIB.dwDIBColorSpace = dwColorSpace;
  678. ps->dhsurf((DHSURF) 0);
  679. ps->dhpdev((DHPDEV) 0);
  680. ps->flags(pdbmi->fl & UMPD_SURFACE);
  681. ps->pwo((EWNDOBJ *) NULL);
  682. sizlTemp.cx = 0;
  683. sizlTemp.cy = 0;
  684. ps->sizlDim(sizlTemp);
  685. ps->hdev((HDEV) 0);
  686. ps->EBitmap.hdc = (HDC) 0;
  687. ps->EBitmap.cRef = 0;
  688. ps->EBitmap.hpalHint = 0;
  689. ps->pdcoAA = NULL;
  690. if (hSecure != (HANDLE) NULL)
  691. {
  692. //
  693. // Set flag for DIBSECTION so driver doesn't cache it.
  694. // because we don't know to increment the uniqueness
  695. // when the app writes on it.
  696. //
  697. ps->so.fjBitmap |= BMF_DONTCACHE;
  698. }
  699. //
  700. // Initialize the DIB fields
  701. //
  702. if (pvBitsIn == (PVOID) NULL)
  703. {
  704. ps->pvBits((PVOID) (((ULONG_PTR) ps) + SURFACE::tSizeOf()));
  705. }
  706. else
  707. {
  708. ps->pvBits(pvBitsIn);
  709. }
  710. if ((pdbmi->iFormat != BMF_8RLE) &&
  711. (pdbmi->iFormat != BMF_4RLE) &&
  712. (pdbmi->iFormat != BMF_JPEG) &&
  713. (pdbmi->iFormat != BMF_PNG ))
  714. {
  715. ps->cjBits(pdbmi->cyBitmap * cjScanTemp);
  716. if (pdbmi->fl & BMF_TOPDOWN)
  717. {
  718. ps->lDelta(cjScanTemp);
  719. ps->pvScan0(ps->pvBits());
  720. }
  721. else
  722. {
  723. ps->lDelta(-(LONG)cjScanTemp);
  724. ps->pvScan0((PVOID) (((PBYTE) ps->pvBits()) +
  725. (ps->cjBits() - cjScanTemp)));
  726. }
  727. }
  728. else
  729. {
  730. //
  731. // lDelta is 0 because RLE's don't have scanlines.
  732. //
  733. ps->lDelta(0);
  734. ps->cjBits(pdbmi->cjBits);
  735. //
  736. // pvScan0 is ignored for JPEG's and PNG's
  737. //
  738. if ((pdbmi->iFormat != BMF_JPEG) && (pdbmi->iFormat != BMF_PNG))
  739. ps->pvScan0(ps->pvBits());
  740. else
  741. ps->pvScan0(NULL);
  742. }
  743. //
  744. // Set initial uniqueness. Not 0 because that means don't cache it.
  745. //
  746. // We used to always set the uniqueness to 1 on creation, but the
  747. // NetMeeting folks ran into tool-bar scenarios where the buttons
  748. // were being created and deleted on every repaint and eventually we
  749. // would run out of uniqueness bits in the handles. So the end
  750. // result would be that the NetMeeting driver would see a surface
  751. // with a handle the same as the one they cached, and with an iUniq
  752. // the same as the one they cached (specifically, a value of '1') --
  753. // but the cached bitmap would not match the actual bitmap bits!
  754. //
  755. // We fix this by always creating the surface with a unique uniqueness.
  756. // Note that it's still possible to get different surfaces with the
  757. // same uniqueness because drawing calls simply increment the surface
  758. // uniqueness, not the global uniqueness. However, this change will
  759. // make the possibility of the driver mis-caching a bitmap extremely
  760. // unlikely.
  761. //
  762. ps->iUniq(ulGetNewUniqueness(_ulGlobalSurfaceUnique));
  763. //
  764. // Now that the surface is set up, give it a handle
  765. //
  766. if (HmgInsertObject(ps, fsAlloc, SURF_TYPE) == 0)
  767. {
  768. WARNING("failed HmgInsertObject\n");
  769. //
  770. // Don't forget to decrement reference count on the palette before
  771. // freeing the surface
  772. //
  773. if (ps->ppal())
  774. {
  775. XEPALOBJ pal(ps->ppal());
  776. pal.vUnrefPalette();
  777. ps->ppal((PPALETTE) NULL); // Not necessary, but makes the code cleaner
  778. }
  779. FREEOBJ(ps, SURF_TYPE);
  780. ps = NULL;
  781. bRet = FALSE;
  782. }
  783. else
  784. {
  785. ps->hsurf(ps->hGet());
  786. #if TRACE_SURFACE_ALLOCS
  787. if (TRACED_SURFACE::bEnabled())
  788. {
  789. TRACED_SURFACE *pts = (TRACED_SURFACE *)ps;
  790. RtlZeroMemory(&pts->Trace, sizeof(pts->Trace));
  791. pts->Trace.pProcess = PsGetCurrentProcess();
  792. pts->Trace.pThread = PsGetCurrentThread();
  793. pts->Trace.KernelLength = RtlWalkFrameChain((PVOID *)pts->Trace.Chain,
  794. lengthof(pts->Trace.Chain),
  795. 0);
  796. ULONG MaxUserLength;
  797. PVOID *UserChain;
  798. PVOID TmpUserChain[TRACE_SURFACE_MIN_USER_CHAIN];
  799. MaxUserLength = lengthof(pts->Trace.Chain) - pts->Trace.KernelLength;
  800. if (MaxUserLength < TRACE_SURFACE_MIN_USER_CHAIN)
  801. {
  802. MaxUserLength = TRACE_SURFACE_MIN_USER_CHAIN;
  803. UserChain = TmpUserChain;
  804. }
  805. else
  806. {
  807. UserChain = (PVOID *)&pts->Trace.Chain[pts->Trace.KernelLength];
  808. }
  809. pts->Trace.UserLength = RtlWalkFrameChain(UserChain,
  810. MaxUserLength,
  811. 1);
  812. if (UserChain == TmpUserChain && pts->Trace.UserLength != 0)
  813. {
  814. pts->Trace.KernelLength = min(pts->Trace.KernelLength, (ULONG) lengthof(pts->Trace.Chain) - pts->Trace.UserLength);
  815. RtlCopyMemory(&pts->Trace.Chain[pts->Trace.KernelLength],
  816. UserChain,
  817. pts->Trace.UserLength);
  818. }
  819. #if TRACE_SURFACE_USER_CHAIN_IN_UM
  820. if (pts->bUMEnabled())
  821. {
  822. SurfaceUserTrace *pSurfUserTrace;
  823. PENTRY pentTmp;
  824. UINT uiIndex = (UINT) HmgIfromH(pts->hGet());
  825. pentTmp = &gpentHmgr[uiIndex];
  826. ASSERTGDI(pentTmp->pUser == NULL,
  827. "SURFACE's pUser is already being used.\n");
  828. pSurfUserTrace = (SurfaceUserTrace *)EngAllocUserMem(sizeof(SurfaceUserTrace), 'rTSG');
  829. if (pSurfUserTrace != NULL)
  830. {
  831. pts->Trace.UserChainAllocated = 1;
  832. pts->Trace.UserChainNotRead = 1;
  833. pSurfUserTrace->MaxLength = lengthof(pSurfUserTrace->Chain);
  834. pSurfUserTrace->UserLength = 0;
  835. pentTmp->pUser = pSurfUserTrace;
  836. }
  837. }
  838. #endif
  839. }
  840. #endif
  841. }
  842. }
  843. //
  844. // cleanup in failure case
  845. //
  846. if (!bRet && pvBitsIn)
  847. {
  848. if (pdbmi->fl & BMF_USERMEM)
  849. {
  850. EngFreeUserMem(pvBitsIn);
  851. }
  852. else if (flAllocateSection & BMF_KMSECTION)
  853. {
  854. vFreeKernelSection(pvBitsIn);
  855. }
  856. }
  857. return(bRet);
  858. }
  859. /******************************Public*Routine******************************\
  860. *
  861. * SURFMEM::~SURFMEM
  862. *
  863. * Description:
  864. *
  865. * SURFACE Destructor, takes appropriate action based
  866. * on allocation flags
  867. *
  868. \**************************************************************************/
  869. SURFMEM::~SURFMEM()
  870. {
  871. if (ps != (SURFACE*) NULL)
  872. {
  873. //
  874. // what type of surface
  875. //
  876. if (AllocationFlags & SURFACE_KEEP)
  877. {
  878. DEC_SHARE_REF_CNT(ps);
  879. } else {
  880. if (AllocationFlags & SURFACE_DIB)
  881. {
  882. //
  883. // free selected palette
  884. //
  885. if (ps->ppal() != NULL)
  886. {
  887. XEPALOBJ pal(ps->ppal());
  888. pal.vUnrefPalette();
  889. }
  890. }
  891. //
  892. // remove object from hmgr and free
  893. //
  894. if (!HmgRemoveObject((HOBJ) ps->hGet(), 0, 1, TRUE, SURF_TYPE))
  895. {
  896. ASSERTGDI(TRUE, "Failed to remove object in ~DIBMEMOBJ");
  897. }
  898. PVOID pvBitsOld = ps->pvBits();
  899. FLONG fl = ps->fjBitmap();
  900. BOOL bUMPD = ps->bUMPD();
  901. FREEOBJ(ps, SURF_TYPE);
  902. if (fl & BMF_USERMEM)
  903. {
  904. if (bUMPD && pvBitsOld)
  905. {
  906. EngFreeUserMem(pvBitsOld);
  907. }
  908. else if (!bUMPD)
  909. {
  910. RIP("SURFMEM destructor has BMF_USERMEM set\n");
  911. }
  912. }
  913. else if (fl & BMF_KMSECTION)
  914. {
  915. vFreeKernelSection(pvBitsOld);
  916. }
  917. }
  918. }
  919. }
  920. #if DBG
  921. void SURFACE::vDump()
  922. {
  923. DbgPrint("SURFACE @ %-#x\n", this);
  924. DbgPrint(" so.dhsurf = %-#x\n" , so.dhsurf);
  925. DbgPrint(" so.hsurf = %-#x\n" , so.hsurf);
  926. DbgPrint(" so.dhpdev = %-#x\n" , so.dhpdev);
  927. DbgPrint(" so.hdev = %-#x\n" , so.hdev);
  928. DbgPrint(" so.sizlBitmap = %u %u\n" , so.sizlBitmap.cx , so.sizlBitmap.cy);
  929. DbgPrint(" so.cjBits = %u\n" , so.cjBits);
  930. DbgPrint(" so.pvBits = %-#x\n" , so.pvBits);
  931. DbgPrint(" so.pvScan0 = %-#x\n" , so.pvScan0);
  932. DbgPrint(" so.lDelta = %d\n" , so.lDelta);
  933. DbgPrint(" so.iUniq = %u\n" , so.iUniq);
  934. DbgPrint(" so.iBitmapFormat = %u\n" , so.iBitmapFormat);
  935. DbgPrint(" so.iType = %u\n" , so.iType);
  936. DbgPrint(" so.fjBitmap = %-#x\n" , so.fjBitmap);
  937. DbgPrint(" SurfFlags = %-#x\n" , SurfFlags);
  938. DbgPrint(" pPal = %-#x\n" , pPal);
  939. DbgPrint(" pWo = %-#x\n" , pWo);
  940. DbgPrint(" EBitmap.sizlDim = %u %u\n" , EBitmap.sizlDim.cx, EBitmap.sizlDim.cy);
  941. DbgPrint(" EBitmap.hdc = %-#x\n" , EBitmap.hdc);
  942. DbgPrint(" EBitmap.cRef = %-#x\n" , EBitmap.cRef);
  943. DbgPrint(" DIB.hDIBSection = %-#x\n" , DIB.hDIBSection);
  944. DbgPrint(" DIB.hSecure = %-#x\n" , DIB.hSecure);
  945. }
  946. #endif
  947. #if TRACE_SURFACE_ALLOCS
  948. #define TRACE_SURFACE_KM_ENABLE_MASK 0x00000001
  949. #define TRACE_SURFACE_UM_ENABLE_MASK 0x00000002
  950. VOID TRACED_SURFACE::vInit()
  951. {
  952. NTSTATUS Status;
  953. DWORD dwDefaultValue = 0;
  954. DWORD dwEnableStack;
  955. // Check registry key to determine whether to enable stack traces
  956. // or not for SURFACE allocations
  957. RTL_QUERY_REGISTRY_TABLE QueryTable[] =
  958. {
  959. {NULL, RTL_QUERY_REGISTRY_DIRECT, L"EnableSurfaceTrace",
  960. &dwEnableStack, REG_DWORD, &dwDefaultValue, sizeof(dwDefaultValue)},
  961. {NULL, 0, NULL}
  962. };
  963. if (eTraceStatus == SURFACE_TRACING_UNINITIALIZED)
  964. {
  965. Status = RtlQueryRegistryValues(RTL_REGISTRY_WINDOWS_NT,
  966. L"GRE_Initialize",
  967. &QueryTable[0],
  968. NULL,
  969. NULL);
  970. if (NT_SUCCESS(Status))
  971. {
  972. if (dwEnableStack & TRACE_SURFACE_KM_ENABLE_MASK)
  973. {
  974. eTraceStatus = SURFACE_TRACING_ENABLED;
  975. SURFACE::tSize = sizeof(TRACED_SURFACE);
  976. if (dwEnableStack & TRACE_SURFACE_UM_ENABLE_MASK)
  977. {
  978. #if TRACE_SURFACE_USER_CHAIN_IN_UM
  979. eUMTraceStatus = SURFACE_TRACING_ENABLED;
  980. #else
  981. WARNING("GDI: UM Surface Trace requested, but not available.\n");
  982. #endif
  983. }
  984. else
  985. {
  986. #if TRACE_SURFACE_USER_CHAIN_IN_UM
  987. eUMTraceStatus = SURFACE_TRACING_DISABLED;
  988. #endif
  989. }
  990. }
  991. else
  992. {
  993. eTraceStatus = SURFACE_TRACING_DISABLED;
  994. #if TRACE_SURFACE_USER_CHAIN_IN_UM
  995. eUMTraceStatus = SURFACE_TRACING_DISABLED;
  996. #endif
  997. }
  998. }
  999. }
  1000. else
  1001. {
  1002. RIP("TRACED_SURFACE::vInit: Tracing already initialized.\n");
  1003. }
  1004. }
  1005. #if TRACE_SURFACE_USER_CHAIN_IN_UM
  1006. VOID TRACED_SURFACE::vProcessStackFromUM(
  1007. BOOL bFreeUserMem
  1008. )
  1009. {
  1010. GDIFunctionID(TRACED_SURFACE::vProcessStackFromUM);
  1011. if (Trace.UserChainAllocated)
  1012. {
  1013. if (Trace.UserChainNotRead || bFreeUserMem)
  1014. {
  1015. PENTRY pentTmp;
  1016. UINT uiIndex = (UINT) HmgIfromH(hHmgr);
  1017. ULONG ulNewKernelLength;
  1018. ULONG ulMaxUserLength;
  1019. ULONG ulMaxLength = lengthof(Trace.Chain);
  1020. if (uiIndex < gcMaxHmgr)
  1021. {
  1022. pentTmp = &gpentHmgr[uiIndex];
  1023. if (pentTmp->pUser != NULL)
  1024. {
  1025. if (Trace.UserChainNotRead)
  1026. {
  1027. SurfaceUserTrace *pUserTrace = (SurfaceUserTrace *)pentTmp->pUser;
  1028. __try {
  1029. if (pUserTrace->UserLength > 0)
  1030. {
  1031. ulMaxUserLength = min(pUserTrace->UserLength, ulMaxLength);
  1032. ulNewKernelLength = ulMaxLength - ulMaxUserLength;
  1033. if (ulNewKernelLength > Trace.KernelLength)
  1034. {
  1035. ulNewKernelLength = Trace.KernelLength;
  1036. }
  1037. RtlCopyMemory(&Trace.Chain[ulNewKernelLength],
  1038. pUserTrace->Chain,
  1039. ulMaxUserLength);
  1040. Trace.UserLength = ulMaxUserLength;
  1041. Trace.UserChainNotRead = 0;
  1042. Trace.KernelLength = ulNewKernelLength;
  1043. }
  1044. }
  1045. __except(EXCEPTION_EXECUTE_HANDLER)
  1046. {
  1047. WARNING("Couldn't read UM stored stack trace.");
  1048. }
  1049. }
  1050. if (bFreeUserMem)
  1051. {
  1052. Trace.UserChainAllocated = 0;
  1053. EngFreeUserMem(pentTmp->pUser);
  1054. pentTmp->pUser = NULL;
  1055. }
  1056. }
  1057. else
  1058. {
  1059. RIP("Lost track of UserMem trace allocation.\n");
  1060. Trace.UserChainAllocated = 0;
  1061. }
  1062. }
  1063. }
  1064. }
  1065. }
  1066. #endif
  1067. #endif