windows-nt/Source/XPSP1/NT/base/fs/dfs/dfsm/server/csites.cxx
2020-09-26 16:20:57 +08:00

979 lines
25 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//+-------------------------------------------------------------------------
//
// 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;
}