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.

626 lines
16 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: hmgrp.hxx
  3. *
  4. * Private definitions for handle manager
  5. *
  6. * Created: 08-Dec-1989 23:03:03
  7. * Author: Donald Sidoroff [donalds]
  8. *
  9. * Copyright (c) 1989-1999 Microsoft Corporation
  10. \**************************************************************************/
  11. HOBJ hGetFreeHandle(OBJTYPE objt);
  12. extern LONG lRandom();
  13. extern LONG glAllocChance;
  14. /**************************************************************************\
  15. *
  16. * Lookaside structures
  17. *
  18. \**************************************************************************/
  19. //
  20. // Define number of lookaside entries to allocate for selected objects.
  21. //
  22. // Note, the following numbers are based in winbench object usage.
  23. //
  24. #define HMG_DC_OBJECTS 40
  25. #define HMG_RGN_OBJECTS 96
  26. #define HMG_SURF_OBJECTS 40
  27. #define HMG_PAL_OBJECTS 12
  28. #define HMG_BRUSH_OBJECTS 96
  29. #define HMG_LFONT_OBJECTS 64
  30. #define HMG_RFONT_OBJECTS 55
  31. //
  32. // Define objects sizes
  33. //
  34. #define HMG_DC_SIZE sizeof(DC)
  35. #define HMG_RGN_SIZE (QUANTUM_REGION_SIZE)
  36. #define HMG_SURF_SIZE (SURFACE::tSizeOf() + 32)
  37. #define HMG_PAL_SIZE (sizeof(PALETTE)+sizeof(DWORD)*16)
  38. #define HMG_BRUSH_SIZE sizeof(BRUSH)
  39. #define HMG_LFONT_SIZE (offsetof(LFONT,elfw) + \
  40. offsetof(ENUMLOGFONTEXDVW,elfDesignVector) + \
  41. SIZEOFDV(0))
  42. #define HMG_RFONT_SIZE sizeof(RFONT)
  43. //
  44. // Define Maximum allowed size when there is enough memory in the system
  45. //
  46. // These numbers are based on WinBench 97, WinStone97, and system boot usage
  47. //
  48. #define HMG_DC_MAX HMG_DC_SIZE
  49. #define HMG_RGN_MAX (QUANTUM_REGION_SIZE)
  50. #define HMG_SURF_MAX (SURFACE::tSizeOf() + 256)
  51. #define HMG_PAL_MAX HMG_PAL_SIZE
  52. #define HMG_BRUSH_MAX (sizeof(BRUSH) + 32)
  53. #define HMG_LFONT_MAX HMG_LFONT_SIZE
  54. #define HMG_RFONT_MAX HMG_RFONT_SIZE
  55. BOOL
  56. HmgInitializeLookAsideList(
  57. ULONG ulType,
  58. ULONG size,
  59. ULONG dwTag,
  60. USHORT Number
  61. );
  62. /*********************************Class************************************\
  63. * class OBJLOCK
  64. *
  65. * This class is used to lock a handle entry against anybody fooling with
  66. * it. This is currently being used for regions to keep another thread
  67. * from using the handle entry since the object pointed to by the handle
  68. * may be invalid for a time.
  69. *
  70. * History:
  71. * 28-Nov-1994 -by- Eric Kutter [erick]
  72. * Wrote it.
  73. \**************************************************************************/
  74. #define OBJLOCK_TYPE DEF_TYPE
  75. class OBJLOCK
  76. {
  77. private:
  78. OBJTYPE objt;
  79. PENTRY pent;
  80. public:
  81. OBJLOCK(HOBJ hobj)
  82. {
  83. pent = &gpentHmgr[HmgIfromH(hobj)];
  84. objt = pent->Objt;
  85. pent->Objt = OBJLOCK_TYPE;
  86. }
  87. ~OBJLOCK()
  88. {
  89. pent->Objt = objt;
  90. }
  91. };
  92. /*********************************Class************************************\
  93. * SIMPLELOCK
  94. *
  95. * Locks a LONG at the given address, will wait for lock to be acquired.
  96. *
  97. * History:
  98. *
  99. * 09-Oct-2001 -by- Pravin Santiago [pravins]
  100. *
  101. \**************************************************************************/
  102. class SIMPLELOCK
  103. {
  104. LONG *pLong;
  105. public:
  106. SIMPLELOCK (LONG *pl)
  107. {
  108. LONG nl = 1;
  109. LONG cl;
  110. BOOL bLockStatus = FALSE;
  111. pLong = 0;
  112. KeEnterCriticalRegion();
  113. do
  114. {
  115. cl = *pl;
  116. if (cl)
  117. {
  118. KeDelayExecutionThread(KernelMode,FALSE,gpLockShortDelay);
  119. WARNING1("DELAY EXECUTION for SIMPLELOCK");
  120. }
  121. else
  122. {
  123. if (InterlockedCompareExchange(pl,nl,cl) == cl)
  124. {
  125. bLockStatus = TRUE;
  126. }
  127. }
  128. } while (!bLockStatus);
  129. pLong = pl;
  130. }
  131. void vUnlock()
  132. {
  133. if (pLong)
  134. {
  135. LONG nl = 0;
  136. LONG cl = *pLong;
  137. LONG exRes = InterlockedCompareExchange(pLong,nl,cl);
  138. ASSERTGDI(exRes == cl, "SIMPLELOCK::~SIMPLELOCK InterlockedCompareExchange failed");
  139. pLong = 0;
  140. KeLeaveCriticalRegion();
  141. }
  142. }
  143. ~SIMPLELOCK() { vUnlock(); }
  144. };
  145. /*********************************Class************************************\
  146. * HANDLELOCK
  147. *
  148. * Locks given handle, will wait for handle lock to be set.
  149. *
  150. * Will be in CriticalRegion for the duration of the handle lock.
  151. *
  152. * History:
  153. *
  154. * 21-Feb-1996 -by- Mark Enstrom [marke]
  155. *
  156. \**************************************************************************/
  157. class HANDLELOCK
  158. {
  159. private:
  160. PENTRY pent;
  161. BOOL bLockStatus;
  162. OBJECTOWNER ObjOld;
  163. OBJECTOWNER ObjNew;
  164. //
  165. // Lock handle
  166. //
  167. public:
  168. //
  169. // no contstructor
  170. //
  171. HANDLELOCK()
  172. {
  173. bLockStatus = FALSE;
  174. pent = NULL;
  175. }
  176. VOID
  177. vLockHandle(PENTRY pentry,BOOL bCheck)
  178. {
  179. PW32THREAD pw32thread = W32GetCurrentThread();
  180. #if defined(_WIN64)
  181. KERNEL_PVOID pclientID = (pw32thread != NULL) ? pw32thread->pClientID : NULL;
  182. #endif
  183. bLockStatus = FALSE;
  184. pent = pentry;
  185. //
  186. // must be in critical region while handle lock held
  187. //
  188. KeEnterCriticalRegion();
  189. do
  190. {
  191. ObjOld = pent->ObjectOwner;
  192. //
  193. // if pclientID is not null, we are doing WOW64 printing via LPC
  194. // allow the proxy server to access the handle
  195. //
  196. if (bCheck &&
  197. (OBJECTOWNER_PID(ObjOld) != W32GetCurrentPID()) &&
  198. (OBJECTOWNER_PID(ObjOld) != OBJECT_OWNER_PUBLIC)
  199. #if defined(_WIN64)
  200. &&
  201. (pclientID == NULL || (OBJECTOWNER_PID(ObjOld) != ((PRINTCLIENTID*)pclientID)->clientPid))
  202. #endif
  203. )
  204. {
  205. WARNING1("CHECK_LOCK_HANDLE failed, incorrect PID owner");
  206. break;
  207. }
  208. if (ObjOld.Share.Lock)
  209. {
  210. KeDelayExecutionThread(KernelMode,FALSE,gpLockShortDelay);
  211. WARNING1("DELAY EXECUTION for handle check lock");
  212. }
  213. else
  214. {
  215. ObjNew = ObjOld;
  216. ObjNew.Share.Lock = 1;
  217. if (InterlockedCompareExchange(
  218. (PLONG)&pent->ObjectOwner.ulObj,
  219. ObjNew.ulObj,
  220. ObjOld.ulObj) == (LONG)ObjOld.ulObj)
  221. {
  222. bLockStatus = TRUE;
  223. }
  224. }
  225. } while (!bLockStatus);
  226. //
  227. // exit critical region if lock failed
  228. //
  229. if (!bLockStatus)
  230. {
  231. pent = NULL;
  232. KeLeaveCriticalRegion();
  233. }
  234. }
  235. HANDLELOCK(PENTRY pentry,BOOL bCheck)
  236. {
  237. vLockHandle(pentry,bCheck);
  238. }
  239. //
  240. // destructor: make sure handle is not locked
  241. //
  242. ~HANDLELOCK()
  243. {
  244. if (bLockStatus)
  245. {
  246. RIP("GDI Handle still locked at destructor!");
  247. if ((pent != (PENTRY)NULL))
  248. {
  249. ObjOld = pent->ObjectOwner;
  250. ObjNew = ObjOld;
  251. ObjNew.Share.Lock = 0;
  252. LONG ExchRes = InterlockedCompareExchange(
  253. (PLONG)&pent->ObjectOwner.ulObj,
  254. ObjNew.ulObj,
  255. ObjOld.ulObj);
  256. //
  257. // Note that the InterlockedCompareExchange should never fail.
  258. // This handle's locked so nobody should be changing it.
  259. //
  260. ASSERTGDI(ExchRes == (LONG)ObjOld.ulObj, "HANDLELOCK ~HANDLELOCK InterlockedCompareExchange failed");
  261. }
  262. bLockStatus = FALSE;
  263. pent = (PENTRY)NULL;
  264. KeLeaveCriticalRegion();
  265. }
  266. }
  267. //
  268. // Full check lock
  269. //
  270. BOOL bLockHobj(HOBJ hobj,OBJTYPE objt)
  271. {
  272. UINT uiIndex = (UINT) HmgIfromH(hobj);
  273. BOOL bStatus = FALSE;
  274. PENTRY pentTemp = (PENTRY)NULL;
  275. if (uiIndex < gcMaxHmgr)
  276. {
  277. pentTemp = &gpentHmgr[uiIndex];
  278. vLockHandle(pentTemp,TRUE);
  279. if (bLockStatus)
  280. {
  281. if (
  282. (pent->Objt != objt) ||
  283. (pent->FullUnique != HmgUfromH(hobj))
  284. )
  285. {
  286. ObjOld = pent->ObjectOwner;
  287. ObjNew = ObjOld;
  288. ObjNew.Share.Lock = 0;
  289. LONG ExchRes = InterlockedCompareExchange(
  290. (PLONG)&pent->ObjectOwner.ulObj,
  291. ObjNew.ulObj,
  292. ObjOld.ulObj);
  293. //
  294. // Note that the InterlockedCompareExchange should never fail.
  295. // This handle's locked so nobody should be changing it.
  296. //
  297. ASSERTGDI(ExchRes == (LONG)ObjOld.ulObj, "HANDLELOCK bLockHobj InterlockedCompareExchange failed");
  298. bLockStatus = FALSE;
  299. pent = (PENTRY)NULL;
  300. KeLeaveCriticalRegion();
  301. }
  302. }
  303. }
  304. return(bLockStatus);
  305. }
  306. //
  307. // Always call unlock explicitly: destructor will RIP
  308. // if it must unlock handle
  309. //
  310. VOID
  311. vUnlock()
  312. {
  313. ASSERTGDI(bLockStatus,"HANDLELOCK vUnlock called when handle not bLockStatus");
  314. ASSERTGDI((pent != NULL),"HANDLELOCK vUnlock called when pent == NULL");
  315. ASSERTGDI((pent->ObjectOwner.Share.Lock == 1),
  316. "HANDLELOCK vUnlock called when handle not locked");
  317. ObjOld = pent->ObjectOwner;
  318. ObjNew = ObjOld;
  319. ObjNew.Share.Lock = 0;
  320. LONG ExchRes = InterlockedCompareExchange(
  321. (PLONG)&pent->ObjectOwner.ulObj,
  322. ObjNew.ulObj,
  323. ObjOld.ulObj);
  324. //
  325. // Note that the InterlockedCompareExchange should never fail.
  326. // This handle's locked so nobody should be changing it.
  327. //
  328. ASSERTGDI(ExchRes == (LONG)ObjOld.ulObj, "HANDLELOCK vUnlock InterlockedCompareExchange failed");
  329. bLockStatus = FALSE;
  330. pent = (PENTRY)NULL;
  331. KeLeaveCriticalRegion();
  332. }
  333. //
  334. // entry routines
  335. //
  336. BOOL bValid()
  337. {
  338. return(bLockStatus && (pent != (PENTRY)NULL));
  339. }
  340. //
  341. // return entry share count
  342. //
  343. ULONG ShareCount()
  344. {
  345. ASSERTGDI((bLockStatus && (pent != NULL)),"HANDLELOCK::ShareCount: handle not locked");
  346. ASSERTGDI(pent->einfo.pobj != NULL, "HANDLELOCK::ShareCount: pent->einfo.pobj is NULL");
  347. return(pent->einfo.pobj->ulShareCount);
  348. }
  349. //
  350. // return entry pEntry
  351. //
  352. PENTRY pentry()
  353. {
  354. ASSERTGDI((bLockStatus && (pent != NULL)),"pUser: handle not locked");
  355. return(pent);
  356. }
  357. //
  358. // return entry pUser
  359. //
  360. PVOID pUser()
  361. {
  362. ASSERTGDI((bLockStatus && (pent != NULL)),"pUser: handle not locked");
  363. return(pent->pUser);
  364. }
  365. //
  366. // return pobj
  367. //
  368. POBJ pObj()
  369. {
  370. ASSERTGDI((bLockStatus && (pent != NULL)),"pObj: handle not locked");
  371. return(pent->einfo.pobj);
  372. }
  373. //
  374. // set PID
  375. //
  376. VOID Pid(W32PID pid)
  377. {
  378. ASSERTGDI((bLockStatus && (pent != NULL)),"Pid: handle not locked");
  379. SET_OBJECTOWNER_PID(pent->ObjectOwner,pid);
  380. }
  381. W32PID Pid()
  382. {
  383. ASSERTGDI((bLockStatus && (pent != NULL)),"Pid: handle not locked");
  384. return(OBJECTOWNER_PID(pent->ObjectOwner));
  385. }
  386. };
  387. // Notes on entry structure
  388. //
  389. // The internal entry in the handle manager appears as follows
  390. //
  391. // +-------------------+
  392. // | einfo.pobj, hfree | 4 bytes
  393. // +-------------------+
  394. // | ObjectOwner | 4 bytes
  395. // +-------------------+
  396. // | FullUnique | 2 bytes
  397. // +-------------------+
  398. // | Objt | 1 byte
  399. // +-------------------+
  400. // | Flags | 1 byte
  401. // +-------------------+
  402. // | pUser | 4 bytes
  403. // +-------------------+
  404. // 16 bytes total space
  405. class ENTRYOBJ : public _ENTRY
  406. {
  407. public:
  408. ENTRYOBJ() { }
  409. ~ENTRYOBJ() { }
  410. VOID vSetup(POBJ pObj,OBJTYPE objt_,FSHORT fs)
  411. {
  412. OBJECTOWNER ObjNew;
  413. PW32THREAD pw32thread = W32GetCurrentThread();
  414. #if defined(_WIN64)
  415. KERNEL_PVOID pclientID = (pw32thread != NULL) ? pw32thread->pClientID : NULL;
  416. #endif
  417. HANDLELOCK HandleLock(this, FALSE);
  418. if (HandleLock.bValid()) {
  419. ObjNew = ObjectOwner;
  420. einfo.pobj = (POBJ) pObj;
  421. Objt = objt_;
  422. Flags = 0;
  423. pUser = NULL;
  424. //
  425. // if pclientID is not NULL we are doing WOW64 printing
  426. // set handle's Tid and owner Pid to print client's.
  427. //
  428. if (fs & HMGR_MAKE_PUBLIC)
  429. {
  430. SET_OBJECTOWNER_PID(ObjNew,OBJECT_OWNER_PUBLIC);
  431. }
  432. else
  433. {
  434. #if defined(_WIN64)
  435. if (pclientID)
  436. {
  437. SET_OBJECTOWNER_PID(ObjNew, ((PRINTCLIENTID*)pclientID)->clientPid);
  438. }
  439. else
  440. #endif
  441. {
  442. SET_OBJECTOWNER_PID(ObjNew,W32GetCurrentPID());
  443. }
  444. }
  445. if (fs & HMGR_ALLOC_LOCK)
  446. {
  447. #if defined(_WIN64)
  448. if (pclientID)
  449. {
  450. pObj->Tid = ((PRINTCLIENTID*)pclientID)->clientTid;
  451. }
  452. else
  453. #endif
  454. {
  455. pObj->Tid = (PW32THREAD)PsGetCurrentThread();
  456. }
  457. }
  458. pObj->cExclusiveLock = (USHORT)(fs & HMGR_ALLOC_LOCK);
  459. pObj->ulShareCount = (USHORT)((fs & HMGR_ALLOC_ALT_LOCK) >> 1);
  460. //
  461. // clear user date pointer
  462. //
  463. pUser = NULL;
  464. //
  465. // Update the ObjectOwner.
  466. //
  467. ObjectOwner = ObjNew;
  468. HandleLock.vUnlock();
  469. }
  470. }
  471. VOID vFree(UINT uiIndex)
  472. {
  473. //
  474. // handle must already be locked
  475. //
  476. ENTRY *pentry = &gpentHmgr[uiIndex];
  477. OBJECTOWNER ObjNew = pentry->ObjectOwner;
  478. ASSERTGDI((ObjNew.Share.Lock == 1), "ENTRYOBJ::vFree must be called with locked handle");
  479. HmgDecProcessHandleCount(OBJECTOWNER_PID(ObjNew));
  480. //
  481. // Insert the specified handle in the free list.
  482. //
  483. pentry->einfo.hFree = ghFreeHmgr;
  484. //Sundown: ghFreeHmgr only has the index, we call MAKE_HMGR_HANDLE in hGetFreeHandle
  485. ghFreeHmgr = (HOBJ) (ULONG_PTR)uiIndex;
  486. //
  487. // Set the object type to the default type so all handle translations
  488. // will fail and increment the uniqueness value.
  489. //
  490. Objt = (OBJTYPE) DEF_TYPE;
  491. FullUnique += UNIQUE_INCREMENT;
  492. //
  493. // clear user date pointer
  494. //
  495. pUser = NULL;
  496. //
  497. // Clear shared count, set initial pid. Caller
  498. // must unlock handle.
  499. //
  500. SET_OBJECTOWNER_PID(ObjNew,0);
  501. pentry->ObjectOwner = ObjNew;
  502. }
  503. BOOL bOwnedBy(W32PID pid_)
  504. {
  505. return((Objt != DEF_TYPE) && (OBJECTOWNER_PID(ObjectOwner) == (pid_ & PID_BITS)));
  506. }
  507. };
  508. typedef ENTRYOBJ *PENTRYOBJ;