979 lines
25 KiB
C++
979 lines
25 KiB
C++
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Copyright (C) 1997, Microsoft Corporation
|
|||
|
//
|
|||
|
// File: csites.cxx
|
|||
|
//
|
|||
|
// Contents: This module contains the functions which deal with the site table
|
|||
|
//
|
|||
|
// History: 02-Dec-1997 JHarper Created.
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
#include "headers.hxx"
|
|||
|
#pragma hdrstop
|
|||
|
|
|||
|
#include "dfsmsrv.h"
|
|||
|
#include "csites.hxx"
|
|||
|
#include "marshal.hxx"
|
|||
|
|
|||
|
INIT_DFS_SITENAME_INFO_MARSHAL_INFO();
|
|||
|
INIT_DFS_SITELIST_INFO_MARSHAL_INFO()
|
|||
|
INIT_DFSM_SITE_ENTRY_MARSHAL_INFO();
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
DfsSendDelete(
|
|||
|
LPWSTR ServerName);
|
|||
|
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: CSites::CSites
|
|||
|
//
|
|||
|
// Synopsis: Constructor for CSites - Initializes, but does not load, the site table
|
|||
|
//
|
|||
|
// Arguments: [pwszFileName] -- Name of the folder/LDAP_OBJECT to use
|
|||
|
// [pdwErr] -- On return, the result of initializing the instance
|
|||
|
//
|
|||
|
// Returns: Result returned in pdwErr argument:
|
|||
|
//
|
|||
|
// [ERROR_SUCCESS] -- Successfully initialized
|
|||
|
//
|
|||
|
// [ERROR_OUTOFMEMORY] -- Out of memory.
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
CSites::CSites(
|
|||
|
LPWSTR pwszFileName,
|
|||
|
LPDWORD pdwErr)
|
|||
|
{
|
|||
|
DWORD dwErr = 0;
|
|||
|
|
|||
|
IDfsVolInlineDebOut((
|
|||
|
DEB_TRACE, "CSites::+CSites(0x%x)\n",
|
|||
|
this));
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("+++CSites::CSites @0x%x\n", this);
|
|||
|
#endif
|
|||
|
|
|||
|
_cRef = 0;
|
|||
|
_fDirty = FALSE;
|
|||
|
RtlZeroMemory(&_SiteTableGuid, sizeof(GUID));
|
|||
|
InitializeListHead(&_SiteTableHead);
|
|||
|
|
|||
|
_pwszFileName = new WCHAR [wcslen(pwszFileName) + 1];
|
|||
|
|
|||
|
if (_pwszFileName != NULL) {
|
|||
|
wcscpy(_pwszFileName, pwszFileName);
|
|||
|
} else {
|
|||
|
dwErr = ERROR_OUTOFMEMORY;
|
|||
|
}
|
|||
|
|
|||
|
*pdwErr = dwErr;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: CSites::~CSites
|
|||
|
//
|
|||
|
// Synopsis: Destructor for CSites - Deallocates the CSites object
|
|||
|
//
|
|||
|
// Arguments: None
|
|||
|
//
|
|||
|
// Returns: Nothing
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
CSites::~CSites()
|
|||
|
{
|
|||
|
PLIST_ENTRY pListHead;
|
|||
|
PDFSM_SITE_ENTRY pSiteInfo;
|
|||
|
|
|||
|
IDfsVolInlineDebOut((
|
|||
|
DEB_TRACE, "CSites::~CSites(0x%x)\n",
|
|||
|
this));
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("---CSites::~CSites @0x%x\n", this);
|
|||
|
#endif
|
|||
|
|
|||
|
ASSERT (_cRef == 0);
|
|||
|
|
|||
|
if (_pwszFileName) {
|
|||
|
delete [] _pwszFileName;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Delete the linked list of SiteInfo's
|
|||
|
//
|
|||
|
|
|||
|
pListHead = &_SiteTableHead;
|
|||
|
|
|||
|
while (pListHead->Flink != pListHead) {
|
|||
|
pSiteInfo = CONTAINING_RECORD(pListHead->Flink, DFSM_SITE_ENTRY, Link);
|
|||
|
RemoveEntryList(pListHead->Flink);
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("CSites::~CSites: deleting SiteInfo@0x%x\n", pSiteInfo);
|
|||
|
#endif
|
|||
|
delete [] pSiteInfo;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: CSites::AddRef
|
|||
|
//
|
|||
|
// Synopsis: Increases the ref count on the in-memory site table. If the
|
|||
|
// refcount is going from 0 to 1, an attempt is made to refresh
|
|||
|
// the in-memory site table from storage.
|
|||
|
//
|
|||
|
// Arguments: None
|
|||
|
//
|
|||
|
// Returns: Nothing
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
VOID
|
|||
|
CSites::AddRef()
|
|||
|
{
|
|||
|
DWORD dwErr = 0;
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "CSites::AddRef()\n"));
|
|||
|
|
|||
|
_cRef++;
|
|||
|
|
|||
|
if (_cRef == 1) {
|
|||
|
|
|||
|
dwErr = _ReadSiteTable();
|
|||
|
|
|||
|
_fDirty = FALSE;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: CSites::Release
|
|||
|
//
|
|||
|
// Synopsis: Decrease the ref count on the in-memory site table. If the
|
|||
|
// refcount is going from 1 to 0, then attempt to flush the
|
|||
|
// table to storage, if something has changed.
|
|||
|
//
|
|||
|
// Arguments: None
|
|||
|
//
|
|||
|
// Returns: Nothing
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
VOID
|
|||
|
CSites::Release()
|
|||
|
{
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "CSites::Release()\n"));
|
|||
|
|
|||
|
ASSERT (_cRef > 0);
|
|||
|
|
|||
|
_cRef--;
|
|||
|
|
|||
|
if (_cRef == 0) {
|
|||
|
|
|||
|
if (_fDirty == TRUE) {
|
|||
|
|
|||
|
_WriteSiteTable();
|
|||
|
|
|||
|
_fDirty = FALSE;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: CSites::AddOrUpdateSiteInfo
|
|||
|
//
|
|||
|
// Synopsis: Adds or updates an entry in the site table.
|
|||
|
//
|
|||
|
// Arguments: [pServerName] -- Server name to update
|
|||
|
// [SiteCount] -- Number of entries in pSites
|
|||
|
// [pSites] -- pointer to array of site information.
|
|||
|
//
|
|||
|
// Returns: [ERROR_SUCCESS] -- Successfully updated the table
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
DWORD
|
|||
|
CSites::AddOrUpdateSiteInfo(
|
|||
|
LPWSTR pServerName,
|
|||
|
ULONG SiteCount,
|
|||
|
PDFS_SITENAME_INFO pSites)
|
|||
|
{
|
|||
|
PDFSM_SITE_ENTRY pSiteInfo;
|
|||
|
PDFSM_SITE_ENTRY pExistingInfo;
|
|||
|
DWORD dwErr;
|
|||
|
ULONG i;
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "CSites::AddOrUpdateSiteInfo(%ws)\n", pServerName));
|
|||
|
|
|||
|
dwErr = _AllocateSiteInfo(
|
|||
|
pServerName,
|
|||
|
SiteCount,
|
|||
|
pSites,
|
|||
|
&pSiteInfo);
|
|||
|
|
|||
|
if (dwErr == ERROR_SUCCESS) {
|
|||
|
//
|
|||
|
// Only put the new entry in if it supercedes one there,
|
|||
|
// or is a new entry.
|
|||
|
//
|
|||
|
pExistingInfo = LookupSiteInfo(pServerName);
|
|||
|
if (pExistingInfo != NULL) {
|
|||
|
if (_CompareEntries(pSiteInfo,pExistingInfo) == TRUE ) {
|
|||
|
//
|
|||
|
// Same info - no update needed
|
|||
|
//
|
|||
|
delete [] pSiteInfo;
|
|||
|
} else {
|
|||
|
//
|
|||
|
// Remove the existing entry
|
|||
|
//
|
|||
|
RemoveEntryList(&pExistingInfo->Link);
|
|||
|
delete [] pExistingInfo;
|
|||
|
//
|
|||
|
// Put the new one in
|
|||
|
//
|
|||
|
DfsSendUpdate(pServerName,SiteCount,pSites);
|
|||
|
InsertHeadList(&_SiteTableHead, &pSiteInfo->Link);
|
|||
|
_fDirty = TRUE;
|
|||
|
}
|
|||
|
} else {
|
|||
|
//
|
|||
|
// Not in table - put it in
|
|||
|
//
|
|||
|
DfsSendUpdate(pServerName,SiteCount,pSites);
|
|||
|
InsertHeadList(&_SiteTableHead, &pSiteInfo->Link);
|
|||
|
_fDirty = TRUE;
|
|||
|
}
|
|||
|
}
|
|||
|
return ERROR_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: CSites::LookupSiteInfo
|
|||
|
//
|
|||
|
// Synopsis: Finds a site table entry
|
|||
|
//
|
|||
|
// Arguments: [pServerName] -- Server name to look up
|
|||
|
//
|
|||
|
// Returns: [NULL] -- No entry found
|
|||
|
// [PDFSM_SITE_ENTRY] -- pointer to found entry
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
PDFSM_SITE_ENTRY
|
|||
|
CSites::LookupSiteInfo(
|
|||
|
LPWSTR pServerName)
|
|||
|
{
|
|||
|
PLIST_ENTRY pListHead, pLink;
|
|||
|
PDFSM_SITE_ENTRY pSiteInfo;
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "CSites::LookupSiteInfo(%ws)\n", pServerName));
|
|||
|
|
|||
|
pListHead = &_SiteTableHead;
|
|||
|
|
|||
|
if (pListHead->Flink == pListHead) { // list empty
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
for (pLink = pListHead->Flink; pLink != pListHead; pLink = pLink->Flink) {
|
|||
|
pSiteInfo = CONTAINING_RECORD(pLink, DFSM_SITE_ENTRY, Link);
|
|||
|
if (_wcsicmp(pSiteInfo->ServerName,pServerName) == 0) {
|
|||
|
//
|
|||
|
// If this was marked for delete, it isn't any more.
|
|||
|
//
|
|||
|
pSiteInfo->Flags &= ~DFSM_SITE_ENTRY_DELETE_PENDING;
|
|||
|
return pSiteInfo;
|
|||
|
}
|
|||
|
}
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: CSites::_AllocateSiteInfo, private
|
|||
|
//
|
|||
|
// Synopsis: Creates a DFSM_SITE_ENTRY struct, as one contiguous chunk of memory
|
|||
|
//
|
|||
|
// Arguments: [pServerName] -- Server name
|
|||
|
// [SiteCount] -- Number of entries in pSites
|
|||
|
// [pSites] -- pointer to array of site information.
|
|||
|
// [ppSiteInfo] -- pointer to pointer for the results
|
|||
|
//
|
|||
|
// Returns: [ERROR_SUCCESS] -- Successfully allocated and filled in the structure
|
|||
|
// [ERROR_OUTOFMEMORY] -- Couldn't allocate needed memory
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
DWORD
|
|||
|
CSites::_AllocateSiteInfo(
|
|||
|
PWSTR pServerName,
|
|||
|
ULONG SiteCount,
|
|||
|
PDFS_SITENAME_INFO pSites,
|
|||
|
PDFSM_SITE_ENTRY *ppSiteInfo)
|
|||
|
{
|
|||
|
PDFSM_SITE_ENTRY pSiteInfo;
|
|||
|
WCHAR *wCp;
|
|||
|
ULONG i;
|
|||
|
ULONG Size = 0;
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "CSites::_AllocateSiteInfo(%ws)\n", pServerName));
|
|||
|
|
|||
|
//
|
|||
|
// Calculate the size chunk of mem we'll need
|
|||
|
//
|
|||
|
|
|||
|
Size = FIELD_OFFSET(DFSM_SITE_ENTRY,Info.Site[SiteCount]);
|
|||
|
|
|||
|
//
|
|||
|
// Add space for server name
|
|||
|
//
|
|||
|
|
|||
|
Size += (wcslen(pServerName) + 1) * sizeof(WCHAR);
|
|||
|
|
|||
|
//
|
|||
|
// And space for all the sitenames
|
|||
|
//
|
|||
|
for (i = 0; i < SiteCount; i++) {
|
|||
|
if (pSites[i].SiteName != NULL) {
|
|||
|
Size += (wcslen(pSites[i].SiteName) + 1) * sizeof(WCHAR);
|
|||
|
} else {
|
|||
|
Size += sizeof(WCHAR);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
pSiteInfo = (PDFSM_SITE_ENTRY) new CHAR [Size];
|
|||
|
|
|||
|
if (pSiteInfo == NULL) {
|
|||
|
*ppSiteInfo = NULL;
|
|||
|
return ERROR_OUTOFMEMORY;
|
|||
|
}
|
|||
|
|
|||
|
RtlZeroMemory(pSiteInfo, Size);
|
|||
|
|
|||
|
//
|
|||
|
// Marshal the info into the buffer
|
|||
|
//
|
|||
|
pSiteInfo->Flags = 0;
|
|||
|
pSiteInfo->Info.cSites = SiteCount;
|
|||
|
|
|||
|
wCp = (WCHAR *) &pSiteInfo->Info.Site[SiteCount];
|
|||
|
pSiteInfo->ServerName = wCp;
|
|||
|
wcscpy(wCp, pServerName);
|
|||
|
wCp += wcslen(pServerName) + 1;
|
|||
|
|
|||
|
for (i = 0; i < SiteCount; i++) {
|
|||
|
pSiteInfo->Info.Site[i].SiteFlags = pSites[i].SiteFlags;
|
|||
|
pSiteInfo->Info.Site[i].SiteName = wCp;
|
|||
|
if (pSites[i].SiteName != NULL) {
|
|||
|
wcscpy(wCp, pSites[i].SiteName);
|
|||
|
wCp += wcslen(pSites[i].SiteName) + 1;
|
|||
|
} else {
|
|||
|
*wCp++ = UNICODE_NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
*ppSiteInfo = pSiteInfo;
|
|||
|
|
|||
|
return ERROR_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: CSites::_ReadSiteTable,private
|
|||
|
//
|
|||
|
// Synopsis: Loads the site table from storage
|
|||
|
//
|
|||
|
// First we check if the GUID has changed. If it hasn't, we abort the
|
|||
|
// load - the existing table is good.
|
|||
|
//
|
|||
|
// If the table is different (the GUID is different), we merge the new
|
|||
|
// data in with the old. This allows us to track which entries need to
|
|||
|
// be updated, which need to be deleted, and which haven't changed. The
|
|||
|
// process is done in three steps:
|
|||
|
//
|
|||
|
// Step 1: Go through the table, marking all the entries DELETE_PENDING
|
|||
|
// Step 2: Load the new entries. As they are loaded, the updated entries'
|
|||
|
// DELETE_PENDING bit(s) are turned off.
|
|||
|
// Step 3: Go though the table again, removing any entries that still
|
|||
|
// have the DELETE_PENDING bit on, and issuing an FSCTL to dfs.sys
|
|||
|
// to have it remove the entry from its table.
|
|||
|
//
|
|||
|
// Arguments: None
|
|||
|
//
|
|||
|
// Returns: [ERROR_SUCCESS] -- Successfully loaded the table
|
|||
|
// [ERROR_OUTOFMEMORY] -- Not enough memory
|
|||
|
// [other] -- returned from LdapGetData/RegGetData/DfsRtlXXX
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
DWORD
|
|||
|
CSites::_ReadSiteTable()
|
|||
|
{
|
|||
|
DWORD dwErr;
|
|||
|
DWORD cbBuffer;
|
|||
|
PBYTE pBuffer = NULL;
|
|||
|
PBYTE bp;
|
|||
|
ULONG cObjects = 0;
|
|||
|
ULONG i;
|
|||
|
ULONG j;
|
|||
|
PDFSM_SITE_ENTRY pSiteInfo;
|
|||
|
MARSHAL_BUFFER marshalBuffer;
|
|||
|
GUID TempGuid;
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "CSites::_ReadSiteTable()\n"));
|
|||
|
|
|||
|
if (ulDfsManagerType == DFS_MANAGER_FTDFS) {
|
|||
|
|
|||
|
dwErr = LdapGetData(
|
|||
|
_pwszFileName,
|
|||
|
&cbBuffer,
|
|||
|
(PCHAR *)&pBuffer);
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
dwErr = RegGetData(
|
|||
|
_pwszFileName,
|
|||
|
SITE_VALUE_NAME,
|
|||
|
&cbBuffer,
|
|||
|
&pBuffer);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (dwErr == ERROR_SUCCESS && cbBuffer >= sizeof(ULONG) + sizeof(GUID)) {
|
|||
|
|
|||
|
//
|
|||
|
// Unmarshal all the objects (DFS_SITENAME_INFO's) in the buffer
|
|||
|
//
|
|||
|
//
|
|||
|
// We marshal into a temporary buffer, big enough to hold whatever is
|
|||
|
// in the buffer.
|
|||
|
//
|
|||
|
|
|||
|
pSiteInfo = (PDFSM_SITE_ENTRY) new BYTE [cbBuffer + sizeof(DFSM_SITE_ENTRY)];
|
|||
|
|
|||
|
if (pSiteInfo == NULL) {
|
|||
|
|
|||
|
dwErr = ERROR_OUTOFMEMORY;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (dwErr == ERROR_SUCCESS) {
|
|||
|
|
|||
|
MarshalBufferInitialize(
|
|||
|
&marshalBuffer,
|
|||
|
cbBuffer,
|
|||
|
pBuffer);
|
|||
|
|
|||
|
DfsRtlGetGuid(&marshalBuffer, &TempGuid);
|
|||
|
|
|||
|
//
|
|||
|
// If the Guid hasn't changed, we abort the load.
|
|||
|
//
|
|||
|
|
|||
|
if (RtlCompareMemory(&TempGuid, &_SiteTableGuid, sizeof(GUID)) == sizeof(GUID)) {
|
|||
|
|
|||
|
delete [] pSiteInfo;
|
|||
|
delete [] pBuffer;
|
|||
|
goto NoLoadNecessary;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Ok, we're committed to loading this (supposedly different) version
|
|||
|
// of the site table. Mark all the existing entries DFSM_SITE_ENTRY_DELETE_PENDING.
|
|||
|
//
|
|||
|
|
|||
|
MarkEntriesForMerge();
|
|||
|
|
|||
|
//
|
|||
|
// Grab the Guid
|
|||
|
//
|
|||
|
|
|||
|
RtlCopyMemory(&_SiteTableGuid, &TempGuid, sizeof(GUID));
|
|||
|
|
|||
|
//
|
|||
|
// Get number of entries we'll be loading
|
|||
|
//
|
|||
|
|
|||
|
DfsRtlGetUlong(&marshalBuffer, &cObjects);
|
|||
|
|
|||
|
//
|
|||
|
// Now unmarshal each object/entry
|
|||
|
//
|
|||
|
|
|||
|
for (j = 0; dwErr == ERROR_SUCCESS && j < cObjects; j++) {
|
|||
|
|
|||
|
dwErr = DfsRtlGet(&marshalBuffer,&MiDfsmSiteEntry, pSiteInfo);
|
|||
|
|
|||
|
if (dwErr == ERROR_SUCCESS) {
|
|||
|
|
|||
|
//
|
|||
|
// And put it in the site table
|
|||
|
//
|
|||
|
|
|||
|
AddOrUpdateSiteInfo(
|
|||
|
pSiteInfo->ServerName,
|
|||
|
pSiteInfo->Info.cSites,
|
|||
|
&pSiteInfo->Info.Site[0]);
|
|||
|
|
|||
|
//
|
|||
|
// The unmarshalling routines allocate buffers; we need to
|
|||
|
// free them.
|
|||
|
//
|
|||
|
|
|||
|
for (i = 0; i < pSiteInfo->Info.cSites; i++) {
|
|||
|
MarshalBufferFree(pSiteInfo->Info.Site[i].SiteName);
|
|||
|
}
|
|||
|
|
|||
|
MarshalBufferFree(pSiteInfo->ServerName);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Now sync up the PKT in dfs.sys with this table
|
|||
|
//
|
|||
|
SyncPktSiteTable();
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
delete [] pSiteInfo;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (pBuffer != NULL) {
|
|||
|
|
|||
|
delete [] pBuffer;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
NoLoadNecessary:
|
|||
|
|
|||
|
return dwErr;
|
|||
|
}
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: CSites::_WriteSiteTable,private
|
|||
|
//
|
|||
|
// Synopsis: Writes the site table to storage
|
|||
|
//
|
|||
|
// Arguments: None
|
|||
|
//
|
|||
|
// Returns: [ERROR_SUCCESS] -- Successfully write the table
|
|||
|
// [ERROR_OUTOFMEMORY] -- Not enough memory
|
|||
|
// [other] -- returned from LdapGetData/RegGetData/DfsRtlXXX
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
DWORD
|
|||
|
CSites::_WriteSiteTable()
|
|||
|
{
|
|||
|
DWORD dwErr;
|
|||
|
DWORD cbBuffer;
|
|||
|
PBYTE pBuffer;
|
|||
|
ULONG cObjects;
|
|||
|
ULONG i;
|
|||
|
PLIST_ENTRY pListHead, pLink;
|
|||
|
PDFSM_SITE_ENTRY pSiteInfo;
|
|||
|
MARSHAL_BUFFER marshalBuffer;
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "CSites::_WriteSiteTable()\n"));
|
|||
|
|
|||
|
//
|
|||
|
// Create a new Guid
|
|||
|
//
|
|||
|
|
|||
|
UuidCreate(&_SiteTableGuid);
|
|||
|
|
|||
|
//
|
|||
|
// The cObjects count
|
|||
|
//
|
|||
|
cbBuffer = sizeof(ULONG) + sizeof(GUID);
|
|||
|
|
|||
|
//
|
|||
|
// Add up the number of entries we need to store, and the total size of all
|
|||
|
// of them.
|
|||
|
//
|
|||
|
cObjects = 0;
|
|||
|
pListHead = &_SiteTableHead;
|
|||
|
for (pLink = pListHead->Flink; pLink != pListHead; pLink = pLink->Flink) {
|
|||
|
pSiteInfo = CONTAINING_RECORD(pLink, DFSM_SITE_ENTRY, Link);
|
|||
|
DfsRtlSize(&MiDfsmSiteEntry, pSiteInfo, &cbBuffer);
|
|||
|
cObjects++;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Get a buffer big enough
|
|||
|
//
|
|||
|
|
|||
|
pBuffer = new BYTE [cbBuffer];
|
|||
|
|
|||
|
if (pBuffer == NULL) {
|
|||
|
|
|||
|
return ERROR_OUTOFMEMORY;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Put the guid, then the object count in the beginning of the buffer
|
|||
|
//
|
|||
|
|
|||
|
MarshalBufferInitialize(
|
|||
|
&marshalBuffer,
|
|||
|
cbBuffer,
|
|||
|
pBuffer);
|
|||
|
|
|||
|
DfsRtlPutGuid(&marshalBuffer, &_SiteTableGuid);
|
|||
|
DfsRtlPutUlong(&marshalBuffer, &cObjects);
|
|||
|
|
|||
|
//
|
|||
|
// Walk the linked list of objects, marshalling them into the buffer.
|
|||
|
//
|
|||
|
for (pLink = pListHead->Flink; pLink != pListHead; pLink = pLink->Flink) {
|
|||
|
pSiteInfo = CONTAINING_RECORD(pLink, DFSM_SITE_ENTRY, Link);
|
|||
|
DfsRtlPut(&marshalBuffer,&MiDfsmSiteEntry, pSiteInfo);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Push out to storage
|
|||
|
//
|
|||
|
if (ulDfsManagerType == DFS_MANAGER_FTDFS) {
|
|||
|
|
|||
|
dwErr = LdapPutData(
|
|||
|
_pwszFileName,
|
|||
|
cbBuffer,
|
|||
|
(PCHAR)pBuffer);
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
dwErr = RegPutData(
|
|||
|
_pwszFileName,
|
|||
|
SITE_VALUE_NAME,
|
|||
|
cbBuffer,
|
|||
|
pBuffer);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// ...and free the marshal buffer we created.
|
|||
|
//
|
|||
|
delete [] pBuffer;
|
|||
|
|
|||
|
return dwErr;
|
|||
|
}
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: CSites::_CompareEntries,private
|
|||
|
//
|
|||
|
// Synopsis: Compare two site table entries - case insensitive, and allows the site
|
|||
|
// lists to be in different order.
|
|||
|
//
|
|||
|
// Arguments: None
|
|||
|
//
|
|||
|
// Returns: [TRUE] -- The entries are essentially identical
|
|||
|
// [FALSE] -- The entries differ in some important way
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
CSites::_CompareEntries(
|
|||
|
PDFSM_SITE_ENTRY pDfsmInfo1,
|
|||
|
PDFSM_SITE_ENTRY pDfsmInfo2)
|
|||
|
{
|
|||
|
ULONG i;
|
|||
|
ULONG j;
|
|||
|
BOOLEAN fFound;
|
|||
|
|
|||
|
//
|
|||
|
// cSites has to be the same
|
|||
|
//
|
|||
|
|
|||
|
if (pDfsmInfo1->Info.cSites != pDfsmInfo2->Info.cSites) {
|
|||
|
goto ReturnFalse;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Server name has to be identical (why are we calling this
|
|||
|
// if they aren't?)
|
|||
|
//
|
|||
|
if (_wcsicmp(pDfsmInfo1->ServerName,pDfsmInfo2->ServerName) != 0) {
|
|||
|
goto ReturnFalse;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Check that every Site in pDfsmInfo1 is in pDfsmSiteInfo2
|
|||
|
//
|
|||
|
for (i = 0; i < pDfsmInfo1->Info.cSites; i++) {
|
|||
|
fFound = FALSE;
|
|||
|
for (j = 0; fFound == FALSE && j < pDfsmInfo2->Info.cSites; j++) {
|
|||
|
if (_wcsicmp(
|
|||
|
pDfsmInfo1->Info.Site[i].SiteName,
|
|||
|
pDfsmInfo2->Info.Site[j].SiteName) == 0) {
|
|||
|
fFound = TRUE;
|
|||
|
}
|
|||
|
}
|
|||
|
if (fFound == FALSE) {
|
|||
|
goto ReturnFalse;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// ...and check that every site in pDfsmInfo2 is in pDfsmInfo1
|
|||
|
//
|
|||
|
for (i = 0; i < pDfsmInfo2->Info.cSites; i++) {
|
|||
|
fFound = FALSE;
|
|||
|
for (j = 0; fFound == FALSE && j < pDfsmInfo1->Info.cSites; j++) {
|
|||
|
if (_wcsicmp(
|
|||
|
pDfsmInfo2->Info.Site[i].SiteName,
|
|||
|
pDfsmInfo1->Info.Site[j].SiteName) == 0) {
|
|||
|
fFound = TRUE;
|
|||
|
}
|
|||
|
}
|
|||
|
if (fFound == FALSE) {
|
|||
|
goto ReturnFalse;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return TRUE;
|
|||
|
|
|||
|
ReturnFalse:
|
|||
|
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: CSites::MarkEntriesForMerge
|
|||
|
//
|
|||
|
// Synopsis: Mark all entries in preparation for a merge.
|
|||
|
// (1) Mark all entries with delete_pending on
|
|||
|
// (2) Load a new table - duplicate entries remove the delete_pending bit
|
|||
|
// (3) Call SyncPktSiteTable(), which will bring the PKT in dfs.sys up to date,
|
|||
|
// by deleting delete_pending entries
|
|||
|
//
|
|||
|
// Arguments: None
|
|||
|
//
|
|||
|
// Returns: nothing
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
VOID
|
|||
|
CSites::MarkEntriesForMerge()
|
|||
|
{
|
|||
|
PLIST_ENTRY pListHead, pLink;
|
|||
|
PDFSM_SITE_ENTRY pSiteInfo;
|
|||
|
ULONG i;
|
|||
|
|
|||
|
pListHead = &_SiteTableHead;
|
|||
|
|
|||
|
for (pLink = pListHead->Flink; pLink != pListHead; pLink = pLink->Flink) {
|
|||
|
pSiteInfo = CONTAINING_RECORD(pLink, DFSM_SITE_ENTRY, Link);
|
|||
|
pSiteInfo->Flags |= DFSM_SITE_ENTRY_DELETE_PENDING;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: CSites::SyncPktSiteTable
|
|||
|
//
|
|||
|
// Synopsis: Step 3 of a table merge. Walk the table, removing any entries
|
|||
|
// with the DFSM_SITE_ENTRY_DELETE_PENDING (and telling dfs.sys
|
|||
|
// to do so)
|
|||
|
//
|
|||
|
// Arguments: None
|
|||
|
//
|
|||
|
// Returns: Nothing
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
VOID
|
|||
|
CSites::SyncPktSiteTable()
|
|||
|
{
|
|||
|
PLIST_ENTRY pListHead;
|
|||
|
PLIST_ENTRY pLink;
|
|||
|
PLIST_ENTRY pNext;
|
|||
|
PDFSM_SITE_ENTRY pSiteInfo;
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "CSites::SyncPktSiteTable()\n"));
|
|||
|
|
|||
|
pListHead = &_SiteTableHead;
|
|||
|
|
|||
|
for (pLink = pListHead->Flink; pLink != pListHead; pLink = pNext) {
|
|||
|
|
|||
|
//
|
|||
|
// Save next in case we delete this one
|
|||
|
//
|
|||
|
pNext = pLink->Flink;
|
|||
|
|
|||
|
pSiteInfo = CONTAINING_RECORD(pLink, DFSM_SITE_ENTRY, Link);
|
|||
|
|
|||
|
if ((pSiteInfo->Flags & DFSM_SITE_ENTRY_DELETE_PENDING) != 0) {
|
|||
|
//
|
|||
|
// call dfs.sys with the update
|
|||
|
//
|
|||
|
DfsSendDelete(pSiteInfo->ServerName);
|
|||
|
RemoveEntryList(pLink);
|
|||
|
delete [] pSiteInfo;
|
|||
|
_fDirty = TRUE;
|
|||
|
}
|
|||
|
}
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "CSites::SyncPktSiteTable exit\n"));
|
|||
|
}
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: CSites::_DumpSiteTable
|
|||
|
//
|
|||
|
// Synopsis: Spill dfs's guts about site table entries.
|
|||
|
//
|
|||
|
// Arguments: None
|
|||
|
//
|
|||
|
// Returns: Nothing
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
VOID
|
|||
|
CSites::_DumpSiteTable()
|
|||
|
{
|
|||
|
PLIST_ENTRY pListHead, pLink;
|
|||
|
PDFSM_SITE_ENTRY pSiteInfo;
|
|||
|
ULONG i;
|
|||
|
|
|||
|
pListHead = &_SiteTableHead;
|
|||
|
|
|||
|
//
|
|||
|
// Print them (for debugging)
|
|||
|
//
|
|||
|
for (pLink = pListHead->Flink; pLink != pListHead; pLink = pLink->Flink) {
|
|||
|
pSiteInfo = CONTAINING_RECORD(pLink, DFSM_SITE_ENTRY, Link);
|
|||
|
DbgPrint("\tpSiteInfo(%ws)\n", pSiteInfo->ServerName);
|
|||
|
for (i = 0; i < pSiteInfo->Info.cSites; i++) {
|
|||
|
DbgPrint("\t\t%02d:%ws\n", i, pSiteInfo->Info.Site[i].SiteName);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: DfsSendDelete, private
|
|||
|
//
|
|||
|
// Synopsis: Send a DFS_DELETE_SITE_ARG down to dfs.sys
|
|||
|
//
|
|||
|
// Arguments: None
|
|||
|
//
|
|||
|
// Returns: Nothing
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
DfsSendDelete(
|
|||
|
LPWSTR ServerName)
|
|||
|
{
|
|||
|
ULONG size;
|
|||
|
DWORD dwErr;
|
|||
|
PDFS_DELETE_SITE_INFO_ARG arg;
|
|||
|
|
|||
|
size = sizeof(DFS_DELETE_SITE_INFO_ARG) +
|
|||
|
wcslen(ServerName) * sizeof(WCHAR);
|
|||
|
|
|||
|
arg = (PDFS_DELETE_SITE_INFO_ARG) new CHAR [size];
|
|||
|
|
|||
|
if (arg == NULL) {
|
|||
|
return ERROR_OUTOFMEMORY;
|
|||
|
}
|
|||
|
|
|||
|
arg->ServerName.Buffer = (WCHAR *) &arg[1];
|
|||
|
arg->ServerName.Length = wcslen(ServerName) * sizeof(WCHAR);
|
|||
|
arg->ServerName.MaximumLength = arg->ServerName.Length;
|
|||
|
RtlCopyMemory(arg->ServerName.Buffer, ServerName, arg->ServerName.Length);
|
|||
|
|
|||
|
LPWSTR_TO_OFFSET(arg->ServerName.Buffer,arg);
|
|||
|
|
|||
|
dwErr = DfsDeleteSiteEntry((PCHAR)arg, size);
|
|||
|
|
|||
|
delete [] arg;
|
|||
|
|
|||
|
return dwErr;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: DfsSendUpdate, private
|
|||
|
//
|
|||
|
// Synopsis: Send a DFS_CREATE_SITE_ARG down to dfs.sys
|
|||
|
//
|
|||
|
// Arguments: None
|
|||
|
//
|
|||
|
// Returns: Nothing
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
DfsSendUpdate(
|
|||
|
LPWSTR ServerName,
|
|||
|
ULONG SiteCount,
|
|||
|
PDFS_SITENAME_INFO pSites)
|
|||
|
{
|
|||
|
ULONG size;
|
|||
|
DWORD dwErr;
|
|||
|
ULONG i;
|
|||
|
PDFS_CREATE_SITE_INFO_ARG arg;
|
|||
|
WCHAR *wCp;
|
|||
|
|
|||
|
size = FIELD_OFFSET(DFS_CREATE_SITE_INFO_ARG,SiteName[SiteCount]) +
|
|||
|
wcslen(ServerName) * sizeof(WCHAR);
|
|||
|
|
|||
|
for (i = 0; i < SiteCount; i++) {
|
|||
|
size += wcslen(pSites[i].SiteName) * sizeof(WCHAR);
|
|||
|
}
|
|||
|
|
|||
|
arg = (PDFS_CREATE_SITE_INFO_ARG) new CHAR [size];
|
|||
|
|
|||
|
if (arg == NULL) {
|
|||
|
return ERROR_OUTOFMEMORY;
|
|||
|
}
|
|||
|
|
|||
|
wCp = (WCHAR *)(&arg->SiteName[SiteCount]);
|
|||
|
|
|||
|
arg->ServerName.Buffer = wCp;
|
|||
|
wCp += wcslen(ServerName);
|
|||
|
arg->ServerName.Length = wcslen(ServerName) * sizeof(WCHAR);
|
|||
|
arg->ServerName.MaximumLength = arg->ServerName.Length;
|
|||
|
RtlCopyMemory(arg->ServerName.Buffer, ServerName, arg->ServerName.Length);
|
|||
|
LPWSTR_TO_OFFSET(arg->ServerName.Buffer,arg);
|
|||
|
arg->SiteCount = SiteCount;
|
|||
|
|
|||
|
for (i = 0; i < SiteCount; i++) {
|
|||
|
arg->SiteName[i].Buffer = wCp;
|
|||
|
wCp += wcslen(pSites[i].SiteName);
|
|||
|
arg->SiteName[i].Length = wcslen(pSites[i].SiteName) * sizeof(WCHAR);
|
|||
|
arg->SiteName[i].MaximumLength = arg->SiteName[i].Length;
|
|||
|
RtlCopyMemory(arg->SiteName[i].Buffer, pSites[i].SiteName, arg->SiteName[i].Length);
|
|||
|
LPWSTR_TO_OFFSET(arg->SiteName[i].Buffer,arg);
|
|||
|
}
|
|||
|
|
|||
|
dwErr = DfsCreateSiteEntry((PCHAR)arg, size);
|
|||
|
|
|||
|
delete [] arg;
|
|||
|
|
|||
|
return dwErr;
|
|||
|
}
|