Source code of Windows XP (NT5)
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.

895 lines
15 KiB

  1. /*++
  2. Copyright (c) 1990-1995 Microsoft Corporation
  3. Module Name:
  4. handle.c
  5. Abstract:
  6. This module contains all function which deal with handle table for the
  7. common UI
  8. Author:
  9. 30-Jan-1996 Tue 16:28:56 created -by- Daniel Chou (danielc)
  10. [Environment:]
  11. NT Windows - Common Printer Driver UI DLL
  12. [Notes:]
  13. Revision History:
  14. --*/
  15. #include "precomp.h"
  16. #pragma hdrstop
  17. #define DBG_CPSUIFILENAME DbgHandle
  18. #define DBG_CPSUI_HTABLE 0x00000001
  19. #define DBG_FINDHANDLE 0x00000002
  20. #define DBG_ADD_DATA 0x00000004
  21. #define DBG_HANDLE_DESTROY 0x00000008
  22. #define DBG_GET_HPSPINFO 0x00000010
  23. #define DBG_SEM 0x00000020
  24. DEFINE_DBGVAR(0);
  25. HANDLE hCPSUIMutex = NULL;
  26. CPSUIHANDLETABLE CPSUIHandleTable = { NULL, 0, 0, 0, 0 };
  27. extern DWORD TlsIndex;
  28. BOOL
  29. LOCK_CPSUI_HANDLETABLE(
  30. VOID
  31. )
  32. /*++
  33. Routine Description:
  34. This function get the lock the object
  35. Arguments:
  36. VOID
  37. Return Value:
  38. BOOL
  39. Author:
  40. 27-Mar-1996 Wed 11:27:26 created -by- Daniel Chou (danielc)
  41. Revision History:
  42. --*/
  43. {
  44. BOOL Ok = FALSE;
  45. if (hCPSUIMutex) {
  46. WORD Idx;
  47. switch (WaitForSingleObject(hCPSUIMutex, MAX_SEM_WAIT)) {
  48. case WAIT_OBJECT_0:
  49. //
  50. // Signaled, and own it now
  51. //
  52. if (!CPSUIHandleTable.cWait++) {
  53. CPSUIHandleTable.ThreadID = GetCurrentThreadId();
  54. }
  55. Idx = TLSVALUE_2_IDX(TlsGetValue(TlsIndex));
  56. TlsSetValue(TlsIndex,
  57. ULongToPtr(MK_TLSVALUE(CPSUIHandleTable.cWait, Idx)));
  58. CPSUIDBG(DBG_SEM, ("LOCK_CPSUI_HANDLETABLE: ThreadID=%ld, cWait=%ld",
  59. GetCurrentThreadId(), CPSUIHandleTable.cWait));
  60. Ok = TRUE;
  61. break;
  62. case WAIT_ABANDONED:
  63. CPSUIERR(("LockCPSUIObject()= WAIT_ABANDONED"));
  64. break;
  65. case WAIT_TIMEOUT:
  66. CPSUIERR(("LockCPSUIObject()= WAIT_TIMEOUT"));
  67. break;
  68. default:
  69. CPSUIERR(("LockCPSUIObject()= UNKNOWN"));
  70. break;
  71. }
  72. }
  73. return(Ok);
  74. }
  75. BOOL
  76. UNLOCK_CPSUI_HANDLETABLE(
  77. VOID
  78. )
  79. /*++
  80. Routine Description:
  81. Arguments:
  82. Return Value:
  83. Author:
  84. 27-Mar-1996 Wed 11:39:37 created -by- Daniel Chou (danielc)
  85. Revision History:
  86. --*/
  87. {
  88. BOOL Ok = FALSE;
  89. if (hCPSUIMutex) {
  90. DWORD ThreadID = GetCurrentThreadId();
  91. WORD Idx;
  92. CPSUIDBG(DBG_SEM, ("UNLOCK_CPSUI_HANDLETABLE: ThreadID=%ld, cWait=%ld",
  93. ThreadID, CPSUIHandleTable.cWait));
  94. if (ThreadID == CPSUIHandleTable.ThreadID) {
  95. if (CPSUIHandleTable.cWait) {
  96. if (--CPSUIHandleTable.cWait == 0) {
  97. CPSUIHandleTable.ThreadID = NO_THREADID;
  98. }
  99. Idx = TLSVALUE_2_IDX(TlsGetValue(TlsIndex));
  100. TlsSetValue(TlsIndex,
  101. ULongToPtr(MK_TLSVALUE(CPSUIHandleTable.cWait, Idx)));
  102. ReleaseMutex(hCPSUIMutex);
  103. Ok = TRUE;
  104. } else {
  105. CPSUIERR(("The Thread ID does not match=%ld",
  106. CPSUIHandleTable.ThreadID));
  107. }
  108. } else {
  109. CPSUIERR(("The ThreadID=%ld does not own the mutex", ThreadID));
  110. }
  111. }
  112. return(Ok);
  113. }
  114. PCPSUIPAGE
  115. HANDLETABLE_GetCPSUIPage(
  116. HANDLE hTable
  117. )
  118. /*++
  119. Routine Description:
  120. This function take a handle table and return the pData assoicated with it,
  121. the pData must already added by HANDLETABLE_AddCPSUIPage()
  122. Arguments:
  123. Return Value:
  124. pCPSUIPage, NULL if FAILED
  125. Author:
  126. 28-Dec-1995 Thu 17:05:11 created -by- Daniel Chou (danielc)
  127. Revision History:
  128. --*/
  129. {
  130. PDATATABLE pDataTable;
  131. PCPSUIPAGE pFoundPage = NULL;
  132. PCPSUIPAGE pCPSUIPage;
  133. WORD Idx;
  134. LOCK_CPSUI_HANDLETABLE();
  135. if ((hTable) &&
  136. (pDataTable = CPSUIHandleTable.pDataTable) &&
  137. (HANDLE_2_PREFIX(hTable) == HANDLE_TABLE_PREFIX) &&
  138. ((Idx = HANDLE_2_IDX(hTable)) < CPSUIHandleTable.MaxCount) &&
  139. (pCPSUIPage = pDataTable[Idx].pCPSUIPage)) {
  140. if (pCPSUIPage->ID != CPSUIPAGE_ID) {
  141. CPSUIERR(("HANDLETABLE_FindpCPSUIPage(%08lx), pCPSUIPage=%08lx INVALID Internal ID",
  142. hTable, pCPSUIPage));
  143. } else if (pCPSUIPage->hCPSUIPage != hTable) {
  144. CPSUIERR(("HANDLETABLE_FIndpCPSUIPage(%08lx), pCPSUIPagePage=%08lx, HANDLE not matched",
  145. hTable, pCPSUIPage));
  146. } else {
  147. pCPSUIPage->cLock++;
  148. pFoundPage = pCPSUIPage;
  149. }
  150. }
  151. UNLOCK_CPSUI_HANDLETABLE();
  152. return(pFoundPage);
  153. }
  154. DWORD
  155. HANDLETABLE_LockCPSUIPage(
  156. PCPSUIPAGE pCPSUIPage
  157. )
  158. /*++
  159. Routine Description:
  160. This function decrement the cLock for the Page currently in USE
  161. Arguments:
  162. pCPSUIPage - Pointer to the CPSUIPAGE
  163. Return Value:
  164. BOOL, true if decrment successfully
  165. Author:
  166. 05-Apr-1996 Fri 16:41:46 created -by- Daniel Chou (danielc)
  167. Revision History:
  168. --*/
  169. {
  170. DWORD cLock = 0;
  171. if (pCPSUIPage) {
  172. LOCK_CPSUI_HANDLETABLE();
  173. cLock = ++(pCPSUIPage->cLock);
  174. UNLOCK_CPSUI_HANDLETABLE();
  175. }
  176. return(cLock);
  177. }
  178. BOOL
  179. HANDLETABLE_UnGetCPSUIPage(
  180. PCPSUIPAGE pCPSUIPage
  181. )
  182. /*++
  183. Routine Description:
  184. This function decrement the cLock for the Page currently in USE
  185. Arguments:
  186. pCPSUIPage - Pointer to the CPSUIPAGE
  187. Return Value:
  188. BOOL, true if decrment successfully
  189. Author:
  190. 05-Apr-1996 Fri 16:41:46 created -by- Daniel Chou (danielc)
  191. Revision History:
  192. --*/
  193. {
  194. BOOL Ok;
  195. if (pCPSUIPage) {
  196. LOCK_CPSUI_HANDLETABLE();
  197. if (Ok = (BOOL)pCPSUIPage->cLock) {
  198. --(pCPSUIPage->cLock);
  199. } else {
  200. CPSUIERR(("HANDLETABLE_UnlockpCPSUIPage(%08lx), cLock is ZERO",
  201. pCPSUIPage));
  202. }
  203. UNLOCK_CPSUI_HANDLETABLE();
  204. } else {
  205. Ok = FALSE;
  206. }
  207. return(Ok);
  208. }
  209. BOOL
  210. HANDLETABLE_IsChildPage(
  211. PCPSUIPAGE pChildPage,
  212. PCPSUIPAGE pParentPage
  213. )
  214. /*++
  215. Routine Description:
  216. This function check if pChildPage is one of the pParentPage's child or
  217. its decedent child
  218. Arguments:
  219. pChildPage - Pointer to the CPSUIPAGE for child
  220. pParentPage - Pointer to the CPSUIPAGE for parent to be checked
  221. Return Value:
  222. TRUE, if this is child, otherwise FALSE
  223. Author:
  224. 08-Apr-1996 Mon 12:52:51 created -by- Daniel Chou (danielc)
  225. Revision History:
  226. --*/
  227. {
  228. BOOL Ok = FALSE;
  229. LOCK_CPSUI_HANDLETABLE();
  230. if (pChildPage) {
  231. while (pChildPage->pParent) {
  232. if (pChildPage->pParent == pParentPage) {
  233. Ok = TRUE;
  234. break;
  235. } else {
  236. pChildPage = pChildPage->pParent;
  237. }
  238. }
  239. }
  240. UNLOCK_CPSUI_HANDLETABLE();
  241. return(Ok);
  242. }
  243. PCPSUIPAGE
  244. HANDLETABLE_GetRootPage(
  245. PCPSUIPAGE pCPSUIPage
  246. )
  247. /*++
  248. Routine Description:
  249. This function find the root page for pCPSUIPage
  250. Arguments:
  251. pCPSUIPage - Pointer to the CPSUIPAGE who's root page to be searched
  252. Return Value:
  253. PCPSUIPAGE - Pointer to root page, NULL if failed
  254. Author:
  255. 08-Apr-1996 Mon 12:49:42 created -by- Daniel Chou (danielc)
  256. Revision History:
  257. --*/
  258. {
  259. PCPSUIPAGE pPage;
  260. PCPSUIPAGE pRootPage = NULL;
  261. LOCK_CPSUI_HANDLETABLE();
  262. pPage = pCPSUIPage;
  263. //
  264. // If we need to search for the root page, then try it now
  265. //
  266. while ((pPage) && (pPage->pParent)) {
  267. pPage = pPage->pParent;
  268. }
  269. if ((pPage) && (pPage->Flags & CPF_ROOT)) {
  270. pPage->cLock++;
  271. pRootPage = pPage;
  272. } else {
  273. CPSUIERR(("HANDLETABLE_FindpRootPage(%08lx): No ROOT Page found",
  274. pCPSUIPage));
  275. }
  276. UNLOCK_CPSUI_HANDLETABLE();
  277. return(pRootPage);
  278. }
  279. HANDLE
  280. HANDLETABLE_AddCPSUIPage(
  281. PCPSUIPAGE pCPSUIPage
  282. )
  283. /*++
  284. Routine Description:
  285. This function add pData to the handle table, if new
  286. Arguments:
  287. pCPSUIPage - Pointer to the CPSUIPAGE to be add to the handle table
  288. Return Value:
  289. HANDLE, if NULL then it failed, the handle already exists
  290. Author:
  291. 28-Dec-1995 Thu 16:03:25 created -by- Daniel Chou (danielc)
  292. Revision History:
  293. --*/
  294. {
  295. HANDLE hTable;
  296. PDATATABLE pDataTable;
  297. LOCK_CPSUI_HANDLETABLE();
  298. if ((!CPSUIHandleTable.pDataTable) ||
  299. (CPSUIHandleTable.CurCount >= CPSUIHandleTable.MaxCount)) {
  300. if (!CPSUIHandleTable.pDataTable) {
  301. CPSUIHandleTable.CurCount =
  302. CPSUIHandleTable.MaxCount = 0;
  303. }
  304. CPSUIDBG(DBG_ADD_DATA,
  305. ("HANDLETABLE_AddCPSUIPage(%08lx): Table reach LIMIT, Expanded=%ld->%ld",
  306. CPSUIHandleTable.pDataTable,
  307. CPSUIHandleTable.CurCount,
  308. CPSUIHandleTable.CurCount + DATATABLE_BLK_COUNT));
  309. //
  310. // Reallocate Table
  311. //
  312. if ((CPSUIHandleTable.MaxCount <= DATATABLE_MAX_COUNT) &&
  313. (pDataTable = LocalAlloc(LPTR,
  314. (CPSUIHandleTable.MaxCount +
  315. DATATABLE_BLK_COUNT) *
  316. sizeof(DATATABLE)))) {
  317. if (CPSUIHandleTable.pDataTable) {
  318. CopyMemory(pDataTable,
  319. CPSUIHandleTable.pDataTable,
  320. CPSUIHandleTable.MaxCount * sizeof(DATATABLE));
  321. LocalFree((HLOCAL)CPSUIHandleTable.pDataTable);
  322. }
  323. CPSUIHandleTable.pDataTable = pDataTable;
  324. CPSUIHandleTable.MaxCount += DATATABLE_BLK_COUNT;
  325. } else {
  326. CPSUIERR(("HANDLETABLE_AddCPSUIPage(): Expand TABLE failed"));
  327. }
  328. }
  329. hTable = NULL;
  330. if (pDataTable = CPSUIHandleTable.pDataTable) {
  331. WORD Idx;
  332. for (Idx = 0; Idx < CPSUIHandleTable.MaxCount; Idx++, pDataTable++) {
  333. if (!pDataTable->pCPSUIPage) {
  334. hTable = WORD_2_HANDLE(Idx);
  335. pDataTable->pCPSUIPage = pCPSUIPage;
  336. pCPSUIPage->cLock = 1;
  337. CPSUIHandleTable.CurCount++;
  338. CPSUIDBG(DBG_ADD_DATA, ("HANDLETABLE_AddCPSUIPage(%08lx): Idx=%ld, Cur=%ld, Max=%ld",
  339. pCPSUIPage, Idx,
  340. CPSUIHandleTable.CurCount,
  341. CPSUIHandleTable.MaxCount));
  342. break;
  343. } else if (pDataTable->pCPSUIPage == pCPSUIPage) {
  344. CPSUIERR(("HANDLETABLE_AddCPSUIPage(%08lx): pCPSUIPage exists, Idx=%ld",
  345. pCPSUIPage, Idx));
  346. }
  347. }
  348. }
  349. if (!hTable) {
  350. CPSUIERR(("HANDLETABLE_AddCPSUIPage(%08lx:%ld) Cannot find empty entry",
  351. CPSUIHandleTable.pDataTable,
  352. CPSUIHandleTable.MaxCount));
  353. }
  354. UNLOCK_CPSUI_HANDLETABLE();
  355. return(hTable);
  356. }
  357. BOOL
  358. HANDLETABLE_DeleteHandle(
  359. HANDLE hTable
  360. )
  361. /*++
  362. Routine Description:
  363. This function delete a handle from the handle table
  364. Arguments:
  365. hTable - Handle to the handle table to be deleted
  366. Return Value:
  367. BOOL
  368. Author:
  369. 28-Dec-1995 Thu 17:42:42 created -by- Daniel Chou (danielc)
  370. Revision History:
  371. --*/
  372. {
  373. PDATATABLE pDataTable;
  374. PCPSUIPAGE pCPSUIPage;
  375. WORD Idx;
  376. BOOL Ok = FALSE;
  377. LOCK_CPSUI_HANDLETABLE();
  378. if ((pDataTable = CPSUIHandleTable.pDataTable) &&
  379. (HANDLE_2_PREFIX(hTable) == HANDLE_TABLE_PREFIX) &&
  380. (CPSUIHandleTable.CurCount) &&
  381. ((Idx = HANDLE_2_IDX(hTable)) < CPSUIHandleTable.MaxCount) &&
  382. (pCPSUIPage = (pDataTable += Idx)->pCPSUIPage)) {
  383. if (pCPSUIPage->cLock) {
  384. CPSUIERR(("HANDLETABLE_DeleteHandle(%08lx), pCPSUIPage=%08lx, cLock=%ld",
  385. hTable, pCPSUIPage, pCPSUIPage->cLock));
  386. } else {
  387. // check to release the activation context (if any)
  388. if (pCPSUIPage->hActCtx && pCPSUIPage->hActCtx != INVALID_HANDLE_VALUE) {
  389. ReleaseActCtx(pCPSUIPage->hActCtx);
  390. pCPSUIPage->hActCtx = INVALID_HANDLE_VALUE;
  391. }
  392. pDataTable->pCPSUIPage = NULL;
  393. Ok = TRUE;
  394. //
  395. // Reduce current count and free the memory
  396. //
  397. CPSUIHandleTable.CurCount--;
  398. LocalFree((HLOCAL)pCPSUIPage);
  399. }
  400. } else {
  401. CPSUIERR(("HANDLETABLE_DeleteHandle(%08lx) not found, Idx=%ld, pDataTable=%08lx",
  402. hTable, Idx, pDataTable));
  403. }
  404. UNLOCK_CPSUI_HANDLETABLE();
  405. return(Ok);
  406. }
  407. BOOL
  408. HANDLETABLE_Create(
  409. VOID
  410. )
  411. /*++
  412. Routine Description:
  413. Arguments:
  414. Return Value:
  415. Author:
  416. 28-Dec-1995 Thu 16:46:27 created -by- Daniel Chou (danielc)
  417. Revision History:
  418. --*/
  419. {
  420. CPSUIHandleTable.pDataTable = NULL;
  421. CPSUIHandleTable.MaxCount =
  422. CPSUIHandleTable.CurCount = 0;
  423. CPSUIHandleTable.ThreadID = NO_THREADID;
  424. CPSUIHandleTable.cWait = 0;
  425. if (hCPSUIMutex = CreateMutex(NULL, FALSE, NULL)) {
  426. CPSUIDBG(DBG_CPSUI_HTABLE, ("CREATE: CreateMutex=%08lx", hCPSUIMutex));
  427. return(TRUE);
  428. } else {
  429. CPSUIERR(("CreateMutex() FAILED, Exit"));
  430. return(FALSE);
  431. }
  432. }
  433. VOID
  434. HANDLETABLE_Destroy(
  435. VOID
  436. )
  437. /*++
  438. Routine Description:
  439. Arguments:
  440. Return Value:
  441. Author:
  442. 28-Dec-1995 Thu 16:48:32 created -by- Daniel Chou (danielc)
  443. Revision History:
  444. --*/
  445. {
  446. PDATATABLE pDataTable;
  447. WORD Idx;
  448. LOCK_CPSUI_HANDLETABLE();
  449. if (hCPSUIMutex) {
  450. if (pDataTable = CPSUIHandleTable.pDataTable) {
  451. for (Idx = 0;
  452. Idx < CPSUIHandleTable.MaxCount;
  453. Idx++, pDataTable++) {
  454. if (pDataTable->pCPSUIPage) {
  455. CPSUIERR(("HANDLETABLE_Destroy: Idx=%ld, pPage=%08lx, cLock=%ld is not delete yet",
  456. Idx, pDataTable->pCPSUIPage, pDataTable->pCPSUIPage->cLock));
  457. LocalFree((HLOCAL)pDataTable->pCPSUIPage);
  458. pDataTable->pCPSUIPage = NULL;
  459. if (CPSUIHandleTable.CurCount) {
  460. --(CPSUIHandleTable.CurCount);
  461. } else {
  462. CPSUIERR(("HANDLETABLE_Destroy(): Unmatched CurCount"));
  463. }
  464. }
  465. }
  466. LocalFree((HLOCAL)CPSUIHandleTable.pDataTable);
  467. CPSUIHandleTable.pDataTable = NULL;
  468. CPSUIHandleTable.MaxCount =
  469. CPSUIHandleTable.CurCount = 0;
  470. }
  471. }
  472. UNLOCK_CPSUI_HANDLETABLE();
  473. CloseHandle(hCPSUIMutex);
  474. }