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.
 
 
 
 
 
 

318 lines
7.1 KiB

#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <windowsx.h>
#include <ntsam.h>
#include <dsgetdc.h>
#include <lmcons.h>
#include <lmapibuf.h>
#include <lmaccess.h>
#include <string.h>
#include <tchar.h>
#include <stdarg.h>
#include <process.h>
#include <ole2.h>
#include <ntdsapi.h>
#include <DfsISTGSupport.hxx>
#include <DfsInit.hxx>
#define NTDSAPI_INTEGRATED
#if defined(NTDSAPI_INTEGRATED)
#define _DsBindToISTG(a,b) DsBindToISTG(a,b)
#define _DsUnBind(a) DsUnBind(a)
#define _DsBindingSetTimeout(a,b) DsBindingSetTimeout(a,b)
#else
#define _DsBindToISTG(a,b) STUB_DsBindToISTG(a,b)
#define _DsUnBind(a) STUB_DsUnBind(a)
#define _DsBindingSetTimeout(a,b) NOTHING
#endif
DWORD
STUB_DsBindToISTG( LPWSTR Site, HANDLE *pDs )
{
*pDs = (HANDLE)101; // bogus
return ERROR_SUCCESS;
UNREFERENCED_PARAMETER(Site);
}
DWORD
STUB_DsUnBind( HANDLE *pDs )
{
*pDs = (HANDLE)99; // bogus
return ERROR_SUCCESS;
}
// return a referenced global handle
DFSSTATUS
DfsISTGHandleSupport::Acquire(
DfsISTGHandle **ppHdl )
{
DFSSTATUS Status = ERROR_NOT_FOUND;
//
// Return a referenced ISTG handle.
// This count is actually good indicator of
// how much the DS APIs are stressed
// at a given point in time.
//
EnterCriticalSection( &_HandleLock );
if ((_GlobalHandle != NULL) && (_GlobalHandle->IsInitialized))
{
_GlobalHandle->AcquireReference();
*ppHdl = _GlobalHandle;
Status = ERROR_SUCCESS;
}
LeaveCriticalSection( &_HandleLock );
return Status;
}
//
// One time call.
//
DFSSTATUS
DfsISTGHandleSupport::Initialize( VOID )
{
DFSSTATUS Status = ERROR_SUCCESS;
BOOL LockCreated = FALSE;
do {
LockCreated = InitializeCriticalSectionAndSpinCount( &_HandleLock, DFS_CRIT_SPIN_COUNT );
if (!LockCreated)
{
Status = GetLastError();
break;
}
//
// The logic is similar to reinitialization.
// However, we ignore the status because we dont want the server-initialize to
// fail because it couldn't bind to an ISTG. We have to handle the possibility of
// not being able to bind to an ISTG anyway.
// We don't actually do the ReBind at this point because we don't want this ISTG
// handle to exist at all when site costing is turned off (by default). ReBind will be
// done on-demand.
//(VOID)ReBind();
} while (FALSE);
//
// Error path
//
if (Status != ERROR_SUCCESS)
{
if (LockCreated)
{
DeleteCriticalSection( &_HandleLock );
LockCreated = FALSE;
}
ASSERT(_GlobalHandle == NULL);
}
return Status;
}
//
// Get a new handle to the ISTG and
// initialize the global handle accordingly.
//
DFSSTATUS
DfsISTGHandleSupport::ReBind( VOID )
{
DFSSTATUS Status = ERROR_SUCCESS;
DfsISTGHandle *TempHandle = NULL;
DfsISTGHandle *OldHandle = NULL;
//
// If it isn't time to retry, let's not.
//
if (_LastRetryTime != 0 &&
!IsTimeToRetry())
{
return STATUS_INVALID_HANDLE;
}
//
// Replace the global handle with a new one.
//
do {
//
// Create a temporary handle first.
//
TempHandle = new DfsISTGHandle;
if (TempHandle == NULL)
{
Status = ERROR_NOT_ENOUGH_MEMORY;
break;
}
Status = TempHandle->Bind();
if (Status != ERROR_SUCCESS)
{
break;
}
_NumberOfBinds++;
//
// Now atomically swap the two handles.
// Let's not close the old handle while
// we are holding the handle-lock.
// It is of course entirely possible for somebody
// else to race with us. Only one will win.
//
EnterCriticalSection( &_HandleLock );
OldHandle = _GlobalHandle;
_GlobalHandle = TempHandle;
LeaveCriticalSection( &_HandleLock );
if (OldHandle != NULL)
{
OldHandle->ReleaseReference();
}
_CreationTime = GetTickCount();
_LastRetryTime = 0;
} while (FALSE);
// Error path
if (Status != ERROR_SUCCESS)
{
_LastRetryTime = GetTickCount();
if (TempHandle != NULL)
{
TempHandle->ReleaseReference();
}
// We don't get rid of the existing handle
// just because we failed to get a new one.
}
return Status;
}
//
// Static one time call to create the global
// handle support class instance.
//
DFSSTATUS
DfsISTGHandleSupport::DfsCreateISTGHandleSupport(
DfsISTGHandleSupport **ppSup )
{
DFSSTATUS Status = ERROR_SUCCESS;
DfsISTGHandleSupport *pSup = NULL;
*ppSup = NULL;
do {
pSup = new DfsISTGHandleSupport;
if (pSup == NULL)
{
Status = ERROR_NOT_ENOUGH_MEMORY;
break;
}
// Bind to ISTG to get a new handle.
Status = pSup->Initialize();
if (Status != ERROR_SUCCESS)
{
break;
}
*ppSup = pSup;
} while (FALSE);
// Error path
if (Status != ERROR_SUCCESS)
{
if (pSup != NULL)
{
delete pSup;
pSup = NULL;
}
}
return Status;
}
DfsISTGHandle::~DfsISTGHandle( VOID )
{
if (IsInitialized == TRUE)
{
// Close our handle to the ISTG
_DsUnBind( &DsHandle );
}
}
DFSSTATUS
DfsISTGHandle::Bind( VOID )
{
DFSSTATUS Status = ERROR_SUCCESS;
if (!IsInitialized)
{
Status = _DsBindToISTG( NULL, &DsHandle );
if (Status == ERROR_SUCCESS)
{
IsInitialized = TRUE;
//
// Set the time out. There's no need to fail the call
// because of an error here. xxxdfsdev: DFSLOG this.
//
_DsBindingSetTimeout( DsHandle, DsTimeOut );
}
}
return Status;
}
//
// Return a referenced handle or NULL.
//
DfsISTGHandle *
DfsAcquireISTGHandle( VOID )
{
DFSSTATUS Status = ERROR_SUCCESS;
DfsISTGHandle *pHdl = NULL;
if (DfsServerGlobalData.pISTGHandleSupport != NULL)
{
Status = DfsServerGlobalData.pISTGHandleSupport->Acquire( &pHdl );
}
return pHdl;
}
//
// Release an ISTG handle acquired using the above DfsAcquireISTGHandle.
//
VOID
DfsReleaseISTGHandle(
DfsISTGHandle *pHdl )
{
if (DfsServerGlobalData.pISTGHandleSupport != NULL)
{
DfsServerGlobalData.pISTGHandleSupport->Release( pHdl );
}
}
DFSSTATUS
DfsReBindISTGHandle( VOID )
{
DFSSTATUS Status = ERROR_NOT_FOUND;
if (DfsServerGlobalData.pISTGHandleSupport != NULL)
{
Status = DfsServerGlobalData.pISTGHandleSupport->ReBind();
}
return Status;
}