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.

416 lines
7.9 KiB

  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Module Name:
  3. util.c
  4. Abstract:
  5. This module contains the routines some helper routines.
  6. - Workitems: These routines manage the scheduled work items.
  7. - Handle table: There routines manage a handle table that creates unique
  8. handles and stores context pointers into the table that are only
  9. accessible by the unique handle generated.
  10. Author:
  11. Hakan Berk - Microsoft, Inc. (hakanb@microsoft.com) Feb-2000
  12. Environment:
  13. Windows 2000 kernel mode Miniport driver or equivalent.
  14. Revision History:
  15. ---------------------------------------------------------------------------*/
  16. #include <ntddk.h>
  17. #include <ntddndis.h>
  18. #include <ndis.h>
  19. #include <ndiswan.h>
  20. #include <ndistapi.h>
  21. #include <ntverp.h>
  22. #include "debug.h"
  23. #include "timer.h"
  24. #include "bpool.h"
  25. #include "ppool.h"
  26. #include "util.h"
  27. #include "packet.h"
  28. #include "protocol.h"
  29. #include "miniport.h"
  30. #include "tapi.h"
  31. VOID InitializeWorkItemLookasideList(
  32. IN PNPAGED_LOOKASIDE_LIST pLookaside,
  33. IN ULONG tagLookaside
  34. )
  35. {
  36. NdisInitializeNPagedLookasideList( pLookaside,
  37. NULL,
  38. NULL,
  39. 0,
  40. sizeof( WORKITEM ),
  41. tagLookaside,
  42. 0 );
  43. }
  44. WORKITEM* AllocWorkItem(
  45. IN PNPAGED_LOOKASIDE_LIST pLookaside,
  46. IN WORKITEM_EXEC_ROUTINE pExecRoutine,
  47. IN WORKITEM_FREE_ROUTINE pFreeRoutine,
  48. IN PVOID Args[4],
  49. IN UINT workType
  50. )
  51. {
  52. WORKITEM* pWorkItem = NULL;
  53. //
  54. // Allocate a binding work item from our pool
  55. //
  56. pWorkItem = NdisAllocateFromNPagedLookasideList( pLookaside );
  57. if ( pWorkItem == NULL )
  58. return NULL;
  59. //
  60. // Clear the memory
  61. //
  62. NdisZeroMemory( pWorkItem, sizeof( WORKITEM ) );
  63. //
  64. // Initialize the state of the work item
  65. //
  66. pWorkItem->workState = WS_NotScheduled;
  67. //
  68. // Initialize the type of work
  69. //
  70. pWorkItem->workType = workType;
  71. //
  72. // Set the lookaside list member
  73. //
  74. pWorkItem->pLookaside = pLookaside;
  75. //
  76. // Initialize the context for the work item
  77. //
  78. NdisMoveMemory( pWorkItem->Args, Args, 4 * sizeof( PVOID ) );
  79. pWorkItem->pExecRoutine = pExecRoutine;
  80. pWorkItem->pFreeRoutine = pFreeRoutine;
  81. //
  82. // As our NDIS_WORK_ITEM structure is embedded into our own work item
  83. // we can initialize it here.
  84. //
  85. NdisInitializeWorkItem( &pWorkItem->ndisWorkItem,
  86. &WorkItemExec,
  87. pWorkItem );
  88. return pWorkItem;
  89. }
  90. VOID ScheduleWorkItem(
  91. IN WORKITEM *pWorkItem
  92. )
  93. {
  94. //
  95. // Initialize the state of the work item
  96. //
  97. pWorkItem->workState = WS_Scheduled;
  98. //
  99. // Schedule the item
  100. //
  101. NdisScheduleWorkItem( &pWorkItem->ndisWorkItem );
  102. }
  103. VOID FreeWorkItem(
  104. IN WORKITEM *pWorkItem
  105. )
  106. {
  107. WORKITEM_FREE_ROUTINE pFreeRoutine = NULL;
  108. ASSERT( pWorkItem != NULL );
  109. //
  110. // Free the associated context information
  111. //
  112. if ( pWorkItem->pFreeRoutine != NULL )
  113. pWorkItem->pFreeRoutine( pWorkItem->Args, pWorkItem->workType );
  114. //
  115. // Free the actual work item
  116. //
  117. NdisFreeToNPagedLookasideList( pWorkItem->pLookaside, (PVOID) pWorkItem );
  118. }
  119. //
  120. // This is the NDIS_WORK_ITEM handler that we schedule for our BINDING_WORKITEMs.
  121. //
  122. VOID WorkItemExec(
  123. IN NDIS_WORK_ITEM* pNdisWorkItem,
  124. IN PVOID pvContext
  125. )
  126. {
  127. WORKITEM* pWorkItem = NULL;
  128. ASSERT( pNdisWorkItem != NULL );
  129. pWorkItem = (WORKITEM*) pvContext;
  130. ASSERT( pWorkItem->workState == WS_Scheduled );
  131. pWorkItem->workState = WS_Executing;
  132. if ( pWorkItem->pExecRoutine != NULL )
  133. pWorkItem->pExecRoutine( pWorkItem->Args, pWorkItem->workType );
  134. pWorkItem->workState = WS_Executed;
  135. FreeWorkItem( pWorkItem );
  136. }
  137. HANDLE_TABLE InitializeHandleTable(
  138. IN UINT nHandleTableSize
  139. )
  140. {
  141. NDIS_STATUS status = NDIS_STATUS_RESOURCES;
  142. HANDLE_TABLE Table = NULL;
  143. do
  144. {
  145. //
  146. // Allocate the table context
  147. //
  148. status = NdisAllocateMemoryWithTag( &Table,
  149. sizeof( HANDLE_TABLE_CB ),
  150. MTAG_HANDLETABLE );
  151. if ( status != NDIS_STATUS_SUCCESS )
  152. break;
  153. NdisZeroMemory( Table, sizeof( HANDLE_TABLE_CB ) );
  154. //
  155. // Allocate the array that holds the handle contexts
  156. //
  157. status = NdisAllocateMemoryWithTag( &Table->HandleTable,
  158. sizeof( HANDLE_CB ) * nHandleTableSize,
  159. MTAG_HANDLECB );
  160. if ( status != NDIS_STATUS_SUCCESS )
  161. break;
  162. NdisZeroMemory( Table->HandleTable, sizeof( HANDLE_CB ) * nHandleTableSize );
  163. Table->nTableSize = nHandleTableSize;
  164. Table->nActiveHandles = 0;
  165. Table->usKeys = 0;
  166. status = NDIS_STATUS_SUCCESS;
  167. } while ( FALSE );
  168. if ( status != NDIS_STATUS_SUCCESS )
  169. FreeHandleTable( Table );
  170. return Table;
  171. }
  172. VOID FreeHandleTable(
  173. IN OUT HANDLE_TABLE Table
  174. )
  175. {
  176. if ( Table == NULL )
  177. return;
  178. if ( Table->HandleTable )
  179. {
  180. NdisFreeMemory( Table->HandleTable,
  181. Table->nTableSize * sizeof( HANDLE_CB ),
  182. 0 );
  183. }
  184. NdisFreeMemory( Table,
  185. sizeof( HANDLE_TABLE_CB ),
  186. 0 );
  187. }
  188. NDIS_HANDLE InsertToHandleTable(
  189. IN HANDLE_TABLE Table,
  190. IN USHORT usPreferedIndex,
  191. IN PVOID pContext
  192. )
  193. {
  194. ULONG ulHandle;
  195. USHORT usKey;
  196. HANDLE_CB* pHandleCB = NULL;
  197. if ( Table == NULL )
  198. return (NDIS_HANDLE) NULL;
  199. if ( usPreferedIndex == NO_PREFERED_INDEX )
  200. {
  201. UINT i;
  202. for (i = 0 ; i < Table->nTableSize ; i++ )
  203. if ( !Table->HandleTable[i].fActive )
  204. break;
  205. usPreferedIndex = (USHORT) i;
  206. }
  207. else
  208. {
  209. if ( Table->HandleTable[ usPreferedIndex ].fActive )
  210. return NULL;
  211. }
  212. if ( usPreferedIndex >= Table->nTableSize )
  213. return NULL;
  214. //
  215. // Generate Handle
  216. //
  217. ulHandle = (ULONG) usPreferedIndex;
  218. usKey = ++Table->usKeys;
  219. ulHandle = ulHandle << 16;
  220. ulHandle |= (ULONG) usKey;
  221. //
  222. // Update the handle control block
  223. //
  224. pHandleCB = &Table->HandleTable[ usPreferedIndex ];
  225. pHandleCB->fActive = TRUE;
  226. pHandleCB->pContext = pContext;
  227. pHandleCB->Handle = (NDIS_HANDLE) ULongToPtr( ulHandle );
  228. //
  229. // Increment the active handle counter
  230. //
  231. Table->nActiveHandles++;
  232. return pHandleCB->Handle;
  233. }
  234. USHORT RetrieveIndexFromHandle(
  235. IN NDIS_HANDLE Handle
  236. )
  237. {
  238. ULONG_PTR ulHandle = (ULONG_PTR) Handle;
  239. USHORT usIndex;
  240. usIndex = (USHORT) ( ulHandle >> 16 );
  241. return usIndex;
  242. }
  243. PVOID RetrieveFromHandleTable(
  244. IN HANDLE_TABLE Table,
  245. IN NDIS_HANDLE Handle
  246. )
  247. {
  248. USHORT usIndex;
  249. HANDLE_CB* pHandleCB = NULL;
  250. if ( Table == NULL )
  251. return NULL;
  252. usIndex = RetrieveIndexFromHandle( Handle );
  253. if ( usIndex >= Table->nTableSize )
  254. return NULL;
  255. pHandleCB = &Table->HandleTable[ usIndex ];
  256. if ( !pHandleCB->fActive )
  257. return NULL;
  258. if ( pHandleCB->Handle != Handle )
  259. return NULL;
  260. return pHandleCB->pContext;
  261. }
  262. PVOID RetrieveFromHandleTableByIndex(
  263. IN HANDLE_TABLE Table,
  264. IN USHORT usIndex
  265. )
  266. {
  267. HANDLE_CB* pHandleCB = NULL;
  268. if ( Table == NULL )
  269. return NULL;
  270. if ( usIndex >= Table->nTableSize )
  271. return NULL;
  272. pHandleCB = &Table->HandleTable[ usIndex ];
  273. if ( !pHandleCB->fActive )
  274. return NULL;
  275. return pHandleCB->pContext;
  276. }
  277. PVOID RetrieveFromHandleTableBySessionId(
  278. IN HANDLE_TABLE Table,
  279. IN USHORT usSessionId
  280. )
  281. {
  282. USHORT usIndex = usSessionId - 1;
  283. return RetrieveFromHandleTableByIndex( Table, usIndex );
  284. }
  285. VOID RemoveFromHandleTable(
  286. IN HANDLE_TABLE Table,
  287. IN NDIS_HANDLE Handle
  288. )
  289. {
  290. USHORT usIndex;
  291. HANDLE_CB* pHandleCB = NULL;
  292. if ( Table == NULL )
  293. return;
  294. usIndex = RetrieveIndexFromHandle( Handle );
  295. if ( usIndex >= Table->nTableSize )
  296. return;
  297. pHandleCB = &Table->HandleTable[ usIndex ];
  298. if ( !pHandleCB->fActive )
  299. return;
  300. if ( pHandleCB->Handle != Handle )
  301. return;
  302. NdisZeroMemory( pHandleCB, sizeof( HANDLE_CB ) );
  303. Table->nActiveHandles--;
  304. }
  305. USHORT RetrieveSessionIdFromHandle(
  306. IN NDIS_HANDLE Handle
  307. )
  308. {
  309. return ( RetrieveIndexFromHandle( Handle ) + 1 );
  310. }