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.
|
|
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
gbuf.cxx
Abstract:
IIS MetaBase subroutines to support global buffers
Author:
Michael W. Thomas 12-July-96
Revision History:
--*/
#include "precomp.hxx"
HRESULT InitBufferPoolGlobalsToNull() /*++
Routine Description:
Initializes the pool of buffers globals to NULL.
Arguments: None
Return Value: HHRESULT - S_OK
Notes: --*/ { HRESULT hr = S_OK;
g_ppvDataBufferBlock = NULL; g_pbcDataContainerBlock = NULL; g_pbcDataFreeBufHead = NULL; g_pbcDataUsedBufHead = NULL; g_fDataBufferCritSecInitialized = FALSE; g_hDataBufferSemaphore = NULL;
return hr; }
HRESULT InitBufferPool() /*++
Routine Description:
Initializes the pool of buffers.
Arguments:
Return Value:
HRESULT - S_OK E_OUTOFMEMORY Errors by CreateSemaphore, InitializeCriticalSectionAndSpinCount Notes:
--*/ { HRESULT hr = S_OK; DWORD dwError = ERROR_SUCCESS; DWORD i;
InitBufferPoolGlobalsToNull();
g_ppvDataBufferBlock = (PVOID *) new PVOID[NUM_DATA_BUFFERS][DATA_BUFFER_LEN]; if ( g_ppvDataBufferBlock == NULL ) { hr = E_OUTOFMEMORY; goto exit; }
g_pbcDataContainerBlock = (PBUFFER_CONTAINER) new BUFFER_CONTAINER[NUM_DATA_BUFFERS]; if (g_pbcDataContainerBlock == NULL) { hr = E_OUTOFMEMORY; goto exit; }
g_hDataBufferSemaphore = IIS_CREATE_SEMAPHORE( "g_hDataBufferSemaphore", &g_hDataBufferSemaphore, NUM_DATA_BUFFERS, NUM_DATA_BUFFERS ); if ( g_hDataBufferSemaphore == NULL ) { dwError = GetLastError(); hr = HRESULT_FROM_WIN32( dwError ); goto exit; }
g_fDataBufferCritSecInitialized = INITIALIZE_CRITICAL_SECTION( &g_csDataBufferCritSec ); if ( !g_fDataBufferCritSecInitialized ) { dwError = GetLastError(); hr = HRESULT_FROM_WIN32( dwError ); goto exit; }
for ( i = 0; i < NUM_DATA_BUFFERS; i++ ) { g_pbcDataContainerBlock[i].ppvBuffer = g_ppvDataBufferBlock + (i * DATA_BUFFER_LEN); g_pbcDataContainerBlock[i].NextPtr = g_pbcDataFreeBufHead; g_pbcDataFreeBufHead = g_pbcDataContainerBlock + i; }
exit: if ( FAILED(hr) ) { DeleteBufferPool(); }
return hr; }
VOID DeleteBufferPool() /*++
Routine Description:
Deletes the pool of buffers.
Arguments:
Return Value:
Notes:
--*/ { if ( g_ppvDataBufferBlock != NULL ) { delete[] g_ppvDataBufferBlock; }
if ( g_pbcDataContainerBlock != NULL ) { delete[] g_pbcDataContainerBlock; }
if ( g_fDataBufferCritSecInitialized ) { DeleteCriticalSection(&g_csDataBufferCritSec); }
if ( g_hDataBufferSemaphore != NULL ) { CloseHandle( g_hDataBufferSemaphore ); }
InitBufferPoolGlobalsToNull(); }
PVOID * GetDataBuffer() /*++
Routine Description:
Gets a buffer.
Arguments:
Return Value:
PVOID * - The buffer.
Notes:
--*/ { DWORD dwError; PVOID *ppvReturn = NULL; PBUFFER_CONTAINER pbcTemp; DWORD i; //
// Use a dual synchonization scheme.
// The semaphore is used to guarantee
// a buffer is available.
// The critical section is used to
// contol access to global data.
//
dwError = WaitForSingleObject(g_hDataBufferSemaphore, INFINITE); if (dwError != WAIT_FAILED) { EnterCriticalSection(&g_csDataBufferCritSec); MD_ASSERT(g_pbcDataFreeBufHead != NULL); ppvReturn = g_pbcDataFreeBufHead->ppvBuffer; pbcTemp = g_pbcDataFreeBufHead->NextPtr; g_pbcDataFreeBufHead->NextPtr = g_pbcDataUsedBufHead; g_pbcDataUsedBufHead = g_pbcDataFreeBufHead; g_pbcDataFreeBufHead = pbcTemp; LeaveCriticalSection(&g_csDataBufferCritSec); for (i = 0; i < DATA_BUFFER_LEN; i++) { ppvReturn[i] = NULL; } } return (ppvReturn); }
VOID FreeDataBuffer( PVOID *ppvBuffer) { /*++
Routine Description:
Gets a buffer.
Arguments:
ppvBuffer - The buffer.
Return Value:
Notes:
--*/ PBUFFER_CONTAINER pbcTemp; EnterCriticalSection(&g_csDataBufferCritSec); MD_ASSERT(g_pbcDataUsedBufHead != NULL); //
// Just grab any container. It's more efficient to set ppvBuffer
// than to find the right container.
// Of course, this eliminates error checking. The caller is
// responsible to make sure that it only passes in correct addresses.
//
pbcTemp = g_pbcDataUsedBufHead->NextPtr; g_pbcDataUsedBufHead->NextPtr = g_pbcDataFreeBufHead; g_pbcDataFreeBufHead = g_pbcDataUsedBufHead; g_pbcDataUsedBufHead = pbcTemp; g_pbcDataFreeBufHead->ppvBuffer = ppvBuffer; LeaveCriticalSection(&g_csDataBufferCritSec); MD_REQUIRE(ReleaseSemaphore(g_hDataBufferSemaphore, 1, NULL)); }
BOOL InsertItemIntoDataBuffer( PVOID pvItem, PVOID *ppvMainDataBuf, DWORD &dwNumBufferEntries) { /*++
Routine Description:
Appends an item to the buffer at the specified location. This must be an append. Random insertion is not supported. This is actually a 2 tiered buffer scheme, where the first buffer is used an array of buffers. Items are pointers.
Arguments:
Item - The pointer to add to the buffer.
MainDataBuf - The buffer.
NumBufferEntries - The number of entries currently in the buffer.
Return Value:
BOOL - TRUE if the item was added successfully.
Notes:
--*/ BOOL bReturn = TRUE; DWORD dwMainBufIndex = dwNumBufferEntries / (DATA_BUFFER_LEN - 1); DWORD dwSubBufIndex = dwNumBufferEntries % (DATA_BUFFER_LEN - 1); PVOID *ppvCurrentDataBuf = ppvMainDataBuf; int i;
MD_ASSERT(ppvMainDataBuf != NULL); for (i = 0; i < ((int)dwMainBufIndex - 1); i++) {
//
// Go to the buffer before the one we want,
// in case we need to get the final one.
//
MD_ASSERT(ppvCurrentDataBuf[DATA_BUFFER_LEN - 1] != NULL); ppvCurrentDataBuf = (PVOID *)(ppvCurrentDataBuf[DATA_BUFFER_LEN -1]); }
if ((dwMainBufIndex != 0) && (dwSubBufIndex == 0)) { MD_ASSERT(ppvCurrentDataBuf[DATA_BUFFER_LEN - 1] == NULL); ppvCurrentDataBuf[DATA_BUFFER_LEN - 1] = GetDataBuffer(); }
MD_ASSERT((dwMainBufIndex == 0) || (i == (int)dwMainBufIndex - 1)); if (dwMainBufIndex != 0) { ppvCurrentDataBuf = (PVOID *)(ppvCurrentDataBuf[DATA_BUFFER_LEN - 1]); }
MD_ASSERT(ppvCurrentDataBuf[dwSubBufIndex] == 0); ppvCurrentDataBuf[dwSubBufIndex] = pvItem; dwNumBufferEntries++;
return(bReturn); }
PVOID GetItemFromDataBuffer( PVOID *ppvMainDataBuf, DWORD dwItemNum) /*++
Routine Description:
Gets the specified item from the buffer.
Arguments:
MainDataBuf - The buffer.
ItemNum - The number of the item to get.
Return Value:
PVOID - The Item from that location. NULL if no item exists at that location.
Notes:
--*/ { DWORD dwMainBufIndex = dwItemNum / (DATA_BUFFER_LEN - 1); DWORD dwSubBufIndex = dwItemNum % (DATA_BUFFER_LEN - 1); PVOID pvReturn; PVOID *ppvCurrentDataBuf = ppvMainDataBuf; int i;
MD_ASSERT(ppvMainDataBuf != NULL); for (i = 0; i < (int)dwMainBufIndex; i++) { ppvCurrentDataBuf = (PVOID *)(ppvCurrentDataBuf[DATA_BUFFER_LEN -1]); }
if (ppvCurrentDataBuf == NULL) { pvReturn = NULL; } else { pvReturn = ppvCurrentDataBuf[dwSubBufIndex]; } return(pvReturn); }
VOID FreeMainDataBuffer( PVOID *ppvMainDataBuf) /*++
Routine Description:
Frees a main data buffer. Deletes all sub buffers.
Arguments:
MainDataBuf - The main data buffer.
Return Value:
Notes:
--*/ { MD_ASSERT(ppvMainDataBuf != NULL); PVOID *ppvCurrentDataBuf; PVOID *ppvNextDataBuf;
for ( ppvCurrentDataBuf = ppvMainDataBuf; ppvCurrentDataBuf != NULL; ppvCurrentDataBuf = ppvNextDataBuf ) { ppvNextDataBuf = (PVOID *)(ppvCurrentDataBuf[DATA_BUFFER_LEN - 1]); FreeDataBuffer(ppvCurrentDataBuf); } }
PVOID * GetMainDataBuffer() /*++
Routine Description:
Gets a main data buffer. Deletes all sub buffers.
Arguments:
Return Value:
PVOID * - The main data buffer.
Notes:
--*/ { return(GetDataBuffer()); }
|