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
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__
|