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.

1489 lines
37 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: muclean.cxx
  3. *
  4. * Cleanup module for WIN32K.SYS GRE
  5. *
  6. * Copyright (c) 1998-1999 Microsoft Corporation
  7. *
  8. \**************************************************************************/
  9. #include "precomp.hxx"
  10. #include "muclean.hxx"
  11. #include "verifier.hxx"
  12. #if DBG
  13. ULONG
  14. DbgPrint(
  15. PCH Format,
  16. ...
  17. );
  18. #define DBGPRINT(x) DbgPrint x
  19. #if DBGTRACE
  20. #define TRACE0(x) DbgPrint x
  21. #define TRACE1(x) DbgPrint x
  22. #else
  23. #define TRACE0(x)
  24. #define TRACE1(x)
  25. #endif
  26. #else
  27. #define DBGPRINT(x)
  28. #define TRACE0(x)
  29. #define TRACE1(x)
  30. #endif
  31. /*
  32. * External variables we must cleanup
  33. */
  34. // hmgrapi.cxx
  35. extern PLARGE_INTEGER gpLockShortDelay;
  36. extern PVOID *gpTmpGlobalFree;
  37. extern PVOID gpTmpGlobal;
  38. extern "C" HFASTMUTEX ghfmMemory;
  39. extern PVOID gpHmgrSharedHandleSection;
  40. // drvsup.cxx
  41. extern PLDEV gpldevDrivers;
  42. extern PBYTE gpRGBXlate;
  43. // invcmap.cxx
  44. extern PBYTE gpDefITable;
  45. /*
  46. * Our global data for tracking lists
  47. */
  48. LIST_ENTRY MultiUserGreEngAllocList;
  49. HSEMAPHORE MultiUserEngAllocListLock = NULL;
  50. #if DBG
  51. LIST_ENTRY DebugGreMapViewList;
  52. HSEMAPHORE DebugGreMapViewListLock = NULL;
  53. #endif
  54. /*
  55. * The EngLoadModule tracking list
  56. */
  57. LIST_ENTRY GreEngLoadModuleAllocList;
  58. HSEMAPHORE GreEngLoadModuleAllocListLock = NULL;
  59. BOOL FASTCALL NtGdiCloseProcess(W32PID,CLEANUPTYPE);
  60. /*
  61. * Forward references
  62. */
  63. VOID MultiUserCleanupPathAlloc();
  64. VOID MultiUserGreCleanupEngResources();
  65. VOID MultiUserGreHmgOwnAll(W32PID);
  66. VOID MultiUserGreCleanupDrivers();
  67. VOID MultiUserGreCleanupAllFonts();
  68. VOID MultiUserGreDeleteXLATE();
  69. VOID vCleanUpFntCache(VOID);
  70. // drvsup.cxx
  71. extern VOID MultiUserDrvCleanupGraphicsDeviceList();
  72. // fontsup.cxx
  73. extern VOID MultiUserGreDeleteScripts();
  74. /*
  75. * Debug only
  76. */
  77. #if DBG
  78. // Hydra session id (see ntuser\kernel\globals.c).
  79. extern "C" ULONG gSessionId;
  80. VOID DebugGreCleanupMapView();
  81. VOID MultiUserGreHmgDbgScan(BOOL, BOOL);
  82. char *gpszHmgrType[] = {
  83. "ObjectType ", // 0x00
  84. "DC_TYPE ", // 0x01
  85. "DD_DIRECTDRAW_TYPE", // 0x02
  86. "DD_SURFACE_TYPE ", // 0x03
  87. "RGN_TYPE ", // 0x04
  88. "SURF_TYPE ", // 0x05
  89. "CLIENTOBJ_TYPE ", // 0x06
  90. "PATH_TYPE ", // 0x07
  91. "PAL_TYPE ", // 0x08
  92. "ICMLCS_TYPE ", // 0x09
  93. "LFONT_TYPE ", // 0x0a
  94. "RFONT_TYPE ", // 0x0b
  95. "PFE_TYPE ", // 0x0c
  96. "PFT_TYPE ", // 0x0d
  97. "ICMCXF_TYPE ", // 0x0e
  98. "SPRITE_TYPE ", // 0x0f
  99. "BRUSH_TYPE ", // 0x10
  100. "D3D_HANDLE_TYPE ", // 0x11
  101. "DD_VIDEOPORT_TYPE ", // 0x12
  102. "SPACE_TYPE ", // 0x13
  103. "DD_MOTIONCOMP_TYPE", // 0x14
  104. "META_TYPE ", // 0x15
  105. "EFSTATE_TYPE ", // 0x16
  106. "BMFD_TYPE ", // 0x17
  107. "VTFD_TYPE ", // 0x18
  108. "TTFD_TYPE ", // 0x19
  109. "RC_TYPE ", // 0x1a
  110. "TEMP_TYPE ", // 0x1b
  111. "DRVOBJ_TYPE ", // 0x1c
  112. "DCIOBJ_TYPE ", // 0x1d
  113. "SPOOL_TYPE " // 0x1e
  114. };
  115. #endif
  116. /*
  117. * Can put these initialization functions in the INIT segment.
  118. */
  119. extern "C" {
  120. BOOL GreEngLoadModuleTrackInit();
  121. BOOL MultiUserGreCleanupInit();
  122. }
  123. #pragma alloc_text(INIT, MultiUserGreCleanupInit)
  124. #pragma alloc_text(INIT, GreEngLoadModuleTrackInit)
  125. extern "C" HSEMAPHORE ghsemBMFD;
  126. extern "C" HSEMAPHORE ghsemVTFD;
  127. extern "C" CP_GLYPHSET *gpcpGlyphsets;
  128. extern "C" CP_GLYPHSET *gpcpVTFD;
  129. extern void vCleanupPrintKViewList();
  130. /******************************Public*Routine******************************\
  131. * GreEngLoadModuleTrackInit
  132. *
  133. * Initializes the EngLoadModule tracking list
  134. *
  135. * Arguments:
  136. *
  137. * Return Value:
  138. *
  139. * History:
  140. *
  141. * 21-Apr-1998 -by- Ori Gershony [orig]
  142. *
  143. \**************************************************************************/
  144. extern "C"
  145. BOOL
  146. GreEngLoadModuleTrackInit()
  147. {
  148. InitializeListHead(&GreEngLoadModuleAllocList);
  149. GreEngLoadModuleAllocListLock = GreCreateSemaphoreNonTracked();
  150. return (GreEngLoadModuleAllocListLock != NULL);
  151. }
  152. /*****************************************************************************
  153. *
  154. * MultiUserGreCleanupInit
  155. *
  156. * Init the GRE cleanup code
  157. *
  158. * ENTRY:
  159. * Param1 (input/output)
  160. * Comments
  161. *
  162. * EXIT:
  163. * STATUS_SUCCESS - no error
  164. *
  165. ****************************************************************************/
  166. extern "C"
  167. BOOL
  168. MultiUserGreCleanupInit()
  169. {
  170. InitializeListHead(&MultiUserGreEngAllocList);
  171. #if DBG
  172. InitializeListHead(&DebugGreMapViewList);
  173. #endif
  174. MultiUserEngAllocListLock = GreCreateSemaphoreNonTracked();
  175. #if DBG
  176. DebugGreMapViewListLock = GreCreateSemaphoreNonTracked();
  177. #endif
  178. #if DBG
  179. return ((MultiUserEngAllocListLock != NULL) &&
  180. (DebugGreMapViewListLock != NULL));
  181. #else
  182. return (MultiUserEngAllocListLock != NULL);
  183. #endif
  184. }
  185. /*****************************************************************************
  186. *
  187. * MultiUserNtGreCleanup
  188. *
  189. * This performs the main additional cleanup processing
  190. * of kernel mode GRE. This supports the unloading of the
  191. * win32k.sys kernel module on WinFrame.
  192. *
  193. * Our concern here is non-paged pool and kernel resource
  194. * objects. Paged pool is not a problem since a WINSTATION SPACE
  195. * paged pool allocator is used which destroys all pageable memory
  196. * allocated by win32k.sys and its video and printer drivers when
  197. * the WINSTATION SPACE is deleted.
  198. *
  199. * ENTRY:
  200. * Param1 (input/output)
  201. * Comments
  202. *
  203. * EXIT:
  204. * STATUS_SUCCESS - no error
  205. *
  206. ****************************************************************************/
  207. extern PPAGED_LOOKASIDE_LIST pHmgLookAsideList[];
  208. extern "C" PVOID LastNlsTableBuffer;
  209. VOID CleanUpEUDC(VOID);
  210. extern "C"
  211. BOOL
  212. MultiUserNtGreCleanup()
  213. {
  214. NTSTATUS ntstatus;
  215. W32PID pid = W32GetCurrentPID();
  216. //
  217. // Assign ownership of all handle manager objects to cleanup process.
  218. // Must be done first.
  219. //
  220. MultiUserGreHmgOwnAll(pid);
  221. GdiMultiUserFontCleanup();
  222. //
  223. // Use the process termination code to delete the majority of objects
  224. // (all except some font related objects).
  225. //
  226. if(gpentHmgr!=NULL) {
  227. NtGdiCloseProcess(pid, CLEANUP_SESSION);
  228. }
  229. if (gpfsTable)
  230. {
  231. VFREEMEM(gpfsTable);
  232. gpfsTable = NULL;
  233. }
  234. if (MAPPER::SignatureTable)
  235. {
  236. VFREEMEM(MAPPER::SignatureTable);
  237. MAPPER::SignatureTable = NULL;
  238. }
  239. // Clean up LastNlsTableBuffer
  240. if (LastNlsTableBuffer)
  241. {
  242. VFREEMEM(LastNlsTableBuffer);
  243. LastNlsTableBuffer = NULL;
  244. }
  245. //
  246. // Cleanup the scripts (created by InitializeScripts during
  247. // InitializeGre).
  248. //
  249. MultiUserGreDeleteScripts();
  250. //
  251. // Cleanup the XLATE cache (created by vInitXLATE during
  252. // InitializeGre).
  253. //
  254. MultiUserGreDeleteXLATE();
  255. //
  256. // Cleanup RBRUSH caches.
  257. //
  258. if (gpCachedEngbrush)
  259. {
  260. //
  261. // Engine brush cache is just one deep (refer to
  262. // EngRealizeBrush in engbrush.cxx).
  263. //
  264. VFREEMEM(gpCachedEngbrush);
  265. }
  266. if (gpCachedDbrush)
  267. {
  268. //
  269. // Device brush cache is just one deep (refer to
  270. // BRUSHOBJ__pvAllocRbrush in brushddi.cxx).
  271. //
  272. VFREEMEM(gpCachedDbrush);
  273. }
  274. if (gpRGBXlate)
  275. {
  276. VFREEMEM(gpRGBXlate);
  277. gpRGBXlate = NULL;
  278. }
  279. if(gpDefITable)
  280. {
  281. VFREEMEM(gpDefITable);
  282. gpDefITable = NULL;
  283. }
  284. //
  285. // Cleanup driver objects.
  286. //
  287. MultiUserGreCleanupDrivers();
  288. #ifdef _PER_SESSION_GDEVLIST_
  289. //
  290. // Currently, the graphics device list (see drvsup.cxx) is allocated
  291. // per-Hydra session. AndreVa has proposed that they be allocated
  292. // globally. He's probably right, but until this changes we need to
  293. // clean them up during Hydra shutdown.
  294. //
  295. // To enable cleanup of the per-Hydra graphics device lists (i.e.,
  296. // the function MultiUserDrvCleanupGraphicsDeviceList in drvsup.cxx),
  297. // define _PER_SESSION_GDEVLIST_ in muclean.hxx.
  298. //
  299. MultiUserDrvCleanupGraphicsDeviceList();
  300. #endif
  301. //
  302. // Handle manager should be empty at this point.
  303. //
  304. #if DBG
  305. if (gpentHmgr != NULL) {
  306. MultiUserGreHmgDbgScan(TRUE, TRUE);
  307. }
  308. #endif
  309. //
  310. // Cleanup random pool allocations.
  311. //
  312. if (gpLockShortDelay)
  313. {
  314. GdiFreePool(gpLockShortDelay);
  315. gpLockShortDelay = NULL;
  316. }
  317. if (gpTmpGlobal)
  318. {
  319. GdiFreePool(gpTmpGlobal);
  320. gpTmpGlobal = NULL;
  321. }
  322. if (gpTmpGlobalFree)
  323. {
  324. GdiFreePool(gpTmpGlobalFree);
  325. gpTmpGlobalFree = NULL;
  326. }
  327. //
  328. // Call the C++ "friend" function for cleanup
  329. //
  330. MultiUserCleanupPathAlloc();
  331. //
  332. // These must be last since they catch all the
  333. // leftover NT kernel resource objects that were
  334. // not released by the above code.
  335. //
  336. // The reason this is done is that these objects
  337. // can be created as the result of embedded classes
  338. // that stay around.
  339. //
  340. // Also every printer driver also can call EngCreateSemaphore
  341. // and leak it.
  342. //
  343. //
  344. // Cleanup the tracked resources.
  345. //
  346. MultiUserGreCleanupEngResources();
  347. #if DBG
  348. //
  349. // On free builds, we track and cleanup only the views
  350. // allocated by drivers (i.e., through the Eng
  351. // helper functions).
  352. //
  353. // However, on debug builds we will track all views
  354. // to help find engine leaks. The functions below
  355. // will cleanup, but they will also assert.
  356. //
  357. DebugGreCleanupMapView();
  358. #endif
  359. //
  360. // Cleanup watchdog's association list mutex.
  361. //
  362. GreDeleteFastMutex(gAssociationListMutex);
  363. gAssociationListMutex = NULL;
  364. //
  365. // Cleanup the HMGR look aside buffer mutex.
  366. //
  367. GreDeleteFastMutex(ghfmMemory);
  368. ghfmMemory = NULL;
  369. if (gpGdiSharedMemory)
  370. {
  371. ntstatus = Win32UnmapViewInSessionSpace(gpGdiSharedMemory);
  372. gpGdiSharedMemory = NULL;
  373. }
  374. if (gpHmgrSharedHandleSection)
  375. {
  376. Win32DestroySection(gpHmgrSharedHandleSection);
  377. gpHmgrSharedHandleSection = NULL;
  378. }
  379. //
  380. // Free the HMGR lookaside lists.
  381. //
  382. for (int i = 0; i <= MAX_TYPE; i++)
  383. {
  384. if (pHmgLookAsideList[i] != NULL)
  385. {
  386. ExDeletePagedLookasideList(pHmgLookAsideList[i]);
  387. GdiFreePool(pHmgLookAsideList[i]);
  388. pHmgLookAsideList[i]=NULL;
  389. }
  390. }
  391. return(TRUE);
  392. }
  393. /*****************************************************************************
  394. *
  395. * MultiUserCleanupPathAlloc
  396. *
  397. * Friend function to cleanup a PATHALLOC object's
  398. * class global state.
  399. *
  400. * ENTRY:
  401. * Param1 (input/output)
  402. * Comments
  403. *
  404. * EXIT:
  405. * STATUS_SUCCESS - no error
  406. *
  407. ****************************************************************************/
  408. VOID
  409. MultiUserCleanupPathAlloc()
  410. {
  411. // pathobj.cxx
  412. if (PATHALLOC::hsemFreelist)
  413. {
  414. GreDeleteSemaphore(PATHALLOC::hsemFreelist);
  415. PATHALLOC::hsemFreelist = NULL;
  416. }
  417. //
  418. // Release the PATHALLOC freelist.
  419. //
  420. while (PATHALLOC::freelist)
  421. {
  422. PATHALLOC *ppa = PATHALLOC::freelist;
  423. PATHALLOC::freelist = ppa->ppanext;
  424. VFREEMEM(ppa);
  425. }
  426. return;
  427. }
  428. /******************************Public*Routine******************************\
  429. * MultiUserGreTrackAddEngResource
  430. *
  431. * Add an entry associated with an EngAllocMem.
  432. *
  433. * WARNING:
  434. * EngInitializeSafeSemaphore calls GreCreateSemaphore which in turn calls
  435. * this function. Since EngInitializeSafeSemaphore does this with the
  436. * HMGR global lock (MLOCKFAST) held, this function must never call any
  437. * anything that grabs MLOCKFAST. If this becomes necessary in the future,
  438. * EngInitializeSafeSemaphore must be rewritten.
  439. *
  440. * History:
  441. * 19-Feb-1998 -by- Gilman Wong [gilmanw]
  442. * Wrote it.
  443. \**************************************************************************/
  444. VOID
  445. MultiUserGreTrackAddEngResource(
  446. PENGTRACKHDR peth,
  447. ULONG ulType
  448. )
  449. {
  450. PLIST_ENTRY Entry = (PLIST_ENTRY) peth;
  451. //setting to 0 would be a waste of time
  452. //peth->ulReserved = 0;
  453. peth->ulType = ulType;
  454. if(MultiUserEngAllocListLock) GreAcquireSemaphore(MultiUserEngAllocListLock);
  455. InsertTailList(&MultiUserGreEngAllocList, Entry);
  456. if(MultiUserEngAllocListLock) GreReleaseSemaphore(MultiUserEngAllocListLock);
  457. }
  458. /******************************Public*Routine******************************\
  459. * MultiUserGreTrackRemoveEngResource
  460. *
  461. * Add an entry associated with an EngAllocMem.
  462. *
  463. * WARNING:
  464. * EngDeleteSafeSemaphore calls GreDeleteSemaphore which in turn calls
  465. * this function. Since EngDeleteSafeSemaphore does this with the
  466. * HMGR global lock (MLOCKFAST) held, this function must never call any
  467. * anything that grabs MLOCKFAST. If this becomes necessary in the future,
  468. * EngDeleteSafeSemaphore must be rewritten.
  469. *
  470. * History:
  471. * 19-Feb-1998 -by- Gilman Wong [gilmanw]
  472. * Wrote it.
  473. \**************************************************************************/
  474. VOID
  475. MultiUserGreTrackRemoveEngResource(
  476. PENGTRACKHDR peth
  477. )
  478. {
  479. PLIST_ENTRY Entry = (PLIST_ENTRY) peth;
  480. if(MultiUserEngAllocListLock) GreAcquireSemaphore(MultiUserEngAllocListLock);
  481. RemoveEntryList(Entry);
  482. if(MultiUserEngAllocListLock) GreReleaseSemaphore(MultiUserEngAllocListLock);
  483. }
  484. /******************************Public*Routine******************************\
  485. * MultiUserGreCleanupEngResources
  486. *
  487. * Cleanup the tracked EngAlloc objects and tracked (Gre and Eng) semaphores.
  488. *
  489. * WARNING: This must not invoke any code which uses tracked semaphores. If
  490. * it is inevitable, the semaphores in question must be changed
  491. * to non-tracked semaphores (and cleaned up explicitly).
  492. *
  493. * WARNING: This function is called late in MultiUserGreCleanupEngResources.
  494. * Be careful to avoid using structures that have already been
  495. * cleaned up.
  496. *
  497. * History:
  498. * 19-Feb-1998 -by- Gilman Wong [gilmanw]
  499. * Wrote it.
  500. \**************************************************************************/
  501. VOID
  502. MultiUserGreCleanupEngResources()
  503. {
  504. volatile PLIST_ENTRY pNextEntry;
  505. if(MultiUserEngAllocListLock)
  506. {
  507. pNextEntry = MultiUserGreEngAllocList.Flink;
  508. while (pNextEntry != &MultiUserGreEngAllocList)
  509. {
  510. //
  511. // Resource starts after the ENGTRACKHDR.
  512. //
  513. PVOID pvVictim = (PVOID) (((ENGTRACKHDR *) pNextEntry) + 1);
  514. //
  515. // Invoke the appropriate deletion function based on type.
  516. //
  517. switch (((ENGTRACKHDR *) pNextEntry)->ulType)
  518. {
  519. case ENGTRACK_ALLOCMEM:
  520. EngFreeMem(pvVictim);
  521. break;
  522. case ENGTRACK_SEMAPHORE:
  523. case ENGTRACK_DRIVER_SEMAPHORE:
  524. GreDeleteSemaphore((HSEMAPHORE)pvVictim);
  525. break;
  526. case ENGTRACK_VERIFIERALLOCMEM:
  527. VerifierEngFreeMem(pvVictim);
  528. break;
  529. default:
  530. #if DBG
  531. DbgPrint("MultiUserGreCleanupEngResources: "
  532. "unrecognized type 0x%08lx\n",
  533. ((ENGTRACKHDR *) pNextEntry)->ulType);
  534. RIP("MultiUserGreCleanupEngResources: possible leak detected\n");
  535. #endif
  536. break;
  537. }
  538. //
  539. // Restart at the begining of the list since our
  540. // entry got deleted.
  541. //
  542. pNextEntry = MultiUserGreEngAllocList.Flink;
  543. }
  544. }
  545. //
  546. // Now delete all objects on the GreEngLoadModuleAllocList.
  547. //
  548. if(GreEngLoadModuleAllocListLock)
  549. {
  550. while (GreEngLoadModuleAllocList.Flink != &GreEngLoadModuleAllocList)
  551. {
  552. //
  553. // Free the module after setting the reference count to 1 (to eliminate
  554. // looping cRef times).
  555. //
  556. ((PENGLOADMODULEHDR)(GreEngLoadModuleAllocList.Flink))->cRef = 1;
  557. EngFreeModule ((HANDLE) (((PENGLOADMODULEHDR)(GreEngLoadModuleAllocList.Flink)) + 1));
  558. }
  559. }
  560. //
  561. // Delete the list locks.
  562. //
  563. GreDeleteSemaphoreNonTracked(MultiUserEngAllocListLock);
  564. MultiUserEngAllocListLock = NULL;
  565. GreDeleteSemaphoreNonTracked(GreEngLoadModuleAllocListLock);
  566. GreEngLoadModuleAllocListLock = NULL;
  567. }
  568. /*****************************Exported*Routine*****************************\
  569. * MultiUserGreHmgOwnAll
  570. *
  571. * Set owner of all objects in handle manager to specified process. Used
  572. * for multi-user (Hydra) shutdown of GRE.
  573. *
  574. * WARNING:
  575. *
  576. * Caller beware! This is very evil code. It ignores the current owner
  577. * and the lock counts. Acceptable for shutdown code, but definitely
  578. * unsafe for any other purpose.
  579. *
  580. * History:
  581. * 03-Feb-1998 -by- Gilman Wong [gilmanw]
  582. * Wrote it.
  583. \**************************************************************************/
  584. VOID
  585. MultiUserGreHmgOwnAll(
  586. W32PID pid)
  587. {
  588. PENTRYOBJ pentTmp;
  589. UINT uiIndex = 1; // 1 is the first valid index
  590. UINT cObj = 0;
  591. //
  592. // Don't bother with locks. We're shutting down, so nobody else
  593. // is here!
  594. //
  595. // MLOCKFAST mo;
  596. //
  597. // Scan through the entire handle manager table and set owner for
  598. // all valid objects.
  599. //
  600. if(gpentHmgr==NULL) {
  601. WARNING("MultiUserGreHmgOwnAll: gpentHmgr is NULL\n");
  602. return;
  603. }
  604. for (uiIndex = 1; uiIndex < gcMaxHmgr; uiIndex++)
  605. {
  606. pentTmp = (PENTRYOBJ) &gpentHmgr[uiIndex];
  607. if ((pentTmp->Objt > DEF_TYPE) && (pentTmp->Objt <= MAX_TYPE))
  608. {
  609. //
  610. // Since this is shutdown, don't bother with lock counts and
  611. // such.
  612. //
  613. SET_OBJECTOWNER_PID(pentTmp->ObjectOwner, pid);
  614. cObj++;
  615. }
  616. }
  617. //
  618. // Reset handle quota count to number objects now owned
  619. // (not really that important for shutdown, but it supresses
  620. // many warnings).
  621. //
  622. PW32PROCESS pw32Current = W32GetCurrentProcess();
  623. if (pw32Current)
  624. {
  625. pw32Current->GDIHandleCount = cObj;
  626. }
  627. }
  628. /******************************Public*Routine******************************\
  629. * MultiUserGreCleanupHmgRemoveAllLocks
  630. *
  631. * For all objects of the specified type, all locks are removed and the
  632. * object is marked as deletable. If the DEF_TYPE is specified, all valid
  633. * objects are modified.
  634. *
  635. * WARNING:
  636. *
  637. * Caller beware! This is very evil code. It ignores the current owner
  638. * and the lock counts. Acceptable for shutdown code, but definitely
  639. * unsafe for any other purpose.
  640. *
  641. * History:
  642. * 07-Feb-1998 -by- Gilman Wong [gilmanw]
  643. * Wrote it.
  644. \**************************************************************************/
  645. VOID
  646. MultiUserGreCleanupHmgRemoveAllLocks(OBJTYPE type)
  647. {
  648. PENTRYOBJ pentTmp;
  649. UINT uiIndex = 1; // 1 is the first valid index
  650. //
  651. // Don't bother with locks. We're shutting down, so nobody else
  652. // is here!
  653. //
  654. // MLOCKFAST mo;
  655. //
  656. // Scan through the entire handle manager table zap the share count
  657. // and lock flag for all objects that belong to specified W32PID.
  658. //
  659. for (uiIndex = 1; uiIndex < gcMaxHmgr; uiIndex++)
  660. {
  661. pentTmp = (PENTRYOBJ) &gpentHmgr[uiIndex];
  662. if (
  663. ((type != DEF_TYPE) && (type == pentTmp->Objt)) ||
  664. ((type == DEF_TYPE) &&
  665. (pentTmp->Objt > DEF_TYPE) && (pentTmp->Objt <= MAX_TYPE))
  666. )
  667. {
  668. ASSERTGDI((OBJECTOWNER_PID(pentTmp->ObjectOwner) == W32GetCurrentPID()),
  669. "MultiUserGreCleanupHmgRemoveAllLocks: "
  670. "found unowned object still in hmgr table\n");
  671. pentTmp->ObjectOwner.Share.Lock = 0;
  672. pentTmp->einfo.pobj->ulShareCount = 0;
  673. pentTmp->Flags &= ~HMGR_ENTRY_UNDELETABLE;
  674. }
  675. }
  676. }
  677. /******************************Public*Routine******************************\
  678. * MultiUserGreCleanupHmgOwnRemoveAllLocks
  679. *
  680. * For all objects of the specified type owned by current process,all locks
  681. * are removed and the object is marked as deletable. If the DEF_TYPE is
  682. * specified, all valid objects are modified.
  683. *
  684. * WARNING:
  685. *
  686. * Caller beware! This is very evil code. It ignores the current owner
  687. * and the lock counts. Acceptable for shutdown code, but definitely
  688. * unsafe for any other purpose.
  689. *
  690. * History:
  691. * 01-Aug-2001 -by- Pravin Santiago [pravins]
  692. * Wrote it.
  693. \**************************************************************************/
  694. VOID
  695. MultiUserGreCleanupHmgOwnRemoveAllLocks(OBJTYPE type)
  696. {
  697. PENTRYOBJ pentTmp;
  698. UINT uiIndex = 1; // 1 is the first valid index
  699. //
  700. // Got to take the Handle manager lock
  701. //
  702. MLOCKFAST mo;
  703. //
  704. // Scan through the entire handle manager table zap the share count
  705. // and lock flag for all objects that belong to specified W32PID.
  706. //
  707. for (uiIndex = 1; uiIndex < gcMaxHmgr; uiIndex++)
  708. {
  709. pentTmp = (PENTRYOBJ) &gpentHmgr[uiIndex];
  710. if (
  711. (((type != DEF_TYPE) && (type == pentTmp->Objt)) ||
  712. ((type == DEF_TYPE) &&
  713. (pentTmp->Objt > DEF_TYPE) && (pentTmp->Objt <= MAX_TYPE))) &&
  714. ((OBJECTOWNER_PID(pentTmp->ObjectOwner) == W32GetCurrentPID()))
  715. )
  716. {
  717. pentTmp->ObjectOwner.Share.Lock = 0;
  718. pentTmp->einfo.pobj->ulShareCount = 0;
  719. pentTmp->Flags &= ~HMGR_ENTRY_UNDELETABLE;
  720. }
  721. }
  722. }
  723. /******************************Public*Routine******************************\
  724. * bCleanupFontHash
  725. * bCleanupFontTable
  726. *
  727. * For MultiUserNtGreCleanup (Hydra) cleanup.
  728. *
  729. * Worker functions for MultiUserGreCleanupAllFonts.
  730. *
  731. * Returns:
  732. * TRUE if successful, FALSE otherwise.
  733. *
  734. * History:
  735. * 06-Feb-1998 -by- Gilman Wong [gilmanw]
  736. * Wrote it.
  737. \**************************************************************************/
  738. BOOL bCleanupFontHash(FONTHASH **ppfh)
  739. {
  740. BOOL bResult = FALSE;
  741. FHOBJ fho(ppfh);
  742. if (fho.bValid())
  743. {
  744. fho.vFree();
  745. bResult = TRUE;
  746. }
  747. return bResult;
  748. }
  749. BOOL bCleanupFontTable(PFT **pppft)
  750. {
  751. BOOL bResult = FALSE;
  752. PFT *ppft = *pppft;
  753. PUBLIC_PFTOBJ pfto(ppft);
  754. if (pfto.bValid())
  755. {
  756. //
  757. // Unload any fonts still in the table.
  758. //
  759. bResult = pfto.bUnloadAllButPermanentFonts(TRUE);
  760. //
  761. // Remove the font hash tables if they exist (for device fonts, the
  762. // font hash tables exist off the PFF rather than the PFT).
  763. //
  764. if (ppft->pfhFace)
  765. {
  766. bResult &= bCleanupFontHash(&ppft->pfhFace);
  767. }
  768. if (ppft->pfhFamily)
  769. {
  770. bResult &= bCleanupFontHash(&ppft->pfhFamily);
  771. }
  772. if (ppft->pfhUFI)
  773. {
  774. bResult &= bCleanupFontHash(&ppft->pfhUFI);
  775. }
  776. //
  777. // Finally, delete the font table.
  778. //
  779. bResult &= pfto.bDelete();
  780. *pppft = NULL;
  781. }
  782. return bResult;
  783. }
  784. /******************************Public*Routine******************************\
  785. * MultiUserGreCleanupAllFonts
  786. *
  787. * For MultiUserNtGreCleanup (Hydra) cleanup.
  788. *
  789. * Delete the font tables and hash tables.
  790. *
  791. * History:
  792. * 06-Feb-1998 -by- Gilman Wong [gilmanw]
  793. * Wrote it.
  794. \**************************************************************************/
  795. VOID MultiUserGreCleanupAllFonts()
  796. {
  797. BOOL bResult;
  798. //
  799. // Note: since this should only be called during win32k shutdown,
  800. // don't bother with grabbing the semaphore.
  801. //
  802. //GreAcquireSemaphore(ghsemPublicPFT);
  803. {
  804. // Hydra
  805. // Saw the case where gpPFTPublic was not initialized on Hydra system
  806. //ASSERTGDI(gpPFTPublic, "MultiUserGreCleanupAllFonts: invalid gpPFTPublic\n");
  807. //ASSERTGDI(gpPFTPublic, "MultiUserGreCleanupAllFonts: invalid gpPFTDevice\n");
  808. //
  809. // Handle private table. Note that private table can be lazily
  810. // created, so we have to check gpPFTPrivate.
  811. //
  812. if (gpPFTPrivate)
  813. {
  814. //
  815. // Delete the private font table.
  816. //
  817. bResult = bCleanupFontTable(&gpPFTPrivate);
  818. }
  819. // Hydra
  820. // Saw the case where gpPFTPublic was not initialized
  821. if (gpPFTPublic)
  822. {
  823. //
  824. // Delete the public font table.
  825. //
  826. bResult = bCleanupFontTable(&gpPFTPublic);
  827. }
  828. // Hydra
  829. // saw the case where gpPFTDevice was not intialized on Hydra system
  830. if (gpPFTDevice)
  831. {
  832. //
  833. // Delete the device font table.
  834. //
  835. bResult = bCleanupFontTable(&gpPFTDevice);
  836. }
  837. // Clean up the gpPrintKViewList
  838. if (gpPrintKViewList)
  839. {
  840. vCleanupPrintKViewList();
  841. }
  842. }
  843. // Clean up FD_GLYPHSET for VTFD and BMFD.
  844. // Here is the cheapest way to do some garbage collection.
  845. GreAcquireSemaphore(ghsemVTFD);
  846. if (gpcpVTFD)
  847. {
  848. CP_GLYPHSET *pcpNext, *pcpCurrent;
  849. pcpCurrent = gpcpVTFD;
  850. while(pcpCurrent)
  851. {
  852. pcpNext = pcpCurrent->pcpNext;
  853. VFREEMEM(pcpCurrent);
  854. pcpCurrent = pcpNext;
  855. }
  856. gpcpVTFD = NULL;
  857. }
  858. GreReleaseSemaphore(ghsemVTFD);
  859. GreAcquireSemaphore(ghsemBMFD);
  860. if (gpcpGlyphsets)
  861. {
  862. CP_GLYPHSET *pcpNext, *pcpCurrent;
  863. pcpCurrent = gpcpGlyphsets;
  864. while(pcpCurrent)
  865. {
  866. pcpNext = pcpCurrent->pcpNext;
  867. VFREEMEM(pcpCurrent);
  868. pcpCurrent = pcpNext;
  869. }
  870. gpcpGlyphsets = NULL;
  871. }
  872. GreReleaseSemaphore(ghsemBMFD);
  873. //GreReleaseSemaphore(ghsemPublicPFT);
  874. }
  875. /******************************Public*Routine******************************\
  876. * MultiUserGreCleanupDrivers
  877. *
  878. * Cleanup the ppdev and lpdev driver lists.
  879. *
  880. * History:
  881. * 07-Feb-1998 -by- Gilman Wong [gilmanw]
  882. * Wrote it.
  883. \**************************************************************************/
  884. VOID
  885. MultiUserGreCleanupDrivers()
  886. {
  887. //
  888. // Note: since this should only be called during win32k shutdown,
  889. // don't bother with grabbing the semaphore.
  890. //
  891. //GreAcquireSemaphore(ghsemDriverMgmt);
  892. //
  893. // Remove all PDEVs from the global list.
  894. //
  895. volatile PDEV *ppdevCur;
  896. while (ppdevCur = gppdevList)
  897. {
  898. //
  899. // Force reference count to 1, so PDEV will be deleted.
  900. //
  901. ppdevCur->cPdevRefs = 1;
  902. ppdevCur->cPdevOpenRefs = 1;
  903. //
  904. // Unload the pdev (PDEVOBJ::vUnreferencePdev will update gppdevList).
  905. //
  906. PDEVOBJ pdo((HDEV) ppdevCur);
  907. ASSERTGDI(pdo.bValid(), "MultiUserGreCleanupDrivers: invalid pdev\n");
  908. pdo.vUnreferencePdev(CLEANUP_SESSION);
  909. }
  910. //
  911. // Cleanup direct draw driver before force unload.
  912. //
  913. DxDdCleanupDxGraphics();
  914. //
  915. // Remove all LDEVs from the global list.
  916. //
  917. volatile PLDEV pldevCur;
  918. while (pldevCur = gpldevDrivers)
  919. {
  920. //
  921. // Force reference count to 1, so LDEV will be deleted.
  922. //
  923. pldevCur->cldevRefs = 1;
  924. ldevUnloadImage(pldevCur);
  925. }
  926. //GreReleaseSemaphore(ghsemDriverMgmt);
  927. }
  928. /******************************Public*Routine******************************\
  929. * MultiUserGreDeleteXLATE
  930. *
  931. * For MultiUserNtGreCleanup (Hydra) cleanup.
  932. *
  933. * Delete the XLATE cache.
  934. *
  935. * History:
  936. * 09-Feb-1998 -by- Gilman Wong [gilmanw]
  937. * Wrote it.
  938. \**************************************************************************/
  939. VOID
  940. MultiUserGreDeleteXLATE()
  941. {
  942. ULONG ulEntry;
  943. for (ulEntry = 0; ulEntry < XLATE_CACHE_SIZE; ulEntry++)
  944. {
  945. if (xlateTable[ulEntry].pxlate)
  946. VFREEMEM(xlateTable[ulEntry].pxlate);
  947. }
  948. }
  949. VOID
  950. GreFreeSemaphoresForCurrentThread(
  951. VOID
  952. )
  953. {
  954. //
  955. // Walk the list of tracked semaphores, and release any held by this
  956. // thread.
  957. //
  958. if (MultiUserEngAllocListLock) {
  959. GreAcquireSemaphore(MultiUserEngAllocListLock);
  960. PENGTRACKHDR EngTrackHdr;
  961. EngTrackHdr = (PENGTRACKHDR) MultiUserGreEngAllocList.Flink;
  962. while (EngTrackHdr->list.Flink != &MultiUserGreEngAllocList) {
  963. if (EngTrackHdr->ulType == ENGTRACK_DRIVER_SEMAPHORE) {
  964. HSEMAPHORE hsem = (HSEMAPHORE)(EngTrackHdr + 1);
  965. if (GreIsSemaphoreOwnedByCurrentThread(hsem)) {
  966. //
  967. // The current thread was holding a semaphore. Release
  968. // it using the same technique the driver would have used.
  969. //
  970. EngReleaseSemaphore(hsem);
  971. }
  972. }
  973. EngTrackHdr = (PENGTRACKHDR)EngTrackHdr->list.Flink;
  974. }
  975. GreReleaseSemaphore(MultiUserEngAllocListLock);
  976. }
  977. }
  978. #if DBG
  979. /******************************Public*Routine******************************\
  980. * MultiUserGreHmgDbgScan
  981. *
  982. * Dumps the current handle manager contents.
  983. *
  984. * History:
  985. * 07-Feb-1998 -by- Gilman Wong [gilmanw]
  986. * Wrote it.
  987. \**************************************************************************/
  988. VOID
  989. MultiUserGreHmgDbgScan(BOOL bDumpTable, BOOL bCheckEmpty)
  990. {
  991. PENTRYOBJ pentTmp;
  992. UINT uiIndex = 1; // 1 is the first valid index
  993. UINT cObj = 0;
  994. BOOL bTitle = FALSE;
  995. ASSERTGDI((gpentHmgr != NULL),
  996. "gpentHmgr MUST be != NULL");
  997. for (uiIndex = 1; uiIndex < gcMaxHmgr; uiIndex++)
  998. {
  999. pentTmp = (PENTRYOBJ) &gpentHmgr[uiIndex];
  1000. if ((pentTmp->Objt > DEF_TYPE) && (pentTmp->Objt <= MAX_TYPE))
  1001. {
  1002. cObj++;
  1003. }
  1004. }
  1005. if (bCheckEmpty && cObj)
  1006. {
  1007. DbgPrint("\n"
  1008. "*****************************************\n");
  1009. DbgPrint(" MultiUserGreHmgDbgScan\n\n");
  1010. DbgPrint(" TERMSRV session id = 0x%08lx\n", gSessionId);
  1011. DbgPrint(" Cleanup process pid = 0x%08lx\n", W32GetCurrentPID());
  1012. DbgPrint("\n"
  1013. "*****************************************\n");
  1014. }
  1015. //
  1016. // Scan through the entire handle manager table and set owner for
  1017. // all valid objects.
  1018. //
  1019. for (uiIndex = 1; uiIndex < gcMaxHmgr && (bDumpTable && cObj != 0); uiIndex++)
  1020. {
  1021. pentTmp = (PENTRYOBJ) &gpentHmgr[uiIndex];
  1022. if ((pentTmp->Objt > DEF_TYPE) && (pentTmp->Objt <= MAX_TYPE))
  1023. {
  1024. //
  1025. // Since this is shutdown, don't bother with lock counts and
  1026. // such.
  1027. //
  1028. if (!bTitle)
  1029. {
  1030. DbgPrint("------------------\t------ ------ ----\n");
  1031. DbgPrint( "%s\tpid count lock\n", gpszHmgrType[0]);
  1032. DbgPrint("------------------\t------ ------ ----\n");
  1033. bTitle = TRUE;
  1034. }
  1035. DbgPrint("%s\t0x%04x 0x%04x %ld\n",
  1036. gpszHmgrType[pentTmp->Objt],
  1037. OBJECTOWNER_PID(pentTmp->ObjectOwner),
  1038. pentTmp->einfo.pobj->ulShareCount,
  1039. pentTmp->ObjectOwner.Share.Lock
  1040. );
  1041. }
  1042. }
  1043. if (bTitle )
  1044. {
  1045. DbgPrint("------------------\t------ ------ ----\n");
  1046. }
  1047. if (bCheckEmpty && (cObj != 0))
  1048. {
  1049. DbgPrint("MultiUserGreHmgDbgScan: %ld objects in hmgr table\n", cObj);
  1050. RIP("MultiUserGreHmgDbgScan: object leak detected\n");
  1051. }
  1052. }
  1053. /*****************************************************************************
  1054. *
  1055. * DebugGreTrackAddMapView
  1056. *
  1057. * Track GRE's Map View's for cleanup purposes
  1058. *
  1059. * ENTRY:
  1060. * Param1 (input/output)
  1061. * Comments
  1062. *
  1063. * EXIT:
  1064. * STATUS_SUCCESS - no error
  1065. *
  1066. ****************************************************************************/
  1067. VOID
  1068. DebugGreTrackAddMapView(
  1069. PVOID ViewBase
  1070. )
  1071. {
  1072. PLIST_ENTRY Entry;
  1073. PVOID Atom;
  1074. if(DebugGreMapViewListLock) GreAcquireSemaphore(DebugGreMapViewListLock);
  1075. Atom = (PVOID) PALLOCNOZ(sizeof(PVOID)+sizeof(LIST_ENTRY), 'mesG');
  1076. if (Atom)
  1077. {
  1078. *(PVOID *)Atom = ViewBase;
  1079. Entry = (PLIST_ENTRY)(((PCHAR)Atom) + sizeof(PVOID));
  1080. InsertTailList(&DebugGreMapViewList, Entry);
  1081. }
  1082. if(DebugGreMapViewListLock) GreReleaseSemaphore(DebugGreMapViewListLock);
  1083. return;
  1084. }
  1085. /*****************************************************************************
  1086. *
  1087. * DebugGreTrackRemoveMapView
  1088. *
  1089. * Remove the GRE Map View from the list
  1090. *
  1091. * ENTRY:
  1092. * Param1 (input/output)
  1093. * Comments
  1094. *
  1095. * EXIT:
  1096. * STATUS_SUCCESS - no error
  1097. *
  1098. ****************************************************************************/
  1099. VOID
  1100. DebugGreTrackRemoveMapView(
  1101. PVOID ViewBase
  1102. )
  1103. {
  1104. #if !defined(_GDIPLUS_)
  1105. PLIST_ENTRY NextEntry;
  1106. PVOID Atom;
  1107. if(DebugGreMapViewListLock) GreAcquireSemaphore(DebugGreMapViewListLock);
  1108. NextEntry = DebugGreMapViewList.Flink;
  1109. while (NextEntry != &DebugGreMapViewList)
  1110. {
  1111. Atom = (PVOID)(((PCHAR)NextEntry) - sizeof(PVOID));
  1112. if (ViewBase == *(PVOID *)Atom)
  1113. {
  1114. RemoveEntryList(NextEntry);
  1115. VFREEMEM(Atom);
  1116. break;
  1117. }
  1118. NextEntry = NextEntry->Flink;
  1119. }
  1120. if(DebugGreMapViewListLock) GreReleaseSemaphore(DebugGreMapViewListLock);
  1121. return;
  1122. #endif // !_GDIPLUS_
  1123. }
  1124. /*****************************************************************************
  1125. *
  1126. * DebugGreCleanupMapView
  1127. *
  1128. * Cleanup the tracked Map View's
  1129. *
  1130. * ENTRY:
  1131. * Param1 (input/output)
  1132. * Comments
  1133. *
  1134. * EXIT:
  1135. * STATUS_SUCCESS - no error
  1136. *
  1137. ****************************************************************************/
  1138. VOID
  1139. DebugGreCleanupMapView()
  1140. {
  1141. volatile PLIST_ENTRY NextEntry;
  1142. PVOID ViewBase;
  1143. PVOID Atom;
  1144. if(DebugGreMapViewListLock)
  1145. {
  1146. if (!IsListEmpty(&DebugGreMapViewList))
  1147. {
  1148. DbgPrint("DebugGreCleanupMapView: DebugGreMapViewList 0x%08lx not empty\n", &DebugGreMapViewList);
  1149. RIP("DebugGreCleanupMapView: leak detected\n");
  1150. }
  1151. //
  1152. // Cleanup every mapped view tracked in the list.
  1153. //
  1154. NextEntry = DebugGreMapViewList.Flink;
  1155. while (NextEntry != &DebugGreMapViewList)
  1156. {
  1157. // We can not use CONTAINING_RECORD since we are
  1158. // not within a single C structure.
  1159. RemoveEntryList(NextEntry);
  1160. Atom = (PVOID)(((PCHAR)NextEntry) - sizeof(PVOID));
  1161. ViewBase = *(PVOID *)Atom;
  1162. DbgPrint("DebugGreCleanupMapView: cleanup Map View %x\n", ViewBase);
  1163. MmUnmapViewInSessionSpace(ViewBase);
  1164. GdiFreePool(Atom);
  1165. // Restart at the begining of the list since our
  1166. // entry got deleted
  1167. NextEntry = DebugGreMapViewList.Flink;
  1168. }
  1169. }
  1170. //
  1171. // Free the list semaphore.
  1172. //
  1173. GreDeleteSemaphoreNonTracked(DebugGreMapViewListLock);
  1174. DebugGreMapViewListLock = NULL;
  1175. return;
  1176. }
  1177. #endif
  1178. /******************************Public*Routine******************************\
  1179. * GdiMultiUserFontCleanup
  1180. *
  1181. * Deletes all the fonts from the system font tables.
  1182. *
  1183. * This is only called by user when CSRSS goes away on a Hydra terminal.
  1184. *
  1185. *
  1186. * History:
  1187. * 29-Sept-1998 -by- Xudong Wu [tessiew]
  1188. * Wrote it.
  1189. \**************************************************************************/
  1190. VOID
  1191. GdiMultiUserFontCleanup()
  1192. {
  1193. if(!gpPFTPublic)
  1194. return;
  1195. #ifdef FE_SB
  1196. CleanUpEUDC();
  1197. #endif
  1198. //
  1199. // Cleanup the rest of the font stuff (font tables, font hash tables,
  1200. // font files, font substitution table, font mapper).
  1201. //
  1202. MultiUserGreCleanupAllFonts();
  1203. vCleanUpFntCache();
  1204. }