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.

414 lines
8.9 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. gbuf.cxx
  5. Abstract:
  6. IIS MetaBase subroutines to support global buffers
  7. Author:
  8. Michael W. Thomas 12-July-96
  9. Revision History:
  10. --*/
  11. #include "precomp.hxx"
  12. HRESULT
  13. InitBufferPoolGlobalsToNull()
  14. /*++
  15. Routine Description:
  16. Initializes the pool of buffers globals to NULL.
  17. Arguments:
  18. None
  19. Return Value:
  20. HHRESULT - S_OK
  21. Notes:
  22. --*/
  23. {
  24. HRESULT hr = S_OK;
  25. g_ppvDataBufferBlock = NULL;
  26. g_pbcDataContainerBlock = NULL;
  27. g_pbcDataFreeBufHead = NULL;
  28. g_pbcDataUsedBufHead = NULL;
  29. g_fDataBufferCritSecInitialized = FALSE;
  30. g_hDataBufferSemaphore = NULL;
  31. return hr;
  32. }
  33. HRESULT
  34. InitBufferPool()
  35. /*++
  36. Routine Description:
  37. Initializes the pool of buffers.
  38. Arguments:
  39. Return Value:
  40. HRESULT - S_OK
  41. E_OUTOFMEMORY
  42. Errors by CreateSemaphore, InitializeCriticalSectionAndSpinCount
  43. Notes:
  44. --*/
  45. {
  46. HRESULT hr = S_OK;
  47. DWORD dwError = ERROR_SUCCESS;
  48. DWORD i;
  49. InitBufferPoolGlobalsToNull();
  50. g_ppvDataBufferBlock = (PVOID *) new PVOID[NUM_DATA_BUFFERS][DATA_BUFFER_LEN];
  51. if ( g_ppvDataBufferBlock == NULL )
  52. {
  53. hr = E_OUTOFMEMORY;
  54. goto exit;
  55. }
  56. g_pbcDataContainerBlock = (PBUFFER_CONTAINER) new BUFFER_CONTAINER[NUM_DATA_BUFFERS];
  57. if (g_pbcDataContainerBlock == NULL)
  58. {
  59. hr = E_OUTOFMEMORY;
  60. goto exit;
  61. }
  62. g_hDataBufferSemaphore = IIS_CREATE_SEMAPHORE( "g_hDataBufferSemaphore",
  63. &g_hDataBufferSemaphore,
  64. NUM_DATA_BUFFERS,
  65. NUM_DATA_BUFFERS );
  66. if ( g_hDataBufferSemaphore == NULL )
  67. {
  68. dwError = GetLastError();
  69. hr = HRESULT_FROM_WIN32( dwError );
  70. goto exit;
  71. }
  72. g_fDataBufferCritSecInitialized = INITIALIZE_CRITICAL_SECTION( &g_csDataBufferCritSec );
  73. if ( !g_fDataBufferCritSecInitialized )
  74. {
  75. dwError = GetLastError();
  76. hr = HRESULT_FROM_WIN32( dwError );
  77. goto exit;
  78. }
  79. for ( i = 0; i < NUM_DATA_BUFFERS; i++ )
  80. {
  81. g_pbcDataContainerBlock[i].ppvBuffer = g_ppvDataBufferBlock + (i * DATA_BUFFER_LEN);
  82. g_pbcDataContainerBlock[i].NextPtr = g_pbcDataFreeBufHead;
  83. g_pbcDataFreeBufHead = g_pbcDataContainerBlock + i;
  84. }
  85. exit:
  86. if ( FAILED(hr) )
  87. {
  88. DeleteBufferPool();
  89. }
  90. return hr;
  91. }
  92. VOID
  93. DeleteBufferPool()
  94. /*++
  95. Routine Description:
  96. Deletes the pool of buffers.
  97. Arguments:
  98. Return Value:
  99. Notes:
  100. --*/
  101. {
  102. if ( g_ppvDataBufferBlock != NULL )
  103. {
  104. delete[] g_ppvDataBufferBlock;
  105. }
  106. if ( g_pbcDataContainerBlock != NULL )
  107. {
  108. delete[] g_pbcDataContainerBlock;
  109. }
  110. if ( g_fDataBufferCritSecInitialized )
  111. {
  112. DeleteCriticalSection(&g_csDataBufferCritSec);
  113. }
  114. if ( g_hDataBufferSemaphore != NULL )
  115. {
  116. CloseHandle( g_hDataBufferSemaphore );
  117. }
  118. InitBufferPoolGlobalsToNull();
  119. }
  120. PVOID *
  121. GetDataBuffer()
  122. /*++
  123. Routine Description:
  124. Gets a buffer.
  125. Arguments:
  126. Return Value:
  127. PVOID * - The buffer.
  128. Notes:
  129. --*/
  130. {
  131. DWORD dwError;
  132. PVOID *ppvReturn = NULL;
  133. PBUFFER_CONTAINER pbcTemp;
  134. DWORD i;
  135. //
  136. // Use a dual synchonization scheme.
  137. // The semaphore is used to guarantee
  138. // a buffer is available.
  139. // The critical section is used to
  140. // contol access to global data.
  141. //
  142. dwError = WaitForSingleObject(g_hDataBufferSemaphore,
  143. INFINITE);
  144. if (dwError != WAIT_FAILED) {
  145. EnterCriticalSection(&g_csDataBufferCritSec);
  146. MD_ASSERT(g_pbcDataFreeBufHead != NULL);
  147. ppvReturn = g_pbcDataFreeBufHead->ppvBuffer;
  148. pbcTemp = g_pbcDataFreeBufHead->NextPtr;
  149. g_pbcDataFreeBufHead->NextPtr = g_pbcDataUsedBufHead;
  150. g_pbcDataUsedBufHead = g_pbcDataFreeBufHead;
  151. g_pbcDataFreeBufHead = pbcTemp;
  152. LeaveCriticalSection(&g_csDataBufferCritSec);
  153. for (i = 0; i < DATA_BUFFER_LEN; i++) {
  154. ppvReturn[i] = NULL;
  155. }
  156. }
  157. return (ppvReturn);
  158. }
  159. VOID
  160. FreeDataBuffer(
  161. PVOID *ppvBuffer)
  162. {
  163. /*++
  164. Routine Description:
  165. Gets a buffer.
  166. Arguments:
  167. ppvBuffer - The buffer.
  168. Return Value:
  169. Notes:
  170. --*/
  171. PBUFFER_CONTAINER pbcTemp;
  172. EnterCriticalSection(&g_csDataBufferCritSec);
  173. MD_ASSERT(g_pbcDataUsedBufHead != NULL);
  174. //
  175. // Just grab any container. It's more efficient to set ppvBuffer
  176. // than to find the right container.
  177. // Of course, this eliminates error checking. The caller is
  178. // responsible to make sure that it only passes in correct addresses.
  179. //
  180. pbcTemp = g_pbcDataUsedBufHead->NextPtr;
  181. g_pbcDataUsedBufHead->NextPtr = g_pbcDataFreeBufHead;
  182. g_pbcDataFreeBufHead = g_pbcDataUsedBufHead;
  183. g_pbcDataUsedBufHead = pbcTemp;
  184. g_pbcDataFreeBufHead->ppvBuffer = ppvBuffer;
  185. LeaveCriticalSection(&g_csDataBufferCritSec);
  186. MD_REQUIRE(ReleaseSemaphore(g_hDataBufferSemaphore,
  187. 1,
  188. NULL));
  189. }
  190. BOOL
  191. InsertItemIntoDataBuffer(
  192. PVOID pvItem,
  193. PVOID *ppvMainDataBuf,
  194. DWORD &dwNumBufferEntries)
  195. {
  196. /*++
  197. Routine Description:
  198. Appends an item to the buffer at the specified location. This
  199. must be an append. Random insertion is not supported.
  200. This is actually a 2 tiered buffer scheme, where the first buffer
  201. is used an array of buffers.
  202. Items are pointers.
  203. Arguments:
  204. Item - The pointer to add to the buffer.
  205. MainDataBuf - The buffer.
  206. NumBufferEntries - The number of entries currently in the buffer.
  207. Return Value:
  208. BOOL - TRUE if the item was added successfully.
  209. Notes:
  210. --*/
  211. BOOL bReturn = TRUE;
  212. DWORD dwMainBufIndex = dwNumBufferEntries / (DATA_BUFFER_LEN - 1);
  213. DWORD dwSubBufIndex = dwNumBufferEntries % (DATA_BUFFER_LEN - 1);
  214. PVOID *ppvCurrentDataBuf = ppvMainDataBuf;
  215. int i;
  216. MD_ASSERT(ppvMainDataBuf != NULL);
  217. for (i = 0; i < ((int)dwMainBufIndex - 1); i++) {
  218. //
  219. // Go to the buffer before the one we want,
  220. // in case we need to get the final one.
  221. //
  222. MD_ASSERT(ppvCurrentDataBuf[DATA_BUFFER_LEN - 1] != NULL);
  223. ppvCurrentDataBuf = (PVOID *)(ppvCurrentDataBuf[DATA_BUFFER_LEN -1]);
  224. }
  225. if ((dwMainBufIndex != 0) && (dwSubBufIndex == 0)) {
  226. MD_ASSERT(ppvCurrentDataBuf[DATA_BUFFER_LEN - 1] == NULL);
  227. ppvCurrentDataBuf[DATA_BUFFER_LEN - 1] = GetDataBuffer();
  228. }
  229. MD_ASSERT((dwMainBufIndex == 0) || (i == (int)dwMainBufIndex - 1));
  230. if (dwMainBufIndex != 0) {
  231. ppvCurrentDataBuf = (PVOID *)(ppvCurrentDataBuf[DATA_BUFFER_LEN - 1]);
  232. }
  233. MD_ASSERT(ppvCurrentDataBuf[dwSubBufIndex] == 0);
  234. ppvCurrentDataBuf[dwSubBufIndex] = pvItem;
  235. dwNumBufferEntries++;
  236. return(bReturn);
  237. }
  238. PVOID
  239. GetItemFromDataBuffer(
  240. PVOID *ppvMainDataBuf,
  241. DWORD dwItemNum)
  242. /*++
  243. Routine Description:
  244. Gets the specified item from the buffer.
  245. Arguments:
  246. MainDataBuf - The buffer.
  247. ItemNum - The number of the item to get.
  248. Return Value:
  249. PVOID - The Item from that location.
  250. NULL if no item exists at that location.
  251. Notes:
  252. --*/
  253. {
  254. DWORD dwMainBufIndex = dwItemNum / (DATA_BUFFER_LEN - 1);
  255. DWORD dwSubBufIndex = dwItemNum % (DATA_BUFFER_LEN - 1);
  256. PVOID pvReturn;
  257. PVOID *ppvCurrentDataBuf = ppvMainDataBuf;
  258. int i;
  259. MD_ASSERT(ppvMainDataBuf != NULL);
  260. for (i = 0; i < (int)dwMainBufIndex; i++) {
  261. ppvCurrentDataBuf = (PVOID *)(ppvCurrentDataBuf[DATA_BUFFER_LEN -1]);
  262. }
  263. if (ppvCurrentDataBuf == NULL) {
  264. pvReturn = NULL;
  265. }
  266. else {
  267. pvReturn = ppvCurrentDataBuf[dwSubBufIndex];
  268. }
  269. return(pvReturn);
  270. }
  271. VOID
  272. FreeMainDataBuffer(
  273. PVOID *ppvMainDataBuf)
  274. /*++
  275. Routine Description:
  276. Frees a main data buffer. Deletes all sub buffers.
  277. Arguments:
  278. MainDataBuf - The main data buffer.
  279. Return Value:
  280. Notes:
  281. --*/
  282. {
  283. MD_ASSERT(ppvMainDataBuf != NULL);
  284. PVOID *ppvCurrentDataBuf;
  285. PVOID *ppvNextDataBuf;
  286. for ( ppvCurrentDataBuf = ppvMainDataBuf;
  287. ppvCurrentDataBuf != NULL;
  288. ppvCurrentDataBuf = ppvNextDataBuf ) {
  289. ppvNextDataBuf = (PVOID *)(ppvCurrentDataBuf[DATA_BUFFER_LEN - 1]);
  290. FreeDataBuffer(ppvCurrentDataBuf);
  291. }
  292. }
  293. PVOID *
  294. GetMainDataBuffer()
  295. /*++
  296. Routine Description:
  297. Gets a main data buffer. Deletes all sub buffers.
  298. Arguments:
  299. Return Value:
  300. PVOID * - The main data buffer.
  301. Notes:
  302. --*/
  303. {
  304. return(GetDataBuffer());
  305. }