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.

688 lines
15 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. buffer.cxx
  5. Abstract:
  6. Contains code to impliment a double buffering class used in SSL/PCT (secure channel)
  7. transactions.
  8. Author:
  9. Arthur L Bierer (arthurbi) 20-March-1996
  10. Revision History:
  11. 20-March-1996 arthurbi
  12. Created
  13. --*/
  14. #include <wininetp.h>
  15. BOOL
  16. DBLBUFFER::InitBuffer(
  17. BOOL fDblBufferMode
  18. )
  19. /*++
  20. Routine Description:
  21. Allocates, and initalizes internal buffers.
  22. Arguments:
  23. fDblBufferMode - TRUE if we are to maintain to buffers,
  24. FALSE if we treat the output and input buffers the same
  25. Return Value:
  26. BOOL
  27. Success - TRUE
  28. Failure - FALSE, not enough memory to allocate buffers.
  29. Comments:
  30. --*/
  31. {
  32. DEBUG_ENTER((DBG_BUFFER,
  33. Bool,
  34. "DBLBUFFER::InitBuffer",
  35. "%B",
  36. fDblBufferMode
  37. ));
  38. INET_ASSERT(_lpBuffer == NULL);
  39. INET_ASSERT(_dwInitDefaultBufferSize > 0 );
  40. _lpBuffer = (LPBYTE)ALLOCATE_FIXED_MEMORY(_dwInitDefaultBufferSize);
  41. DEBUG_PRINT(API,
  42. INFO,
  43. ("allocated %d byte buffer %#x\n",
  44. _dwInitDefaultBufferSize,
  45. _lpBuffer
  46. ));
  47. BOOL success = FALSE;
  48. if (_lpBuffer != NULL) {
  49. INET_ASSERT(_dwBufferOut == 0);
  50. INET_ASSERT(_dwBufferIn == 0);
  51. _fDblBufferMode = fDblBufferMode;
  52. _dwBufferLength = _dwInitDefaultBufferSize ;
  53. _lpBufferOut = _lpBuffer + _dwBufferLength;
  54. _lpBufferIn = _lpBuffer + _dwBufferLength;
  55. success = TRUE;
  56. }
  57. DEBUG_LEAVE(success);
  58. return success;
  59. }
  60. DWORD
  61. DBLBUFFER::GetInputBufferRemaining(
  62. VOID
  63. )
  64. /*++
  65. Routine Description:
  66. Determines the amount of free bytes availble for reading into the input buffer.
  67. Will attempt to push current data to the front of the buffer, to make the
  68. most room in the currently allocated buffer.
  69. Arguments:
  70. none.
  71. Return Value:
  72. DWORD
  73. Number of bytes free.
  74. Comments:
  75. Assumed to only be called in DblBuffer mode.
  76. --*/
  77. {
  78. DEBUG_ENTER((DBG_INET,
  79. Int,
  80. "DBLBUFFER::GetInputBufferRemaining",
  81. NULL
  82. ));
  83. INET_ASSERT(_lpBuffer);
  84. INET_ASSERT(_dwBufferOut == 0 );
  85. INET_ASSERT(_fDblBufferMode );
  86. BOOL fIsInputBufferCompressed = (_lpBufferIn == _lpBuffer);
  87. if ( ! fIsInputBufferCompressed )
  88. {
  89. BOOL fIsSuccess;
  90. fIsSuccess = CompressInputBufferUsage( ) ;
  91. INET_ASSERT(fIsSuccess);
  92. }
  93. INET_ASSERT(_lpBufferIn == _lpBuffer );
  94. DEBUG_LEAVE((DWORD) (_lpEndOfBuffer - (_dwBufferIn + _lpBuffer) ));
  95. return (DWORD) (_lpEndOfBuffer - (_dwBufferIn + _lpBuffer) );
  96. }
  97. BOOL
  98. DBLBUFFER::CopyIn(
  99. IN LPBYTE lpBuffer,
  100. IN DWORD dwBufferSize
  101. )
  102. {
  103. DEBUG_ENTER((DBG_INET,
  104. Bool,
  105. "DBLBUFFER::CopyIn",
  106. "%x, %d",
  107. lpBuffer,
  108. dwBufferSize
  109. ));
  110. INET_ASSERT(lpBuffer);
  111. INET_ASSERT(dwBufferSize > 0);
  112. LPBYTE pbPointer;
  113. DWORD dwCurInputSize;
  114. //
  115. // Get the current input buffer size
  116. //
  117. dwCurInputSize = GetInputBufferSize();
  118. if ( ! ResizeBufferIfNeeded(dwBufferSize) )
  119. {
  120. DEBUG_LEAVE(FALSE);
  121. return FALSE;
  122. }
  123. pbPointer = GetInputBufferPointer()+dwCurInputSize;
  124. SetInputBufferSize(dwBufferSize+dwCurInputSize);
  125. CopyMemory(
  126. pbPointer, // dest
  127. lpBuffer, // src
  128. dwBufferSize // size
  129. );
  130. DEBUG_LEAVE(TRUE);
  131. return TRUE;
  132. }
  133. BOOL
  134. DBLBUFFER::CopyOut(
  135. OUT LPBYTE lpBuffer,
  136. IN OUT LPDWORD lpdwBufferRemaining,
  137. IN OUT LPDWORD lpdwBytesReceived,
  138. IN OUT LPDWORD lpdwBytesRead
  139. )
  140. /*++
  141. Routine Description:
  142. Fills passed in buffer with the contents of the output buffer.
  143. Arguments:
  144. lpBuffer - Buffer to fill with output buffer bytes
  145. lpdwBufferRemaining - Number of bytes remaining in Buffer to fill.
  146. lpdwBytesReceived - Number of bytes currently in Buffer to fill.
  147. lpdwBytesRead - Current total of bytes copied into Buffer to fill.
  148. Return Value:
  149. BOOL
  150. Success - TRUE
  151. Failure - FALSE
  152. Comments:
  153. --*/
  154. {
  155. DEBUG_ENTER((DBG_INET,
  156. Bool,
  157. "DBLBUFFER::CopyOut",
  158. "%x, %u, %u, %u",
  159. lpBuffer,
  160. (lpdwBufferRemaining ? *lpdwBufferRemaining : 0),
  161. (lpdwBytesReceived ? *lpdwBytesReceived : 0),
  162. (lpdwBytesRead ? *lpdwBytesRead : 0)
  163. ));
  164. INET_ASSERT(lpBuffer);
  165. INET_ASSERT(lpdwBufferRemaining);
  166. INET_ASSERT(lpdwBytesReceived);
  167. INET_ASSERT(lpdwBytesRead);
  168. //
  169. // Figure out the max number of bytes we can copy into our user's buffer
  170. // We need to make sure it will fit into the user's buffer.
  171. //
  172. DWORD dwBytesToCopy = (*lpdwBufferRemaining >= _dwBufferOut)
  173. ? _dwBufferOut : *lpdwBufferRemaining;
  174. DEBUG_PRINT(API,
  175. INFO,
  176. ("DBLBUFFER::CopyOut: Copying ( to: %x bytes-to-copy=%d )\n",
  177. (lpBuffer+*lpdwBytesReceived),
  178. dwBytesToCopy
  179. ));
  180. //
  181. // Transfer Data to User's buffer.
  182. //
  183. CopyMemory ((lpBuffer+*lpdwBytesReceived),
  184. _lpBufferOut,
  185. dwBytesToCopy);
  186. //
  187. // Update the number of bytes we copied to the user buffer
  188. //
  189. *lpdwBytesRead += dwBytesToCopy;
  190. *lpdwBytesReceived += dwBytesToCopy;
  191. *lpdwBufferRemaining -= dwBytesToCopy;
  192. //
  193. // Update Our Internal Vars
  194. //
  195. _dwBufferOut -= dwBytesToCopy;
  196. _lpBufferOut += dwBytesToCopy;
  197. UpdateVars();
  198. //
  199. // We always succeed for now !
  200. //
  201. DEBUG_LEAVE(TRUE);
  202. return TRUE;
  203. }
  204. BOOL
  205. DBLBUFFER::CompressInputBufferUsage(
  206. VOID
  207. )
  208. /*++
  209. Routine Description:
  210. Moves the input buffer to the begining of the internal allocated buffer.
  211. This produces a larger block of internal free space.
  212. Arguments:
  213. none.
  214. Return Value:
  215. BOOL
  216. Success - TRUE
  217. Success - FALSE, there was no need to compress the buffer.
  218. Comments:
  219. Assumed to be called only if DblBufferMode is enabled.
  220. --*/
  221. {
  222. DEBUG_ENTER((DBG_INET,
  223. Bool,
  224. "DBLBUFFER::CompressInputBufferUsage",
  225. NULL
  226. ));
  227. BOOL bResult = FALSE;
  228. //
  229. // Maximize use of buffer by moving input data to the front
  230. // of the buffer.
  231. //
  232. INET_ASSERT(_lpBuffer);
  233. INET_ASSERT(_dwBufferOut == 0);
  234. INET_ASSERT(_fDblBufferMode);
  235. if (_lpBufferIn > _lpBuffer) {
  236. DEBUG_PRINT(API,
  237. INFO,
  238. ("compressing input buffer %d (%#x) @ %#x => %#x\n",
  239. _dwBufferIn,
  240. _dwBufferIn,
  241. _lpBufferIn,
  242. _lpBuffer
  243. ));
  244. MoveMemory(_lpBuffer,
  245. _lpBufferIn,
  246. _dwBufferIn
  247. );
  248. //
  249. // Input Buffer now starts at the begining of the allocated buffer
  250. //
  251. _lpBufferIn = _lpBuffer;
  252. bResult = TRUE;
  253. }
  254. DEBUG_LEAVE(bResult);
  255. return bResult;
  256. }
  257. BOOL
  258. DBLBUFFER::ConcatenateOutputBufferUsage(
  259. IN LPBYTE lpSecondOutputBuffer,
  260. IN DWORD dwSecondOutputBufferSize
  261. )
  262. /*++
  263. Routine Description:
  264. Combines the current output buffer with the contents of a new buffer.
  265. (Note: intented for use in combining decrypted data which may be seperated by
  266. header or trailer data)
  267. Arguments:
  268. lpSecondOutputBuffer - New Buffer to combine with internal output buffer.
  269. dwSecondOutputBufferSize - Size of New Buffer in bytes.
  270. Return Value:
  271. BOOL
  272. Success - TRUE
  273. Failure - FALSE
  274. Comments:
  275. If the internal buffer is sized 0, the new buffer replaces the internal buffer.
  276. Its assumed that the New buffer is a former input buffer turned output by
  277. some external operation, such as a block decryption operation.
  278. --*/
  279. {
  280. DEBUG_ENTER((DBG_INET,
  281. Bool,
  282. "DBLBUFFER::ConcatenateOutputBufferUsage",
  283. "%x, %u",
  284. lpSecondOutputBuffer,
  285. dwSecondOutputBufferSize
  286. ));
  287. //
  288. // Combinate Two buffers into one.
  289. //
  290. INET_ASSERT(_lpBuffer);
  291. INET_ASSERT(_fDblBufferMode );
  292. INET_ASSERT(lpSecondOutputBuffer);
  293. INET_ASSERT(dwSecondOutputBufferSize);
  294. INET_ASSERT(_lpBufferOut < _lpBufferIn );
  295. INET_ASSERT(lpSecondOutputBuffer >= _lpBuffer && lpSecondOutputBuffer <=_lpEndOfBuffer );
  296. if ( _dwBufferOut != 0 )
  297. {
  298. DEBUG_PRINT(API,
  299. INFO,
  300. ("DBLBUFFER::ConcatenateOutputBufferUsage: Combining new data with output buffer\n"
  301. ));
  302. MoveMemory((_lpBufferOut+_dwBufferOut),
  303. lpSecondOutputBuffer,
  304. dwSecondOutputBufferSize);
  305. //
  306. // Output Buffer is now bigger ( sum of orginal + new buffer size )
  307. //
  308. _dwBufferOut += dwSecondOutputBufferSize;
  309. }
  310. else
  311. {
  312. //
  313. // No previous output buffer, new buffer becomes output buffer
  314. //
  315. INET_ASSERT(_lpBufferOut == _lpEndOfBuffer );
  316. _lpBufferOut = lpSecondOutputBuffer;
  317. _dwBufferOut = dwSecondOutputBufferSize;
  318. }
  319. DEBUG_LEAVE(TRUE);
  320. return TRUE;
  321. }
  322. BOOL
  323. DBLBUFFER::ResizeBufferIfNeeded(
  324. IN DWORD dwAddlBufferNeeded
  325. )
  326. /*++
  327. Routine Description:
  328. ReSizes internal buffer space to extend size of the buffer by dwAddlBufferNeeded.
  329. If the additional bytes can be made availble by compressing currently stored
  330. into one place ( ie the start of the buffer ), the reallocation of the buffer
  331. will not be done.
  332. Arguments:
  333. dwAddlBufferNeeded - Number of additional bytes to resize
  334. Return Value:
  335. BOOL
  336. Success - TRUE
  337. Failure - FALSE, the reallocation failed due to lack of memory.
  338. Comments:
  339. Its assumed the caller will only use this function in dbl buffering mode.
  340. --*/
  341. {
  342. DEBUG_ENTER((DBG_INET,
  343. Bool,
  344. "DBLBUFFER::ResizeBufferIfNeeded",
  345. "%u",
  346. dwAddlBufferNeeded
  347. ));
  348. INET_ASSERT(_lpBuffer);
  349. INET_ASSERT(_dwBufferOut == 0 );
  350. INET_ASSERT(_fDblBufferMode );
  351. DWORD dwInputBytesFree = GetInputBufferRemaining();
  352. INET_ASSERT(_lpBuffer == _lpBufferIn );
  353. //
  354. // #bytes needed > #bytes left free in Buffer.
  355. //
  356. if ( dwAddlBufferNeeded > dwInputBytesFree )
  357. {
  358. HLOCAL hBuffer;
  359. hBuffer = (HLOCAL) _lpBuffer;
  360. //
  361. // length increases by (bytes needed - current bytes free[in old buffer])
  362. //
  363. _dwBufferLength += (dwAddlBufferNeeded - dwInputBytesFree);
  364. DEBUG_PRINT(API,
  365. INFO,
  366. ("DBLBUFFER::ResizeBufferIfNeeded: Resizing Buffer to %d, addl=%d, free=%d\n",
  367. _dwBufferLength,
  368. dwAddlBufferNeeded,
  369. dwInputBytesFree
  370. ));
  371. INET_ASSERT(_dwBufferLength < DBLBUFFER_MAX_SIZE);
  372. //
  373. // Do Resize, and store result
  374. //
  375. _lpBuffer = (LPBYTE)ResizeBuffer(hBuffer, _dwBufferLength, FALSE);
  376. DEBUG_PRINT(BUFFER,
  377. INFO,
  378. ("resized %#x => %#x, %d bytes\n",
  379. hBuffer,
  380. _lpBuffer,
  381. _dwBufferLength
  382. ));
  383. if ( ! _lpBuffer )
  384. {
  385. DEBUG_PRINT(API,
  386. ERROR,
  387. ("DBLBUFFER::ResizeBufferIfNeeded: Failed while Resizing, Out of Mem?\n"
  388. ));
  389. DEBUG_LEAVE(FALSE);
  390. return FALSE; // failing due to NOT_ENOUGH_MEMORY
  391. }
  392. //
  393. // Update ReSized Buffer pointers
  394. //
  395. _lpBufferIn = _lpBuffer;
  396. UpdateVars();
  397. }
  398. DEBUG_LEAVE(TRUE);
  399. return TRUE;
  400. }
  401. BOOL
  402. DBLBUFFER::SetOutputInputBuffer(
  403. IN LPBYTE lpNewOutputBuffer,
  404. IN DWORD dwNewOutputBufferSize,
  405. IN LPBYTE lpNewInputBuffer,
  406. IN DWORD dwNewInputBufferSize,
  407. IN BOOL fConcatenatePreviousOutput
  408. )
  409. /*++
  410. Routine Description:
  411. Allows caller to specify new addresses for input and output buffer.
  412. If fConcatenatePreviousOutput is set, SetOutputInputBuffer will combine
  413. the passed in output buffer with any internal output buffer.
  414. Also allows size changes to buffers.
  415. Arguments:
  416. lpNewOutputBuffer - New Output Buffer.
  417. dwNewOutputBufferSize - Size of New Output Buffer.
  418. lpNewInputBuffer - New Input Buffer.
  419. dwNewInputBufferSize - New Input Buffer Size.
  420. fConcatenatePreviousOutput - TRUE if we are to combine internal output buffer
  421. with (passed in) new output buffer
  422. FALSE if we are to just replace output buffer pointers.
  423. Return Value:
  424. BOOL
  425. Success - TRUE
  426. Failure - FALSE
  427. Comments:
  428. Assumed to be called from double buffering mode.
  429. --*/
  430. {
  431. INET_ASSERT(_lpBuffer);
  432. INET_ASSERT(lpNewOutputBuffer >= _lpBuffer && lpNewOutputBuffer <= _lpEndOfBuffer );
  433. INET_ASSERT((lpNewInputBuffer >= _lpBuffer && lpNewInputBuffer <= _lpEndOfBuffer) || dwNewInputBufferSize == 0);
  434. INET_ASSERT(fConcatenatePreviousOutput || _dwBufferOut == 0 );
  435. INET_ASSERT(_fDblBufferMode );
  436. DEBUG_PRINT(API,
  437. INFO,
  438. ("DBLBUFFER::SetOutputInputBuffer: Getting New Output( %x, size=%d ) New Input( %x, size=%d)\n",
  439. lpNewOutputBuffer,
  440. dwNewOutputBufferSize,
  441. lpNewInputBuffer,
  442. dwNewInputBufferSize
  443. ));
  444. if ( fConcatenatePreviousOutput )
  445. {
  446. ConcatenateOutputBufferUsage(
  447. lpNewOutputBuffer,
  448. dwNewOutputBufferSize
  449. );
  450. }
  451. else
  452. {
  453. _lpBufferOut = lpNewOutputBuffer;
  454. _dwBufferOut = dwNewOutputBufferSize;
  455. }
  456. _lpBufferIn = lpNewInputBuffer;
  457. _dwBufferIn = dwNewInputBufferSize;
  458. UpdateVars();
  459. return TRUE;
  460. }