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

/*++
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());
}