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.
|
|
/***************************************************************************\
* * File: TicketManager.cpp * * Description: * * This file contains the implementation of relevant classes, structs, and * types for the DUser Ticket Manager. * * The following classes are defined for public use: * * DuTicketManager * A facility which can assign a unique "ticket" to a BaseObject. * * History: * 9/20/2000: DwayneN: Created * * Copyright (C) 2000 by Microsoft Corporation. All rights reserved. * \***************************************************************************/
#include "stdafx.h"
#include "Services.h"
#include "TicketManager.h"
#define INIT_OUT_PARAM(p,v) if(p != NULL) *p = v
#define VALIDATE_REQUIRED_OUT_PARAM(p) if(p == NULL) return E_POINTER;
#define VALIDATE_IN_PARAM_NOT_VALUE(p,v) if(p == v) return E_INVALIDARG;
//------------------------------------------------------------------------------
DuTicketManager::DuTicketManager() { Assert(sizeof(DuTicket) == sizeof(DWORD));
m_idxFreeStackTop = -1; m_idxFreeStackBottom = -1; }
//------------------------------------------------------------------------------
DuTicketManager::~DuTicketManager() { }
//------------------------------------------------------------------------------
HRESULT DuTicketManager::Add( IN BaseObject * pObject, OUT DWORD * pdwTicket) { HRESULT hr = S_OK; int idxFree = 0;
//
// Parameter checking.
// - Initialize all out parameters
// - Validate in parameters
//
INIT_OUT_PARAM(pdwTicket, 0); VALIDATE_REQUIRED_OUT_PARAM(pdwTicket); VALIDATE_IN_PARAM_NOT_VALUE(pObject, NULL);
m_crit.Enter();
//
// Scan to make sure the object isn't already in the array.
// This is too expensive to do outside of DEBUG builds.
//
Assert(FAILED(Find(pObject, idxFree)));
hr = PopFree(idxFree); if (SUCCEEDED(hr)) { DuTicket ticket;
m_arTicketData[idxFree].pObject = pObject;
ticket.Unused = 0; ticket.Uniqueness = m_arTicketData[idxFree].cUniqueness; ticket.Type = pObject->GetHandleType(); ticket.Index = idxFree;
*pdwTicket = DuTicket::CastToDWORD(ticket); } m_crit.Leave();
return hr; }
//------------------------------------------------------------------------------
HRESULT DuTicketManager::Remove( IN DWORD dwTicket, OUT OPTIONAL BaseObject ** ppObject) { HRESULT hr = S_OK; //
// Parameter checking.
// - Initialize all out parameters
// - Validate in parameters
//
INIT_OUT_PARAM(ppObject, NULL); VALIDATE_IN_PARAM_NOT_VALUE(dwTicket, 0);
m_crit.Enter();
hr = Lookup(dwTicket, ppObject); if (SUCCEEDED(hr)) { DuTicket ticket = DuTicket::CastFromDWORD(dwTicket);
//
// Clear out the object at this index just in case.
//
m_arTicketData[ticket.Index].pObject = NULL; //
// Increment the uniqueness to invalidate any outstanding tickets.
//
m_arTicketData[ticket.Index].cUniqueness++; if (m_arTicketData[ticket.Index].cUniqueness == 0) { m_arTicketData[ticket.Index].cUniqueness = 1; }
//
// Push this index back onto the free stack.
//
PushFree(ticket.Index); }
m_crit.Leave();
return(hr); }
//------------------------------------------------------------------------------
HRESULT DuTicketManager::Lookup( IN DWORD dwTicket, OUT OPTIONAL BaseObject ** ppObject) { HRESULT hr = S_OK; DuTicket ticket = DuTicket::CastFromDWORD(dwTicket); //
// Parameter checking.
// - Initialize all out parameters
// - Validate in parameters
// - Check for manifest errors in the ticket
//
INIT_OUT_PARAM(ppObject, NULL); VALIDATE_IN_PARAM_NOT_VALUE(dwTicket, 0); if (ticket.Unused != 0 || ticket.Uniqueness == 0 || ticket.Index >= WORD(m_arTicketData.GetSize())) { return E_INVALIDARG; } m_crit.Enter();
//
// Look up the information in the tables and see if the
// ticket still looks valid.
//
if (m_arTicketData[ticket.Index].cUniqueness == ticket.Uniqueness) { if (ppObject != NULL && m_arTicketData[ticket.Index].pObject != NULL) { if (ticket.Type == BYTE(m_arTicketData[ticket.Index].pObject->GetHandleType())) { *ppObject = m_arTicketData[ticket.Index].pObject; } } } else { //
// It seems like the ticket has gone stale.
//
hr = DU_E_NOTFOUND; }
m_crit.Leave();
return hr; }
//------------------------------------------------------------------------------
HRESULT DuTicketManager::Expand() { //
// We only need to resize our internal arrays when the free stack is empty.
//
Assert(m_idxFreeStackBottom == -1 && m_idxFreeStackTop == -1);
//
// Get the old size of the array, and calculate a new size.
// Note that we limit how big the table can grow.
//
int cOldSize = m_arTicketData.GetSize(); int cNewSize; if (cOldSize > 0) { if (cOldSize < USHRT_MAX) { cNewSize = min(cOldSize * 2, USHRT_MAX); } else { return E_OUTOFMEMORY; } } else { cNewSize = 16; }
//
// Resize the array of objects. The contents of the new items will
// be set to NULL;
//
if (m_arTicketData.SetSize(cNewSize)) { //
// Initialize the new data.
//
for (int i = cOldSize; i < cNewSize; i++) { m_arTicketData[i].pObject = NULL; m_arTicketData[i].cUniqueness = 1; m_arTicketData[i].idxFree = WORD(i); }
m_idxFreeStackBottom = cOldSize; m_idxFreeStackTop = cNewSize - 1; } else { return E_OUTOFMEMORY; }
return S_OK; }
//------------------------------------------------------------------------------
HRESULT DuTicketManager::PushFree(int idxFree) { if (m_idxFreeStackBottom == -1 && m_idxFreeStackTop == -1) { Assert(m_arTicketData.GetSize() > 0);
m_idxFreeStackBottom = 0; m_idxFreeStackTop = 0; m_arTicketData[0].idxFree = WORD(idxFree); } else { int iNewTop = (m_idxFreeStackTop + 1) % m_arTicketData.GetSize(); AssertMsg(iNewTop != m_idxFreeStackBottom, "Probably more pushes than pops!");
m_arTicketData[iNewTop].idxFree = WORD(idxFree); m_idxFreeStackTop = iNewTop; }
return S_OK; }
//------------------------------------------------------------------------------
HRESULT DuTicketManager::PopFree(int & idxFree) { HRESULT hr = S_OK;
//
// Resize our arrays if our stack of available slots is empty.
//
if (m_idxFreeStackBottom == -1 || m_idxFreeStackTop == -1) { hr = Expand(); Assert(SUCCEEDED(hr));
if (FAILED(hr)) { return hr; } }
Assert(m_idxFreeStackBottom >=0 && m_idxFreeStackTop >=0 );
//
// Take the available slot from the bottom of the stack.
//
idxFree = m_arTicketData[m_idxFreeStackBottom].idxFree;
//
// Increment the bottom of the stack. If the stack is now empty,
// indicate so by setting the top and bottom to -1.
//
if (m_idxFreeStackBottom == m_idxFreeStackTop) { m_idxFreeStackBottom = -1; m_idxFreeStackTop = -1; } else { m_idxFreeStackBottom = (m_idxFreeStackBottom + 1) % m_arTicketData.GetSize(); }
return S_OK; }
//------------------------------------------------------------------------------
HRESULT DuTicketManager::Find(BaseObject * pObject, int & iFound) { HRESULT hr = DU_E_NOTFOUND;
iFound = -1;
//
// Note: This is a brute-force find. It does a linear search for the
// specified pointer. This is very, very slow so don't use it unless
// you absolutely have to. The BaseObject itself should remember what
// its ticket is so it doesn't have to search.
//
for (int i = 0; i < m_arTicketData.GetSize(); i++) { if (m_arTicketData[i].pObject == pObject) { hr = S_OK; iFound = i; break; } }
return hr; }
|