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.

466 lines
11 KiB

  1. //+-----------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (c) Microsoft Corporation
  6. //
  7. // File: ktcontext.cxx
  8. //
  9. // Contents: Kerberos Tunneller, context management routines
  10. //
  11. // History: 28-Jun-2001 t-ryanj Created
  12. //
  13. //------------------------------------------------------------------------
  14. #include "ktcontext.h"
  15. #include "ktmem.h"
  16. //
  17. // We keep track of our contexts in a list, so that we
  18. // can shut down all our connections when we're asked to close.
  19. //
  20. PKTCONTEXT KtContextList = NULL;
  21. //
  22. // This critsec will guarantee mutual exclusion on the context list.
  23. //
  24. BOOL KtContextListCritSecInit = FALSE;
  25. CRITICAL_SECTION KtContextListCritSec;
  26. //+-------------------------------------------------------------------------
  27. //
  28. // Function: KtInitContexts
  29. //
  30. // Synopsis: Does anything necessary to make ready to acquire and
  31. // release contexts
  32. //
  33. // Effects:
  34. //
  35. // Arguments:
  36. //
  37. // Requires:
  38. //
  39. // Returns: Success value. If FALSE, GetLastError() for more info.
  40. //
  41. // Notes:
  42. //
  43. //
  44. //--------------------------------------------------------------------------
  45. BOOL
  46. KtInitContexts(
  47. VOID
  48. )
  49. {
  50. BOOL fRet = TRUE;
  51. //
  52. // All we need to do is initialize our critsec
  53. //
  54. __try
  55. {
  56. InitializeCriticalSectionAndSpinCount( &KtContextListCritSec, 4000 );
  57. KtContextListCritSecInit = TRUE;
  58. }
  59. __except( EXCEPTION_EXECUTE_HANDLER )
  60. {
  61. DebugLog( DEB_ERROR, "%s(%d): InitializeCriticalSectionAndSpinCount raised an exception.\n", __FILE__, __LINE__ );
  62. goto Error;
  63. }
  64. Cleanup:
  65. return fRet;
  66. Error:
  67. fRet = FALSE;
  68. goto Cleanup;
  69. }
  70. //+-------------------------------------------------------------------------
  71. //
  72. // Function: KtCleanupContexts
  73. //
  74. // Synopsis: Cleans up any trash left by the context routines.
  75. //
  76. // Effects:
  77. //
  78. // Arguments:
  79. //
  80. // Requires:
  81. //
  82. // Returns:
  83. //
  84. // Notes:
  85. //
  86. //
  87. //--------------------------------------------------------------------------
  88. VOID
  89. KtCleanupContexts(
  90. VOID
  91. )
  92. {
  93. //
  94. // As we release the context at the head of the list, it will remove
  95. // itself from the list. Hence, we can free the head of the list until
  96. // the entire list is freed.
  97. //
  98. while( KtContextList )
  99. KtReleaseContext(KtContextList);
  100. if( KtContextListCritSecInit )
  101. DeleteCriticalSection(&KtContextListCritSec);
  102. }
  103. //+-------------------------------------------------------------------------
  104. //
  105. // Function: KtAcquireContext
  106. //
  107. // Synopsis: Returns a context for use with the session associated with
  108. // the passed in socket.
  109. //
  110. // Effects:
  111. //
  112. // Arguments: sock - socket on which to communicate with the user
  113. // size - size of the initial buffer
  114. //
  115. // Requires:
  116. //
  117. // Returns: The new context, or NULL on failure.
  118. //
  119. // Notes: If fails, GetLastError() for more info.
  120. //
  121. //--------------------------------------------------------------------------
  122. PKTCONTEXT
  123. KtAcquireContext(
  124. IN SOCKET sock,
  125. IN ULONG size
  126. )
  127. {
  128. PKTCONTEXT pContext = NULL;
  129. DebugLog( DEB_TRACE, "%s(%d): Creating new context.\n", __FILE__, __LINE__ );
  130. //
  131. // Alloc memory for the structure.
  132. //
  133. pContext = (PKTCONTEXT)KtAlloc(sizeof(KTCONTEXT));
  134. if( !pContext )
  135. {
  136. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  137. DebugLog( DEB_ERROR, "%s(%d): Error in KtAlloc while trying to alloc a KTCONTEXT.\n", __FILE__, __LINE__ );
  138. goto Error;
  139. }
  140. ZeroMemory( pContext, sizeof(KTCONTEXT) );
  141. //
  142. // Associate the socket
  143. //
  144. pContext->sock = sock;
  145. //
  146. // Make the first read buffer.
  147. //
  148. pContext->buffers = (PKTBUFFER)KtAlloc( sizeof(KTBUFFER) + size );
  149. if( !pContext->buffers )
  150. {
  151. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  152. DebugLog( DEB_ERROR, "%s(%d): Error allocating memory for receive buffer.\n", __FILE__, __LINE__ );
  153. goto Error;
  154. }
  155. pContext->buffers->buflen = size;
  156. pContext->buffers->next = NULL;
  157. pContext->emptybuf = pContext->buffers;
  158. //
  159. // Wait for mutual exclusion on the socket list
  160. //
  161. __try
  162. {
  163. EnterCriticalSection(&KtContextListCritSec);
  164. }
  165. __except( EXCEPTION_EXECUTE_HANDLER )
  166. {
  167. DebugLog( DEB_ERROR, "%s(%d): EnterCriticalSection raised an exception.\n", __FILE__, __LINE__ );
  168. goto Error;
  169. }
  170. //
  171. // Add to KtContextList.
  172. //
  173. pContext->prev = NULL;
  174. pContext->next = KtContextList;
  175. if( KtContextList != NULL )
  176. KtContextList->prev = pContext;
  177. KtContextList = pContext;
  178. //
  179. // We're done.
  180. //
  181. LeaveCriticalSection(&KtContextListCritSec);
  182. Cleanup:
  183. return pContext;
  184. Error:
  185. //
  186. // If something goes wrong, don't allocate any memory.
  187. //
  188. if( pContext )
  189. {
  190. if( pContext->buffers )
  191. KtFree( pContext->buffers );
  192. KtFree( pContext );
  193. pContext = NULL;
  194. }
  195. goto Cleanup;
  196. }
  197. //+-------------------------------------------------------------------------
  198. //
  199. // Function: KtReleaseContext
  200. //
  201. // Synopsis: Releases a context, signalling the end of the session.
  202. // All resources associated with the context are freed.
  203. //
  204. // Effects:
  205. //
  206. // Arguments: pContext - The context who's session is complete.
  207. //
  208. // Requires:
  209. //
  210. // Returns:
  211. //
  212. // Notes: If pContext is NULL, the call quietly does nothing.
  213. //
  214. //--------------------------------------------------------------------------
  215. VOID
  216. KtReleaseContext(
  217. IN PKTCONTEXT pContext
  218. )
  219. {
  220. if( pContext )
  221. {
  222. DebugLog( DEB_TRACE, "%s(%d): Releasing context.\n", __FILE__, __LINE__ );
  223. //
  224. // So first close any open connections.
  225. //
  226. if( pContext->sock )
  227. closesocket( pContext->sock );
  228. if( pContext->hRequest )
  229. InternetCloseHandle( pContext->hRequest );
  230. if( pContext->hConnect )
  231. InternetCloseHandle( pContext->hConnect );
  232. //
  233. // Free any buffers
  234. //
  235. while( pContext->buffers )
  236. {
  237. PKTBUFFER car = pContext->buffers;
  238. pContext->buffers = car->next;
  239. KtFree( car );
  240. }
  241. if( pContext->pbProxies )
  242. KtFree( pContext->pbProxies );
  243. //
  244. // Wait for lock on the socklist.
  245. //
  246. __try
  247. {
  248. EnterCriticalSection(&KtContextListCritSec);
  249. }
  250. __except( EXCEPTION_EXECUTE_HANDLER )
  251. {
  252. DebugLog( DEB_ERROR, "%s(%d): EnterCriticalSection raised an exception.\n", __FILE__, __LINE__ );
  253. /* TODO: Something must be done, here. */
  254. return;
  255. }
  256. //
  257. // Remove the structure from KtContextList.
  258. //
  259. if( pContext->prev == NULL )
  260. KtContextList = pContext->next;
  261. else
  262. pContext->prev->next = pContext->next;
  263. if( pContext->next != NULL )
  264. pContext->next->prev = pContext->prev;
  265. //
  266. // Done with list.
  267. //
  268. LeaveCriticalSection(&KtContextListCritSec);
  269. //
  270. // Free the memory
  271. //
  272. KtFree( pContext );
  273. }
  274. }
  275. //+-------------------------------------------------------------------------
  276. //
  277. // Function: KtCoalesceBuffers
  278. //
  279. // Synopsis: Coalesces all data buffers from a context into one.
  280. //
  281. // Effects:
  282. //
  283. // Arguments: pContext - The context that has buffers to coalesce.
  284. //
  285. // Requires:
  286. //
  287. // Returns: Success value. Failure indicates an allocation failure.
  288. //
  289. // Notes: At the beginning of this call, there are 'x' buffers in the
  290. // pContext->buffers list. At the end of this call there is a
  291. // sole buffer in this list, holding all the data from the 'x'
  292. // buffers. The pContext->emptybuffer member is also made to
  293. // point at this new buffer, so that it will be reused as the
  294. // first buffer in the next read transaction.
  295. //
  296. //--------------------------------------------------------------------------
  297. BOOL
  298. KtCoalesceBuffers(
  299. IN PKTCONTEXT pContext
  300. )
  301. {
  302. PKTBUFFER blist = pContext->buffers;
  303. PKTBUFFER bigbuf = NULL;
  304. BOOL fSuccess = TRUE;
  305. //
  306. // If there's only one buffer, nothing to do.
  307. //
  308. if( !pContext->buffers->next )
  309. return TRUE;
  310. //
  311. // Allocate a buffer of appropriate size to hold everything.
  312. //
  313. bigbuf = (PKTBUFFER)KtAlloc( sizeof(KTBUFFER) + pContext->TotalBytes );
  314. if( !bigbuf )
  315. {
  316. DebugLog( DEB_ERROR, "%s(%d): Unable to allocate enough memory to coalesce buffers.\n", __FILE__, __LINE__ );
  317. goto Error;
  318. }
  319. bigbuf->buflen = pContext->TotalBytes;
  320. bigbuf->bytesused = 0;
  321. bigbuf->next = NULL;
  322. //
  323. // Copy everything in.
  324. //
  325. while( blist = pContext->buffers )
  326. {
  327. pContext->buffers = blist->next;
  328. RtlCopyMemory( bigbuf->buffer + bigbuf->bytesused,
  329. blist->buffer,
  330. blist->bytesused );
  331. bigbuf->bytesused += blist->bytesused;
  332. KtFree( blist );
  333. }
  334. DsysAssert( bigbuf->bytesused == pContext->TotalBytes );
  335. //
  336. // This is now the sole buffer in the bufferlist.
  337. //
  338. pContext->buffers = bigbuf;
  339. pContext->emptybuf = bigbuf;
  340. Cleanup:
  341. return fSuccess;
  342. Error:
  343. fSuccess = FALSE;
  344. goto Cleanup;
  345. }
  346. //+-------------------------------------------------------------------------
  347. //
  348. // Function: KtGetMoreSpace
  349. //
  350. // Synopsis: Adds a new buffer to the end of the pContext->buffers list,
  351. // and points the pContext->emptybuf member at it.
  352. //
  353. // Effects:
  354. //
  355. // Arguments: pContext - The context that needs more space.
  356. // size - Amount of space needed.
  357. //
  358. // Requires:
  359. //
  360. // Returns: Success value. Failure indicates an allocation failure.
  361. //
  362. // Notes: As emptybuf is essentially a pointer to the tail of the
  363. // list, the new buffer is tacked onto the list after emptybuf,
  364. // then emptybuf is made to point to the new buffer.
  365. //
  366. //--------------------------------------------------------------------------
  367. BOOL
  368. KtGetMoreSpace(
  369. IN PKTCONTEXT pContext,
  370. IN ULONG size
  371. )
  372. {
  373. BOOL fRet = TRUE;
  374. PKTBUFFER newbuf = NULL;
  375. //
  376. // Allocate a new, empty buffer.
  377. //
  378. newbuf = (PKTBUFFER)KtAlloc( sizeof(KTBUFFER) + size );
  379. if( !newbuf )
  380. {
  381. DebugLog( DEB_ERROR, "%s(%d): Error allocating space for transmission buffer.\n", __FILE__, __LINE__ );
  382. goto Error;
  383. }
  384. newbuf->buflen = (ULONG)size;
  385. newbuf->bytesused = 0;
  386. newbuf->next = NULL;
  387. //
  388. // Add it to the buffer list.
  389. //
  390. DsysAssert( pContext->emptybuf );
  391. DsysAssert( !pContext->emptybuf->next );
  392. pContext->emptybuf->next = newbuf;
  393. pContext->emptybuf = newbuf;
  394. Cleanup:
  395. return fRet;
  396. Error:
  397. fRet = FALSE;
  398. goto Cleanup;
  399. }