// // 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 #include #include #include #include #include "dfsadsiapi.hxx" #include #include #include 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__