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.

1064 lines
20 KiB

  1. /*++
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. umpdobj.cxx
  5. Abstract:
  6. Object and memory management for um-km thunking
  7. Environment:
  8. Windows NT user mode driver support
  9. Revision History:
  10. 09/16/97 -davidx-
  11. Created it.
  12. --*/
  13. #include "precomp.hxx"
  14. #if !defined(_GDIPLUS_)
  15. //
  16. // Maximum number of pages for UMPD user mode memory heap
  17. //
  18. #define MAX_UMPD_HEAP 1024
  19. //
  20. // Create or initialize a UMPD user mode memory heap
  21. //
  22. PUMPDHEAP
  23. UMPDOBJ::CreateUMPDHeap(void)
  24. {
  25. PUMPDHEAP pHeap;
  26. //
  27. // Allocate memory to hold the UMPDHEAP structure if necessary
  28. //
  29. if (!(pHeap = (PUMPDHEAP) PALLOCMEM(sizeof(UMPDHEAP), UMPD_MEMORY_TAG)))
  30. return NULL;
  31. //
  32. // Reserve the maximum address range if needed
  33. //
  34. NTSTATUS Status;
  35. PVOID p = NULL;
  36. SIZE_T cj = MAX_UMPD_HEAP * PAGE_SIZE;
  37. Status = ZwAllocateVirtualMemory(
  38. NtCurrentProcess(),
  39. &p,
  40. 0,
  41. &cj,
  42. MEM_RESERVE,
  43. PAGE_READWRITE);
  44. if (NT_SUCCESS(Status))
  45. pHeap->pAddress = p;
  46. else
  47. {
  48. VFREEMEM(pHeap);
  49. return NULL;
  50. }
  51. pHeap->AllocSize = 0;
  52. return pHeap;
  53. }
  54. VOID
  55. UMPDOBJ::ResetHeap()
  56. {
  57. ASSERTGDI(bWOW64(), "UMPDOBJ__ResetHeap called by none WOW64 printing\n");
  58. PROXYPORT proxyport(m_proxyPort);
  59. proxyport.HeapInit();
  60. }
  61. PUMPDHEAP
  62. UMPDOBJ::InitUMPDHeap(
  63. PUMPDHEAP pHeap
  64. )
  65. {
  66. pHeap->AllocSize = 0;
  67. return pHeap;
  68. }
  69. //
  70. // Grow a UMPD user mode memory heap by one more page
  71. //
  72. BOOL
  73. UMPDOBJ::GrowUMPDHeap(
  74. PUMPDHEAP pHeap,
  75. ULONG ulBytesNeeded
  76. )
  77. {
  78. PVOID p;
  79. SIZE_T NewCommitSize;
  80. HANDLE hNewSecure;
  81. NTSTATUS Status;
  82. NewCommitSize = ROUNDUP_MULTIPLE(pHeap->CommitSize + ulBytesNeeded, PAGE_SIZE);
  83. if (NewCommitSize > MAX_UMPD_HEAP * PAGE_SIZE)
  84. {
  85. WARNING("Not enough space for UMPD user mode memory heap\n");
  86. return FALSE;
  87. }
  88. //
  89. // Commit one more page and secure it
  90. //
  91. p = pHeap->pAddress;
  92. Status = ZwAllocateVirtualMemory(
  93. NtCurrentProcess(),
  94. &p,
  95. 0,
  96. &NewCommitSize,
  97. MEM_COMMIT,
  98. PAGE_READWRITE);
  99. hNewSecure = NT_SUCCESS(Status) ?
  100. MmSecureVirtualMemory(p, NewCommitSize, PAGE_READWRITE) :
  101. NULL;
  102. if (hNewSecure == NULL)
  103. {
  104. WARNING("Failed to commit/secure more UMPD user mode memory\n");
  105. return FALSE;
  106. }
  107. if (pHeap->hSecure)
  108. MmUnsecureVirtualMemory(pHeap->hSecure);
  109. pHeap->hSecure = hNewSecure;
  110. pHeap->CommitSize = NewCommitSize;
  111. return TRUE;
  112. }
  113. //
  114. // Destroy a UMPD user mode memory heap
  115. //
  116. VOID
  117. DestroyUMPDHeap(
  118. PUMPDHEAP pHeap
  119. )
  120. {
  121. if (pHeap != NULL)
  122. {
  123. if (pHeap->hSecure)
  124. MmUnsecureVirtualMemory(pHeap->hSecure);
  125. if (pHeap->pAddress != NULL)
  126. {
  127. PVOID pv = pHeap->pAddress;
  128. SIZE_T cj = MAX_UMPD_HEAP * PAGE_SIZE;
  129. ZwFreeVirtualMemory(NtCurrentProcess(), &pv, &cj, MEM_RELEASE);
  130. }
  131. VFREEMEM(pHeap);
  132. }
  133. }
  134. //
  135. // UMPDOBJ constructor
  136. //
  137. BOOL
  138. UMPDOBJ::Init()
  139. {
  140. PW32THREAD pThread;
  141. PW32PROCESS pw32Process;
  142. ULONG_PTR pPeb32;
  143. #if defined(_WIN64)
  144. BOOL bWOW64 = TRUE;
  145. #endif
  146. RtlZeroMemory(this, sizeof(UMPDOBJ));
  147. m_magic = UMPD_MEMORY_TAG;
  148. pThread = W32GetCurrentThread();
  149. m_pNext = (PUMPDOBJ) pThread->pUMPDObjs;
  150. #if defined(_WIN64)
  151. if (pThread->pProxyPort == NULL)
  152. {
  153. pw32Process = W32GetCurrentProcess();
  154. if (pw32Process->W32PF_Flags & W32PF_WOW64)
  155. {
  156. PROXYPORT proxyport(MAX_UMPD_HEAP * PAGE_SIZE);
  157. if (proxyport.bValid())
  158. {
  159. pThread->pProxyPort = proxyport.GetProxyPort();
  160. }
  161. else
  162. {
  163. return FALSE;
  164. }
  165. }
  166. else
  167. bWOW64 = FALSE;
  168. }
  169. if (bWOW64)
  170. {
  171. m_proxyPort = (ProxyPort *) pThread->pProxyPort;
  172. ResetHeap();
  173. }
  174. else
  175. #endif
  176. {
  177. // WINBUG 364408 what happens if these heaps fail to initialize?
  178. if (m_pNext == NULL)
  179. {
  180. if(pThread->pUMPDHeap == NULL)
  181. {
  182. pThread->pUMPDHeap = m_pHeap = CreateUMPDHeap();
  183. }
  184. else
  185. {
  186. m_pHeap = InitUMPDHeap((PUMPDHEAP) pThread->pUMPDHeap);
  187. }
  188. }
  189. else
  190. {
  191. m_pHeap = CreateUMPDHeap();
  192. }
  193. }
  194. m_clientTid = (PW32THREAD)PsGetCurrentThread();
  195. m_clientPid = W32GetCurrentPID();
  196. if (HmgInsertObject(this, HMGR_ALLOC_ALT_LOCK, UMPD_TYPE) == NULL)
  197. {
  198. return FALSE;
  199. }
  200. pThread->pUMPDObjs = (PVOID) this;
  201. return TRUE;
  202. }
  203. //
  204. // UMPDOBJ destructor
  205. //
  206. VOID UMPDOBJ::Cleanup()
  207. {
  208. W32GetCurrentThread()->pUMPDObjs = (PVOID) m_pNext;
  209. if (HmgRemoveObject((HOBJ)hGet(), 0, 1, TRUE, UMPD_TYPE))
  210. {
  211. //
  212. // Delete any PATHOBJ's returned by CLIPOBJ_ppoGetPath
  213. //
  214. if (m_poClip.kmobj != NULL)
  215. EngDeletePath((PATHOBJ *) m_poClip.kmobj);
  216. //
  217. // Destroy UMPD user mode memory heap if necessary
  218. //
  219. if(!bWOW64())
  220. {
  221. if (m_pNext != NULL && m_pHeap != NULL)
  222. DestroyUMPDHeap(m_pHeap);
  223. }
  224. //
  225. // Unmap any cached font file view
  226. //
  227. if (m_pvFontBase != NULL)
  228. MmUnmapViewOfSection(m_pFontProcess, m_pvFontBase);
  229. vFreeFontLinks();
  230. }
  231. else
  232. {
  233. ASSERTGDI(FALSE, "UMPDOBJ::Cleanup() leaking UMPD handle\n");
  234. }
  235. }
  236. BOOL UMPDOBJ::pxlo(
  237. XLATEOBJ **ppxlo
  238. )
  239. /*++
  240. Routine Description:
  241. Thunk an XLATEOBJ to user mode
  242. Arguments:
  243. ppxlo - Address of the variable containing the pointer to the kernel mode
  244. XLATEOBJ to be thunked. Upon returning from this function, the variable
  245. contains the user mode object corresponding to the specified kernel mode object.
  246. Return Value:
  247. TRUE if successful, FALSE otherwise
  248. --*/
  249. {
  250. XLATEOBJ *kmobj;
  251. PULONG pulXlate;
  252. if ((kmobj = *ppxlo) == NULL)
  253. return TRUE;
  254. //
  255. // Copy the color lookup table
  256. //
  257. if (kmobj->cEntries)
  258. {
  259. PULONG pulSrc;
  260. if ((pulXlate = (PULONG) AllocUserMem(kmobj->cEntries * sizeof(ULONG))) == NULL ||
  261. (pulSrc = kmobj->pulXlate) == NULL &&
  262. (pulSrc = XLATEOBJ_piVector(kmobj)) == NULL)
  263. {
  264. WARNING("Couldn't get XLATEOBJ color lookup table\n");
  265. return FALSE;
  266. }
  267. RtlCopyMemory(GetKernelPtr(pulXlate), pulSrc, kmobj->cEntries * sizeof(ULONG));
  268. }
  269. else
  270. pulXlate = NULL;
  271. //
  272. // Perform the standard object thunk
  273. //
  274. if (!ThunkDDIOBJ(&m_xlo, (PVOID *) ppxlo, sizeof(XLATEOBJ)))
  275. return FALSE;
  276. XLATEOBJ * pxlo = (XLATEOBJ *) GetKernelPtr(*ppxlo);
  277. pxlo->pulXlate = pulXlate;
  278. return TRUE;
  279. }
  280. BOOL UMPDOBJ::pso(
  281. PDDIOBJMAP pMap,
  282. SURFOBJ **ppso,
  283. BOOL bLargeBitmap
  284. )
  285. /*++
  286. Routine Description:
  287. Thunk an SURFOBJ to user mode
  288. Arguments:
  289. pMap - Address of the um-to-km object mapping structure
  290. ppso - Address of the variable containing the pointer to the kernel mode
  291. SURFOBJ to be thunked. Upon returning from this function, the variable
  292. contains the user mode object corresponding to the specified kernel mode object.
  293. Return Value:
  294. TRUE if successful, FALSE otherwise
  295. --*/
  296. {
  297. SURFOBJ *kmobj;
  298. PVOID pvBits;
  299. if ((kmobj = *ppso) == NULL)
  300. return TRUE;
  301. //
  302. // If we're thunking a bitmap surface and the bitmap memory
  303. // is in kernel address space, we need to make a copy of it
  304. // in user address space.
  305. //
  306. if ((pvBits = kmobj->pvBits) != NULL &&
  307. (kmobj->iType == STYPE_BITMAP) &&
  308. bNeedThunk(kmobj->pvBits) &&
  309. !(bWOW64() && bLargeBitmap))
  310. {
  311. if (! ThunkMemBlock(&pvBits, kmobj->cjBits))
  312. return FALSE;
  313. }
  314. //
  315. // Perform the standard object thunk
  316. //
  317. if (! ThunkDDIOBJ(pMap, (PVOID *) ppso, sizeof(SURFOBJ)))
  318. return FALSE;
  319. SURFOBJ * pso = (SURFOBJ *) GetKernelPtr(*ppso);
  320. if (pvBits != kmobj->pvBits)
  321. {
  322. pso->pvBits = pvBits;
  323. pso->pvScan0 = (PBYTE) pvBits + ((PBYTE) kmobj->pvScan0 - (PBYTE) kmobj->pvBits);
  324. //
  325. // umpd64 only
  326. //
  327. if (bWOW64())
  328. {
  329. kmobj->pvBits = pvBits;
  330. kmobj->pvScan0 = pso->pvScan0;
  331. }
  332. }
  333. return TRUE;
  334. }
  335. BOOL UMPDOBJ::pstro(
  336. STROBJ **ppstro
  337. )
  338. /*++
  339. Routine Description:
  340. Thunk an STROBJ to user mode
  341. Arguments:
  342. ppstro - Address of the variable containing the pointer to the kernel mode
  343. STROBJ to be thunked. Upon returning from this function, the variable
  344. contains the user mode object corresponding to the specified kernel mode object.
  345. Return Value:
  346. TRUE if successful, FALSE otherwise
  347. --*/
  348. {
  349. STROBJ *kmobj;
  350. PWSTR pwszOrg;
  351. GLYPHPOS *pgp;
  352. if ((kmobj = *ppstro) == NULL)
  353. return TRUE;
  354. //
  355. // Thunk STROBJ.pwszOrg field
  356. //
  357. if ((pwszOrg = kmobj->pwszOrg) != NULL &&
  358. !ThunkMemBlock((PVOID *) &pwszOrg, sizeof(WCHAR) * kmobj->cGlyphs))
  359. {
  360. return FALSE;
  361. }
  362. //
  363. // Thunk STROBJ.pgp field
  364. //
  365. if ((pgp = kmobj->pgp) != NULL)
  366. {
  367. if (! ThunkMemBlock((PVOID *) &pgp, sizeof(GLYPHPOS) * kmobj->cGlyphs))
  368. return FALSE;
  369. //
  370. // NULL out GLYPHPOS.pgdf field to force the driver
  371. // to call FONTOBJ_cGetGlyphs.
  372. //
  373. GLYPHPOS *kmpgp = (GLYPHPOS *) GetKernelPtr(pgp);
  374. for (ULONG i=0; i < kmobj->cGlyphs; i++)
  375. kmpgp[i].pgdf = NULL;
  376. }
  377. //
  378. // Perform the standard object thunk
  379. //
  380. if (!ThunkDDIOBJ(&m_stro, (PVOID *) ppstro, sizeof(STROBJ)))
  381. return FALSE;
  382. STROBJ * pstro = (STROBJ *) GetKernelPtr(*ppstro);
  383. pstro->pwszOrg = pwszOrg;
  384. pstro->pgp = pgp;
  385. return TRUE;
  386. }
  387. BOOL UMPDOBJ::ThunkLINEATTRS(
  388. PLINEATTRS *pplineattrs
  389. )
  390. /*++
  391. Routine Description:
  392. Thunk a LINEATTRS structure from kernel mode to user mode
  393. Arguments:
  394. pplineattrs - On input, contains the address of the kernel mode
  395. LINEATTRS structure to be thunked. On output, contains the
  396. address of the thunked user mode copy of LINEATTRS structure.
  397. Return Value:
  398. TRUE if successful, FALSE if there is an error
  399. --*/
  400. {
  401. PLINEATTRS plineattrsKM;
  402. PVOID pStyle;
  403. ULONG ulStyleSize;
  404. if ((plineattrsKM = *pplineattrs) == NULL)
  405. return TRUE;
  406. pStyle = plineattrsKM->pstyle;
  407. ulStyleSize = plineattrsKM->cstyle * sizeof(FLOAT_LONG);
  408. if (! ThunkMemBlock((PVOID *) pplineattrs, sizeof(LINEATTRS)) ||
  409. ! ThunkMemBlock(&pStyle, ulStyleSize))
  410. {
  411. return FALSE;
  412. }
  413. else
  414. {
  415. PLINEATTRS plineattrs = (PLINEATTRS) GetKernelPtr(*pplineattrs);
  416. plineattrs->pstyle = (PFLOAT_LONG) pStyle;
  417. return TRUE;
  418. }
  419. }
  420. PATHOBJ *UMPDOBJ::GetCLIPOBJPath(
  421. CLIPOBJ *pco
  422. )
  423. /*++
  424. Routine Description:
  425. Implement CLIPOBJ_ppoGetPath for user mode printer driver
  426. Arguments:
  427. pco - Points to a user mode CLIPOBJ
  428. Return Value:
  429. Pointer to user mode PATHOBJ structure
  430. NULL if there is an error
  431. --*/
  432. {
  433. PATHOBJ *ppokm, *ppoum;
  434. //
  435. // Note: During the same DDI entrypoint, drivers must
  436. // call EngDeletePath after each CLIPOBJ_ppoGetPath.
  437. //
  438. if (m_poClip.umobj ||
  439. ! (ppokm = ppoum = (pco = GetDDIOBJ(pco)) ? CLIPOBJ_ppoGetPath(pco) : NULL))
  440. {
  441. return NULL;
  442. }
  443. if (! ppoClip(&ppoum))
  444. {
  445. EngDeletePath(ppokm);
  446. return NULL;
  447. }
  448. return ppoum;
  449. }
  450. VOID UMPDOBJ::DeleteCLIPOBJPath(
  451. PATHOBJ *ppo
  452. )
  453. /*++
  454. Routine Description:
  455. Implement EngDeletePath for user mode printer driver
  456. Arguments:
  457. ppo - Points to user mode PATHOBJ to be deleted.
  458. This pointer must come from GetCLIPOBJPath.
  459. Return Value:
  460. NONE
  461. --*/
  462. {
  463. if (ppo != NULL && ppo == m_poClip.umobj)
  464. {
  465. EngDeletePath((PATHOBJ *) m_poClip.kmobj);
  466. m_poClip.umobj = m_poClip.kmobj = NULL;
  467. }
  468. }
  469. CLIPOBJ *UMPDOBJ::CreateCLIPOBJ()
  470. /*++
  471. Routine Description:
  472. Implement EngCreateClip for user-mode drivers
  473. Arguments:
  474. NONE
  475. Return Value:
  476. Pointer to user mode CLIPOBJ structure
  477. NULL if there is an error
  478. --*/
  479. {
  480. CLIPOBJ *pcokm, *pcoum;
  481. //
  482. // Note: During the same DDI entrypoint, drivers must
  483. // call EngDeleteClip after each EngCreateClip.
  484. //
  485. if (m_coCreated.umobj ||
  486. ! (pcokm = pcoum = EngCreateClip()))
  487. {
  488. return NULL;
  489. }
  490. if (! pcoCreated(&pcoum))
  491. {
  492. EngDeleteClip(pcokm);
  493. return NULL;
  494. }
  495. return pcoum;
  496. }
  497. VOID UMPDOBJ::DeleteCLIPOBJ(
  498. CLIPOBJ *pco
  499. )
  500. /*++
  501. Routine Description:
  502. Implement EngDeleteClip for user-mode drivers
  503. Arguments:
  504. pco - Points to user-mode CLIPOBJ to be deleted
  505. This must have come from EngCreateClip.
  506. Return Value:
  507. NONE
  508. --*/
  509. {
  510. if (pco != NULL && pco == m_coCreated.umobj)
  511. {
  512. EngDeleteClip((CLIPOBJ *) m_coCreated.kmobj);
  513. m_coCreated.umobj = m_coCreated.kmobj = NULL;
  514. }
  515. }
  516. XFORMOBJ *UMPDOBJ::GetFONTOBJXform(
  517. FONTOBJ *pfo
  518. )
  519. /*++
  520. Routine Description:
  521. Implement FONTOBJ_pxoGetXform for user mode printer driver
  522. Arguments:
  523. pfo - Points to a user mode FONTOBJ
  524. Return Value:
  525. Pointer to a user mode XFORMOBJ structure
  526. NULL if there is an error
  527. --*/
  528. {
  529. XFORMOBJ *pxo;
  530. //
  531. // Check if this function has been called already
  532. // during the current DDI entrypoint
  533. //
  534. if (! (pfo = GetDDIOBJ(pfo)))
  535. return NULL;
  536. if (m_xoFont.umobj != NULL)
  537. pxo = (XFORMOBJ *) m_xoFont.umobj;
  538. else
  539. {
  540. RFONTTMPOBJ rfto(PFO_TO_PRF(pfo));
  541. UMPDAcquireRFONTSem(rfto, this, 0, 0, NULL);
  542. if (!(pxo = FONTOBJ_pxoGetXform(pfo)) || !pxoFont(&pxo))
  543. pxo = NULL;
  544. UMPDReleaseRFONTSem(rfto, this, NULL, NULL, NULL);
  545. }
  546. return pxo;
  547. }
  548. GLYPHBITS *UMPDOBJ::CacheGlyphBits(
  549. GLYPHBITS *pgb
  550. )
  551. /*++
  552. Routine Description:
  553. Thunk and cache GLYPHBITS structure returned by FONTOBJ_cGetGlyphs
  554. Arguments:
  555. pgb - Points to kernel mode GLYPHBITS structure
  556. Return Value:
  557. Pointer to user mode GLYPHBITS structure
  558. NULL if there is an error
  559. --*/
  560. {
  561. GLYPHBITS *pgbum = NULL;
  562. ULONG ulSize;
  563. ASSERTGDI(pgb != NULL, "No glyph bits!\n");
  564. ulSize = offsetof(GLYPHBITS, aj) +
  565. ((pgb->sizlBitmap.cx + 7) / 8) * pgb->sizlBitmap.cy;
  566. if (ulSize <= m_gbSize)
  567. {
  568. //
  569. // Reuse previous GLYPHBITS buffer if possible
  570. //
  571. pgbum = m_pgb;
  572. }
  573. else
  574. {
  575. if ((pgbum = (GLYPHBITS *) AllocUserMem(ulSize)) != NULL)
  576. {
  577. m_pgb = pgbum;
  578. m_gbSize = ulSize;
  579. }
  580. }
  581. if (pgbum != NULL)
  582. RtlCopyMemory(pgbum, pgb, ulSize);
  583. return pgbum;
  584. }
  585. PATHOBJ *UMPDOBJ::CacheGlyphPath(
  586. PATHOBJ *ppo
  587. )
  588. /*++
  589. Routine Description:
  590. Thunk and cache PATHOBJ structure returned by FONTOBJ_cGetGlyphs
  591. Arguments:
  592. pgb - Points to kernel mode PATHOBJ structure
  593. Return Value:
  594. Pointer to user mode PATHOBJ structure
  595. NULL if there is an error
  596. --*/
  597. {
  598. ASSERTGDI(ppo != NULL, "No glyph path!\n");
  599. if (m_poGlyph.umobj != NULL)
  600. {
  601. //
  602. // Reuse the previous PATHOBJ if possible
  603. //
  604. *((PATHOBJ *) m_poGlyph.umobj) = *ppo;
  605. m_poGlyph.kmobj = ppo;
  606. ppo = (PATHOBJ *) m_poGlyph.umobj;
  607. }
  608. else if (! ppoGlyph(&ppo))
  609. ppo = NULL;
  610. return ppo;
  611. }
  612. //
  613. // User mode data structure used for storing the surface object
  614. // thunked by UMPDOBJ::LockSurface.
  615. //
  616. typedef struct _UMSO {
  617. DWORD dwSignature;
  618. HSURF hsurf;
  619. SURFOBJ so;
  620. } UMSO, *PUMSO;
  621. #define UMSO_SIGNATURE 'UMSO'
  622. SURFOBJ *UMPDOBJ::LockSurface(
  623. HSURF hsurf
  624. )
  625. /*++
  626. Routine Description:
  627. Implement EngLockSurface for user mode printer driver
  628. Arguments:
  629. hsurf - Handle to the surface to be locked
  630. Return Value:
  631. Pointer to a user-mode SURFOBJ structure corresponding to
  632. the specified surface handle. NULL if there is an error.
  633. --*/
  634. {
  635. SURFOBJ *psokm;
  636. PUMSO pumso = NULL;
  637. if (hsurf == NULL || (psokm = EngLockSurface(hsurf)) == NULL)
  638. return NULL;
  639. //
  640. // Check if the surface bitmap uses kernel mode memory
  641. //
  642. if (psokm->pvBits != NULL &&
  643. psokm->iType == STYPE_BITMAP &&
  644. IS_SYSTEM_ADDRESS(psokm->pvBits))
  645. {
  646. WARNING("EngLockSurface can't handle kernel mode bitmap\n");
  647. }
  648. else if (pumso = (PUMSO) EngAllocUserMem(sizeof(UMSO), UMPD_MEMORY_TAG))
  649. {
  650. //
  651. // We're can't allocate memory from our cache here because
  652. // pso returned by EngLockSurface may potentially out-live
  653. // the current DDI entrypoint and/or the current thread.
  654. //
  655. pumso->dwSignature = UMSO_SIGNATURE;
  656. pumso->hsurf = hsurf;
  657. pumso->so = *psokm;
  658. //
  659. // if this is a surface that has been called by EngAssociateSurface,
  660. // we give them back the original dhpdev
  661. //
  662. if (pumso->so.dhpdev)
  663. {
  664. PUMDHPDEV pUMdhpdev = (PUMDHPDEV)pumso->so.dhpdev;
  665. pumso->so.dhpdev = pUMdhpdev->dhpdev;
  666. }
  667. }
  668. EngUnlockSurface(psokm);
  669. return pumso ? &pumso->so : NULL;
  670. }
  671. VOID UMPDOBJ::UnlockSurface(
  672. SURFOBJ *pso
  673. )
  674. /*++
  675. Routine Description:
  676. Implement EngUnlockSurface for user mode printer driver
  677. Arguments:
  678. pso - Pointer to user mode SURFOBJ to be unlocked
  679. Return Value:
  680. NONE
  681. --*/
  682. {
  683. PUMSO pumso;
  684. if (pso != NULL)
  685. {
  686. __try
  687. {
  688. pumso = (PUMSO) ((PBYTE) pso - offsetof(UMSO, so));
  689. ProbeForRead (pumso, sizeof(UMSO), sizeof(BYTE));
  690. if (pumso->dwSignature != UMSO_SIGNATURE ||
  691. pumso->hsurf == NULL)
  692. {
  693. WARNING("Invalid surface in EngUnlockSurface\n");
  694. return;
  695. }
  696. EngFreeUserMem(pumso);
  697. }
  698. __except(EXCEPTION_EXECUTE_HANDLER)
  699. {
  700. WARNING("Bad user mode SURFOBJ\n");
  701. }
  702. }
  703. }
  704. SURFOBJ *UMPDSURFOBJ::GetLockedSURFOBJ(
  705. SURFOBJ *pso
  706. )
  707. /*++
  708. Routine Description:
  709. Map a user mode SURFOBJ to its kernel mode counterpart.
  710. This pointer must be returned by a previous called to
  711. UMPDOBJ::LockSurface.
  712. Arguments:
  713. pso - Pointer to user mode SURFOBJ
  714. Return Value:
  715. Pointer to kernel mode SURFOBJ corresponding to the specified
  716. user mode SURFOBJ. NULL if there is an error.
  717. --*/
  718. {
  719. PUMSO pumso;
  720. HSURF hsurf = NULL;
  721. if (pso != NULL)
  722. {
  723. __try
  724. {
  725. pumso = (PUMSO) ((PBYTE) pso - offsetof(UMSO, so));
  726. ProbeForRead (pumso, sizeof(UMSO), sizeof(BYTE));
  727. if (pumso->dwSignature == UMSO_SIGNATURE)
  728. hsurf = pumso->hsurf;
  729. }
  730. __except(EXCEPTION_EXECUTE_HANDLER)
  731. {
  732. WARNING("Bad user mode SURFOBJ\n");
  733. hsurf = NULL;
  734. }
  735. }
  736. return hsurf ? EngLockSurface(hsurf) : NULL;
  737. }
  738. #endif // !_GDIPLUS_