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.

557 lines
12 KiB

  1. /*************************************************************************
  2. *
  3. * khandle.c
  4. *
  5. * Manage kernel mode handles for transport drivers.
  6. *
  7. * Copyright 1998, Microsoft.
  8. *
  9. *************************************************************************/
  10. /*
  11. * Includes
  12. */
  13. #include <precomp.h>
  14. #pragma hdrstop
  15. ULONG gHandleTableSize;
  16. #ifdef TERMDD_NO_USE_TABLE_PACKAGE
  17. typedef struct _TDHANDLE_ENTRY {
  18. LIST_ENTRY Link;
  19. PVOID Context;
  20. ULONG ContextSize;
  21. } TDHANDLE_ENTRY, *PTDHANDLE_ENTRY;
  22. /*
  23. * Global Data
  24. */
  25. LIST_ENTRY IcaTdHandleList;
  26. /*
  27. * These set of routines allows TD's to create a handle that will survive
  28. * across them being unloaded and re-loaded. This allows a handle to be
  29. * passed back to ICASRV in a secure manner.
  30. *
  31. * NOTE: We do not deal with ICASRV leaking these handles. It never exits.
  32. * If it does, we will need to have ICADD return a real NT handle, or
  33. * destroy all handles for a TD when it unloads.
  34. */
  35. /*****************************************************************************
  36. *
  37. * IcaCreateHandle
  38. *
  39. * Create a handle entry for the context and length.
  40. *
  41. * ENTRY:
  42. * Param1 (input/output)
  43. * Comments
  44. *
  45. * EXIT:
  46. * STATUS_SUCCESS - no error
  47. *
  48. ****************************************************************************/
  49. NTSTATUS
  50. IcaCreateHandle(
  51. PVOID Context,
  52. ULONG ContextSize,
  53. PVOID *ppHandle
  54. )
  55. {
  56. KIRQL OldIrql;
  57. PTDHANDLE_ENTRY p;
  58. p = ICA_ALLOCATE_POOL( NonPagedPool, sizeof(TDHANDLE_ENTRY) );
  59. if( p == NULL ) {
  60. return( STATUS_NO_MEMORY );
  61. }
  62. RtlZeroMemory( p, sizeof(TDHANDLE_ENTRY) );
  63. p->Context = Context;
  64. p->ContextSize = ContextSize;
  65. *ppHandle = (PVOID)p;
  66. IcaAcquireSpinLock( &IcaSpinLock, &OldIrql );
  67. InsertHeadList( &IcaTdHandleList, &p->Link );
  68. IcaReleaseSpinLock( &IcaSpinLock, OldIrql );
  69. InterlockedIncrement(&gHandleTableSize);
  70. return( STATUS_SUCCESS );
  71. }
  72. /*****************************************************************************
  73. *
  74. * IcaReturnHandle
  75. *
  76. * Return the context and length for the handle.
  77. *
  78. * ENTRY:
  79. * Param1 (input/output)
  80. * Comments
  81. *
  82. * EXIT:
  83. * STATUS_SUCCESS - no error
  84. *
  85. ****************************************************************************/
  86. NTSTATUS
  87. IcaReturnHandle(
  88. PVOID Handle,
  89. PVOID *ppContext,
  90. PULONG pContextSize
  91. )
  92. {
  93. KIRQL OldIrql;
  94. PLIST_ENTRY pEntry;
  95. PTDHANDLE_ENTRY p;
  96. IcaAcquireSpinLock( &IcaSpinLock, &OldIrql );
  97. pEntry = IcaTdHandleList.Flink;
  98. while( pEntry != &IcaTdHandleList ) {
  99. p = CONTAINING_RECORD( pEntry, TDHANDLE_ENTRY, Link );
  100. if( (PVOID)p == Handle ) {
  101. *ppContext = p->Context;
  102. *pContextSize = p->ContextSize;
  103. IcaReleaseSpinLock( &IcaSpinLock, OldIrql );
  104. return( STATUS_SUCCESS );
  105. }
  106. pEntry = pEntry->Flink;
  107. }
  108. IcaReleaseSpinLock( &IcaSpinLock, OldIrql );
  109. return( STATUS_INVALID_HANDLE );
  110. }
  111. /*****************************************************************************
  112. *
  113. * IcaCloseHandle
  114. *
  115. * Return the context and length for the handle. Delete the
  116. * handle entry.
  117. *
  118. * ENTRY:
  119. * Param1 (input/output)
  120. * Comments
  121. *
  122. * EXIT:
  123. * STATUS_SUCCESS - no error
  124. *
  125. ****************************************************************************/
  126. NTSTATUS
  127. IcaCloseHandle(
  128. PVOID Handle,
  129. PVOID *ppContext,
  130. PULONG pContextSize
  131. )
  132. {
  133. KIRQL OldIrql;
  134. PLIST_ENTRY pEntry;
  135. PTDHANDLE_ENTRY p;
  136. IcaAcquireSpinLock( &IcaSpinLock, &OldIrql );
  137. pEntry = IcaTdHandleList.Flink;
  138. while( pEntry != &IcaTdHandleList ) {
  139. p = CONTAINING_RECORD( pEntry, TDHANDLE_ENTRY, Link );
  140. if( (PVOID)p == Handle ) {
  141. RemoveEntryList( &p->Link );
  142. IcaReleaseSpinLock( &IcaSpinLock, OldIrql );
  143. InterlockedDecrement(&gHandleTableSize);
  144. *ppContext = p->Context;
  145. *pContextSize = p->ContextSize;
  146. ICA_FREE_POOL( p );
  147. return( STATUS_SUCCESS );
  148. }
  149. pEntry = pEntry->Flink;
  150. }
  151. IcaReleaseSpinLock( &IcaSpinLock, OldIrql );
  152. return( STATUS_INVALID_HANDLE );
  153. }
  154. /*****************************************************************************
  155. *
  156. * IcaInitializeHandleTable
  157. *
  158. * Initializes handle table at driver load.
  159. *
  160. * ENTRY:
  161. * None
  162. * Comments
  163. *
  164. * EXIT:
  165. * None
  166. *
  167. ****************************************************************************/
  168. void
  169. IcaInitializeHandleTable(
  170. void
  171. )
  172. {
  173. InitializeListHead( &IcaTdHandleList );
  174. }
  175. /*****************************************************************************
  176. *
  177. * IcaCleanupHandleTable
  178. *
  179. * Cleans up handle table at driver unload.
  180. *
  181. * ENTRY:
  182. * None
  183. * Comments
  184. *
  185. * EXIT:
  186. * None
  187. *
  188. ****************************************************************************/
  189. void
  190. IcaCleanupHandleTable(
  191. void
  192. )
  193. {
  194. KIRQL OldIrql;
  195. PLIST_ENTRY pEntry;
  196. PTDHANDLE_ENTRY p;
  197. KdPrint(("TermDD: IcaCleanupHandleTable table size is %d\n",gHandleTableSize));
  198. for (pEntry = IcaTdHandleList.Flink; pEntry != &IcaTdHandleList; pEntry = IcaTdHandleList.Flink) {
  199. p = CONTAINING_RECORD( pEntry, TDHANDLE_ENTRY, Link );
  200. RemoveEntryList(&p->Links);
  201. ICA_FREE_POOL( p->Context );
  202. ICA_FREE_POOL( p );
  203. }
  204. }
  205. #else
  206. typedef struct _TDHANDLE_ENTRY {
  207. PVOID Context;
  208. ULONG ContextSize;
  209. } TDHANDLE_ENTRY, *PTDHANDLE_ENTRY;
  210. RTL_GENERIC_TABLE IcaHandleReferenceTable;
  211. RTL_GENERIC_COMPARE_RESULTS
  212. NTAPI
  213. IcaCompareHandleTableEntry (
  214. IN struct _RTL_GENERIC_TABLE *Table,
  215. IN PVOID FirstInstance,
  216. IN PVOID SecondInstance
  217. );
  218. PVOID
  219. IcaAllocateHandleTableEntry (
  220. IN struct _RTL_GENERIC_TABLE *Table,
  221. IN CLONG ByteSize
  222. );
  223. VOID
  224. IcaFreeHandleTableEntry (
  225. IN struct _RTL_GENERIC_TABLE *Table,
  226. IN PVOID Buffer
  227. );
  228. /*****************************************************************************
  229. *
  230. * IcaInitializeHandleTable
  231. *
  232. * Initializes handle table at driver load.
  233. *
  234. * ENTRY:
  235. * None
  236. * Comments
  237. *
  238. * EXIT:
  239. * None
  240. *
  241. ****************************************************************************/
  242. void
  243. IcaInitializeHandleTable(
  244. void
  245. )
  246. {
  247. RtlInitializeGenericTable( &IcaHandleReferenceTable,
  248. IcaCompareHandleTableEntry,
  249. IcaAllocateHandleTableEntry,
  250. IcaFreeHandleTableEntry,
  251. NULL);
  252. }
  253. /*****************************************************************************
  254. *
  255. * IcaCleanupHandleTable
  256. *
  257. * Cleanup handle table at driver unload.
  258. *
  259. * ENTRY:
  260. * None
  261. * Comments
  262. *
  263. * EXIT:
  264. * None
  265. *
  266. ****************************************************************************/
  267. void
  268. IcaCleanupHandleTable(
  269. void
  270. )
  271. {
  272. KIRQL OldIrql;
  273. PLIST_ENTRY pEntry;
  274. PTDHANDLE_ENTRY p;
  275. PVOID pContext;
  276. TDHANDLE_ENTRY key;
  277. KdPrint(("TermDD: IcaCleanupHandleTable table size is %d\n",gHandleTableSize));
  278. while (p = RtlEnumerateGenericTable(&IcaHandleReferenceTable,TRUE)) {
  279. key.Context = p->Context;
  280. RtlDeleteElementGenericTable(&IcaHandleReferenceTable, &key);
  281. ICA_FREE_POOL(key.Context);
  282. }
  283. }
  284. /*****************************************************************************
  285. *
  286. * IcaCreateHandle
  287. *
  288. * Create a handle entry for the context and length.
  289. *
  290. * ENTRY:
  291. * Param1 (input/output)
  292. * Comments
  293. *
  294. * EXIT:
  295. * STATUS_SUCCESS - no error
  296. *
  297. ****************************************************************************/
  298. NTSTATUS
  299. IcaCreateHandle(
  300. PVOID Context,
  301. ULONG ContextSize,
  302. PVOID *ppHandle
  303. )
  304. {
  305. KIRQL OldIrql;
  306. TDHANDLE_ENTRY key;
  307. BOOLEAN bNewElement;
  308. key.Context = Context;
  309. key.ContextSize = ContextSize;
  310. IcaAcquireSpinLock( &IcaSpinLock, &OldIrql );
  311. if (!RtlInsertElementGenericTable(&IcaHandleReferenceTable,(PVOID) &key, sizeof(TDHANDLE_ENTRY), &bNewElement )) {
  312. IcaReleaseSpinLock( &IcaSpinLock, OldIrql );
  313. return STATUS_NO_MEMORY;
  314. }
  315. IcaReleaseSpinLock( &IcaSpinLock, OldIrql );
  316. ASSERT(bNewElement);
  317. if (!bNewElement) {
  318. return STATUS_INVALID_PARAMETER;
  319. }
  320. InterlockedIncrement(&gHandleTableSize);
  321. *ppHandle = Context;
  322. return( STATUS_SUCCESS );
  323. }
  324. /*****************************************************************************
  325. *
  326. * IcaReturnHandle
  327. *
  328. * Return the context and length for the handle.
  329. *
  330. * ENTRY:
  331. * Param1 (input/output)
  332. * Comments
  333. *
  334. * EXIT:
  335. * STATUS_SUCCESS - no error
  336. *
  337. ****************************************************************************/
  338. NTSTATUS
  339. IcaReturnHandle(
  340. PVOID Handle,
  341. PVOID *ppContext,
  342. PULONG pContextSize
  343. )
  344. {
  345. KIRQL OldIrql;
  346. PTDHANDLE_ENTRY p;
  347. TDHANDLE_ENTRY key;
  348. key.Context = Handle;
  349. IcaAcquireSpinLock( &IcaSpinLock, &OldIrql );
  350. p = RtlLookupElementGenericTable(&IcaHandleReferenceTable, &key);
  351. if (p != NULL) {
  352. *ppContext = p->Context;
  353. *pContextSize = p->ContextSize;
  354. IcaReleaseSpinLock( &IcaSpinLock, OldIrql );
  355. return STATUS_SUCCESS;
  356. } else {
  357. IcaReleaseSpinLock( &IcaSpinLock, OldIrql );
  358. return STATUS_INVALID_HANDLE;
  359. }
  360. }
  361. /*****************************************************************************
  362. *
  363. * IcaCloseHandle
  364. *
  365. * Return the context and length for the handle. Delete the
  366. * handle entry.
  367. *
  368. * ENTRY:
  369. * Param1 (input/output)
  370. * Comments
  371. *
  372. * EXIT:
  373. * STATUS_SUCCESS - no error
  374. *
  375. ****************************************************************************/
  376. NTSTATUS
  377. IcaCloseHandle(
  378. PVOID Handle,
  379. PVOID *ppContext,
  380. PULONG pContextSize
  381. )
  382. {
  383. KIRQL OldIrql;
  384. PTDHANDLE_ENTRY p;
  385. TDHANDLE_ENTRY key;
  386. key.Context = Handle;
  387. IcaAcquireSpinLock( &IcaSpinLock, &OldIrql );
  388. p = RtlLookupElementGenericTable(&IcaHandleReferenceTable, &key);
  389. if (p != NULL) {
  390. *ppContext = p->Context;
  391. *pContextSize = p->ContextSize;
  392. RtlDeleteElementGenericTable(&IcaHandleReferenceTable, &key);
  393. IcaReleaseSpinLock( &IcaSpinLock, OldIrql );
  394. InterlockedDecrement(&gHandleTableSize);
  395. return STATUS_SUCCESS;
  396. } else {
  397. IcaReleaseSpinLock( &IcaSpinLock, OldIrql );
  398. return STATUS_INVALID_HANDLE;
  399. }
  400. }
  401. /*****************************************************************************
  402. *
  403. * IcaCompareHandleTableEntry
  404. *
  405. * Generic table support.Compare two handles table entry instances
  406. *
  407. *
  408. ****************************************************************************/
  409. RTL_GENERIC_COMPARE_RESULTS
  410. NTAPI
  411. IcaCompareHandleTableEntry (
  412. IN struct _RTL_GENERIC_TABLE *Table,
  413. IN PVOID FirstInstance,
  414. IN PVOID SecondInstance
  415. )
  416. {
  417. ULONG_PTR FirstHandle = (ULONG_PTR)((PTDHANDLE_ENTRY)FirstInstance)->Context;
  418. ULONG_PTR SecondHandle = (ULONG_PTR)((PTDHANDLE_ENTRY)SecondInstance)->Context;
  419. if (FirstHandle < SecondHandle ) {
  420. return GenericLessThan;
  421. }
  422. if (FirstHandle > SecondHandle ) {
  423. return GenericGreaterThan;
  424. }
  425. return GenericEqual;
  426. }
  427. /*****************************************************************************
  428. *
  429. * IcaAllocateHandleTableEntry
  430. *
  431. * Generic table support. Allocates a new table entry
  432. *
  433. *
  434. ****************************************************************************/
  435. PVOID
  436. IcaAllocateHandleTableEntry (
  437. IN struct _RTL_GENERIC_TABLE *Table,
  438. IN CLONG ByteSize
  439. )
  440. {
  441. return ICA_ALLOCATE_POOL( NonPagedPool, ByteSize );
  442. }
  443. /*****************************************************************************
  444. *
  445. * IcaFreeHandleTableEntry
  446. *
  447. * Generic table support. frees a new table entry
  448. *
  449. *
  450. ****************************************************************************/
  451. VOID
  452. IcaFreeHandleTableEntry (
  453. IN struct _RTL_GENERIC_TABLE *Table,
  454. IN PVOID Buffer
  455. )
  456. {
  457. ICA_FREE_POOL(Buffer);
  458. }
  459. #endif