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.
 
 
 
 
 
 

587 lines
15 KiB

//
// Copyright (C) 2000, Microsoft Corporation
//
// File: DfsADBlobCache.hxx
//
// Contents: the ADBlob DFS Store class, this contains the
// old AD blob store specific functionality.
//
// Classes: DfsADBlobStore.
//
// History: April. 9 2001, Author: Rohanp
//
//-----------------------------------------------------------------------------
#ifndef __DFS_ADBLOB_CACHE__
#define __DFS_ADBLOB_CACHE__
#include <dfsgeneric.hxx>
#include <dfsstore.hxx>
#include <shellapi.h>
#include <ole2.h>
#include <activeds.h>
#include "dfsadsiapi.hxx"
#include <WinLdap.h>
#include <NtLdap.h>
#include <shash.h>
class DfsRootFolder;
#define ADBlobAttribute L"pKT"
#define ADBlobPktGuidAttribute L"pKTGuid"
//
// It appears that siteroot is case sensitive on downlevel DFS.
// dont change case.
//
#define ADBlobSiteRoot L"\\siteroot"
//
// domainroot is case-sensitive along some paths of downlevel DFS as well.
// Leave this lowercase also.
//
#define ADBlobMetaDataNamePrefix L"\\domainroot"
#define ADBlobDefaultBlobPackSize 1* 1024 * 1024
#define ADBlobMaximumBlobPackSize 32 * 1024 * 1024
#define PKT_ENTRY_TYPE_CAIRO 0x0001 // Entry refers to Cairo srv
#define PKT_ENTRY_TYPE_MACHINE 0x0002 // Entry is a machine volume
#define PKT_ENTRY_TYPE_INSITE_ONLY 0x0020 // Only give insite referrals.
#define PKT_ENTRY_TYPE_COST_BASED_SITE_SELECTION 0x0040 // get inter-site costs from DS.
#define PKT_ENTRY_TYPE_REFERRAL_SVC 0x0080 // Entry refers to a DC
#define PKT_ENTRY_TYPE_PERMANENT 0x0100 // Entry cannot be scavenged
#define PKT_ENTRY_TYPE_LOCAL 0x0400 // Entry refers to local vol
#define DFS_USE_LDAP 1
#define DFS_ROOTSCALABILTY_FORCED_REFRESH_INTERVAL 20
typedef struct _BLOB_DATA
{
SHASH_HEADER Header;
UNICODE_STRING BlobName;
ULONG Size;
PBYTE pBlob;
LONG SequenceNumber;
} DFSBLOB_DATA, *PDFSBLOB_DATA;
typedef struct _BLOB_ITERATOR
{
BOOLEAN Started;
PDFSBLOB_DATA RootReferenced;
SHASH_ITERATOR Iter;
}DFSBOB_ITER, *PDFSBLOB_ITER;
void *
AllocateShashData(ULONG Size );
void
DeallocateShashData(void *pPointer );
#define ADSBLOB_DEFAULT_BUFFER_SIZE 8192
#define DFS_DS_NOERROR 1
#define DFS_DS_ERROR 0
class DfsADBlobCache : public DfsGeneric
{
private:
PSHASH_TABLE m_pTable;
PDFSBLOB_DATA m_pBlob;
PDFSBLOB_DATA m_pRootBlob;
ULONG m_BlobSize;
DfsRootFolder *m_pRootFolder;
BOOL m_fCritInit;
GUID m_BlobAttributePktGuid;
LONG m_CurrentSequenceNumber;
LONG m_ErrorOccured;
PVOID m_pAdHandle;
ULONG m_AdReferenceCount;
LONG m_RefreshCount;
UNICODE_STRING m_LogicalShare;
UNICODE_STRING m_ObjectDN;
CRITICAL_SECTION m_Lock;
public:
DfsADBlobCache(DFSSTATUS *pStatus,
PUNICODE_STRING pShareName,
DfsRootFolder * pRootFolder);
~DfsADBlobCache();
//
// Note: This is protected by the critical section of the
// root object. Any changed intentions of using this should
// protect this code under a critical section.
//
#ifndef DFS_USE_LDAP
DFSSTATUS
SetObjectPktGuid(
IADs *pADs,
GUID *pGuid );
DFSSTATUS
GetADObject( PVOID *ppHandle )
{
DFSSTATUS Status;
Status = DfsAcquireWriteLock(&m_Lock);
if (Status != ERROR_SUCCESS)
{
return Status;
}
if (m_pAdHandle == NULL)
{
Status = DfsGetDfsRootADObject( NULL,
m_LogicalShare.Buffer,
(IADs **)&m_pAdHandle );
if (Status == ERROR_SUCCESS)
{
m_AdReferenceCount = 1;
*ppHandle = m_pAdHandle;
}
}
else
{
m_AdReferenceCount++;
*ppHandle = m_pAdHandle;
}
DfsReleaseLock(&m_Lock);
return Status;
}
VOID
ReleaseADObject( PVOID pObject )
{
DFSSTATUS Status;
if (pObject != NULL)
{
// make sure the object is the one we have cached?
}
Status = DfsAcquireWriteLock(&m_Lock);
if (Status != ERROR_SUCCESS)
{
return;
}
if (--m_AdReferenceCount == 0)
{
((IADs *)m_pAdHandle)->Release();
m_pAdHandle = NULL;
}
DfsReleaseLock(&m_Lock);
return NOTHING;
}
#else
DFSSTATUS DfsLdapConnect(LPWSTR DcName, LDAP **ppLdap );
VOID DfsLdapDisconnect(LDAP *pLdap );
DFSSTATUS DfsGetPktBlob( LDAP *pLdap,
LPWSTR ObjectDN,
PVOID *ppBlob,
PULONG pBlobSize,
PVOID *ppHandle,
PVOID *ppHandle1 );
VOID DfsReleasePktBlob( PVOID pHandle,
PVOID pHandle1 );
DFSSTATUS DfsSetPktBlobAndPktGuid ( LDAP *pLdap,
LPWSTR ObjectDN,
PVOID pBlob,
ULONG BlobSize,
GUID *pGuid );
DFSSTATUS
GetADObject( PVOID *ppHandle,
LPWSTR DCName )
{
DFSSTATUS Status = ERROR_SUCCESS;
Status = DfsAcquireWriteLock(&m_Lock);
if (Status != ERROR_SUCCESS)
{
return Status;
}
if (m_pAdHandle == NULL)
{
Status = DfsLdapConnect( DCName, (LDAP **)&m_pAdHandle );
if (Status == ERROR_SUCCESS)
{
m_AdReferenceCount = 1;
*ppHandle = m_pAdHandle;
}
}
else
{
m_AdReferenceCount++;
*ppHandle = m_pAdHandle;
}
DfsReleaseLock(&m_Lock);
return Status;
}
DFSSTATUS
GetCachedADObject( PVOID *ppHandle )
{
DFSSTATUS Status = ERROR_SUCCESS;
Status = DfsAcquireWriteLock(&m_Lock);
if (Status != ERROR_SUCCESS)
{
return Status;
}
if (m_pAdHandle == NULL)
{
Status = ERROR_NOT_FOUND;
}
else
{
m_AdReferenceCount++;
*ppHandle = m_pAdHandle;
}
DfsReleaseLock(&m_Lock);
return Status;
}
VOID
ReleaseADObject( PVOID pObject )
{
DFSSTATUS Status;
if (pObject != NULL)
{
// make sure the object is the one we have cached?
}
Status = DfsAcquireWriteLock(&m_Lock);
if (Status != ERROR_SUCCESS)
{
return;
}
if (--m_AdReferenceCount == 0)
{
DfsLdapDisconnect( (LDAP *)m_pAdHandle );
m_pAdHandle = NULL;
}
DfsReleaseLock(&m_Lock);
return NOTHING;
}
#endif
DFSSTATUS
CacheRefresh(BOOLEAN fForceSync,
BOOLEAN fFromPDC);
DFSSTATUS
CacheFlush(PVOID pObject) ;
DFSSTATUS
GetObjectPktGuid(
PVOID pHandle,
GUID *pGuid );
DFSSTATUS
UpdateDSBlobFromCache(
PVOID pHandle,
GUID *pGuid );
DFSSTATUS
UpdateCacheWithDSBlob(
PVOID pHandle );
BOOLEAN
IsStaleBlob( PDFSBLOB_DATA pBlob)
{
return (pBlob->SequenceNumber != m_CurrentSequenceNumber);
}
void InvalidateCache();
DFSSTATUS
UnpackBlob (BYTE *pBuffer,
PULONG pLength,
PDFSBLOB_DATA * pRetBlob);
DFSSTATUS
StoreBlobInCache(PUNICODE_STRING BlobName,
PBYTE pBlobBuffer,
ULONG BlobSize);
DFSSTATUS
GetSubBlob(
PUNICODE_STRING pName,
BYTE **ppBlobBuffer,
PULONG pBlobSize,
BYTE **ppBuffer,
PULONG pSize );
DFSSTATUS
GetNamedBlob (PUNICODE_STRING pBlobName,
PDFSBLOB_DATA *pBlobStructure);
DFSSTATUS
SetNamedBlob (PDFSBLOB_DATA pBlob);
DFSSTATUS
RemoveNamedBlob(PUNICODE_STRING pBlobName );
DFSSTATUS
PutBinaryIntoVariant(VARIANT * ovData,
BYTE * pBuf,
unsigned long cBufLen);
DFSSTATUS
GetBinaryFromVariant(VARIANT *ovData,
BYTE ** ppBuf,
unsigned long * pcBufLen);
DFSSTATUS
PackBlob(BYTE *pBuffer,
PULONG pLength,
PULONG TotalBlobBytes );
DFSSTATUS
CreateBlob(PUNICODE_STRING BlobName,
PBYTE pBlobBuffer,
ULONG BlobSize,
PDFSBLOB_DATA *pNewBlob
);
PDFSBLOB_DATA AcquireRootBlob()
{
if (m_pRootBlob != NULL)
{
AcquireBlobReference(m_pRootBlob);
}
return m_pRootBlob;
}
VOID
ReleaseRootBlob()
{
if (m_pRootBlob != NULL)
{
ReleaseBlobReference(m_pRootBlob);
}
m_pRootBlob = NULL;
}
VOID
AcquireBlobReference(
PDFSBLOB_DATA pBlobData)
{
PSHASH_HEADER pData = (PSHASH_HEADER)pBlobData;
InterlockedIncrement(&pData->RefCount);
}
VOID
ReleaseBlobReference(
PDFSBLOB_DATA pBlobData)
{
PSHASH_HEADER pData = (PSHASH_HEADER)pBlobData;
if(InterlockedDecrement(&pData->RefCount) == 0)
{
DeallocateShashData(pData);
}
}
void
ReleaseBlobCacheReference(PDFSBLOB_DATA pBlobStructure)
{
NTSTATUS Status = STATUS_SUCCESS;
if (IsEmptyString(pBlobStructure->BlobName.Buffer))
{
ReleaseBlobReference(pBlobStructure);
}
else
{
Status = SHashReleaseReference(m_pTable, (PSHASH_HEADER) pBlobStructure);
}
}
PDFSBLOB_DATA
FindFirstBlob(PDFSBLOB_ITER pIter);
PDFSBLOB_DATA
FindNextBlob(PDFSBLOB_ITER pIter);
void
FindCloseBlob(PDFSBLOB_ITER pIter);
DFSSTATUS
WriteBlobToAd(
BOOLEAN ForceFlush = FALSE);
DFSSTATUS
SetupObjectDN()
{
DFSSTATUS Status = ERROR_SUCCESS;
LPWSTR DNBuffer;
LPWSTR RemainingDN;
RemainingDN = DfsGetDfsAdNameContextString();
if (RemainingDN == NULL)
{
Status = ERROR_NOT_READY;
}
if (Status == ERROR_SUCCESS)
{
ULONG DNSize = 3 +
wcslen(m_LogicalShare.Buffer) +
1 +
wcslen(DFS_AD_CONFIG_DATA) +
1 +
wcslen(RemainingDN) + 1;
DNBuffer = new WCHAR[DNSize];
if (DNBuffer != NULL)
{
wcscpy(DNBuffer, L"CN=");
wcscat(DNBuffer, m_LogicalShare.Buffer);
wcscat(DNBuffer, L",");
wcscat(DNBuffer, DFS_AD_CONFIG_DATA);
wcscat(DNBuffer, L",");
wcscat(DNBuffer, RemainingDN);
Status = DfsRtlInitUnicodeStringEx( &m_ObjectDN, DNBuffer );
if(Status != ERROR_SUCCESS)
{
delete [] DNBuffer;
}
}
else
{
Status = ERROR_NOT_ENOUGH_MEMORY;
}
}
return Status;
}
DFSSTATUS
GetObjectDN(
PUNICODE_STRING pObjectDN)
{
DFSSTATUS Status = ERROR_SUCCESS;
if (m_ObjectDN.Buffer == NULL)
{
Status = SetupObjectDN();
}
*pObjectDN = m_ObjectDN;
return Status;
}
ULONG
GetBlobSize();
DFSSTATUS
DfsDoesUserHaveAccess(DWORD DesiredAccess);
DFSSTATUS
CreateSiteBlobIfNecessary(void);
DFSSTATUS
UpdateSiteBlob(PVOID pBuffer, ULONG Size);
DFSSTATUS
GetSiteBlob(PVOID *ppBuffer, PULONG pSize)
{
DFSSTATUS Status = ERROR_SUCCESS;
if (m_pBlob != NULL)
{
*ppBuffer = m_pBlob->pBlob;
*pSize = m_pBlob->Size;
}
else
{
Status = ERROR_NOT_FOUND;
}
return Status;
}
DFSSTATUS
SetSiteBlob(PVOID pBuffer, ULONG Size)
{
DFSSTATUS Status;
Status = UpdateSiteBlob(pBuffer, Size);
return Status;
}
};
DWORD PackBlobEnumerator( void* pvkey,
void* pvData,
void * pContext ) ;
DFSSTATUS
AddStreamToBlob(PUNICODE_STRING BlobName,
BYTE *pBlobBuffer,
ULONG BlobSize,
BYTE ** pUseBuffer,
ULONG *BufferSize );
typedef struct _PACKBLOB_ENUMCTX
{
DFSSTATUS Status;
ULONG Size;
ULONG NumItems;
ULONG CurrentSize;
LONG SequenceNumber;
BYTE * pBuffer;
} PACKBLOB_ENUMCTX, *PPACKBLOB_ENUMCTX;
#endif // __DFS_ADBLOB_CACHE__