1873 lines
49 KiB
C++
1873 lines
49 KiB
C++
|
//-------------------------------------------------------------
|
|||
|
//
|
|||
|
// Microsoft Windows
|
|||
|
//
|
|||
|
// Copyright (CC) Microsoft Corporation 1992, 1992
|
|||
|
//
|
|||
|
// File: idfsvsup.cxx
|
|||
|
//
|
|||
|
// Contents: This contains support methods for the IDfsVol interface
|
|||
|
// implementation.
|
|||
|
//
|
|||
|
//-------------------------------------------------------------
|
|||
|
//#include <ntos.h>
|
|||
|
//#include <ntrtl.h>
|
|||
|
//#include <nturtl.h>
|
|||
|
//#include <dfsfsctl.h>
|
|||
|
//#include <windows.h>
|
|||
|
|
|||
|
#include <headers.hxx>
|
|||
|
#pragma hdrstop
|
|||
|
|
|||
|
#include <dfserr.h>
|
|||
|
#include "cdfsvol.hxx"
|
|||
|
#include "dfsmwml.h"
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
DfspCreateExitPoint (
|
|||
|
IN HANDLE DriverHandle,
|
|||
|
IN LPGUID Uid,
|
|||
|
IN LPWSTR Prefix,
|
|||
|
IN ULONG Type,
|
|||
|
IN ULONG ShortPrefixLen,
|
|||
|
OUT LPWSTR ShortPrefix);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
DfspDeleteExitPoint (
|
|||
|
IN HANDLE DriverHandle,
|
|||
|
IN LPGUID Uid,
|
|||
|
IN LPWSTR Prefix,
|
|||
|
IN ULONG Type);
|
|||
|
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Member: CDfsVolume::CreateObject, public
|
|||
|
//
|
|||
|
// Synopsis: This method merely creates a volume object. This has no
|
|||
|
// distributed operations associated with this operation.
|
|||
|
//
|
|||
|
// Arguments: [pwzVolObjName] -- VOlume object Name
|
|||
|
// [EntryPath] -- The EntryPath
|
|||
|
// [VolType] -- VolumeType
|
|||
|
// [pReplicaInfo] -- ReplicaInfo. This is optional.
|
|||
|
//
|
|||
|
// Returns:
|
|||
|
//
|
|||
|
// Notes: Raid: 455299 This function could potentially fail and leave an
|
|||
|
// object hanging around??
|
|||
|
//
|
|||
|
// History: 17-May-1993 SudK Created.
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
DWORD
|
|||
|
CDfsVolume::CreateObject(
|
|||
|
PWSTR pwszVolObjName,
|
|||
|
LPWSTR pwszPrefix,
|
|||
|
ULONG ulVolType,
|
|||
|
PDFS_REPLICA_INFO pReplicaInfo,
|
|||
|
PWCHAR pwszComment,
|
|||
|
GUID *pUid
|
|||
|
)
|
|||
|
{
|
|||
|
DWORD dwErr = ERROR_SUCCESS;
|
|||
|
CDfsService *pService;
|
|||
|
SYSTEMTIME st;
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::CreateVolObject(%ws,%ws,0x%x,%ws)\n",
|
|||
|
pwszVolObjName, pwszPrefix, ulVolType, pwszComment));
|
|||
|
|
|||
|
//
|
|||
|
// First put this name in the private section.
|
|||
|
//
|
|||
|
ULONG volLen = wcslen(pwszVolObjName);
|
|||
|
if (volLen > MAX_PATH) {
|
|||
|
_pwzFileName = new WCHAR[volLen + 1];
|
|||
|
} else {
|
|||
|
_pwzFileName = _FileNameBuffer;
|
|||
|
}
|
|||
|
|
|||
|
if (_pwzFileName == NULL)
|
|||
|
return( ERROR_OUTOFMEMORY );
|
|||
|
|
|||
|
wcscpy(_pwzFileName, pwszVolObjName);
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "Creating Object%ws\n", pwszVolObjName));
|
|||
|
|
|||
|
//
|
|||
|
// Create the storage object.
|
|||
|
//
|
|||
|
dwErr = DfsmCreateStorage(
|
|||
|
pwszVolObjName,
|
|||
|
&_pStorage);
|
|||
|
|
|||
|
if (dwErr != ERROR_SUCCESS) {
|
|||
|
IDfsVolInlineDebOut((DEB_ERROR,
|
|||
|
"Unable to create directory storage object %08lx %ws\n",
|
|||
|
dwErr, pwszVolObjName));
|
|||
|
return(dwErr);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// First thing we do now is to setup the Class.
|
|||
|
//
|
|||
|
dwErr = _pStorage->SetClass(CLSID_CDfsVolume);
|
|||
|
|
|||
|
if (dwErr != ERROR_SUCCESS) {
|
|||
|
IDfsVolInlineDebOut((DEB_ERROR,
|
|||
|
"Unable to set Class on this %ws\n", pwszVolObjName));
|
|||
|
return(dwErr);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// This is where we need to init and create the dummy property sets
|
|||
|
// so that next time around we can set them and dont need to create them.
|
|||
|
//
|
|||
|
|
|||
|
dwErr = SetVersion( TRUE );
|
|||
|
|
|||
|
if (dwErr != ERROR_SUCCESS) {
|
|||
|
IDfsVolInlineDebOut((DEB_ERROR,
|
|||
|
"Unable to create version propset for %ws Error: %08lx\n",
|
|||
|
pwszVolObjName, dwErr));
|
|||
|
return(dwErr);
|
|||
|
}
|
|||
|
|
|||
|
GUID Uid;
|
|||
|
|
|||
|
if (pUid == NULL) {
|
|||
|
dwErr = UuidCreate(&Uid);
|
|||
|
_peid.Uid = Uid;
|
|||
|
} else {
|
|||
|
_peid.Uid = *pUid;
|
|||
|
}
|
|||
|
|
|||
|
_EntryType = ulVolType;
|
|||
|
|
|||
|
ULONG epLen = wcslen(pwszPrefix);
|
|||
|
if (epLen > MAX_PATH) {
|
|||
|
_peid.Prefix.Buffer = new WCHAR[epLen + 1];
|
|||
|
_peid.Prefix.MaximumLength = (USHORT) ((epLen + 1)*sizeof(WCHAR));
|
|||
|
} else {
|
|||
|
_peid.Prefix.MaximumLength = sizeof(_EntryPathBuffer);
|
|||
|
_peid.Prefix.Buffer = _EntryPathBuffer;
|
|||
|
}
|
|||
|
|
|||
|
if (_peid.Prefix.Buffer == NULL)
|
|||
|
return( ERROR_OUTOFMEMORY );
|
|||
|
|
|||
|
_peid.Prefix.Length = (USHORT) epLen*sizeof(WCHAR);
|
|||
|
wcscpy(_peid.Prefix.Buffer, pwszPrefix);
|
|||
|
|
|||
|
//
|
|||
|
// We don't yet know the short name of this volume, so simply allocate
|
|||
|
// enough room and fill it with the full prefix. When an exit point
|
|||
|
// corresponding to this volume is created, the short prefix might be
|
|||
|
// modified.
|
|||
|
//
|
|||
|
// Note that it is tempting to think that the short prefix is <= the full
|
|||
|
// prefix in size. This, however, is not a valid assumption, because
|
|||
|
// names like A.BCDE qualify as LFNs, and their 8.3 equivalents look like
|
|||
|
// A12345~1.BCD!
|
|||
|
//
|
|||
|
|
|||
|
ULONG i, sepLen;
|
|||
|
|
|||
|
for (i = 0, sepLen = 0; i < epLen; i++) {
|
|||
|
if (pwszPrefix[i] == UNICODE_PATH_SEP)
|
|||
|
sepLen ++;
|
|||
|
}
|
|||
|
|
|||
|
sepLen *= (1+8+1+3); // For \8.3
|
|||
|
|
|||
|
if (sepLen < epLen)
|
|||
|
sepLen = epLen;
|
|||
|
|
|||
|
if (sepLen > MAX_PATH) {
|
|||
|
_peid.ShortPrefix.Buffer = new WCHAR[sepLen + 1];
|
|||
|
_peid.ShortPrefix.MaximumLength = (USHORT) ((sepLen + 1)*sizeof(WCHAR));
|
|||
|
} else {
|
|||
|
_peid.ShortPrefix.Buffer = _ShortPathBuffer;
|
|||
|
_peid.ShortPrefix.MaximumLength = sizeof(_ShortPathBuffer);
|
|||
|
}
|
|||
|
|
|||
|
if (_peid.ShortPrefix.Buffer == NULL)
|
|||
|
return( ERROR_OUTOFMEMORY );
|
|||
|
|
|||
|
_peid.ShortPrefix.Length = (USHORT) epLen*sizeof(WCHAR);
|
|||
|
wcscpy(_peid.ShortPrefix.Buffer, pwszPrefix);
|
|||
|
|
|||
|
//
|
|||
|
// We need to deal with a NULL comment as well.
|
|||
|
//
|
|||
|
if (pwszComment != NULL) {
|
|||
|
_pwszComment = new WCHAR[wcslen(pwszComment) + 1];
|
|||
|
if (_pwszComment != NULL) {
|
|||
|
wcscpy(_pwszComment, pwszComment);
|
|||
|
}
|
|||
|
} else {
|
|||
|
_pwszComment = new WCHAR[1];
|
|||
|
if (_pwszComment != NULL) {
|
|||
|
*_pwszComment = UNICODE_NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
if (_pwszComment == NULL) {
|
|||
|
return( ERROR_OUTOFMEMORY );
|
|||
|
}
|
|||
|
|
|||
|
GetSystemTime( &st );
|
|||
|
SystemTimeToFileTime( &st, &_ftEntryPath );
|
|||
|
_ftComment = _ftState = _ftEntryPath;
|
|||
|
|
|||
|
dwErr = SetIdProps(
|
|||
|
ulVolType,
|
|||
|
_State,
|
|||
|
pwszPrefix,
|
|||
|
pwszPrefix,
|
|||
|
_peid.Uid,
|
|||
|
_pwszComment,
|
|||
|
_Timeout,
|
|||
|
_ftEntryPath,
|
|||
|
_ftState,
|
|||
|
_ftComment,
|
|||
|
TRUE);
|
|||
|
|
|||
|
if (dwErr != ERROR_SUCCESS)
|
|||
|
return(dwErr);
|
|||
|
|
|||
|
_Recover.Initialize(_pStorage);
|
|||
|
_Recover.SetDefaultProps();
|
|||
|
|
|||
|
//
|
|||
|
// Now let us set a NULL service List property. This method will create
|
|||
|
// the stream as well. We dont need to bother.
|
|||
|
//
|
|||
|
dwErr = _DfsSvcList.SetNullSvcList(_pStorage);
|
|||
|
|
|||
|
if (dwErr != ERROR_SUCCESS)
|
|||
|
return(dwErr);
|
|||
|
|
|||
|
_Deleted = FALSE;
|
|||
|
|
|||
|
//
|
|||
|
// Everything is setup now. We can set the appropriate service etc.
|
|||
|
//
|
|||
|
if (pReplicaInfo != NULL) {
|
|||
|
pService = new CDfsService(pReplicaInfo, FALSE, &dwErr);
|
|||
|
if (pService == NULL) {
|
|||
|
dwErr = ERROR_OUTOFMEMORY;
|
|||
|
}
|
|||
|
|
|||
|
if (dwErr == ERROR_SUCCESS) {
|
|||
|
dwErr = _DfsSvcList.SetNewService(pService);
|
|||
|
if (dwErr != ERROR_SUCCESS) {
|
|||
|
delete pService;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::CreateVolObject() exit\n"));
|
|||
|
|
|||
|
return(dwErr);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Member: CDfsVolume::GetDfsVolumeFromStg, private
|
|||
|
//
|
|||
|
// Synopsis: This method takes a STATDIR structure and returns a CDfsVol
|
|||
|
// pointer to the object corresponding to that.
|
|||
|
//
|
|||
|
// Arguments: [rgelt] -- Pointer to the DFSMSTATDIR structure.
|
|||
|
// [ppDfsVol] -- This is where the DfsVol is returned.
|
|||
|
//
|
|||
|
// Returns: [ERROR_SUCCESS] -- If successfully set the parent's path.
|
|||
|
//
|
|||
|
// [ERROR_OUTOFMEMORY] -- If unable to allocate memory for parent's
|
|||
|
// path.
|
|||
|
//
|
|||
|
// Error from loading the volume object
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
DWORD
|
|||
|
CDfsVolume::GetDfsVolumeFromStg(
|
|||
|
DFSMSTATDIR *rgelt,
|
|||
|
CDfsVolume **ppDfsVol)
|
|||
|
{
|
|||
|
DWORD dwErr = ERROR_SUCCESS;
|
|||
|
PWCHAR pwszFullName;
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::GetDfsVolumeFromStg()\n"));
|
|||
|
|
|||
|
//
|
|||
|
// Allocate a new CDfsVolume and initialize with appropriate name.
|
|||
|
//
|
|||
|
*ppDfsVol = new CDfsVolume();
|
|||
|
if (*ppDfsVol == NULL)
|
|||
|
return( ERROR_OUTOFMEMORY );
|
|||
|
|
|||
|
pwszFullName = new WCHAR[wcslen(_pwzFileName) + wcslen(rgelt->pwcsName) + 2];
|
|||
|
|
|||
|
if (pwszFullName != NULL) {
|
|||
|
|
|||
|
wcscpy(pwszFullName, _pwzFileName);
|
|||
|
wcscat(pwszFullName, L"\\");
|
|||
|
wcscat(pwszFullName, rgelt->pwcsName);
|
|||
|
|
|||
|
dwErr = (*ppDfsVol)->LoadNoRegister(pwszFullName, 0);
|
|||
|
|
|||
|
delete [] pwszFullName;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
dwErr = ERROR_OUTOFMEMORY;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (dwErr != ERROR_SUCCESS) {
|
|||
|
(*ppDfsVol)->Release();
|
|||
|
*ppDfsVol = NULL;
|
|||
|
}
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::GetDfsVolumeFromStg() exit\n"));
|
|||
|
|
|||
|
return(dwErr);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Member: CDfsVolume::SetParentPath, private
|
|||
|
//
|
|||
|
// Synopsis: This method figures out the name of the parent object and
|
|||
|
// sets it up in the private section of this instance.
|
|||
|
//
|
|||
|
// Arguments: None
|
|||
|
//
|
|||
|
// Returns: [ERROR_SUCCESS] -- If successfully set the parent's path.
|
|||
|
//
|
|||
|
// [ERROR_OUTOFMEMORY] -- If unable to allocate memory for parent's
|
|||
|
// path.
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
DWORD
|
|||
|
CDfsVolume::SetParentPath(void)
|
|||
|
{
|
|||
|
|
|||
|
PWCHAR pwszLastComponent;
|
|||
|
ULONG parentLen;
|
|||
|
|
|||
|
pwszLastComponent = wcsrchr(_pwzFileName, L'\\');
|
|||
|
|
|||
|
if(pwszLastComponent == NULL) {
|
|||
|
return ERROR_INVALID_DATA;
|
|||
|
}
|
|||
|
|
|||
|
ASSERT(*(pwszLastComponent + 1) != UNICODE_NULL);
|
|||
|
|
|||
|
//
|
|||
|
// Let us now figure out the length of the parent Name and copy over
|
|||
|
// appropriate number of characters.
|
|||
|
//
|
|||
|
|
|||
|
if (_pwszParentName != _ParentNameBuffer)
|
|||
|
delete [] _pwszParentName;
|
|||
|
|
|||
|
parentLen = wcslen(_pwzFileName) - wcslen(pwszLastComponent);
|
|||
|
|
|||
|
if (parentLen > MAX_PATH) {
|
|||
|
|
|||
|
_pwszParentName = new WCHAR[parentLen + 1];
|
|||
|
|
|||
|
if (_pwszParentName == NULL)
|
|||
|
return( ERROR_OUTOFMEMORY );
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
_pwszParentName = _ParentNameBuffer;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
wcsncpy(_pwszParentName, _pwzFileName, parentLen);
|
|||
|
|
|||
|
_pwszParentName[parentLen] = UNICODE_NULL;
|
|||
|
|
|||
|
return(ERROR_SUCCESS);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Member: CDfsVolume::GetParent, private
|
|||
|
//
|
|||
|
// Synopsis: This function returns a pointer to IDfsVolume to the parent
|
|||
|
// of the present object. The release function on this
|
|||
|
// should be called by the caller of this function. We use
|
|||
|
// Ths IStorage interface to get to the parent.
|
|||
|
//
|
|||
|
// Arguments: [pIDfsParent] -- This is where the IDfsVolume for parent is
|
|||
|
// returned.
|
|||
|
//
|
|||
|
// Returns: [ERROR_SUCCESS] -- If everything went well.
|
|||
|
//
|
|||
|
// [ERROR_OUTOFMEMORY] -- Unable to create parent instance.
|
|||
|
//
|
|||
|
// History: 14-Sep-92 SudK Created
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
DWORD
|
|||
|
CDfsVolume::GetParent(
|
|||
|
CDfsVolume **parent)
|
|||
|
{
|
|||
|
DWORD dwErr = ERROR_SUCCESS;
|
|||
|
CDfsVolume *pDfsVol;
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::GetParent()\n"));
|
|||
|
|
|||
|
//
|
|||
|
// First we get the parent's pathname and then we can do the appropriate.
|
|||
|
//
|
|||
|
|
|||
|
dwErr = SetParentPath();
|
|||
|
|
|||
|
if (dwErr != ERROR_SUCCESS) {
|
|||
|
IDfsVolInlineDebOut((
|
|||
|
DEB_ERROR, "Unable to get parentPath %ws %08lx\n",
|
|||
|
_pwzFileName, dwErr));
|
|||
|
return(dwErr);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Now we instantiate a CDfsVolume structure and then initialise it.
|
|||
|
//
|
|||
|
|
|||
|
pDfsVol = new CDfsVolume();
|
|||
|
|
|||
|
if (pDfsVol == NULL)
|
|||
|
return( ERROR_OUTOFMEMORY );
|
|||
|
|
|||
|
dwErr = pDfsVol->LoadNoRegister(_pwszParentName, 0);
|
|||
|
|
|||
|
if (dwErr != ERROR_SUCCESS) {
|
|||
|
|
|||
|
pDfsVol->Release();
|
|||
|
|
|||
|
*parent = NULL;
|
|||
|
|
|||
|
return(dwErr);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
*parent = pDfsVol;
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::GetParent() exit\n"));
|
|||
|
|
|||
|
return(dwErr);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Method: CDfsVolume::DeleteObject, private
|
|||
|
//
|
|||
|
// Synopsis: Support method to merely delete a volume object from
|
|||
|
// persistent store.
|
|||
|
//
|
|||
|
// Arguments: None
|
|||
|
//
|
|||
|
// Returns: [ERROR_SUCCESS] -- If successfully deleted object.
|
|||
|
//
|
|||
|
// [ERROR_OUTOFMEMORY] -- Unable to get parent instance.
|
|||
|
//
|
|||
|
// History: 16-Sep-1992 SudK Created
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
DWORD
|
|||
|
CDfsVolume::DeleteObject()
|
|||
|
{
|
|||
|
DWORD dwErr = ERROR_SUCCESS;
|
|||
|
CStorage *parentStg;
|
|||
|
PWCHAR pwszLastComponent;
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::DeleteObject()\n"));
|
|||
|
|
|||
|
//
|
|||
|
// We are going to delete this object so let us release all our pointers.
|
|||
|
//
|
|||
|
|
|||
|
ASSERT ((_pStorage != NULL));
|
|||
|
|
|||
|
_pStorage->Release();
|
|||
|
|
|||
|
_pStorage = NULL;
|
|||
|
|
|||
|
//
|
|||
|
// Let us now release all the IStorage's which are with CRecover & SvcList
|
|||
|
//
|
|||
|
if (_Recover._pPSStg != NULL) {
|
|||
|
|
|||
|
_Recover._pPSStg->Release();
|
|||
|
|
|||
|
_Recover._pPSStg = NULL;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (_DfsSvcList._pPSStg != NULL) {
|
|||
|
|
|||
|
_DfsSvcList._pPSStg->Release();
|
|||
|
|
|||
|
_DfsSvcList._pPSStg = NULL;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// First we get the parent's pathname and then we can do the appropriate.
|
|||
|
//
|
|||
|
|
|||
|
dwErr = SetParentPath();
|
|||
|
|
|||
|
if (dwErr != ERROR_SUCCESS) {
|
|||
|
|
|||
|
IDfsVolInlineDebOut((
|
|||
|
DEB_ERROR, "Failed to get parent path for %ws\n", _pwzFileName));
|
|||
|
|
|||
|
return( dwErr );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
dwErr = DfsmOpenStorage( _pwszParentName, &parentStg);
|
|||
|
|
|||
|
if (dwErr != ERROR_SUCCESS) {
|
|||
|
|
|||
|
IDfsVolInlineDebOut((
|
|||
|
DEB_ERROR, "Unable to open [%ws] %08lx\n", _pwszParentName, dwErr));
|
|||
|
|
|||
|
return( dwErr );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Now we have to delete ourselves using our parent's IStorage.
|
|||
|
// So we extract the last component name from the file name.
|
|||
|
//
|
|||
|
|
|||
|
pwszLastComponent = _pwzFileName + wcslen(_pwszParentName) + 1;
|
|||
|
|
|||
|
dwErr = parentStg->DestroyElement(pwszLastComponent);
|
|||
|
|
|||
|
parentStg->Release();
|
|||
|
|
|||
|
if (dwErr != ERROR_SUCCESS) {
|
|||
|
|
|||
|
IDfsVolInlineDebOut((
|
|||
|
DEB_ERROR, "Unable to delete [%ws] %08lx\n", _pwzFileName, dwErr));
|
|||
|
|
|||
|
return( dwErr );
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// The storage object has really been deleted, so delete the mapping
|
|||
|
// of this prefix from the storage directory.
|
|||
|
//
|
|||
|
|
|||
|
dwErr = pDfsmStorageDirectory->_Delete( _peid.Prefix.Buffer );
|
|||
|
|
|||
|
ASSERT( dwErr == ERROR_SUCCESS );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
_Deleted = TRUE;
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::DeleteObject() exit\n"));
|
|||
|
|
|||
|
return( ERROR_SUCCESS );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: CDfsVolume::GetVersion, private
|
|||
|
//
|
|||
|
// Synopsis: Retrieves the version of the volume object from the property
|
|||
|
// stamped on it.
|
|||
|
//
|
|||
|
// Arguments: [pVersion] -- The version is returned here.
|
|||
|
//
|
|||
|
// Returns: Result of reading the version property.
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
DWORD
|
|||
|
CDfsVolume::GetVersion(
|
|||
|
ULONG * pVersion)
|
|||
|
{
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::GetVersion()\n"));
|
|||
|
|
|||
|
DWORD dwErr = ERROR_SUCCESS;
|
|||
|
|
|||
|
dwErr = _pStorage->GetVersionProps(pVersion);
|
|||
|
|
|||
|
if (dwErr != ERROR_SUCCESS) {
|
|||
|
IDfsVolInlineDebOut((DEB_ERROR,
|
|||
|
"Unable to read Version Properties %08lx\n",
|
|||
|
dwErr));
|
|||
|
return(dwErr);
|
|||
|
}
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::GetVersion() exit\n"));
|
|||
|
|
|||
|
return( dwErr );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: SetVersion
|
|||
|
//
|
|||
|
// Synopsis: Sets the version property on the volume object to
|
|||
|
// VOL_OBJ_VERSION_NUMBER
|
|||
|
//
|
|||
|
// Arguments: [bCreate] -- TRUE if the property set should be created,
|
|||
|
// FALSE if the property set should be assumed to
|
|||
|
// exist
|
|||
|
//
|
|||
|
// Returns: Result of setting the property
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
DWORD
|
|||
|
CDfsVolume::SetVersion(
|
|||
|
BOOL bCreate)
|
|||
|
{
|
|||
|
DWORD dwErr;
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::SetVersion()\n"));
|
|||
|
|
|||
|
dwErr = _pStorage->SetVersionProps( VOL_OBJ_VERSION_NUMBER );
|
|||
|
if (dwErr != ERROR_SUCCESS) {
|
|||
|
IDfsVolInlineDebOut(( DEB_ERROR,
|
|||
|
"Unable to set Version Properties %08lx\n",
|
|||
|
dwErr));
|
|||
|
return(dwErr);
|
|||
|
}
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::SetVersion() exit\n"));
|
|||
|
|
|||
|
return( dwErr );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Method: CDfsVolume::GetIdProps, private
|
|||
|
//
|
|||
|
// Synopsis: Gets the ID Properties from a volume object.
|
|||
|
// Memory for the string values is allocated using new. The
|
|||
|
// caller is responsible for freeing it.
|
|||
|
//
|
|||
|
// Arguments: [pdwType] -- The Volume Type property is returned here.
|
|||
|
// [ppwszEntryPath] -- EntryPath is returned here.
|
|||
|
// [ppwszShortPath] -- The 8.3 form of EntryPath is returned here
|
|||
|
// [ppwszComment] -- Comment is returned here.
|
|||
|
// [pGuid] -- The Guid (VolumeID) is returned here.
|
|||
|
// [pdwVolumeState] -- The volume state is returned here.
|
|||
|
// [pftPathTime] -- Time that EntryPath was last modified.
|
|||
|
// [pftStateTime] -- Time that Volume State was last modified.
|
|||
|
// [pftCommentTime] -- Time that Comment was last modified.
|
|||
|
//
|
|||
|
// Returns:
|
|||
|
//
|
|||
|
// History: 16-Sep-1992 SudK Imported from PART.CXX
|
|||
|
// 01-Jan-1996 Milans Ported to NT/SUR
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
DWORD
|
|||
|
CDfsVolume::GetIdProps(
|
|||
|
ULONG *pdwType,
|
|||
|
PWCHAR *ppwszEntryPath,
|
|||
|
PWCHAR *ppwszShortPath,
|
|||
|
PWCHAR *ppwszComment,
|
|||
|
GUID *pGuid,
|
|||
|
ULONG *pdwVolumeState,
|
|||
|
ULONG *pdwTimeout,
|
|||
|
FILETIME *pftPathTime,
|
|||
|
FILETIME *pftStateTime,
|
|||
|
FILETIME *pftCommentTime
|
|||
|
)
|
|||
|
{
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::GetIdProps()\n"));
|
|||
|
|
|||
|
DWORD dwErr = ERROR_SUCCESS;
|
|||
|
|
|||
|
dwErr = _pStorage->GetIdProps(
|
|||
|
pdwType,
|
|||
|
pdwVolumeState,
|
|||
|
ppwszEntryPath,
|
|||
|
ppwszShortPath,
|
|||
|
pGuid,
|
|||
|
ppwszComment,
|
|||
|
pdwTimeout,
|
|||
|
pftPathTime,
|
|||
|
pftStateTime,
|
|||
|
pftCommentTime);
|
|||
|
|
|||
|
if (dwErr != ERROR_SUCCESS) {
|
|||
|
IDfsVolInlineDebOut((
|
|||
|
DEB_ERROR, "Unable to read Id Props %08lx\n", dwErr));
|
|||
|
}
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::GetIdProps() exit\n"));
|
|||
|
|
|||
|
return( dwErr );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Method: CDfsVolume::SetIdProps, private
|
|||
|
//
|
|||
|
// Synopsis: Exact opposite of GetIdProps function. A wrapper around the
|
|||
|
// property interface to set the appropriate properties that
|
|||
|
// identify a volume.
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
//
|
|||
|
// Returns:
|
|||
|
//
|
|||
|
// History: 16-Sep-1992 SudK Imported from PART.CXX
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
DWORD
|
|||
|
CDfsVolume::SetIdProps(
|
|||
|
ULONG Type,
|
|||
|
ULONG State,
|
|||
|
PWCHAR pwszPrefix,
|
|||
|
PWCHAR pwszShortPath,
|
|||
|
GUID & Guid,
|
|||
|
PWSTR pwszComment,
|
|||
|
ULONG Timeout,
|
|||
|
FILETIME ftPrefix,
|
|||
|
FILETIME ftState,
|
|||
|
FILETIME ftComment,
|
|||
|
BOOLEAN bCreate
|
|||
|
)
|
|||
|
{
|
|||
|
DWORD dwErr;
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::SetIdProps()\n"));
|
|||
|
|
|||
|
dwErr = _pStorage->SetIdProps(
|
|||
|
Type,
|
|||
|
State,
|
|||
|
pwszPrefix,
|
|||
|
pwszShortPath,
|
|||
|
Guid,
|
|||
|
pwszComment,
|
|||
|
Timeout,
|
|||
|
ftPrefix,
|
|||
|
ftState,
|
|||
|
ftComment);
|
|||
|
|
|||
|
if (dwErr != ERROR_SUCCESS) {
|
|||
|
IDfsVolInlineDebOut(( DEB_ERROR,
|
|||
|
"Unable to Set IDProperties %08lx\n",
|
|||
|
dwErr));
|
|||
|
return(dwErr);
|
|||
|
}
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::SetIdProps() exit\n"));
|
|||
|
|
|||
|
return( dwErr );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: CDfsVolume::SaveShortName
|
|||
|
//
|
|||
|
// Synopsis: Updates the short name for the volume entry path and saves it
|
|||
|
// to the registry.
|
|||
|
//
|
|||
|
// Arguments: None - the short name is picked up from the _peid private
|
|||
|
// member.
|
|||
|
//
|
|||
|
// Returns:
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
DWORD
|
|||
|
CDfsVolume::SaveShortName()
|
|||
|
{
|
|||
|
DWORD dwErr;
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::SetShortName()\n"));
|
|||
|
|
|||
|
dwErr = SetIdProps(
|
|||
|
_EntryType,
|
|||
|
_State,
|
|||
|
_peid.Prefix.Buffer,
|
|||
|
_peid.ShortPrefix.Buffer,
|
|||
|
_peid.Uid,
|
|||
|
_pwszComment,
|
|||
|
_Timeout,
|
|||
|
_ftEntryPath,
|
|||
|
_ftState,
|
|||
|
_ftComment,
|
|||
|
FALSE);
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::SetShortName() exit\n"));
|
|||
|
|
|||
|
return( dwErr );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Method: CDfsVolume::DeletePktEntry, private
|
|||
|
//
|
|||
|
// Synopsis: This method deletes an entry from the PKT. Given an ID to
|
|||
|
// identify the entry this method deletes the entry.
|
|||
|
//
|
|||
|
// Arguments: victim - The entryID that identifies the PKT entry to go.
|
|||
|
//
|
|||
|
// Returns:
|
|||
|
//
|
|||
|
// History: 24-Nov-1992 SudK Created.
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
DWORD
|
|||
|
CDfsVolume :: DeletePktEntry(
|
|||
|
PDFS_PKT_ENTRY_ID victim
|
|||
|
)
|
|||
|
{
|
|||
|
DWORD dwErr = ERROR_SUCCESS;
|
|||
|
NTSTATUS status = STATUS_SUCCESS;
|
|||
|
HANDLE pktHandle = NULL;
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "IDfsVol::DeletePktEntry()\n"));
|
|||
|
|
|||
|
//
|
|||
|
// Open the local PKT...
|
|||
|
//
|
|||
|
|
|||
|
status = PktOpen(&pktHandle, 0, 0, NULL);
|
|||
|
|
|||
|
if(NT_SUCCESS(status)) {
|
|||
|
status = PktDestroyEntry(
|
|||
|
pktHandle,
|
|||
|
*victim
|
|||
|
);
|
|||
|
|
|||
|
PktClose(pktHandle);
|
|||
|
|
|||
|
if (status == DFS_STATUS_NO_SUCH_ENTRY) {
|
|||
|
|
|||
|
dwErr = ERROR_SUCCESS;
|
|||
|
|
|||
|
} else if (!NT_SUCCESS(status)) {
|
|||
|
|
|||
|
dwErr = RtlNtStatusToDosError(status);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
dwErr = RtlNtStatusToDosError(status);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "IDfsVol::DeletePktEntry() exit\n"));
|
|||
|
|
|||
|
return( dwErr );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Method: CDfsVolume::CreateSubordinatePktEntry, private
|
|||
|
//
|
|||
|
// Synopsis: This method is basically an interface into the driver to be
|
|||
|
// able to manipulate the PKT. This creates an entry for the
|
|||
|
// current volume object and at the same time links it with its
|
|||
|
// superior volume object's PKT entry. This method makes one
|
|||
|
// assumption that no services are associated with the service.
|
|||
|
// It adds a NULL serviceList infact if the Boolean bWithService
|
|||
|
// is FALSE else it puts in the servicelist also.
|
|||
|
//
|
|||
|
// Arguments: [pSuperior] -- The Superior's EntryID info is passed here to
|
|||
|
// identify the superior in the PKT.
|
|||
|
// [bWithService] -- Whether to include the serviceinfo in EINFO.
|
|||
|
//
|
|||
|
// Returns:
|
|||
|
//
|
|||
|
// History: 22-Nov-1992 SudK Created
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
DWORD
|
|||
|
CDfsVolume::CreateSubordinatePktEntry(
|
|||
|
HANDLE pktHandle,
|
|||
|
PDFS_PKT_ENTRY_ID pSuperior,
|
|||
|
BOOLEAN bWithService)
|
|||
|
{
|
|||
|
ULONG etype = 0;
|
|||
|
DFS_PKT_ENTRY_INFO einfo;
|
|||
|
DWORD dwErr = ERROR_SUCCESS;
|
|||
|
NTSTATUS status = STATUS_SUCCESS;
|
|||
|
CDfsService *pDfsSvc = NULL;
|
|||
|
DFS_SERVICE *pService;
|
|||
|
ULONG count = 0;
|
|||
|
UNICODE_STRING ustrShortName;
|
|||
|
WCHAR ShortPrefix[MAX_PATH+1];
|
|||
|
BOOLEAN CloseHandle = FALSE;
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "IDfsVol::CreateSubordinatePktEntry()\n"));
|
|||
|
|
|||
|
//
|
|||
|
// We setup the servicelist based on the CreateDisposition.
|
|||
|
//
|
|||
|
if (!bWithService) {
|
|||
|
memset(&einfo, 0, sizeof(DFS_PKT_ENTRY_INFO));
|
|||
|
einfo.ServiceList = NULL;
|
|||
|
einfo.Timeout = _Timeout;
|
|||
|
} else {
|
|||
|
einfo.Timeout = _Timeout;
|
|||
|
count = _DfsSvcList.GetServiceCount();
|
|||
|
einfo.ServiceCount = count;
|
|||
|
einfo.ServiceList = new DFS_SERVICE[count];
|
|||
|
//447491, dont use null pointer.
|
|||
|
if (einfo.ServiceList == NULL) {
|
|||
|
dwErr = ERROR_OUTOFMEMORY;
|
|||
|
return dwErr;
|
|||
|
}
|
|||
|
memset(einfo.ServiceList, 0, sizeof(DFS_SERVICE)*count);
|
|||
|
|
|||
|
pDfsSvc = _DfsSvcList.GetFirstService();
|
|||
|
pService = einfo.ServiceList;
|
|||
|
for (ULONG i=0; i<count; i++) {
|
|||
|
*pService = *(pDfsSvc->GetDfsService());
|
|||
|
pService++;
|
|||
|
pDfsmSites->LookupSiteInfo((pDfsSvc->GetReplicaInfo())->pwszServerName);
|
|||
|
pDfsSvc = _DfsSvcList.GetNextService(pDfsSvc);
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Note: We depend upon the correspondence of certain bits between the DFS
|
|||
|
// volume types and PKT entry types here.
|
|||
|
//
|
|||
|
#if (DFS_VOL_TYPE_ALL & (PKT_ENTRY_TYPE_LOCAL|PKT_ENTRY_TYPE_PERMANENT|PKT_ENTRY_TYPE_INUSE|PKT_ENTRY_TYPE_REFERRAL_SVC|PKT_ENTRY_TYPE_LOCAL_XPOINT))
|
|||
|
#error (DFS_VOL_TYPE_ALL & (PKT_ENTRY_TYPE_LOCAL|PKT_ENTRY_TYPE_PERMANENT|PKT_ENTRY_TYPE_INUSE|PKT_ENTRY_TYPE_REFERRAL_SVC|PKT_ENTRY_TYPE_LOCAL_XPOINT))
|
|||
|
#endif
|
|||
|
|
|||
|
etype = _EntryType | PKT_ENTRY_TYPE_PERMANENT;
|
|||
|
|
|||
|
//
|
|||
|
// If the handle supplied is NULL, open the local pkt
|
|||
|
//
|
|||
|
|
|||
|
if (pktHandle == NULL) {
|
|||
|
|
|||
|
status = PktOpen(&pktHandle, 0, 0, NULL);
|
|||
|
|
|||
|
if (NT_SUCCESS(status))
|
|||
|
CloseHandle = TRUE;
|
|||
|
}
|
|||
|
|
|||
|
if(NT_SUCCESS(status)) {
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose & 0x80000000) {
|
|||
|
WCHAR wszGuid[sizeof(GUID)*2+1];
|
|||
|
|
|||
|
GuidToString(&_peid.Uid, wszGuid);
|
|||
|
DbgPrint("CDfsVolume::CreateSubordinatePktEntry:\n"
|
|||
|
"\tSupName=%ws\n"
|
|||
|
"\tPrefix=%ws\n"
|
|||
|
"\tShortPrefix=%ws\n"
|
|||
|
"\tType=0x%x\n"
|
|||
|
"\tCount=%d\n"
|
|||
|
"\tGUID=%ws\n",
|
|||
|
pSuperior->Prefix.Buffer,
|
|||
|
_peid.Prefix.Buffer,
|
|||
|
_peid.ShortPrefix.Buffer,
|
|||
|
_EntryType,
|
|||
|
einfo.ServiceCount,
|
|||
|
wszGuid);
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
DfspCreateExitPoint(
|
|||
|
pktHandle,
|
|||
|
&_peid.Uid,
|
|||
|
_peid.Prefix.Buffer,
|
|||
|
_EntryType,
|
|||
|
sizeof(ShortPrefix),
|
|||
|
ShortPrefix);
|
|||
|
|
|||
|
status = PktCreateSubordinateEntry(
|
|||
|
pktHandle,
|
|||
|
pSuperior,
|
|||
|
etype,
|
|||
|
&_peid,
|
|||
|
&einfo,
|
|||
|
PKT_ENTRY_SUPERSEDE);
|
|||
|
|
|||
|
//
|
|||
|
// If we opened the handle, close it
|
|||
|
//
|
|||
|
|
|||
|
if (CloseHandle == TRUE) {
|
|||
|
PktClose(pktHandle);
|
|||
|
pktHandle = NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (!NT_SUCCESS(status)) {
|
|||
|
dwErr = RtlNtStatusToDosError(status);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Now before we leave we may have to delete the service list if we
|
|||
|
// allocated it.
|
|||
|
//
|
|||
|
delete [] einfo.ServiceList;
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "IDfsVol::CreateSubordinatePktEntry() exit\n"));
|
|||
|
|
|||
|
return( dwErr );
|
|||
|
}
|
|||
|
|
|||
|
//+------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Method: CDfsVolume::UpdatePktEntry, public
|
|||
|
//
|
|||
|
// Synopsis: This method updates the PKT with all the info regarding this
|
|||
|
// volume. It however, does not bother about any kind of
|
|||
|
// Relational Info at all.
|
|||
|
//
|
|||
|
// Arguments: None
|
|||
|
//
|
|||
|
// Returns: ERROR_SUCCESS -- If all went well.
|
|||
|
//
|
|||
|
// Notes:
|
|||
|
//
|
|||
|
// History: 03-Feb-93 SudK Created.
|
|||
|
//
|
|||
|
//-------------------------------------------------------------------------
|
|||
|
DWORD
|
|||
|
CDfsVolume::UpdatePktEntry(
|
|||
|
HANDLE pktHandle)
|
|||
|
{
|
|||
|
DFS_PKT_ENTRY_INFO einfo;
|
|||
|
PDFS_SERVICE pService;
|
|||
|
CDfsService *pDfsSvc;
|
|||
|
DWORD dwErr = ERROR_SUCCESS;
|
|||
|
NTSTATUS status = STATUS_SUCCESS;
|
|||
|
ULONG EntryType, count;
|
|||
|
UNICODE_STRING ustrShortName;
|
|||
|
BOOLEAN CloseHandle = FALSE;
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::UpdatePktEntry()\n"));
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("CDfsVolume::UpdatePktEntry()\n");
|
|||
|
#endif
|
|||
|
|
|||
|
memset(&einfo, 0, sizeof(DFS_PKT_ENTRY_INFO));
|
|||
|
EntryType = _EntryType | PKT_ENTRY_TYPE_PERMANENT;
|
|||
|
|
|||
|
//
|
|||
|
// Let us collect the service info now. Some memory allocation out here.
|
|||
|
//
|
|||
|
count = _DfsSvcList.GetServiceCount();
|
|||
|
einfo.Timeout = _Timeout;
|
|||
|
einfo.ServiceCount = count;
|
|||
|
einfo.ServiceList = new DFS_SERVICE[count];
|
|||
|
|
|||
|
//447492, dont use null pointer.
|
|||
|
if (einfo.ServiceList == NULL) {
|
|||
|
dwErr = ERROR_OUTOFMEMORY;
|
|||
|
return dwErr;
|
|||
|
}
|
|||
|
|
|||
|
memset(einfo.ServiceList, 0, sizeof(DFS_SERVICE)*count);
|
|||
|
|
|||
|
pService = einfo.ServiceList;
|
|||
|
pDfsSvc = _DfsSvcList.GetFirstService();
|
|||
|
|
|||
|
//
|
|||
|
// In this loop we merely do an assignment of all the services. The
|
|||
|
// conversion operator returns the DFS_SERVICE struct embedded in class.
|
|||
|
//
|
|||
|
for (ULONG i=0;i<count;i++) {
|
|||
|
*pService = *(pDfsSvc->GetDfsService());
|
|||
|
pService++;
|
|||
|
pDfsmSites->LookupSiteInfo((pDfsSvc->GetReplicaInfo())->pwszServerName);
|
|||
|
pDfsSvc = _DfsSvcList.GetNextService(pDfsSvc);
|
|||
|
}
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose) {
|
|||
|
WCHAR wszGuid[sizeof(GUID)*2+1];
|
|||
|
|
|||
|
GuidToString(&_peid.Uid, wszGuid);
|
|||
|
DbgPrint("CDfsVolume::UpdatePktEntry\n"
|
|||
|
"\tPrefix=%ws\n"
|
|||
|
"\tShortPrefix=%ws\n"
|
|||
|
"\tType=0x%x\n"
|
|||
|
"\tCount=%d\n"
|
|||
|
"\tGUID=%ws\n",
|
|||
|
_peid.Prefix.Buffer,
|
|||
|
_peid.ShortPrefix.Buffer,
|
|||
|
_EntryType,
|
|||
|
einfo.ServiceCount,
|
|||
|
wszGuid);
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// If we weren't given a handle, create one
|
|||
|
//
|
|||
|
|
|||
|
if (pktHandle == NULL) {
|
|||
|
status = PktOpen(&pktHandle, 0, 0, NULL);
|
|||
|
if (NT_SUCCESS(status))
|
|||
|
CloseHandle = TRUE;
|
|||
|
}
|
|||
|
|
|||
|
if (NT_SUCCESS(status)) {
|
|||
|
|
|||
|
status = PktCreateEntry(
|
|||
|
pktHandle,
|
|||
|
EntryType,
|
|||
|
&_peid,
|
|||
|
&einfo,
|
|||
|
PKT_ENTRY_SUPERSEDE);
|
|||
|
|
|||
|
if (CloseHandle == TRUE) {
|
|||
|
PktClose(pktHandle);
|
|||
|
pktHandle = NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (!NT_SUCCESS(status)) {
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("PktCreateEntry returned 0x%x\n", status);
|
|||
|
#endif
|
|||
|
dwErr = RtlNtStatusToDosError(status);
|
|||
|
}
|
|||
|
|
|||
|
delete [] einfo.ServiceList;
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::UpdatePktEntry() exit %d\n", dwErr));
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose)
|
|||
|
DbgPrint("CDfsVolume::UpdatePktEntry() exit %d\n", dwErr);
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// Cant blindly return this error. This needs to be processed.
|
|||
|
//
|
|||
|
|
|||
|
return(dwErr);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: GuidToString
|
|||
|
//
|
|||
|
// Synopsis: Converts a GUID to a 32 char wchar null terminated string.
|
|||
|
//
|
|||
|
// Arguments: [pGuid] -- Pointer to Guid structure.
|
|||
|
// [pwszGuid] -- wchar buffer into which to put the string
|
|||
|
// representation of the GUID. Must be atleast
|
|||
|
// 2 * sizeof(GUID) + 1 long.
|
|||
|
//
|
|||
|
// Returns: Nothing
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
const WCHAR rgwchHexDigits[] = L"0123456789ABCDEF";
|
|||
|
|
|||
|
VOID GuidToString(
|
|||
|
IN GUID *pGuid,
|
|||
|
OUT PWSTR pwszGuid)
|
|||
|
{
|
|||
|
PBYTE pbBuffer = (PBYTE) pGuid;
|
|||
|
USHORT i;
|
|||
|
|
|||
|
for(i = 0; i < sizeof(GUID); i++) {
|
|||
|
pwszGuid[2 * i] = rgwchHexDigits[(pbBuffer[i] >> 4) & 0xF];
|
|||
|
pwszGuid[2 * i + 1] = rgwchHexDigits[pbBuffer[i] & 0xF];
|
|||
|
}
|
|||
|
pwszGuid[2 * i] = UNICODE_NULL;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Method: CDfsVolume::CreateChildPartition, private
|
|||
|
//
|
|||
|
// Synopsis: This is somewhat of a wrapper around the IStorage interface.
|
|||
|
// It merely creates a new volume object and associates the
|
|||
|
// properties passed in with the Volume Object. We use the
|
|||
|
// IStorage interface for this purpose.
|
|||
|
// This method generates a GUID and uses that. It also sets
|
|||
|
// a NULL service list and Initial State on the volume object.
|
|||
|
//
|
|||
|
// Arguments: [Name] -- Child Volume Object's name.
|
|||
|
// [Type] -- Type of this volume object.
|
|||
|
// [EntryPath] -- Dfs prefix of child volume.
|
|||
|
// [pwszComment] -- Comment associated with this new volume
|
|||
|
// [pUid] -- Optional guid of child volume
|
|||
|
// [pReplInfo] -- Info regarding the server\share supporting volume
|
|||
|
// [NewIDfsVol] -- On successful return, pointer to new child
|
|||
|
// volume object is returned here.
|
|||
|
//
|
|||
|
// Returns:
|
|||
|
//
|
|||
|
// Notes: This Method creates a GUID and uses it. It also sets a default
|
|||
|
// state on the volume object and associates a NULL serviceList.
|
|||
|
//
|
|||
|
// History: 16-Sep-1992 SudK Imported from PART.CXX
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
DWORD
|
|||
|
CDfsVolume::CreateChildPartition(
|
|||
|
PWCHAR Name,
|
|||
|
ULONG Type,
|
|||
|
PWCHAR EntryPath,
|
|||
|
PWCHAR pwszComment,
|
|||
|
GUID *pUid,
|
|||
|
PDFS_REPLICA_INFO pReplInfo,
|
|||
|
CDfsVolume **NewIDfsVol
|
|||
|
)
|
|||
|
{
|
|||
|
DWORD dwErr = ERROR_SUCCESS;
|
|||
|
CDfsVolume *pDfsVol;
|
|||
|
PWSTR pwszChildName;
|
|||
|
CDfsService *pService;
|
|||
|
WCHAR wszChildElement[sizeof(GUID)*2+1];
|
|||
|
GUID Uid, *pVolId;
|
|||
|
PWCHAR pwszChild;
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::CreateChildPartition(%ws)\n", Name));
|
|||
|
|
|||
|
if (Name == NULL) {
|
|||
|
//
|
|||
|
// Get a guid first.
|
|||
|
//
|
|||
|
dwErr = UuidCreate(&Uid);
|
|||
|
|
|||
|
if (dwErr != ERROR_SUCCESS) {
|
|||
|
IDfsVolInlineDebOut((DEB_ERROR, "UuidCreate failed %08lx\n", dwErr));
|
|||
|
return(dwErr);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Now figure out the last element of the child name from the GUID.
|
|||
|
//
|
|||
|
GuidToString(&Uid, wszChildElement);
|
|||
|
pwszChild = wszChildElement;
|
|||
|
pVolId = pUid == NULL ? &Uid : pUid;
|
|||
|
} else {
|
|||
|
pwszChild = Name;
|
|||
|
pVolId = pUid;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Now compose the full name of the child object.
|
|||
|
//
|
|||
|
pwszChildName = new WCHAR[wcslen(_pwzFileName)+wcslen(pwszChild)+2];
|
|||
|
|
|||
|
if (pwszChildName == NULL) {
|
|||
|
|
|||
|
*NewIDfsVol = NULL;
|
|||
|
dwErr = ERROR_OUTOFMEMORY;
|
|||
|
return dwErr;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
wcscpy(pwszChildName, _pwzFileName);
|
|||
|
wcscat(pwszChildName, L"\\");
|
|||
|
wcscat(pwszChildName, pwszChild);
|
|||
|
|
|||
|
//
|
|||
|
// Let us now instantiate a new instance of CDfsVolume and then we will
|
|||
|
// initialise it with the appropriate Name.
|
|||
|
//
|
|||
|
pDfsVol = new CDfsVolume();
|
|||
|
|
|||
|
if (pDfsVol != NULL) {
|
|||
|
|
|||
|
dwErr = pDfsVol->CreateObject( pwszChildName,
|
|||
|
EntryPath,
|
|||
|
Type,
|
|||
|
pReplInfo,
|
|||
|
pwszComment,
|
|||
|
pVolId);
|
|||
|
|
|||
|
//
|
|||
|
// We set up recovery properties of creation here though this is also used
|
|||
|
// by Move operation. This is OK however.
|
|||
|
//
|
|||
|
if (dwErr == ERROR_SUCCESS) {
|
|||
|
dwErr = pDfsVol->_Recover.SetOperationStart( DFS_RECOVERY_STATE_CREATING, NULL);
|
|||
|
if (dwErr == ERROR_SUCCESS) {
|
|||
|
*NewIDfsVol = pDfsVol;
|
|||
|
//
|
|||
|
// Create object merely creates the object. We now need to call
|
|||
|
// initPktSvc on the service inside the serviceList.
|
|||
|
//
|
|||
|
pService = pDfsVol->_DfsSvcList.GetFirstService();
|
|||
|
ASSERT(((pService==NULL) && (pReplInfo==NULL)) ||
|
|||
|
((pService!=NULL) && (pReplInfo!=NULL)));
|
|||
|
if (pService != NULL)
|
|||
|
pService->InitializePktSvc();
|
|||
|
}
|
|||
|
else {
|
|||
|
pDfsVol->Release();
|
|||
|
*NewIDfsVol = NULL;
|
|||
|
}
|
|||
|
} else {
|
|||
|
pDfsVol->Release();
|
|||
|
*NewIDfsVol = NULL;
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
*NewIDfsVol = NULL;
|
|||
|
dwErr = ERROR_OUTOFMEMORY;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
delete [] pwszChildName;
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::CreateChildPartition() exit\n"));
|
|||
|
|
|||
|
return(dwErr);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: CDfsVolume::IsValidChildName,private
|
|||
|
//
|
|||
|
// Synopsis: Determines whether a prefix is a valid child prefix for this
|
|||
|
// volume (ie, is hierarchically subordinate and there is no
|
|||
|
// conflicting child.
|
|||
|
//
|
|||
|
// Arguments: [pwszChildPrefix] -- The prefix to test.
|
|||
|
// [pidChild] -- The volume id of the proposed child volume.
|
|||
|
//
|
|||
|
// Returns: TRUE if the child prefix is legal, FALSE otherwise
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
BOOL CDfsVolume::IsValidChildName(
|
|||
|
PWCHAR pwszChildPrefix,
|
|||
|
GUID *pidChild)
|
|||
|
{
|
|||
|
NTSTATUS Status;
|
|||
|
|
|||
|
Status = PktIsChildnameLegal(
|
|||
|
_peid.Prefix.Buffer,
|
|||
|
pwszChildPrefix,
|
|||
|
pidChild);
|
|||
|
|
|||
|
return( (BOOL) (Status == STATUS_SUCCESS) );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Method: CDfsVolume::NotLeafVolume, private
|
|||
|
//
|
|||
|
// Synopsis: Uses IStorage to find if child exists.
|
|||
|
//
|
|||
|
// Arguments:None
|
|||
|
//
|
|||
|
// Returns: TRUE if NotLeafVolume else FALSE.
|
|||
|
//
|
|||
|
// History: 18-May-1993 SudK Created.
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
BOOL
|
|||
|
CDfsVolume::NotLeafVolume(void)
|
|||
|
{
|
|||
|
ULONG fetched = 0;
|
|||
|
CEnumDirectory *pdir;
|
|||
|
DFSMSTATDIR rgelt;
|
|||
|
DWORD dwErr;
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::NotLeafVolume()\n"));
|
|||
|
|
|||
|
ASSERT(!(VolumeDeleted()));
|
|||
|
|
|||
|
memset(&rgelt, 0, sizeof(DFSMSTATDIR));
|
|||
|
|
|||
|
//
|
|||
|
// First, we get a hold of the IDirectory interface to our own volume
|
|||
|
// object.
|
|||
|
//
|
|||
|
|
|||
|
dwErr = _pStorage->GetEnumDirectory(&pdir);
|
|||
|
if (dwErr != ERROR_SUCCESS) {
|
|||
|
IDfsVolInlineDebOut((DEB_ERROR, "Failed to get IDirectory %08lx\n", dwErr));
|
|||
|
return(FALSE);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// While there are children still to be handled we continue on.
|
|||
|
//
|
|||
|
|
|||
|
while (TRUE) {
|
|||
|
|
|||
|
if (rgelt.pwcsName != NULL) {
|
|||
|
delete [] rgelt.pwcsName;
|
|||
|
rgelt.pwcsName = NULL;
|
|||
|
}
|
|||
|
|
|||
|
dwErr = pdir->Next(&rgelt, &fetched);
|
|||
|
|
|||
|
//
|
|||
|
// Will we get an error if there are no more children.
|
|||
|
//
|
|||
|
if (dwErr != ERROR_SUCCESS) {
|
|||
|
IDfsVolInlineDebOut((DEB_ERROR, "Failed to Enumeraate %08lx\n",dwErr));
|
|||
|
pdir->Release();
|
|||
|
return(FALSE);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If we did not get back any children we are done.
|
|||
|
//
|
|||
|
if (fetched == 0) {
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "No Children Found\n",0));
|
|||
|
pdir->Release();
|
|||
|
return(FALSE);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If the child is . or .. we look for next child.
|
|||
|
//
|
|||
|
ULONG cbLen = wcslen(rgelt.pwcsName);
|
|||
|
|
|||
|
if (cbLen < sizeof(L"..")/sizeof(WCHAR))
|
|||
|
continue;
|
|||
|
|
|||
|
//
|
|||
|
// If we got here it means that we came across a volume object
|
|||
|
// and we have to return TRUE now.
|
|||
|
//
|
|||
|
IDfsVolInlineDebOut((DEB_ERROR, "Child Found - NotLeafVolume %ws\n",
|
|||
|
rgelt.pwcsName));
|
|||
|
pdir->Release();
|
|||
|
delete [] rgelt.pwcsName;
|
|||
|
return(TRUE);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::NotLeafVolume() exit\n"));
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: CDfsVolume::IsValidService
|
|||
|
//
|
|||
|
// Synopsis: Given a server name, indicates whether the server is a valid
|
|||
|
// server for this volume.
|
|||
|
//
|
|||
|
// Arguments: [pwszServer] -- Name of server to verify.
|
|||
|
//
|
|||
|
// Returns: TRUE if server is a valid server for this volume, FALSE
|
|||
|
// otherwise
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
CDfsVolume::IsValidService(
|
|||
|
IN LPWSTR pwszServer)
|
|||
|
{
|
|||
|
DWORD dwErr;
|
|||
|
CDfsService *pSvc;
|
|||
|
|
|||
|
dwErr = _DfsSvcList.GetServiceFromPrincipalName( pwszServer, &pSvc );
|
|||
|
|
|||
|
return( dwErr == ERROR_SUCCESS );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Method: DeallocateCacheRelationInfo, private
|
|||
|
//
|
|||
|
// Synopsis: This function is used to deallocate relationInfo structures
|
|||
|
// that were allocated by GetPktCacheRelationInfo.
|
|||
|
//
|
|||
|
// Arguments: RelationInfo - The relationInfo struct to deallocate.
|
|||
|
//
|
|||
|
// Returns:
|
|||
|
//
|
|||
|
// History: 24-Nov-1992 SudK Created.
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
VOID
|
|||
|
DeallocateCacheRelationInfo(
|
|||
|
DFS_PKT_RELATION_INFO & RelationInfo
|
|||
|
)
|
|||
|
{
|
|||
|
PDFS_PKT_ENTRY_ID peid = &RelationInfo.EntryId;
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "Dfsm::DeallocateCacheRelationInfo()\n"));
|
|||
|
|
|||
|
MarshalBufferFree(peid->Prefix.Buffer);
|
|||
|
peid->Prefix.Buffer = NULL;
|
|||
|
|
|||
|
if (peid->ShortPrefix.Buffer) {
|
|||
|
MarshalBufferFree(peid->ShortPrefix.Buffer);
|
|||
|
peid->ShortPrefix.Buffer = NULL;
|
|||
|
}
|
|||
|
|
|||
|
if(peid = RelationInfo.SubordinateIdList)
|
|||
|
{
|
|||
|
for(ULONG i = 0; i < RelationInfo.SubordinateIdCount; i++)
|
|||
|
{
|
|||
|
MarshalBufferFree(peid[i].Prefix.Buffer);
|
|||
|
peid[i].Prefix.Buffer = NULL;
|
|||
|
if (peid[i].ShortPrefix.Buffer != NULL) {
|
|||
|
MarshalBufferFree(peid[i].ShortPrefix.Buffer);
|
|||
|
peid[i].ShortPrefix.Buffer = NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
MarshalBufferFree(RelationInfo.SubordinateIdList);
|
|||
|
RelationInfo.SubordinateIdList = NULL;
|
|||
|
}
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "Dfsm::DeallocateCacheRelationInfo() exit\n"));
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Method: GetPktCacheRelationInfo, private
|
|||
|
//
|
|||
|
// Synopsis: This method retrieves the relational information regarding
|
|||
|
// a particular volume (identified by the ENTRY_ID props)
|
|||
|
// passed in to it.
|
|||
|
//
|
|||
|
// Arguments: [RelationInfo] -- The relational info is returned here.
|
|||
|
// [peid] -- The EntryID is passed in here.
|
|||
|
//
|
|||
|
// Returns:
|
|||
|
//
|
|||
|
// History: 24-Nov-1992 SudK Created.
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
|
|||
|
DWORD
|
|||
|
GetPktCacheRelationInfo(
|
|||
|
PDFS_PKT_ENTRY_ID peid,
|
|||
|
PDFS_PKT_RELATION_INFO RelationInfo
|
|||
|
)
|
|||
|
{
|
|||
|
//
|
|||
|
// Initialize all return values to be NULL...
|
|||
|
//
|
|||
|
|
|||
|
HANDLE pktHandle;
|
|||
|
DWORD dwErr = ERROR_SUCCESS;
|
|||
|
NTSTATUS status;
|
|||
|
memset(RelationInfo, 0, sizeof(DFS_PKT_RELATION_INFO));
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "IDfsVol::GetPktCacheRelationInfo()\n"));
|
|||
|
|
|||
|
status = PktOpen(&pktHandle, 0, 0, NULL);
|
|||
|
if (NT_SUCCESS(status))
|
|||
|
{
|
|||
|
|
|||
|
//
|
|||
|
// Create/Update the Entry...
|
|||
|
//
|
|||
|
|
|||
|
status = PktGetRelationInfo(
|
|||
|
pktHandle,
|
|||
|
peid,
|
|||
|
RelationInfo
|
|||
|
);
|
|||
|
|
|||
|
PktClose(pktHandle);
|
|||
|
pktHandle = NULL;
|
|||
|
};
|
|||
|
|
|||
|
if (!NT_SUCCESS(status))
|
|||
|
dwErr = RtlNtStatusToDosError(status);
|
|||
|
else
|
|||
|
dwErr = ERROR_SUCCESS;
|
|||
|
|
|||
|
if (dwErr != ERROR_SUCCESS) {
|
|||
|
IDfsVolInlineDebOut((DEB_ERROR, "Failed GetRelationInfo %08lx\n",dwErr));
|
|||
|
}
|
|||
|
|
|||
|
IDfsVolInlineDebOut((DEB_TRACE, "IDfsVol::GetPktCacheRelationInfo() exit\n"));
|
|||
|
|
|||
|
return( dwErr );
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
DfspCreateExitPoint (
|
|||
|
IN HANDLE DriverHandle,
|
|||
|
IN LPGUID Uid,
|
|||
|
IN LPWSTR Prefix,
|
|||
|
IN ULONG Type,
|
|||
|
IN ULONG Len,
|
|||
|
OUT LPWSTR ShortPrefix)
|
|||
|
{
|
|||
|
NTSTATUS NtStatus;
|
|||
|
IO_STATUS_BLOCK IoStatusBlock;
|
|||
|
PDFS_CREATE_EXIT_POINT_ARG CreateArg;
|
|||
|
ULONG Size = sizeof(*CreateArg);
|
|||
|
PCHAR pWc;
|
|||
|
|
|||
|
if (Uid == NULL || Prefix == NULL) {
|
|||
|
NtStatus = STATUS_INVALID_PARAMETER;
|
|||
|
DFSM_TRACE_HIGH(ERROR, DfspCreateExitPoint_Error1,
|
|||
|
LOGSTATUS(NtStatus)
|
|||
|
LOGWSTR(Prefix));
|
|||
|
goto ExitWithStatus;
|
|||
|
}
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose & 0x80000000) {
|
|||
|
WCHAR wszGuid[sizeof(GUID)*2+1];
|
|||
|
|
|||
|
GuidToString(Uid, wszGuid);
|
|||
|
DbgPrint("DfspCreateExitPoint(%ws,%ws,0x%x)\n",
|
|||
|
wszGuid,
|
|||
|
Prefix,
|
|||
|
Type);
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// Pack the args into a single buffer that can be sent to
|
|||
|
// the dfs driver:
|
|||
|
//
|
|||
|
|
|||
|
//
|
|||
|
// First find the size...
|
|||
|
//
|
|||
|
|
|||
|
if (Prefix != NULL) {
|
|||
|
|
|||
|
Size += (wcslen(Prefix) + 1) * sizeof(WCHAR);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Now allocate the memory
|
|||
|
//
|
|||
|
|
|||
|
CreateArg = (PDFS_CREATE_EXIT_POINT_ARG)malloc(Size);
|
|||
|
|
|||
|
if (CreateArg == NULL) {
|
|||
|
|
|||
|
NtStatus = STATUS_INSUFFICIENT_RESOURCES;
|
|||
|
DFSM_TRACE_HIGH(ERROR, DfspCreateExitPoint_Error2,
|
|||
|
LOGSTATUS(NtStatus)
|
|||
|
LOGWSTR(Prefix));
|
|||
|
goto ExitWithStatus;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
RtlZeroMemory(CreateArg, Size);
|
|||
|
|
|||
|
//
|
|||
|
// Put the fixed parameters into the buffer
|
|||
|
//
|
|||
|
CreateArg->Uid = *Uid;
|
|||
|
CreateArg->Type = Type;
|
|||
|
|
|||
|
//
|
|||
|
// Put the variable data in the buffer
|
|||
|
//
|
|||
|
pWc = (PCHAR)(CreateArg + 1);
|
|||
|
|
|||
|
CreateArg->Prefix = (LPWSTR)pWc;
|
|||
|
RtlCopyMemory(CreateArg->Prefix, Prefix, wcslen(Prefix)*sizeof(WCHAR));
|
|||
|
LPWSTR_TO_OFFSET(CreateArg->Prefix, CreateArg);
|
|||
|
|
|||
|
//
|
|||
|
// Tell the driver!!
|
|||
|
//
|
|||
|
|
|||
|
NtStatus = NtFsControlFile(
|
|||
|
DriverHandle,
|
|||
|
NULL, // Event,
|
|||
|
NULL, // ApcRoutine,
|
|||
|
NULL, // ApcContext,
|
|||
|
&IoStatusBlock,
|
|||
|
FSCTL_DFS_CREATE_EXIT_POINT,
|
|||
|
CreateArg,
|
|||
|
Size,
|
|||
|
ShortPrefix,
|
|||
|
Len);
|
|||
|
|
|||
|
DFSM_TRACE_ERROR_HIGH(NtStatus, ALL_ERROR, DfspCreateExitPoint_Error_NtFsControlFile,
|
|||
|
LOGSTATUS(NtStatus)
|
|||
|
LOGWSTR(Prefix));
|
|||
|
free(CreateArg);
|
|||
|
|
|||
|
ExitWithStatus:
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose & 0x80000000)
|
|||
|
DbgPrint("DfspCreateExitPoint exit 0x%x\n", NtStatus);
|
|||
|
#endif
|
|||
|
|
|||
|
return NtStatus;
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
DfspDeleteExitPoint (
|
|||
|
IN HANDLE DriverHandle,
|
|||
|
IN LPGUID Uid,
|
|||
|
IN LPWSTR Prefix,
|
|||
|
IN ULONG Type)
|
|||
|
{
|
|||
|
NTSTATUS NtStatus;
|
|||
|
IO_STATUS_BLOCK IoStatusBlock;
|
|||
|
PDFS_DELETE_EXIT_POINT_ARG DeleteArg;
|
|||
|
ULONG Size = sizeof(*DeleteArg);
|
|||
|
PCHAR pWc;
|
|||
|
|
|||
|
if (Uid == NULL || Prefix == NULL) {
|
|||
|
NtStatus = STATUS_INVALID_PARAMETER;
|
|||
|
DFSM_TRACE_HIGH(ERROR, DfspDeleteExitPoint_Error1,
|
|||
|
LOGSTATUS(NtStatus)
|
|||
|
LOGWSTR(Prefix));
|
|||
|
goto ExitWithStatus;
|
|||
|
}
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose & 0x80000000) {
|
|||
|
WCHAR wszGuid[sizeof(GUID)*2+1];
|
|||
|
|
|||
|
GuidToString(Uid, wszGuid);
|
|||
|
DbgPrint("DfspDeleteExitPoint(%ws,%ws,0x%x)\n",
|
|||
|
wszGuid,
|
|||
|
Prefix,
|
|||
|
Type);
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// Pack the args into a single buffer that can be sent to
|
|||
|
// the dfs driver:
|
|||
|
//
|
|||
|
|
|||
|
//
|
|||
|
// First find the size...
|
|||
|
//
|
|||
|
|
|||
|
if (Prefix != NULL) {
|
|||
|
|
|||
|
Size += (wcslen(Prefix) + 1) * sizeof(WCHAR);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Now allocate the memory
|
|||
|
//
|
|||
|
|
|||
|
DeleteArg = (PDFS_DELETE_EXIT_POINT_ARG)malloc(Size);
|
|||
|
|
|||
|
if (DeleteArg == NULL) {
|
|||
|
|
|||
|
NtStatus = STATUS_INSUFFICIENT_RESOURCES;
|
|||
|
DFSM_TRACE_HIGH(ERROR, DfspDeleteExitPoint_Error2,
|
|||
|
LOGSTATUS(NtStatus)
|
|||
|
LOGWSTR(Prefix));
|
|||
|
goto ExitWithStatus;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
RtlZeroMemory(DeleteArg, Size);
|
|||
|
|
|||
|
//
|
|||
|
// Put the fixed parameters into the buffer
|
|||
|
//
|
|||
|
DeleteArg->Uid = *Uid;
|
|||
|
DeleteArg->Type = Type;
|
|||
|
|
|||
|
//
|
|||
|
// Put the variable data in the buffer
|
|||
|
//
|
|||
|
pWc = (PCHAR)(DeleteArg + 1);
|
|||
|
|
|||
|
DeleteArg->Prefix = (LPWSTR)pWc;
|
|||
|
RtlCopyMemory(DeleteArg->Prefix, Prefix, wcslen(Prefix)*sizeof(WCHAR));
|
|||
|
LPWSTR_TO_OFFSET(DeleteArg->Prefix, DeleteArg);
|
|||
|
|
|||
|
//
|
|||
|
// Tell the driver!!
|
|||
|
//
|
|||
|
|
|||
|
NtStatus = NtFsControlFile(
|
|||
|
DriverHandle,
|
|||
|
NULL, // Event,
|
|||
|
NULL, // ApcRoutine,
|
|||
|
NULL, // ApcContext,
|
|||
|
&IoStatusBlock,
|
|||
|
FSCTL_DFS_DELETE_EXIT_POINT,
|
|||
|
DeleteArg,
|
|||
|
Size,
|
|||
|
NULL,
|
|||
|
0);
|
|||
|
|
|||
|
DFSM_TRACE_ERROR_HIGH(NtStatus, ALL_ERROR, DfspDeleteExitPoint_Error_NtFsControlFile,
|
|||
|
LOGSTATUS(NtStatus)
|
|||
|
LOGWSTR(Prefix));
|
|||
|
free(DeleteArg);
|
|||
|
|
|||
|
ExitWithStatus:
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (DfsSvcVerbose & 0x80000000)
|
|||
|
DbgPrint("DfspDeleteExitPoint exit 0x%x\n", NtStatus);
|
|||
|
#endif
|
|||
|
|
|||
|
return NtStatus;
|
|||
|
}
|