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.

1021 lines
26 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: DdHmgr.cxx
  3. *
  4. * DirectDraw handle manager API entry points
  5. *
  6. * Created: 30-Apr-1999 23:03:03
  7. * Author: Lindsay Steventon [linstev]
  8. *
  9. * Copyright (c) 1989-1999 Microsoft Corporation
  10. \**************************************************************************/
  11. #include "precomp.hxx"
  12. ULONG gcSizeDdHmgr = DD_TABLESIZE_DELTA; // Start table size
  13. DD_ENTRY *gpentDdHmgrLast = NULL; // Previous handle table
  14. DD_ENTRY *gpentDdHmgr = NULL; // Points to handle table
  15. HDD_OBJ ghFreeDdHmgr; // Free handle
  16. ULONG gcMaxDdHmgr; // Max handle alloc-ed so far
  17. HSEMAPHORE ghsemHmgr = NULL; // Synchronization of the handle manager
  18. PLARGE_INTEGER gpLockShortDelay;
  19. // Prototype for a handy debugging routine.
  20. #if DBG
  21. extern "C"
  22. VOID
  23. DdHmgPrintBadHandle(
  24. HDD_OBJ hobj,
  25. DD_OBJTYPE objt
  26. );
  27. #else
  28. #define DdHmgPrintBadHandle(hobj, objt)
  29. #endif
  30. HDD_OBJ hDdGetFreeHandle(DD_OBJTYPE objt);
  31. VOID DdFreeObject(PVOID pvFree, ULONG ulType);
  32. HDD_OBJ FASTCALL DdHmgNextOwned(HDD_OBJ hobj, W32PID pid);
  33. /*****************************Exported*Routine*****************************\
  34. * DdHmgCreate()
  35. *
  36. * Initializes a new handle manager with an initial allocation.
  37. *
  38. * History:
  39. *
  40. * 30-Apr-1999 -by- Lindsay Steventon [linstev]
  41. * Wrote it.
  42. \**************************************************************************/
  43. BOOL
  44. DdHmgCreate()
  45. {
  46. //
  47. // Initialize the handle manager allocation database.
  48. //
  49. ghFreeDdHmgr = 0; // No free handles
  50. gcMaxDdHmgr = DD_HMGR_HANDLE_BASE; // Initialize with handle index base
  51. //
  52. // Create memory block for handle table
  53. //
  54. gpentDdHmgr = (DD_ENTRY *)PALLOCMEM(sizeof(DD_ENTRY) * gcSizeDdHmgr, 'ddht');
  55. if (gpentDdHmgr == NULL)
  56. {
  57. WARNING("Could not allocated DDraw handle table.");
  58. return(FALSE);
  59. }
  60. //
  61. // Initialize exclusion stuff.
  62. //
  63. if ((ghsemHmgr = EngCreateSemaphore()) == NULL)
  64. {
  65. WARNING("Could not allocated DDraw handle semaphore.");
  66. VFREEMEM(gpentDdHmgr);
  67. gpentDdHmgr = NULL;
  68. return(FALSE);
  69. }
  70. //
  71. // allocate and initialize the timeout lock for the handle manager.
  72. //
  73. gpLockShortDelay = (PLARGE_INTEGER) PALLOCNONPAGED(sizeof(LARGE_INTEGER),
  74. 'iniG');
  75. if (gpLockShortDelay == NULL)
  76. {
  77. WARNING("Could not allocated DDraw shortdelay.");
  78. EngDeleteSemaphore(ghsemHmgr);
  79. ghsemHmgr = NULL;
  80. VFREEMEM(gpentDdHmgr);
  81. gpentDdHmgr = NULL;
  82. return(FALSE);
  83. }
  84. gpLockShortDelay->LowPart = (ULONG) -100000;
  85. gpLockShortDelay->HighPart = -1;
  86. return(TRUE);
  87. }
  88. /*****************************Exported*Routine*****************************\
  89. * DdHmgDestroy()
  90. *
  91. * Free memory allocated by the handle manager. This happens on system
  92. * shutdown. Always succeeds.
  93. *
  94. * History:
  95. *
  96. * 30-Apr-1999 -by- Lindsay Steventon [linstev]
  97. * Wrote it.
  98. \**************************************************************************/
  99. BOOL
  100. DdHmgDestroy()
  101. {
  102. ghFreeDdHmgr = 0; // Zero free handles
  103. gcMaxDdHmgr = 0; // Zero current last handle
  104. gcSizeDdHmgr = 0; // Handle table size
  105. gpentDdHmgrLast = NULL; // Zero previos handle table pointer
  106. if (gpentDdHmgr) // Free handle table
  107. {
  108. VFREEMEM(gpentDdHmgr);
  109. gpentDdHmgr = NULL;
  110. }
  111. if (ghsemHmgr)
  112. {
  113. EngDeleteSemaphore(ghsemHmgr);
  114. ghsemHmgr = NULL;
  115. }
  116. return(TRUE);
  117. }
  118. /*****************************Exported*Routine*****************************\
  119. * DdHmgCloseProcess()
  120. *
  121. * Free handles in handle table from process. Occurs on process cleanup.
  122. *
  123. * History:
  124. *
  125. * 30-Apr-1999 -by- Lindsay Steventon [linstev]
  126. * Wrote it.
  127. \**************************************************************************/
  128. BOOL
  129. DdHmgCloseProcess(W32PID W32Pid)
  130. {
  131. BOOL bRes = TRUE;
  132. HDD_OBJ hobj;
  133. DdHmgAcquireHmgrSemaphore();
  134. hobj = DdHmgNextOwned((HDD_OBJ) 0, W32Pid);
  135. DdHmgReleaseHmgrSemaphore();
  136. while (hobj != (HDD_OBJ) NULL)
  137. {
  138. switch (DdHmgObjtype(hobj))
  139. {
  140. case DD_DIRECTDRAW_TYPE:
  141. bRes = bDdDeleteDirectDrawObject((HANDLE)hobj, TRUE);
  142. break;
  143. case DD_SURFACE_TYPE:
  144. bRes = bDdDeleteSurfaceObject((HANDLE)hobj, NULL);
  145. break;
  146. case DD_MOTIONCOMP_TYPE:
  147. bRes = bDdDeleteMotionCompObject((HANDLE)hobj, NULL);
  148. break;
  149. case DD_VIDEOPORT_TYPE:
  150. bRes = bDdDeleteVideoPortObject((HANDLE)hobj, NULL);
  151. break;
  152. case D3D_HANDLE_TYPE:
  153. HRESULT hr;
  154. bRes = D3dDeleteHandle((HANDLE)hobj, 0, NULL, &hr) ==
  155. DDHAL_DRIVER_HANDLED;
  156. break;
  157. default:
  158. bRes = FALSE;
  159. break;
  160. }
  161. #if DBG
  162. if (bRes == FALSE)
  163. {
  164. DbgPrint("DDRAW ERROR: DdHmgCloseProcess couldn't delete "
  165. "obj = %p, type j=%lx\n", hobj, DdHmgObjtype(hobj));
  166. }
  167. #endif
  168. // Move on to next object.
  169. DdHmgAcquireHmgrSemaphore();
  170. hobj = DdHmgNextOwned(hobj, W32Pid);
  171. DdHmgReleaseHmgrSemaphore();
  172. }
  173. return (bRes);
  174. }
  175. /******************************Public*Routine******************************\
  176. * DdHmgValidHandle
  177. *
  178. * Returns TRUE if the handle is valid, FALSE if not.
  179. *
  180. * Note we don't need to lock the semaphore, we aren't changing anything,
  181. * we are just looking.
  182. *
  183. * History:
  184. *
  185. * 30-Apr-1999 -by- Lindsay Steventon [linstev]
  186. * Wrote it.
  187. \**************************************************************************/
  188. BOOL
  189. DdHmgValidHandle(
  190. HDD_OBJ hobj,
  191. DD_OBJTYPE objt)
  192. {
  193. BOOL bRes = FALSE;
  194. PDD_ENTRY pentTmp;
  195. UINT uiIndex = (UINT) (UINT) DdHmgIfromH(hobj);
  196. //
  197. // Acquire the handle manager lock before touching gpentDdHmgr
  198. //
  199. DdHmgAcquireHmgrSemaphore();
  200. if ((uiIndex < gcMaxDdHmgr) &&
  201. ((pentTmp = &gpentDdHmgr[uiIndex])->Objt == objt) &&
  202. (pentTmp->FullUnique == DdHmgUfromH(hobj)))
  203. {
  204. ASSERTGDI(pentTmp->einfo.pobj != (PDD_OBJ) NULL, "ERROR how can it be NULL");
  205. bRes = TRUE;
  206. }
  207. DdHmgReleaseHmgrSemaphore();
  208. return (bRes);
  209. }
  210. /******************************Public*Routine******************************\
  211. * DdHmgRemoveObject
  212. *
  213. * Removes an object from the handle table if certain conditions are met.
  214. *
  215. * History:
  216. *
  217. * 30-Apr-1999 -by- Lindsay Steventon [linstev]
  218. * Wrote it.
  219. \**************************************************************************/
  220. PVOID
  221. DdHmgRemoveObject(
  222. HDD_OBJ hobj,
  223. LONG cExclusiveLock,
  224. LONG cShareLock,
  225. BOOL bIgnoreUndeletable,
  226. DD_OBJTYPE objt)
  227. {
  228. PDD_OBJ pobj;
  229. UINT uiIndex = (UINT) DdHmgIfromH(hobj);
  230. if (uiIndex < gcMaxDdHmgr)
  231. {
  232. //
  233. // Acquire the handle manager lock before touching gpentDdHmgr
  234. //
  235. DdHmgAcquireHmgrSemaphore();
  236. //
  237. // lock handle
  238. //
  239. PDD_ENTRY pentTmp = &gpentDdHmgr[uiIndex];
  240. if (VerifyObjectOwner(pentTmp))
  241. {
  242. //
  243. // verify objt and unique
  244. //
  245. if ((pentTmp->Objt == objt) &&
  246. (pentTmp->FullUnique == DdHmgUfromH(hobj)))
  247. {
  248. pobj = pentTmp->einfo.pobj;
  249. if ((pobj->cExclusiveLock == (USHORT)cExclusiveLock) &&
  250. (pobj->ulShareCount == (ULONG)cShareLock))
  251. {
  252. if (bIgnoreUndeletable || (!(pentTmp->Flags & DD_HMGR_ENTRY_UNDELETABLE)))
  253. {
  254. //
  255. // set the handle in the object to NULL
  256. // to prevent/catch accidental decrement of the
  257. // shared reference count
  258. //
  259. pobj->hHmgr = NULL;
  260. //
  261. // free the handle
  262. //
  263. ((DD_ENTRYOBJ *) pentTmp)->vFree(uiIndex);
  264. }
  265. else
  266. {
  267. WARNING1("DdHmgRemove failed object is undeletable\n");
  268. pobj = NULL;
  269. }
  270. }
  271. else
  272. {
  273. //
  274. // object is busy
  275. //
  276. WARNING1("DdHmgRemove failed - object busy elsewhere\n");
  277. pobj = NULL;
  278. }
  279. }
  280. else
  281. {
  282. WARNING1("DdHmgRemove: bad objt or unique\n");
  283. pobj = NULL;
  284. }
  285. }
  286. else
  287. {
  288. WARNING1("DdHmgRemove: failed to lock handle\n");
  289. pobj = NULL;
  290. }
  291. DdHmgReleaseHmgrSemaphore();
  292. }
  293. else
  294. {
  295. WARNING1("DdHmgRemove failed invalid index\n");
  296. pobj = NULL;
  297. }
  298. return((PVOID)pobj);
  299. }
  300. /******************************Public*Routine******************************\
  301. * DdAllocateObject
  302. *
  303. * Allocates an object out of the heap.
  304. *
  305. * History:
  306. *
  307. * 30-Apr-1999 -by- Lindsay Steventon [linstev]
  308. * Wrote it.
  309. \**************************************************************************/
  310. //
  311. // This struct and the following union can be thrown away
  312. // when someone fixes the BASEOBJECT cExclusiveLock and BaseFlags sharing
  313. // the same DWORD.
  314. //
  315. struct SplitLockAndFlags {
  316. USHORT c_cExclusiveLock;
  317. USHORT c_BaseFlags;
  318. };
  319. union SplitOrCombinedLockAndFlags {
  320. SplitLockAndFlags S;
  321. ULONG W;
  322. };
  323. PVOID
  324. DdAllocateObject(
  325. ULONG cBytes,
  326. ULONG ulType,
  327. BOOL bZero)
  328. {
  329. PVOID pvReturn = NULL;
  330. ASSERTGDI(ulType != DD_DEF_TYPE, "DdAllocateObject ulType is bad");
  331. ASSERTGDI(cBytes >= sizeof(DD_BASEOBJECT), "DdAllocateObject cBytes is bad");
  332. //
  333. // Debug check to avoid assert in ExAllocatePool
  334. //
  335. #if DBG
  336. if (cBytes >= (PAGE_SIZE * 10000))
  337. {
  338. WARNING("DdAllocateObject: cBytes >= 10000 pages");
  339. return(NULL);
  340. }
  341. #endif
  342. ULONG ulTag = '0 hD';
  343. ulTag += ulType << 24;
  344. //
  345. // BASEOBJECT is always zero-initialized.
  346. //
  347. if (bZero)
  348. {
  349. pvReturn = PALLOCMEM(cBytes, ulTag);
  350. }
  351. else
  352. {
  353. pvReturn = PALLOCNOZ(cBytes, ulTag);
  354. //
  355. // At least the BASEOBJECT should be initialized.
  356. //
  357. if (pvReturn)
  358. {
  359. RtlZeroMemory(pvReturn, (UINT) sizeof(DD_BASEOBJECT));
  360. }
  361. }
  362. //
  363. // If the allocation failed again, then set the extended
  364. // error status and return an invalid handle.
  365. //
  366. if (!pvReturn)
  367. {
  368. KdPrint(("DXG: DdAllocateObject failed alloc of %lu bytes\n", (cBytes)));
  369. SAVE_ERROR_CODE(ERROR_NOT_ENOUGH_MEMORY);
  370. return NULL;
  371. }
  372. return(pvReturn);
  373. }
  374. /******************************Public*Routine******************************\
  375. * DdHmgAlloc
  376. *
  377. * Allocate an object from Handle Manager.
  378. *
  379. * WARNING:
  380. * --------
  381. *
  382. * If the object is share-lockable via an API, you MUST use DdHmgInsertObject
  383. * instead. If the object is only exclusive-lockable via an API, you MUST
  384. * either use DdHmgInsertObject or specify HMGR_ALLOC_LOCK.
  385. *
  386. * (This is because if you use DdHmgAlloc, a malicious multi-threaded
  387. * application could guess the handle and cause it to be dereferenced
  388. * before you've finished initializing it, possibly causing an access
  389. * violation.)
  390. *
  391. * History:
  392. *
  393. * 30-Apr-1999 -by- Lindsay Steventon [linstev]
  394. * Wrote it.
  395. \**************************************************************************/
  396. HDD_OBJ
  397. DdHmgAlloc(
  398. ULONGSIZE_T cb,
  399. DD_OBJTYPE objt,
  400. FSHORT fs) // fs can be a combination of the following:
  401. // HMGR_NO_ZERO_INIT - Don't zero initialize
  402. // HMGR_MAKE_PUBLIC - Allow object to be lockable by
  403. // any process
  404. // HMGR_ALLOC_LOCK - Do an DdHmgLock on the object and
  405. // return a pointer instead of handle
  406. {
  407. HDD_OBJ Handle;
  408. PVOID pv;
  409. ASSERTGDI(objt != (DD_OBJTYPE) DD_DEF_TYPE, "DdHmgAlloc objt is bad");
  410. ASSERTGDI(cb >= 8, "ERROR DdHmgr writes in first 8 bytes");
  411. //
  412. // Allocate a pointer.
  413. //
  414. pv = DdAllocateObject(cb, (ULONG) objt, ((fs & HMGR_NO_ZERO_INIT) == 0));
  415. if (pv != (PVOID) NULL)
  416. {
  417. //
  418. // We need the semaphore to access the free list
  419. //
  420. DdHmgAcquireHmgrSemaphore();
  421. //
  422. // Allocate a handle: can only fail if we run out of memory or bits to
  423. // store the handle index.
  424. //
  425. Handle = hDdGetFreeHandle(objt);
  426. if (Handle != (HDD_OBJ) 0)
  427. {
  428. //
  429. // Store a pointer to the object in the entry corresponding to the
  430. // allocated handle and initialize the handle data.
  431. //
  432. ((DD_ENTRYOBJ *) &(gpentDdHmgr[DdHmgIfromH(Handle)]))->vSetup((PDD_OBJ) pv, objt, fs);
  433. //
  434. // Store the object handle at the beginning of the object memory.
  435. //
  436. ((DD_OBJECT *)pv)->hHmgr = (HANDLE)Handle;
  437. DdHmgReleaseHmgrSemaphore();
  438. return ((fs & HMGR_ALLOC_LOCK) ? (HDD_OBJ)pv : Handle);
  439. }
  440. else
  441. {
  442. //
  443. // We just failed a handle allocation. Release the memory.
  444. //
  445. WARNING("Failed DdHmgAlloc to allocate a handle\n");
  446. DdHmgReleaseHmgrSemaphore();
  447. DdFreeObject(pv,(ULONG) objt);
  448. }
  449. }
  450. return((HDD_OBJ) 0);
  451. }
  452. /******************************Public*Routine******************************\
  453. * DdFreeObject
  454. *
  455. * Frees the object from where it was allocated. We have this as a separate
  456. * function in case we implement lookaside lists (as in GDI) later.
  457. *
  458. * History:
  459. *
  460. * 30-Apr-1999 -by- Lindsay Steventon [linstev]
  461. * Wrote it.
  462. \**************************************************************************/
  463. VOID
  464. DdFreeObject(PVOID pvFree, ULONG ulType)
  465. {
  466. VFREEMEM(pvFree);
  467. }
  468. /******************************Public*Routine******************************\
  469. * DdHmgFree
  470. *
  471. * Free an object from the handle manager.
  472. *
  473. * History:
  474. *
  475. * 30-Apr-1999 -by- Lindsay Steventon [linstev]
  476. * Wrote it.
  477. \**************************************************************************/
  478. VOID
  479. DdHmgFree(HDD_OBJ hobj)
  480. {
  481. UINT uiIndex = (UINT) DdHmgIfromH(hobj);
  482. PDD_OBJ pobjTmp;
  483. DD_OBJTYPE objtTmp;
  484. ASSERTGDI(uiIndex != 0, "ERROR DdHmgFree invalid 0 handle");
  485. if (uiIndex < gcMaxDdHmgr)
  486. {
  487. //
  488. // Acquire the handle manager lock before touching gpentDdHmgr
  489. //
  490. DdHmgAcquireHmgrSemaphore();
  491. PDD_ENTRY pentTmp = &gpentDdHmgr[uiIndex];
  492. pobjTmp = pentTmp->einfo.pobj;
  493. objtTmp = pentTmp->Objt;
  494. //
  495. // Free the object handle
  496. //
  497. ((DD_ENTRYOBJ *) pentTmp)->vFree(uiIndex);
  498. DdHmgReleaseHmgrSemaphore();
  499. if (pobjTmp)
  500. {
  501. DdFreeObject((PVOID)pobjTmp, (ULONG) objtTmp);
  502. }
  503. }
  504. else
  505. {
  506. WARNING1("DdHmgFree: bad handle index");
  507. }
  508. }
  509. /*****************************Exported*Routine*****************************\
  510. * HDD_OBJ DdHmgNextOwned(hobj, pid)
  511. *
  512. * Report the next object owned by specified process
  513. *
  514. * Must be called with the Hmgr semaphore acquired.
  515. *
  516. * History:
  517. *
  518. * 30-Apr-1999 -by- Lindsay Steventon [linstev]
  519. * Wrote it.
  520. \**************************************************************************/
  521. HDD_OBJ
  522. FASTCALL
  523. DdHmgNextOwned(
  524. HDD_OBJ hobj,
  525. W32PID pid)
  526. {
  527. PDD_ENTRYOBJ pentTmp;
  528. UINT uiIndex = (UINT) DdHmgIfromH(hobj);
  529. //
  530. // If we are passed 0 we inc to 1 because 0 can never be valid.
  531. // If we are passed != 0 we inc 1 to find the next one valid.
  532. //
  533. uiIndex++;
  534. while (uiIndex < gcMaxDdHmgr)
  535. {
  536. pentTmp = (PDD_ENTRYOBJ) &gpentDdHmgr[uiIndex];
  537. if (pentTmp->bOwnedBy(pid))
  538. {
  539. LONG_PTR uiIndex1 = (LONG_PTR)DD_MAKE_HMGR_HANDLE(uiIndex,pentTmp->FullUnique);
  540. return((HDD_OBJ)(uiIndex1 & 0xFFFFFFFF));
  541. }
  542. // Advance to next object
  543. uiIndex++;
  544. }
  545. // No objects found
  546. return((HDD_OBJ) 0);
  547. }
  548. /*****************************Exported*Routine*****************************\
  549. * HDD_OBJ DdHmgNextObjt
  550. *
  551. * Report the next object of a certain type.
  552. *
  553. * Must be called with the Hmgr semaphore acquired.
  554. *
  555. * History:
  556. *
  557. * 30-Apr-1999 -by- Lindsay Steventon [linstev]
  558. * Wrote it.
  559. \**************************************************************************/
  560. PDD_OBJ
  561. FASTCALL
  562. DdHmgNextObjt(
  563. HDD_OBJ hobj,
  564. DD_OBJTYPE objt)
  565. {
  566. PDD_ENTRYOBJ pentTmp;
  567. UINT uiIndex = (UINT) DdHmgIfromH(hobj);
  568. //
  569. // If we are passed 0 we inc to 1 because 0 can never be valid.
  570. // If we are passed != 0 we inc 1 to find the next one valid.
  571. //
  572. uiIndex++;
  573. while (uiIndex < gcMaxDdHmgr)
  574. {
  575. pentTmp = (PDD_ENTRYOBJ) &gpentDdHmgr[uiIndex];
  576. if (pentTmp->Objt == objt)
  577. {
  578. return(pentTmp->einfo.pobj);
  579. }
  580. //
  581. // Advance to next object
  582. //
  583. uiIndex++;
  584. }
  585. //
  586. // no objects found
  587. //
  588. return((PDD_OBJ) 0);
  589. }
  590. /*******************************Routine************************************\
  591. * DdHmgLock
  592. *
  593. * Description:
  594. *
  595. * Acquire an exclusive lock on an object, PID owner must match current PID
  596. * or be a public.
  597. *
  598. * Arguments:
  599. *
  600. * hobj - Handle to lock
  601. * objt - Check to make sure handle is of expected type
  602. *
  603. * Return Value:
  604. *
  605. * Pointer to object or NULL
  606. *
  607. * History:
  608. *
  609. * 30-Apr-1999 -by- Lindsay Steventon [linstev]
  610. * Wrote it.
  611. \**************************************************************************/
  612. PDD_OBJ
  613. FASTCALL
  614. DdHmgLock(
  615. HDD_OBJ hobj,
  616. DD_OBJTYPE objt,
  617. BOOL underSemaphore
  618. )
  619. {
  620. PDD_OBJ pobj = (PDD_OBJ)NULL;
  621. UINT uiIndex = (UINT)DdHmgIfromH(hobj);
  622. //
  623. // Acquire the handle manager lock before touching gpentDdHmgr
  624. // Only do this if we are not already under the semaphore
  625. //
  626. if (!underSemaphore) {
  627. DdHmgAcquireHmgrSemaphore();
  628. }
  629. if (uiIndex < gcMaxDdHmgr)
  630. {
  631. PDD_ENTRY pentry = &gpentDdHmgr[uiIndex];
  632. if (VerifyObjectOwner(pentry))
  633. {
  634. if ((pentry->Objt == objt) &&
  635. (pentry->FullUnique == DdHmgUfromH(hobj)))
  636. {
  637. ULONG_PTR thread = (ULONG_PTR)PsGetCurrentThread();
  638. pobj = pentry->einfo.pobj;
  639. if ((pobj->cExclusiveLock == 0) ||
  640. (pobj->Tid == thread))
  641. {
  642. INC_EXCLUSIVE_REF_CNT(pobj);
  643. pobj->Tid = thread;
  644. }
  645. else
  646. {
  647. WARNING1("DdHmgLock: object already locked by another thread");
  648. pobj = (PDD_OBJ)NULL;
  649. }
  650. }
  651. else
  652. {
  653. DdHmgPrintBadHandle(hobj, objt);
  654. }
  655. }
  656. else
  657. {
  658. DdHmgPrintBadHandle(hobj, objt);
  659. }
  660. }
  661. else
  662. {
  663. DdHmgPrintBadHandle(hobj, objt);
  664. }
  665. if (!underSemaphore) {
  666. DdHmgReleaseHmgrSemaphore();
  667. }
  668. return(pobj);
  669. }
  670. /******************************Public*Routine******************************\
  671. * DdHmgQueryLock
  672. *
  673. * This returns the number of times an object has been Locked.
  674. *
  675. * Expects: A valid handle. The handle should be validated and locked
  676. * before calling this. Note we don't need to grab the semaphore
  677. * because this call assumes the handle has already been locked
  678. * down and we are just reading memory.
  679. *
  680. * Returns: The number of times the object has been locked.
  681. *
  682. * History:
  683. *
  684. * 30-Apr-1999 -by- Lindsay Steventon [linstev]
  685. * Wrote it.
  686. \**************************************************************************/
  687. ULONG
  688. FASTCALL
  689. DdHmgQueryLock(HDD_OBJ hobj)
  690. {
  691. //
  692. // Acquire the handle manager lock before touching gpentDdHmgr
  693. //
  694. DdHmgAcquireHmgrSemaphore();
  695. UINT uiIndex = (UINT)DdHmgIfromH(hobj);
  696. ASSERTGDI(uiIndex < gcMaxDdHmgr, "DdHmgQueryLock invalid handle");
  697. ULONG ulRes = gpentDdHmgr[uiIndex].einfo.pobj->cExclusiveLock;
  698. DdHmgReleaseHmgrSemaphore();
  699. return ulRes;
  700. }
  701. /******************************Public*Routine******************************\
  702. * HDD_OBJ hDdGetFreeHandle()
  703. *
  704. * Get the next available handle. If the handle table is full, we grow it.
  705. * This function can fail under any of these circumstances:
  706. * 1. Handle manager didn't initialize
  707. * 2. Insufficient memory to grow the handle table
  708. * 3. Insufficient bits to store the handle index
  709. *
  710. * Note:
  711. * We must already have the HmgrSemaphore
  712. *
  713. * History:
  714. *
  715. * 30-Apr-1999 -by- Lindsay Steventon [linstev]
  716. * Wrote it.
  717. \**************************************************************************/
  718. HDD_OBJ
  719. hDdGetFreeHandle(
  720. DD_OBJTYPE objt
  721. )
  722. {
  723. LONG_PTR uiIndex;
  724. //
  725. // Handle manager initialized and bounds check
  726. //
  727. if ((gpentDdHmgr == NULL) || (gcMaxDdHmgr == DD_MAX_HANDLE_COUNT))
  728. {
  729. return ((HDD_OBJ)0);
  730. }
  731. //
  732. // Check if there is a free handle we can use
  733. //
  734. if (ghFreeDdHmgr != (HDD_OBJ) 0)
  735. {
  736. PDD_ENTRYOBJ pentTmp;
  737. uiIndex = (LONG_PTR)ghFreeDdHmgr;
  738. pentTmp = (PDD_ENTRYOBJ) &gpentDdHmgr[uiIndex];
  739. ghFreeDdHmgr = pentTmp->einfo.hFree;
  740. pentTmp->FullUnique = DD_USUNIQUE(pentTmp->FullUnique,objt);
  741. uiIndex = (LONG_PTR)DD_MAKE_HMGR_HANDLE(uiIndex,pentTmp->FullUnique);
  742. return((HDD_OBJ)(uiIndex & 0xFFFFFFFF));
  743. }
  744. //
  745. // Check if we've run out of handles
  746. //
  747. if (gcMaxDdHmgr == gcSizeDdHmgr)
  748. {
  749. // Increase the table size
  750. ULONG dwNewSize = gcSizeDdHmgr + DD_TABLESIZE_DELTA;
  751. // Allocate a new block
  752. DD_ENTRY *ptHmgr = (DD_ENTRY *)PALLOCMEM(sizeof(DD_ENTRY) * dwNewSize, 'ddht');
  753. if (ptHmgr == NULL)
  754. {
  755. WARNING("DdHmgr failed to grow handle table\n");
  756. return ((HDD_OBJ) 0);
  757. }
  758. //
  759. // Copy the old handles into the new table
  760. //
  761. RtlMoveMemory(ptHmgr, gpentDdHmgr, sizeof(DD_ENTRY) * gcSizeDdHmgr);
  762. gcSizeDdHmgr = dwNewSize;
  763. gpentDdHmgrLast = gpentDdHmgr;
  764. VFREEMEM(gpentDdHmgr);
  765. gpentDdHmgr = ptHmgr;
  766. }
  767. //
  768. // Allocate a new handle table entry and set the uniqueness value.
  769. //
  770. uiIndex = DD_USUNIQUE(DD_UNIQUE_INCREMENT,objt);
  771. gpentDdHmgr[gcMaxDdHmgr].FullUnique = (USHORT) uiIndex;
  772. uiIndex = (LONG_PTR)DD_MAKE_HMGR_HANDLE(gcMaxDdHmgr,uiIndex);
  773. gcMaxDdHmgr++;
  774. return((HDD_OBJ)(uiIndex & 0xFFFFFFFF));
  775. }
  776. /******************************Public*Routines*****************************\
  777. * DdHmgAcquireHmgrSemaphore *
  778. * DdHmgReleaseHmgrSemaphore *
  779. * *
  780. * Convenience functions for the handle manager semaphore. *
  781. * *
  782. \**************************************************************************/
  783. VOID
  784. DdHmgAcquireHmgrSemaphore()
  785. {
  786. EngAcquireSemaphore(ghsemHmgr);
  787. }
  788. VOID
  789. DdHmgReleaseHmgrSemaphore()
  790. {
  791. EngReleaseSemaphore(ghsemHmgr);
  792. }
  793. /******************************Public*Routine******************************\
  794. * DdHmgPrintBadHandle
  795. *
  796. * Simple routine that prints out a warning when a handle manager
  797. * lock fails due to a bad handle.
  798. *
  799. \**************************************************************************/
  800. #if DBG
  801. CONST CHAR* aszDdType[] = {
  802. "hdef", // DD_DEF_TYPE
  803. "hddraw", // DD_DIRECTDRAW_TYPE
  804. "hddrawsurf", // DD_SURFACE_TYPE
  805. "hd3d", // D3D_HANDLE_TYPE
  806. "hddrawvport", // DD_VIDEOPORT_TYPE
  807. "hmotioncomp", // DD_MOTIONCOMP_TYPE
  808. "hunused", //
  809. };
  810. VOID
  811. DdHmgPrintBadHandle(
  812. HDD_OBJ hobj,
  813. DD_OBJTYPE objt
  814. )
  815. {
  816. static CHAR *szSystem = "System";
  817. static CHAR *szUnknown = "???";
  818. CHAR *pszImage;
  819. {
  820. PETHREAD pet;
  821. PEPROCESS pep;
  822. if (pep = PsGetCurrentProcess())
  823. {
  824. pszImage = (CHAR *)PsGetProcessImageFileName(pep);
  825. if (*pszImage == '\0')
  826. {
  827. pszImage = szSystem;
  828. }
  829. }
  830. else
  831. {
  832. pszImage = szUnknown;
  833. }
  834. }
  835. KdPrint(("DXG: %s or DLL gave bad handle 0x%p as an %s.\n",
  836. pszImage, hobj, aszDdType[objt]));
  837. }
  838. #endif