2025-04-27 07:49:33 -04:00

4376 lines
131 KiB
C++

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name :
comobj.cxx
Abstract:
This module defines DCOM Admin APIs.
Author:
Sophia Chung (sophiac) 23-Nov-1996
--*/
extern "C" {
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
}
#include <dbgutil.h>
#include <ole2.h>
#include <windows.h>
#include <coiadm.hxx>
#include <admacl.hxx>
#include <iiscnfg.h>
#include <secpriv.h>
#include <buffer.hxx>
#include <pwsctrl.h>
#include <inetinfo.h>
#include <metabase.hxx>
#include <stdio.h>
#include <iis64.h>
//
// Globals
//
DECLARE_DEBUG_PRINTS_OBJECT();
ULONG g_dwRefCount = 0;
COpenHandle g_ohMasterRootHandle;
HANDLE_TABLE g_MasterRoot = { NULL,
0,
METADATA_MASTER_ROOT_HANDLE,
ALL_HANDLE,
&g_ohMasterRootHandle };
//
// Private prototypes
//
#define MAX_SINK_CALLS_TOBE_REMOVED 10
//
// Used by RestoreHelper
//
#define RESTORE_HISTORY 0x1
#define RESTORE_BACKUP 0x2
BOOL
MakeParentPath(
LPWSTR pszPath
);
BOOL
IsValidNsepmPath(
LPCWSTR pszMDPath
);
//------------------------------
CADMCOMW::CADMCOMW():
m_ImpIConnectionPointContainer(),
m_pMdObject(NULL),
m_dwRefCount(1),
m_dwHandleValue(1),
m_pEventSink(NULL),
m_pConnPoint(NULL),
m_bSinkConnected(FALSE),
m_bCallSinks(TRUE),
m_piuFTM(NULL),
m_pNseObject(NULL),
m_bTerminated(FALSE),
m_bIsTerminateRoutineComplete(FALSE)
{
HRESULT hRes;
UINT i;
memset((PVOID)m_hashtab, 0, sizeof(m_hashtab) );
// Null all entries in the connection point array.
for (i=0; i<MAX_CONNECTION_POINTS; i++) {
m_aConnectionPoints[i] = NULL;
}
InitializeListHead( &m_ObjectListEntry );
hRes = CoCreateInstance(CLSID_MDCOM, NULL, CLSCTX_INPROC_SERVER, IID_IMDCOM2, (void**) &m_pMdObject);
if (FAILED(hRes)) {
DBGPRINTF(( DBG_CONTEXT,
"[CADMCOMW::CADMCOMW] CoCreateInstance(MDCOM) failed, error %lx\n",
hRes ));
}
else {
hRes = m_pMdObject->ComMDInitialize();
if (FAILED(hRes)) {
DBGPRINTF(( DBG_CONTEXT,
"[CADMCOMW::CADMCOMW] ComMDInitialize(MDCOM) failed, error %lx\n",
hRes ));
m_pMdObject->Release();
m_pMdObject = NULL;
}
}
if (SUCCEEDED(hRes)) {
if ( IISGetPlatformType() != PtWindows95 ) {
hRes = CoCreateInstance(CLSID_NSEPMCOM,
NULL,
CLSCTX_INPROC_SERVER,
IID_NSECOM,
(void**) &m_pNseObject);
if (FAILED(hRes)) {
DBGPRINTF(( DBG_CONTEXT,
"[CADMCOM::CADMCOM] CoCreateInstance(NSEPMCOM) failed, error %lx\n",
GetLastError() ));
}
else {
hRes = m_pNseObject->ComMDInitialize();
if (FAILED(hRes)) {
DBGPRINTF(( DBG_CONTEXT,
"[CADMCOM::CADMCOM] ComMDInitialize(NSEPMCOM) failed, error %lx\n",
hRes ));
m_pNseObject->Release();
m_pNseObject = NULL;
}
}
}
m_pEventSink = new CImpIMDCOMSINKW((IMSAdminBaseW*)this);
if( m_pEventSink == NULL ) {
DBGPRINTF(( DBG_CONTEXT,
"[CADMCOMW::CADMCOMW] CImpIMDCOMSINKW failed, error %lx\n",
ERROR_NOT_ENOUGH_MEMORY ));
hRes = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
}
else {
m_pEventSink->AddRef();
COConnectionPoint* pCOConnPt;
m_ImpIConnectionPointContainer.Init(this);
// Rig this COPaper COM object to be connectable. Assign the connection
// point array. This object's connection points are determined at
// compile time--it currently has only one connection point:
// the CONNPOINT_PAPERSINK connection point. Create a connection
// point object for this and assign it into the array. This array could
// easily grow to support additional connection points in the future.
// First try creating a new connection point object. Pass 'this' as the
// pHostObj pointer used by the connection point to pass its AddRef and
// Release calls back to the host connectable object.
pCOConnPt = new COConnectionPoint((IUnknown*)this);
if (NULL != pCOConnPt)
{
// If creation succeeded then initialize it (including creating
// its initial dynamic connection array).
hRes = pCOConnPt->Init(IID_IMSAdminBaseSink_W);
// If the init succeeded then use QueryInterface to obtain the
// IConnectionPoint interface on the new connection point object.
// The interface pointer is assigned directly into the
// connection point array. The QI also does the needed AddRef.
if (SUCCEEDED(hRes)) {
hRes = pCOConnPt->QueryInterface(IID_IConnectionPoint,
(PPVOID)&m_aConnectionPoints[ADM_CONNPOINT_WRITESINK]);
}
if (FAILED(hRes)) {
delete (pCOConnPt);
}
}
if (SUCCEEDED(hRes)) {
//
// Admin's sink
//
IConnectionPointContainer* pConnPointContainer = NULL;
// First query the object for its Connection Point Container. This
// essentially asks the object in the server if it is connectable.
hRes = m_pMdObject->QueryInterface( IID_IConnectionPointContainer,
(PVOID *)&pConnPointContainer);
if SUCCEEDED(hRes)
{
// Find the requested Connection Point. This AddRef's the
// returned pointer.
hRes = pConnPointContainer->FindConnectionPoint(IID_IMDCOMSINK_W, &m_pConnPoint);
if (SUCCEEDED(hRes)) {
hRes = m_pConnPoint->Advise((IUnknown *)m_pEventSink, &m_dwCookie);
if (SUCCEEDED(hRes)) {
m_bSinkConnected = TRUE;
}
}
RELEASE_INTERFACE(pConnPointContainer);
if (SUCCEEDED(hRes)) {
hRes = CoCreateFreeThreadedMarshaler((IUnknown *)this, &m_piuFTM);
}
}
}
}
}
SetStatus(hRes);
//
// Insert our object into the global list only if it is valid.
//
if( SUCCEEDED(hRes) )
{
AddObjectToList();
}
}
CADMCOMW::~CADMCOMW()
{
Terminate();
}
VOID
CADMCOMW::Terminate()
{
HANDLE_TABLE *node;
HANDLE_TABLE *nextnode;
DWORD i;
//
// Terminate must only be called from two locations. And they
// should synchronize correctly.
//
// 1. From ~CADMCOMW. Obviously this should only be called once.
//
// 2. From ForceTerminate. That routine should only be called in
// shutdown. With a reference held on this object. So the final
// release should call the dtor and this routine should noop.
//
if( !m_bTerminated )
{
m_bTerminated = TRUE;
if (m_bSinkConnected) {
m_pConnPoint->Unadvise(m_dwCookie);
m_rSinkResource.Lock(TSRES_LOCK_WRITE);
m_bCallSinks = FALSE;
m_rSinkResource.Unlock();
}
//
// Tell ADMWPROX.DLL to release this object's associated security
// context.
//
ReleaseObjectSecurityContextW( ( IUnknown* )this );
//
// Do final release of the connection point objects.
// If this isn't the final release, then the client has an outstanding
// unbalanced reference to a connection point and a memory leak may
// likely result because the host COPaper object is now going away yet
// a connection point for this host object will not end up deleting
// itself (and its connections array).
//
for (i=0; i<MAX_CONNECTION_POINTS; i++)
{
CoDisconnectObject (m_aConnectionPoints[i],0);
RELEASE_INTERFACE(m_aConnectionPoints[i]);
}
if (SUCCEEDED(GetStatus())) {
//
// Close all opened handles
//
m_rHandleResource.Lock(TSRES_LOCK_WRITE);
for( i = 0; i < HASHSIZE; i++ ) {
for( node = nextnode = m_hashtab[i]; node != NULL; node = nextnode ) {
if ( node->hAdminHandle != INVALID_ADMINHANDLE_VALUE ) {
AdminAclNotifyClose( (LPVOID)this, node->hAdminHandle );
if( node->HandleType == NSEPM_HANDLE ) {
//
// call nse com api
//
m_pNseObject->ComMDCloseMetaObject( node->hActualHandle );
}
else {
//
// call metadata com api
//
m_pMdObject->ComMDCloseMetaObject( node->hActualHandle );
}
}
nextnode = node->next;
delete node->pohHandle;
LocalFree(node);
}
m_hashtab[i] = NULL;
}
//
// Issue TaylorW 3/20/2001
// QFE tree contains this call:
//
// AdminAclNotifyClose( (LPVOID)this, METADATA_MASTER_ROOT_HANDLE );
//
// I have no idea when this may have entered their tree or been lost
// from ours. I don't see any record in source depot of it being
// removed or added. Need to investigate why it would be needed.
//
m_rHandleResource.Unlock();
}
if ( m_pEventSink != NULL )
{
m_pEventSink->Release();
m_pEventSink = NULL;
}
if ( m_pMdObject != NULL )
{
m_pMdObject->ComMDTerminate(TRUE);
m_pMdObject->Release();
m_pMdObject = NULL;
}
if ( m_piuFTM != NULL )
{
m_piuFTM->Release();
m_piuFTM = NULL;
}
if ( m_pNseObject != NULL )
{
m_pNseObject->ComMDTerminate(TRUE);
m_pNseObject->Release();
m_pNseObject = NULL;
}
m_bIsTerminateRoutineComplete = TRUE;
}
DBG_ASSERT( m_bIsTerminateRoutineComplete );
}
VOID
CADMCOMW::ForceTerminate()
{
DBG_ASSERT( !m_bIsTerminateRoutineComplete );
DBG_ASSERT( !m_bTerminated );
//
// Wait on the reference count of this object. But bound
// the wait so a leaked in process object does not prevent
// us from shutting down the service.
//
// Wait on a ref count of 1, because the caller better be
// holding our last reference. This assumes all external
// references are killed through CoDisconnect() and all
// internal references are released because of dependent
// services shutting down.
//
// Issue TaylorW 3/20/2001
//
// In iis 5.1 the web service will shutdown filters after
// it has already reported that it is done shutting down.
// This is bad, but changing the shutdown logic of the
// web service is not worth doing at this time. Hopefully
// the shutdown timeout will be sufficient to allow this
// operation to complete.
//
// Windows Bugs 318006
//
const INT MAX_WAIT_TRIES = 5;
INT WaitTries;
for( WaitTries = 0;
m_dwRefCount > 1 && WaitTries < MAX_WAIT_TRIES;
WaitTries++ )
{
Sleep( 1000 );
}
//
// If we timed out. Something is wrong. Most likely someone in
// process has leaked this object. These asserts are actually
// overactive unless ref tracing is enabled on this object.
//
//
// Issue TaylorW 4/9/2001
//
// It looks like front page leaks a base object from in process.
// So these assertions need to be turned off.
//
#define DEBUG_BASE_OBJ_LEAK 0x80000000L
IF_DEBUG( BASE_OBJ_LEAK ) {
DBG_ASSERT( m_dwRefCount == 1 );
DBG_ASSERT( WaitTries < MAX_WAIT_TRIES );
}
//
// Go ahead and try to clean up.
//
Terminate();
}
HRESULT
CADMCOMW::QueryInterface(
REFIID riid,
void **ppObject)
{
if (riid==IID_IUnknown || riid==IID_IMSAdminBase_W) {
*ppObject = (IMSAdminBase *) this;
AddRef();
}
else if (IID_IMSAdminBase2_W == riid) {
*ppObject = (IMSAdminBase2 *) this;
AddRef();
}
else if (IID_IConnectionPointContainer == riid) {
*ppObject = &m_ImpIConnectionPointContainer;
AddRef();
}
else if (IID_IMarshal == riid) {
return m_piuFTM->QueryInterface(riid, ppObject);
}
else {
return E_NOINTERFACE;
}
return S_OK;
}
ULONG
CADMCOMW::AddRef(
)
{
DWORD dwRefCount;
dwRefCount = InterlockedIncrement((long *)&m_dwRefCount);
#if DBG
if( sm_pDbgRefTraceLog )
{
WriteRefTraceLog( sm_pDbgRefTraceLog, dwRefCount, this );
}
#endif
return dwRefCount;
}
ULONG
CADMCOMW::Release(
)
{
DWORD dwRefCount;
dwRefCount = InterlockedDecrement((long *)&m_dwRefCount);
#if DBG
if( sm_pDbgRefTraceLog )
{
WriteRefTraceLog( sm_pDbgRefTraceLog, -(LONG)dwRefCount, this );
}
#endif
if( dwRefCount == 1 ) {
//
// We keep a list of objects around so that we can clean up and
// shutdown successfully. The list holds a reference to this object
// when we hit a reference of 1, we know it is time to remove
// ourselves from the list. If we are in shutdown we may already
// have been removed from the list. But normally, this call to
// RemoveObjectFromList removes our last reference and thus sends
// us back through Release and ultimately to our destructor.
//
RemoveObjectFromList();
}
else if( dwRefCount == 0 ) {
delete this;
}
return dwRefCount;
}
HRESULT
CADMCOMW::AddKey(
IN METADATA_HANDLE hMDHandle,
IN LPCWSTR pszMDPath
)
/*++
Routine Description:
Add meta object and adds it to the list of child objects for the object
specified by Path.
Arguments:
hMDHandle - open handle
pszMDPath - path of the object to be added
Return Value:
Status.
--*/
{
HRESULT hresReturn = MD_ERROR_NOT_INITIALIZED;
hresReturn = AddKeyHelper(hMDHandle, pszMDPath);
return hresReturn;
}
HRESULT
CADMCOMW::DeleteKey(
IN METADATA_HANDLE hMDHandle,
IN LPCWSTR pszMDPath
)
/*++
Routine Description:
Deletes a meta object and all of its data.
Arguments:
hMDHandle - open handle
pszMDPath - path of object to be deleted, relative to the path of Handle.
Must not be NULL.
Return Value:
Status.
--*/
{
HRESULT hresReturn = MD_ERROR_NOT_INITIALIZED;
if (pszMDPath == NULL) {
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
else {
METADATA_HANDLE hActualHandle;
HANDLE_TYPE HandleType;
//
// lookup and access check
//
hresReturn = LookupAndAccessCheck(hMDHandle,
&hActualHandle,
&HandleType,
pszMDPath,
AAC_DELETEKEY,
METADATA_PERMISSION_WRITE);
if (SUCCEEDED(hresReturn)) {
if( HandleType == NSEPM_HANDLE ) {
//
// call nse com api
//
hresReturn = m_pNseObject->ComMDDeleteMetaObjectW( hActualHandle,
pszMDPath );
}
else {
//
// call metadata com api
//
hresReturn = m_pMdObject->ComMDDeleteMetaObjectW( hActualHandle,
pszMDPath );
}
}
}
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CADMCOMW::DeleteChildKeys(
/* [in] */ METADATA_HANDLE hMDHandle,
/* [string][in][unique] */ LPCWSTR pszMDPath
)
/*++
Routine Description:
Deletes all child meta objects of the specified object, with all of their
data.
Arguments:
hMDHandle - open handle
pszMDPath - path of the parent of the objects to be deleted, relative to
the path of Handle.
Return Value:
Status.
--*/
{
METADATA_HANDLE hActualHandle;
HANDLE_TYPE HandleType;
HRESULT hresReturn = MD_ERROR_NOT_INITIALIZED;
//
// lookup and access check
//
hresReturn = LookupAndAccessCheck(hMDHandle,
&hActualHandle,
&HandleType,
pszMDPath,
0,
METADATA_PERMISSION_WRITE);
if (SUCCEEDED(hresReturn)) {
if( HandleType == NSEPM_HANDLE ) {
//
// call nse com api
//
hresReturn = m_pNseObject->ComMDDeleteChildMetaObjectsW( hActualHandle,
pszMDPath );
}
else {
//
// call metadata com api
//
hresReturn = m_pMdObject->ComMDDeleteChildMetaObjectsW( hActualHandle,
pszMDPath );
}
}
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CADMCOMW::EnumKeys(
/* [in] */ METADATA_HANDLE hMDHandle,
/* [size_is][in] */ LPCWSTR pszMDPath,
/* [size_is][out] */ LPWSTR pszMDName,
/* [in] */ DWORD dwMDEnumObjectIndex
)
/*++
Routine Description:
Enumerate objects in path.
Arguments:
hMDHandle - open handle
pszMDPath - path of parent object, relative to the path of Handle
eg. "Root Object/Child/GrandChild"
pszMDName - buffer where the Name of the object is returned
dwEnumObjectIndex - index of the value to be retrieved
Return Value:
Status.
--*/
{
HRESULT hresReturn = MD_ERROR_NOT_INITIALIZED;
if (pszMDName == NULL) {
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
else {
METADATA_HANDLE hActualHandle;
HANDLE_TYPE HandleType;
//
// lookup and access check
//
hresReturn = LookupAndAccessCheck(hMDHandle,
&hActualHandle,
&HandleType,
pszMDPath,
AAC_ENUM_KEYS,
METADATA_PERMISSION_READ);
if (SUCCEEDED(hresReturn)) {
if( HandleType == NSEPM_HANDLE ) {
//
// call nse com api
//
hresReturn = m_pNseObject->ComMDEnumMetaObjectsW( hActualHandle,
pszMDPath,
pszMDName,
dwMDEnumObjectIndex );
}
else {
//
// call metadata com api
//
hresReturn = m_pMdObject->ComMDEnumMetaObjectsW( hActualHandle,
pszMDPath,
pszMDName,
dwMDEnumObjectIndex );
}
}
}
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CADMCOMW::CopyKey(
/* [in] */ METADATA_HANDLE hMDSourceHandle,
/* [string][in][unique] */ LPCWSTR pszMDSourcePath,
/* [in] */ METADATA_HANDLE hMDDestHandle,
/* [string][in][unique] */ LPCWSTR pszMDDestPath,
/* [in] */ BOOL bMDOverwriteFlag,
/* [in] */ BOOL bMDCopyFlag
)
/*++
Routine Description:
Copy or move source meta object and its data and descendants to Dest.
Arguments:
hMDSourceHandle - open handle
pszMDSourcePath - path of the object to be copied
hMDDestHandle - handle of the new location for the object
pszMDDestPath - path of the new location for the object, relative
to the path of hMDDestHandle
bMDOverwriteFlag - determine the behavior if a meta object with the same
name as source is already a child of pszMDDestPath.
bMDCopyFlag - determine whether Source is deleted from its original location
Return Value:
Status
--*/
{
METADATA_HANDLE hSActualHandle;
HANDLE_TYPE SHandleType;
METADATA_HANDLE hDActualHandle;
HANDLE_TYPE DHandleType;
HRESULT hresReturn = MD_ERROR_NOT_INITIALIZED;
//
// lookup and access check source
//
if (bMDCopyFlag) {
hresReturn = LookupAndAccessCheck(hMDSourceHandle,
&hSActualHandle,
&SHandleType,
pszMDSourcePath,
0,
METADATA_PERMISSION_READ);
}
else {
//
// Deleting source path, so need delete permission
//
hresReturn = LookupAndAccessCheck(hMDSourceHandle,
&hSActualHandle,
&SHandleType,
pszMDSourcePath,
AAC_DELETEKEY,
METADATA_PERMISSION_WRITE);
}
if (SUCCEEDED(hresReturn)) {
//
// lookup and access check dest
//
hresReturn = LookupAndAccessCheck(hMDDestHandle,
&hDActualHandle,
&DHandleType,
pszMDDestPath,
AAC_COPYKEY,
METADATA_PERMISSION_WRITE);
if (SUCCEEDED(hresReturn)) {
if( SHandleType == NSEPM_HANDLE ) {
//
// call nse com api
//
hresReturn = m_pNseObject->ComMDCopyMetaObjectW( hSActualHandle,
pszMDSourcePath,
hDActualHandle,
pszMDDestPath,
bMDOverwriteFlag,
bMDCopyFlag );
}
else {
//
// call metadata com api
//
hresReturn = m_pMdObject->ComMDCopyMetaObjectW( hSActualHandle,
pszMDSourcePath,
hDActualHandle,
pszMDDestPath,
bMDOverwriteFlag,
bMDCopyFlag );
}
}
}
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CADMCOMW::RenameKey(
/* [in] */ METADATA_HANDLE hMDHandle,
/* [string][in][unique] */ LPCWSTR pszMDPath,
/* [string][in][unique] */ LPCWSTR pszMDNewName)
{
HRESULT hresReturn = MD_ERROR_NOT_INITIALIZED;
if ((LPSTR)pszMDNewName == NULL) {
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
else {
METADATA_HANDLE hActualHandle;
HANDLE_TYPE HandleType;
//
// lookup and access check
//
hresReturn = LookupAndAccessCheck(hMDHandle,
&hActualHandle,
&HandleType,
pszMDPath,
0,
METADATA_PERMISSION_WRITE);
if (SUCCEEDED(hresReturn)) {
if( HandleType == NSEPM_HANDLE ) {
//
// call nse com api
//
hresReturn = m_pNseObject->ComMDRenameMetaObjectW(hActualHandle,
pszMDPath,
pszMDNewName );
}
else {
//
// call metadata com api
//
hresReturn = m_pMdObject->ComMDRenameMetaObjectW(hActualHandle,
pszMDPath,
pszMDNewName );
}
}
}
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CADMCOMW::SetData(
/* [in] */ METADATA_HANDLE hMDHandle,
/* [size_is][in] */ LPCWSTR pszMDPath,
/* [in] */ PMETADATA_RECORD pmdrMDData
)
/*++
Routine Description:
Set a data object.
Arguments:
hMDHandle - open handle
pszMDPath - path of the meta object with which this data is associated
pmdrMDData - data to set
Return Value:
Status.
--*/
{
METADATA_HANDLE hActualHandle;
HANDLE_TYPE HandleType;
HRESULT hresReturn = MD_ERROR_NOT_INITIALIZED;
//
// lookup and access check
//
hresReturn = LookupAndAccessCheck(hMDHandle,
&hActualHandle,
&HandleType,
pszMDPath,
pmdrMDData->dwMDIdentifier,
METADATA_PERMISSION_WRITE );
if (SUCCEEDED(hresReturn)) {
if ( !AdminAclNotifySetOrDeleteProp(
hMDHandle,
pmdrMDData->dwMDIdentifier ) )
{
DBGPRINTF(( DBG_CONTEXT,
"[CADMCOMW::SetData] AdminAclNotifySetOrDel failed, error %lx\n",
GetLastError() ));
hresReturn = RETURNCODETOHRESULT( GetLastError() );
}
else {
if( HandleType == NSEPM_HANDLE ) {
//
// call nse com api
//
hresReturn = m_pNseObject->ComMDSetMetaDataW( hActualHandle,
pszMDPath,
pmdrMDData );
}
else {
//
// call metadata com api
//
hresReturn = m_pMdObject->ComMDSetMetaDataW( hActualHandle,
pszMDPath,
pmdrMDData );
}
}
}
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CADMCOMW::GetData(
/* [in] */ METADATA_HANDLE hMDHandle,
/* [string][in] */ LPCWSTR pszMDPath,
/* [out][in] */ PMETADATA_RECORD pmdrMDData,
/* [out] */ DWORD __RPC_FAR *pdwMDRequiredDataLen
)
/*++
Routine Description:
Get one metadata value
Arguments:
hMDHandle - open handle
pszMDPath - path of the meta object with which this data is associated
pmdrMDData - data structure
pdwMDRequiredDataLen - updated with required length
Return Value:
Status.
--*/
{
BOOL fEnableSecureAccess;
BOOL fRequestedInheritedStatus;
HRESULT hresReturn = MD_ERROR_NOT_INITIALIZED;
if ((pmdrMDData == NULL) ||
((pmdrMDData->dwMDDataLen != 0) && (pmdrMDData->pbMDData == NULL)) ||
!CheckGetAttributes(pmdrMDData->dwMDAttributes) ||
(pmdrMDData->dwMDDataType >= INVALID_END_METADATA)) {
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
else {
METADATA_HANDLE hActualHandle;
HANDLE_TYPE HandleType;
//
// lookup and access check
//
hresReturn = LookupAndAccessCheck(hMDHandle,
&hActualHandle,
&HandleType,
pszMDPath,
pmdrMDData->dwMDIdentifier,
METADATA_PERMISSION_READ,
&fEnableSecureAccess );
if (SUCCEEDED(hresReturn)) {
if( HandleType == NSEPM_HANDLE ) {
//
// call nse com api
//
hresReturn = m_pNseObject->ComMDGetMetaDataW( hActualHandle,
pszMDPath,
pmdrMDData,
pdwMDRequiredDataLen );
}
else {
DWORD RetCode;
fRequestedInheritedStatus = pmdrMDData->dwMDAttributes & METADATA_ISINHERITED;
pmdrMDData->dwMDAttributes |= METADATA_ISINHERITED;
//
// call metadata com api
//
hresReturn = m_pMdObject->ComMDGetMetaDataW( hActualHandle,
pszMDPath,
pmdrMDData,
pdwMDRequiredDataLen );
//
// if metadata is secure, check if can access this property from
// where it is defined, i.e using the ACL visible at the definition
// point in tree.
//
if ( SUCCEEDED( hresReturn ) &&
(pmdrMDData->dwMDAttributes & METADATA_SECURE) &&
(RetCode = IsReadAccessGranted( hMDHandle,
(LPWSTR)pszMDPath,
pmdrMDData ))
!= ERROR_SUCCESS )
{
hresReturn = RETURNCODETOHRESULT( RetCode );
}
if ( !fRequestedInheritedStatus )
{
pmdrMDData->dwMDAttributes &= ~METADATA_ISINHERITED;
}
}
//
// if metadata secure, check access allowed to secure properties
//
if ( SUCCEEDED( hresReturn ) &&
(pmdrMDData->dwMDAttributes & METADATA_SECURE) &&
!fEnableSecureAccess) {
*pdwMDRequiredDataLen = 0;
pmdrMDData->dwMDDataLen = 0;
hresReturn = RETURNCODETOHRESULT( ERROR_ACCESS_DENIED );
}
}
}
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CADMCOMW::DeleteData(
/* [in] */ METADATA_HANDLE hMDHandle,
/* [string][in] */ LPCWSTR pszMDPath,
/* [in] */ DWORD dwMDIdentifier,
/* [in] */ DWORD dwMDDataType
)
/*++
Routine Description:
Deletes a data object.
Arguments:
hMDHandle - open handle
pszMDPath - path of the meta object with which this data is associated
dwMDIdentifier - identifier of the data to remove
dwMDDataType - optional type of the data to remove
Return Value:
Status.
--*/
{
HRESULT hresReturn = MD_ERROR_NOT_INITIALIZED;
if (dwMDDataType >= INVALID_END_METADATA) {
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
else {
METADATA_HANDLE hActualHandle;
HANDLE_TYPE HandleType;
//
// lookup and access check
//
hresReturn = LookupAndAccessCheck(hMDHandle,
&hActualHandle,
&HandleType,
pszMDPath,
dwMDIdentifier,
METADATA_PERMISSION_WRITE);
if (SUCCEEDED(hresReturn)) {
if ( !AdminAclNotifySetOrDeleteProp(
hMDHandle,
dwMDIdentifier ) )
{
DBGPRINTF(( DBG_CONTEXT,
"[CADMCOMW::DeleteData] AdminAclNotifySetOrDel failed, error %lx\n",
GetLastError() ));
hresReturn = RETURNCODETOHRESULT( GetLastError() );
}
else {
if( HandleType == NSEPM_HANDLE ) {
//
// call nse com api
//
hresReturn = m_pNseObject->ComMDDeleteMetaDataW( hActualHandle,
pszMDPath,
dwMDIdentifier,
dwMDDataType );
}
else {
//
// call metadata com api
//
hresReturn = m_pMdObject->ComMDDeleteMetaDataW( hActualHandle,
pszMDPath,
dwMDIdentifier,
dwMDDataType );
}
}
}
}
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CADMCOMW::EnumData(
/* [in] */ METADATA_HANDLE hMDHandle,
/* [string][in] */ LPCWSTR pszMDPath,
/* [out][in] */ PMETADATA_RECORD pmdrMDData,
/* [in] */ DWORD dwMDEnumDataIndex,
/* [out] */ DWORD __RPC_FAR *pdwMDRequiredDataLen
)
/*++
Routine Description:
Enumerate properties of object.
Arguments:
hMDHandle - open handle
pszMDPath - path of the meta object with which this data is associated
pmdrMDData - data structure
pdwMDRequiredDataLen - updated with required length
Return Value:
Status.
--*/
{
BOOL fSecure;
BOOL fRequestedInheritedStatus;
HRESULT hresReturn = MD_ERROR_NOT_INITIALIZED;
if ((pmdrMDData == NULL) ||
((pmdrMDData->dwMDDataLen != 0) && (pmdrMDData->pbMDData == NULL)) ||
!CheckGetAttributes(pmdrMDData->dwMDAttributes) ||
(pmdrMDData->dwMDDataType >= INVALID_END_METADATA)) {
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
else {
METADATA_HANDLE hActualHandle;
HANDLE_TYPE HandleType;
//
// lookup and access check
//
hresReturn = LookupAndAccessCheck(hMDHandle,
&hActualHandle,
&HandleType,
pszMDPath,
0,
METADATA_PERMISSION_READ,
&fSecure);
if (SUCCEEDED(hresReturn)) {
if( HandleType == NSEPM_HANDLE ) {
//
// call nse com api
//
hresReturn = m_pNseObject->ComMDEnumMetaDataW( hActualHandle,
pszMDPath,
pmdrMDData,
dwMDEnumDataIndex,
pdwMDRequiredDataLen );
if ( !fSecure && SUCCEEDED(hresReturn) )
{
hresReturn = RETURNCODETOHRESULT( ERROR_ACCESS_DENIED );
memset( pmdrMDData->pbMDData, 0x0, pmdrMDData->dwMDDataLen );
}
}
else {
fRequestedInheritedStatus = pmdrMDData->dwMDAttributes & METADATA_ISINHERITED;
pmdrMDData->dwMDAttributes |= METADATA_ISINHERITED;
//
// call metadata com api
//
hresReturn = m_pMdObject->ComMDEnumMetaDataW( hActualHandle,
pszMDPath,
pmdrMDData,
dwMDEnumDataIndex,
pdwMDRequiredDataLen );
//
// if metadata is secure, check if can access this property from
// where it is defined, i.e using the ACL visible at the definition
// point in tree.
//
DWORD RetCode;
if ( SUCCEEDED( hresReturn ) &&
(pmdrMDData->dwMDAttributes & METADATA_SECURE) &&
(RetCode = IsReadAccessGranted( hMDHandle,
(LPWSTR)pszMDPath,
pmdrMDData ))
!= ERROR_SUCCESS )
{
hresReturn = RETURNCODETOHRESULT( RetCode );
if ( !pmdrMDData->dwMDDataTag )
{
memset( pmdrMDData->pbMDData, 0x0, pmdrMDData->dwMDDataLen );
}
}
if ( !fRequestedInheritedStatus )
{
pmdrMDData->dwMDAttributes &= ~METADATA_ISINHERITED;
}
if ( !fSecure && SUCCEEDED(hresReturn) )
{
if ( pmdrMDData->dwMDAttributes & METADATA_SECURE )
{
hresReturn = RETURNCODETOHRESULT( ERROR_ACCESS_DENIED );
if ( !pmdrMDData->dwMDDataTag )
{
memset( pmdrMDData->pbMDData, 0x0, pmdrMDData->dwMDDataLen );
}
}
}
}
}
}
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CADMCOMW::GetAllData(
/* [in] */ METADATA_HANDLE hMDHandle,
/* [string][in] */ LPCWSTR pszMDPath,
/* [in] */ DWORD dwMDAttributes,
/* [in] */ DWORD dwMDUserType,
/* [in] */ DWORD dwMDDataType,
/* [out] */ DWORD __RPC_FAR *pdwMDNumDataEntries,
/* [out] */ DWORD __RPC_FAR *pdwMDDataSetNumber,
/* [in] */ DWORD dwMDBufferSize,
/* [size_is][out] */ unsigned char __RPC_FAR *pbMDBuffer,
/* [out] */ DWORD __RPC_FAR *pdwMDRequiredBufferSize
)
/*++
Routine Description:
Gets all data associated with a Meta Object
Arguments:
hMDHandle - open handle
pszMDPath - path of the meta object with which this data is associated
dwMDAttributes - flags for the data
dwMDUserType - user Type for the data
dwMDDataType - type of the data
pdwMDNumDataEntries - number of entries copied to Buffer
pdwMDDataSetNumber - number associated with this data set
dwMDBufferSize - size in bytes of buffer
pbMDBuffer - buffer to store the data
pdwMDRequiredBufferSize - updated with required length of buffer
Return Value:
Status.
--*/
{
BOOL fSecure;
BOOL fRequestedInheritedStatus;
HRESULT hresReturn = MD_ERROR_NOT_INITIALIZED;
if ((pdwMDNumDataEntries == NULL) || ((dwMDBufferSize != 0) && (pbMDBuffer == NULL)) ||
!CheckGetAttributes(dwMDAttributes) ||
(dwMDDataType >= INVALID_END_METADATA)) {
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
else {
METADATA_HANDLE hActualHandle;
HANDLE_TYPE HandleType;
//
// lookup and access check
//
hresReturn = LookupAndAccessCheck(hMDHandle,
&hActualHandle,
&HandleType,
pszMDPath,
AAC_GETALL,
METADATA_PERMISSION_READ,
&fSecure );
if (SUCCEEDED(hresReturn)) {
if( HandleType == NSEPM_HANDLE ) {
//
// call nse com api
//
hresReturn = m_pNseObject->ComMDGetAllMetaDataW( hActualHandle,
pszMDPath,
dwMDAttributes,
dwMDUserType,
dwMDDataType,
pdwMDNumDataEntries,
pdwMDDataSetNumber,
dwMDBufferSize,
pbMDBuffer,
pdwMDRequiredBufferSize );
if ( !fSecure && SUCCEEDED(hresReturn) )
{
hresReturn = RETURNCODETOHRESULT( ERROR_ACCESS_DENIED );
}
}
else {
fRequestedInheritedStatus = dwMDAttributes & METADATA_ISINHERITED;
dwMDAttributes |= METADATA_ISINHERITED;
//
// call metadata com api
//
hresReturn = m_pMdObject->ComMDGetAllMetaDataW( hActualHandle,
pszMDPath,
dwMDAttributes,
dwMDUserType,
dwMDDataType,
pdwMDNumDataEntries,
pdwMDDataSetNumber,
dwMDBufferSize,
pbMDBuffer,
pdwMDRequiredBufferSize );
if ( SUCCEEDED(hresReturn) )
{
PMETADATA_GETALL_RECORD pMDRecord;
DWORD iP;
//
// Scan for secure properties
// For such properties, check if user has access to it using following rules:
// - must have right to access secure properties in ACE
// - must have access to property using ACL visible where property is defined
// if no access to property then remove it from list of returned properties
pMDRecord = (PMETADATA_GETALL_RECORD)pbMDBuffer;
for ( iP = 0 ; iP < *pdwMDNumDataEntries ; )
{
if ( pMDRecord->dwMDAttributes & METADATA_SECURE )
{
if ( !fSecure ||
IsReadAccessGranted( hMDHandle,
(LPWSTR)pszMDPath,
(PMETADATA_RECORD)pMDRecord ) != ERROR_SUCCESS )
{
//
// remove this property from METADATA_RECORD list,
// zero out content
//
memset( pbMDBuffer + pMDRecord->dwMDDataOffset,
0x0,
pMDRecord->dwMDDataLen );
--*pdwMDNumDataEntries;
memmove( pMDRecord,
pMDRecord + 1,
sizeof(METADATA_GETALL_RECORD) * (*pdwMDNumDataEntries-iP) );
continue;
}
}
if ( !fRequestedInheritedStatus )
{
pMDRecord->dwMDAttributes &= ~METADATA_ISINHERITED;
}
++iP;
++pMDRecord;
}
}
}
}
}
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CADMCOMW::DeleteAllData(
/* [in] */ METADATA_HANDLE hMDHandle,
/* [string][in][unique] */ LPCWSTR pszMDPath,
/* [in] */ DWORD dwMDUserType,
/* [in] */ DWORD dwMDDataType
)
{
HRESULT hresReturn = MD_ERROR_NOT_INITIALIZED;
if (dwMDDataType >= INVALID_END_METADATA) {
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
else {
METADATA_HANDLE hActualHandle;
HANDLE_TYPE HandleType;
//
// lookup and access check
//
hresReturn = LookupAndAccessCheck(hMDHandle,
&hActualHandle,
&HandleType,
pszMDPath,
0,
METADATA_PERMISSION_WRITE);
if (SUCCEEDED(hresReturn)) {
if( HandleType == NSEPM_HANDLE ) {
//
// call nse com api
//
hresReturn = m_pNseObject->ComMDDeleteAllMetaDataW( hActualHandle,
pszMDPath,
dwMDUserType,
dwMDDataType );
}
else {
//
// call metadata com api
//
hresReturn = m_pMdObject->ComMDDeleteAllMetaDataW( hActualHandle,
pszMDPath,
dwMDUserType,
dwMDDataType );
}
}
}
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CADMCOMW::CopyData(
/* [in] */ METADATA_HANDLE hMDSourceHandle,
/* [string][in] */ LPCWSTR pszMDSourcePath,
/* [in] */ METADATA_HANDLE hMDDestHandle,
/* [string][in] */ LPCWSTR pszMDDestPath,
/* [in] */ DWORD dwMDAttributes,
/* [in] */ DWORD dwMDUserType,
/* [in] */ DWORD dwMDDataType,
/* [in] */ BOOL bMDCopyFlag
)
/*++
Routine Description:
Copies or moves data associated with the source object to the destination
object.
Arguments:
hMDSourceHandle - open handle
pszMDSourcePath - path of the meta object with which then source data is
associated
hMDDestHandle - handle returned by MDOpenKey with write permission
pszMDDestPath - path of the meta object for data to be copied to
dwMDAttributes - flags for the data
dwMDUserType - user Type for the data
dwMDDataType - optional type of the data to copy
bMDCopyFlag - if true, data will be copied; if false, data will be moved.
Return Value:
Status.
--*/
{
HRESULT hresReturn = MD_ERROR_NOT_INITIALIZED;
if (((!bMDCopyFlag) && (dwMDAttributes & METADATA_INHERIT)) ||
((dwMDAttributes & METADATA_PARTIAL_PATH) && !(dwMDAttributes & METADATA_INHERIT))){
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
else {
METADATA_HANDLE hSActualHandle;
HANDLE_TYPE SHandleType;
METADATA_HANDLE hDActualHandle;
HANDLE_TYPE DHandleType;
//
// lookup and access check source
//
if (bMDCopyFlag) {
hresReturn = LookupAndAccessCheck(hMDSourceHandle,
&hSActualHandle,
&SHandleType,
pszMDSourcePath,
0,
METADATA_PERMISSION_READ);
}
else {
//
// Deleting source data, so need delete permission
//
hresReturn = LookupAndAccessCheck(hMDSourceHandle,
&hSActualHandle,
&SHandleType,
pszMDSourcePath,
0,
METADATA_PERMISSION_WRITE);
}
if (SUCCEEDED(hresReturn)) {
//
// lookup and access check dest
//
hresReturn = LookupAndAccessCheck(hMDDestHandle,
&hDActualHandle,
&DHandleType,
pszMDDestPath,
0,
METADATA_PERMISSION_WRITE);
if (SUCCEEDED(hresReturn)) {
if( SHandleType != DHandleType ) {
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_HANDLE);
}
else {
if( SHandleType == NSEPM_HANDLE ) {
//
// call nse com api
//
hresReturn = m_pNseObject->ComMDCopyMetaDataW(hSActualHandle,
pszMDSourcePath,
hDActualHandle,
pszMDDestPath,
dwMDAttributes,
dwMDUserType,
dwMDDataType,
bMDCopyFlag );
}
else {
//
// call metadata com api
//
hresReturn = m_pMdObject->ComMDCopyMetaDataW(hSActualHandle,
pszMDSourcePath,
hDActualHandle,
pszMDDestPath,
dwMDAttributes,
dwMDUserType,
dwMDDataType,
bMDCopyFlag );
}
}
}
}
}
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CADMCOMW::GetDataPaths(
/* [in] */ METADATA_HANDLE hMDHandle,
/* [string][in][unique] */ LPCWSTR pszMDPath,
/* [in] */ DWORD dwMDIdentifier,
/* [in] */ DWORD dwMDDataType,
/* [in] */ DWORD dwMDBufferSize,
/* [size_is][out] */ LPWSTR pszMDBuffer,
/* [out] */ DWORD __RPC_FAR *pdwMDRequiredBufferSize)
{
DWORD RetCode;
BOOL fSecure;
HRESULT hresReturn = MD_ERROR_NOT_INITIALIZED;
if (((pszMDBuffer == NULL) && (dwMDBufferSize != 0)) ||
(dwMDDataType >= INVALID_END_METADATA) ||
(pdwMDRequiredBufferSize == NULL)) {
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
else {
METADATA_HANDLE hActualHandle;
HANDLE_TYPE HandleType;
//
// lookup and access check
//
hresReturn = LookupAndAccessCheck(hMDHandle,
&hActualHandle,
&HandleType,
pszMDPath,
0,
METADATA_PERMISSION_READ,
&fSecure);
if (SUCCEEDED(hresReturn)) {
if( HandleType == NSEPM_HANDLE ) {
//
// call nse com api
//
hresReturn = m_pNseObject->ComMDGetMetaDataPathsW(hActualHandle,
pszMDPath,
dwMDIdentifier,
dwMDDataType,
dwMDBufferSize,
pszMDBuffer,
pdwMDRequiredBufferSize );
}
else {
//
// call metadata com api
//
hresReturn = m_pMdObject->ComMDGetMetaDataPathsW( hActualHandle,
pszMDPath,
dwMDIdentifier,
dwMDDataType,
dwMDBufferSize,
pszMDBuffer,
pdwMDRequiredBufferSize );
}
}
}
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CADMCOMW::OpenKey(
/* [in] */ METADATA_HANDLE hMDHandle,
/* [string][in] */ LPCWSTR pszMDPath,
/* [in] */ DWORD dwMDAccessRequested,
/* [in] */ DWORD dwMDTimeOut,
/* [out] */ PMETADATA_HANDLE phMDNewHandle
)
/*++
Routine Description:
Opens a meta object for read and/or write access.
Arguments:
hMDHandle - open handle
pszMDPath - path of the object to be opened
dwMDAccessRequested - permissions requested
dwMDTimeOut - time to block waiting for open to succeed, in miliseconds.
phMDNewHandle - handle to be passed to other MD routines
Return Value:
Status.
--*/
{
HRESULT hresReturn = MD_ERROR_NOT_INITIALIZED;
hresReturn = OpenKeyHelper(hMDHandle, pszMDPath, dwMDAccessRequested, dwMDTimeOut, phMDNewHandle);
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CADMCOMW::CloseKey(
/* [in] */ METADATA_HANDLE hMDHandle
)
/*++
Routine Description:
Closes a handle to a meta object.
Arguments:
hMDHandle - open handle
Return Value:
Status.
--*/
{
DWORD dwTemp;
COpenHandle *pohHandle;
HRESULT hresReturn = MD_ERROR_NOT_INITIALIZED;
if ((hMDHandle == METADATA_MASTER_ROOT_HANDLE)) {
hresReturn = E_HANDLE;
}
else {
METADATA_HANDLE hActualHandle;
HANDLE_TYPE HandleType;
//
// Map Admin Handle to Actual Handle
//
if( (dwTemp = Lookup( hMDHandle,
&hActualHandle,
&HandleType,
&pohHandle )) != ERROR_SUCCESS ) {
hresReturn = RETURNCODETOHRESULT(dwTemp);
}
else {
if( HandleType == NSEPM_HANDLE ) {
//
// call nse com api
//
hresReturn = m_pNseObject->ComMDCloseMetaObject( hActualHandle );
}
else {
//
// call metadata com api
//
hresReturn = m_pMdObject->ComMDCloseMetaObject( hActualHandle );
}
pohHandle->Release(this);
//
// Remove node from handle table
//
if (SUCCEEDED(hresReturn)) {
pohHandle->Release(this);
}
}
}
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CADMCOMW::ChangePermissions(
/* [in] */ METADATA_HANDLE hMDHandle,
/* [in] */ DWORD dwMDTimeOut,
/* [in] */ DWORD dwMDAccessRequested)
/*++
Routine Description:
Changes permissions on an open meta object handle.
Arguments:
hMDHandle - handle to be modified
dwMDTimeOut - time to block waiting for open to succeed, in miliseconds.
dwMDAccessRequested - requested permissions
Return Value:
Status.
--*/
{
DWORD RetCode = ERROR_SUCCESS;
METADATA_HANDLE hActualHandle;
HANDLE_TYPE HandleType;
HRESULT hresReturn = MD_ERROR_NOT_INITIALIZED;
//
// Map Admin Handle to Actual Handle
//
if( (RetCode = Lookup( hMDHandle,
&hActualHandle,
&HandleType )) != ERROR_SUCCESS ) {
hresReturn = RETURNCODETOHRESULT(RetCode);
}
else {
if( HandleType == NSEPM_HANDLE ) {
//
// call nse com api
//
hresReturn = m_pNseObject->ComMDChangePermissions( hActualHandle,
dwMDTimeOut,
dwMDAccessRequested );
}
else {
//
// call metadata com api
//
hresReturn = m_pMdObject->ComMDChangePermissions( hActualHandle,
dwMDTimeOut,
dwMDAccessRequested );
}
}
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CADMCOMW::SaveData(
)
/*++
Routine Description:
Saves all data changed since the last load or save to permanent storage.
Arguments:
None.
Return Value:
Status.
--*/
{
METADATA_HANDLE mdhRoot = METADATA_MASTER_ROOT_HANDLE;
HRESULT hresReturn = MD_ERROR_NOT_INITIALIZED;
if (m_pNseObject != NULL) {
//
// call nse com api
// Do this while metabase is not open, as NSE may open
// metabase internally
//
m_pNseObject->ComMDSaveData();
}
//
// First try to lock the tree
//
hresReturn = m_pMdObject->ComMDOpenMetaObjectW(METADATA_MASTER_ROOT_HANDLE,
NULL,
METADATA_PERMISSION_READ,
DEFAULT_SAVE_TIMEOUT,
&mdhRoot);
if (SUCCEEDED(hresReturn)) {
//
// call metadata com api
//
hresReturn = m_pMdObject->ComMDSaveData(mdhRoot);
m_pMdObject->ComMDCloseMetaObject(mdhRoot);
}
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CADMCOMW::GetHandleInfo(
/* [in] */ METADATA_HANDLE hMDHandle,
/* [out] */ PMETADATA_HANDLE_INFO pmdhiInfo
)
/*++
Routine Description:
Gets the information associated with a handle.
Arguments:
hMDHandle - handle to get information about
pmdhiInfo - structure filled in with the information
Return Value:
Status.
--*/
{
DWORD RetCode = ERROR_SUCCESS;
HRESULT hresReturn = MD_ERROR_NOT_INITIALIZED;
if (pmdhiInfo == NULL) {
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
else {
METADATA_HANDLE hActualHandle;
HANDLE_TYPE HandleType;
//
// Map Admin Handle to Actual Handle
//
if( (RetCode = Lookup( hMDHandle,
&hActualHandle,
&HandleType )) != ERROR_SUCCESS ) {
hresReturn = RETURNCODETOHRESULT(RetCode);
}
else {
if( HandleType == NSEPM_HANDLE ) {
//
// call nse com api
//
hresReturn = m_pNseObject->ComMDGetHandleInfo( hActualHandle,
pmdhiInfo );
}
else {
//
// call metadata com api
//
hresReturn = m_pMdObject->ComMDGetHandleInfo( hActualHandle,
pmdhiInfo );
}
}
}
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CADMCOMW::GetSystemChangeNumber(
/* [out] */ DWORD __RPC_FAR *pdwSystemChangeNumber
)
/*++
Routine Description:
Gets the System Change Number.
Arguments:
pdwSystemChangeNumber - system change number
Return Value:
Status.
--*/
{
HRESULT hresReturn = MD_ERROR_NOT_INITIALIZED;
if (pdwSystemChangeNumber == NULL) {
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
else {
//
// call metadata com api
//
hresReturn = m_pMdObject->ComMDGetSystemChangeNumber( pdwSystemChangeNumber );
}
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CADMCOMW::GetDataSetNumber(
/* [in] */ METADATA_HANDLE hMDHandle,
/* [string][in] */ LPCWSTR pszMDPath,
/* [out] */ DWORD __RPC_FAR *pdwMDDataSetNumber
)
/*++
Routine Description:
Gets all the data set number associated with a Meta Object.
Arguments:
hMDHandle - open handle
pszMDPath - path of the meta object with which this data is associated
pdwMDDataSetNumber - number associated with this data set
Return Value:
Status.
--*/
{
HRESULT hresReturn = MD_ERROR_NOT_INITIALIZED;
if (pdwMDDataSetNumber == NULL){
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
else {
METADATA_HANDLE hActualHandle;
HANDLE_TYPE HandleType;
//
// lookup and access check
//
hresReturn = LookupAndAccessCheck(hMDHandle,
&hActualHandle,
&HandleType,
pszMDPath,
0,
METADATA_PERMISSION_READ);
if (SUCCEEDED(hresReturn)) {
if( HandleType == NSEPM_HANDLE ) {
//
// call nse com api
//
hresReturn = m_pNseObject->ComMDGetDataSetNumberW( hActualHandle,
pszMDPath,
pdwMDDataSetNumber );
}
else {
//
// call metadata com api
//
hresReturn = m_pMdObject->ComMDGetDataSetNumberW( hActualHandle,
pszMDPath,
pdwMDDataSetNumber );
}
}
}
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CADMCOMW::SetLastChangeTime(
/* [in] */ METADATA_HANDLE hMDHandle,
/* [string][in][unique] */ LPCWSTR pszMDPath,
/* [in] */ PFILETIME pftMDLastChangeTime,
/* [in] */ BOOL bLocalTime)
/*++
Routine Description:
Set the last change time associated with a Meta Object.
Arguments:
hMDHandle - open handle
pszMDPath - path of the affected meta object
pftMDLastChangeTime - new change time for the meta object
Return Value:
Status.
--*/
{
FILETIME ftTime;
FILETIME *pftTime = pftMDLastChangeTime;
HRESULT hresReturn = MD_ERROR_NOT_INITIALIZED;
if (pftMDLastChangeTime == NULL){
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
else {
METADATA_HANDLE hActualHandle;
HANDLE_TYPE HandleType;
//
// lookup and access check
//
hresReturn = LookupAndAccessCheck(hMDHandle,
&hActualHandle,
&HandleType,
pszMDPath,
0,
METADATA_PERMISSION_WRITE);
if (SUCCEEDED(hresReturn)) {
if (bLocalTime) {
if (!LocalFileTimeToFileTime(pftMDLastChangeTime, &ftTime)) {
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
pftTime = &ftTime;
}
if (SUCCEEDED(hresReturn)) {
if( HandleType == NSEPM_HANDLE ) {
//
// call nse com api
//
hresReturn = m_pNseObject->ComMDSetLastChangeTimeW( hActualHandle,
pszMDPath,
pftTime );
}
else {
//
// call metadata com api
//
hresReturn = m_pMdObject->ComMDSetLastChangeTimeW( hActualHandle,
pszMDPath,
pftTime );
}
}
}
}
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CADMCOMW::GetLastChangeTime(
/* [in] */ METADATA_HANDLE hMDHandle,
/* [string][in][unique] */ LPCWSTR pszMDPath,
/* [out] */ PFILETIME pftMDLastChangeTime,
/* [in] */ BOOL bLocalTime)
/*++
Routine Description:
Set the last change time associated with a Meta Object.
Arguments:
Handle - open handle
pszMDPath - path of the affected meta object
pftMDLastChangeTime - place to return the change time for the meta object
Return Value:
Status.
--*/
{
DWORD RetCode = ERROR_SUCCESS;
FILETIME ftTime;
HRESULT hresReturn = MD_ERROR_NOT_INITIALIZED;
if (pftMDLastChangeTime == NULL){
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
else {
METADATA_HANDLE hActualHandle;
HANDLE_TYPE HandleType;
//
// lookup and access check
//
hresReturn = LookupAndAccessCheck(hMDHandle,
&hActualHandle,
&HandleType,
pszMDPath,
0,
METADATA_PERMISSION_READ);
if (SUCCEEDED(hresReturn)) {
if( HandleType == NSEPM_HANDLE ) {
//
// call nse com api
//
hresReturn = m_pNseObject->ComMDGetLastChangeTimeW( hActualHandle,
pszMDPath,
&ftTime );
}
else {
//
// call metadata com api
//
hresReturn = m_pMdObject->ComMDGetLastChangeTimeW( hActualHandle,
pszMDPath,
&ftTime );
}
if (bLocalTime) {
if (!FileTimeToLocalFileTime(&ftTime, pftMDLastChangeTime)) {
hresReturn = E_UNEXPECTED;
}
}
else {
*pftMDLastChangeTime = ftTime;
}
}
}
return hresReturn;
}
HRESULT
CADMCOMW::BackupHelper(
LPCWSTR pszMDBackupLocation,
DWORD dwMDVersion,
DWORD dwMDFlags,
LPCWSTR pszPasswd
)
{
HRESULT hresWarning = ERROR_SUCCESS;
METADATA_HANDLE mdhRoot = METADATA_MASTER_ROOT_HANDLE;
HRESULT hresReturn = MD_ERROR_NOT_INITIALIZED;
hresReturn = ERROR_SUCCESS;
if ( !AdminAclAccessCheck( m_pMdObject,
(LPVOID)this,
METADATA_MASTER_ROOT_HANDLE,
L"",
0,
METADATA_PERMISSION_READ,
&g_ohMasterRootHandle ) )
{
DBGPRINTF(( DBG_CONTEXT,
"[CADMCOMW::Backup] AdminAclAccessCheck failed, error %lx\n",
GetLastError() ));
hresReturn = RETURNCODETOHRESULT( GetLastError() );
}
else {
if ((dwMDFlags & MD_BACKUP_SAVE_FIRST) != 0) {
//
// First lock the tree
//
hresReturn = m_pMdObject->ComMDOpenMetaObjectW(METADATA_MASTER_ROOT_HANDLE,
NULL,
METADATA_PERMISSION_READ,
DEFAULT_SAVE_TIMEOUT,
&mdhRoot);
}
if (FAILED(hresReturn)) {
if ((dwMDFlags & MD_BACKUP_FORCE_BACKUP) != 0) {
hresWarning = MD_WARNING_SAVE_FAILED;
hresReturn = ERROR_SUCCESS;
dwMDFlags &= ~(MD_BACKUP_FORCE_BACKUP | MD_BACKUP_SAVE_FIRST);
}
}
if (SUCCEEDED(hresReturn)) {
//
// call metadata com api
//
if( !pszPasswd )
{
hresReturn = m_pMdObject->ComMDBackupW(mdhRoot,
pszMDBackupLocation,
dwMDVersion,
dwMDFlags);
}
else
{
hresReturn = m_pMdObject->ComMDBackupWithPasswdW(mdhRoot,
pszMDBackupLocation,
dwMDVersion,
dwMDFlags,
pszPasswd);
}
if ((dwMDFlags & MD_BACKUP_SAVE_FIRST) != 0) {
m_pMdObject->ComMDCloseMetaObject(mdhRoot);
}
}
if (hresReturn == ERROR_SUCCESS) {
hresReturn = hresWarning;
}
}
return hresReturn;
}
HRESULT
CADMCOMW::RestoreHelper(
LPCWSTR pszMDBackupLocation,
DWORD dwMDVersion,
DWORD dwMDMinorVersion,
LPCWSTR pszPasswd,
DWORD dwMDFlags,
DWORD dwRestoreType // RESTORE_HISTORY or RESTORE_BACKUP
)
{
DBG_ASSERT(dwRestoreType == RESTORE_HISTORY || dwRestoreType == RESTORE_BACKUP);
BOOL bIsWin95 = FALSE;
BOOL bIsW3svcStarted;
BUFFER bufDependentServices;
SC_HANDLE schSCM = NULL;
SC_HANDLE schIISADMIN = NULL;
DWORD dwBytesNeeded;
DWORD dwNumServices = 0;
LPENUM_SERVICE_STATUS pessDependentServices;
SERVICE_STATUS ssDependent;
HRESULT hresReturn = MD_ERROR_NOT_INITIALIZED;
hresReturn = ERROR_SUCCESS;
if ( !AdminAclAccessCheck( m_pMdObject,
(LPVOID)this,
METADATA_MASTER_ROOT_HANDLE,
L"",
0,
METADATA_PERMISSION_WRITE,
&g_ohMasterRootHandle ) )
{
if(dwRestoreType == RESTORE_HISTORY)
{
DBGPRINTF(( DBG_CONTEXT,
"[CADMCOMW::RestoreHistory] AdminAclAccessCheck failed, error %lx\n",
GetLastError() ));
}
else
{
DBGPRINTF(( DBG_CONTEXT,
"[CADMCOMW::Restore] AdminAclAccessCheck failed, error %lx\n",
GetLastError() ));
}
hresReturn = RETURNCODETOHRESULT( GetLastError() );
}
else {
if ((dwRestoreType == RESTORE_BACKUP && pszMDBackupLocation == NULL) ||
(pszMDBackupLocation && wcslen(pszMDBackupLocation) >= MD_BACKUP_MAX_LEN)) {
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
else {
WCHAR pszEnumLocation[MD_BACKUP_MAX_LEN] = {0};
DWORD dwEnumVersion;
DWORD dwEnumMinorVersion;
FILETIME ftEnumTime;
if(pszMDBackupLocation != NULL)
{
wcscpy(pszEnumLocation, pszMDBackupLocation);
}
for (DWORD i = 0; SUCCEEDED(hresReturn); i++) {
if(dwRestoreType == RESTORE_HISTORY)
{
hresReturn = m_pMdObject->ComMDEnumHistoryW(pszEnumLocation,
&dwEnumVersion,
&dwEnumMinorVersion,
&ftEnumTime,
i);
if (SUCCEEDED(hresReturn)) {
// DBG_ASSERT(_wcsicmp(pszEnumLocation, pszMDBackupLocation) == 0);
if(dwMDFlags & MD_HISTORY_LATEST)
{
break;
}
else if (dwEnumVersion == dwMDVersion &&
dwEnumMinorVersion == dwMDMinorVersion)
{
break;
}
}
}
else
{
hresReturn = m_pMdObject->ComMDEnumBackupsW(pszEnumLocation,
&dwEnumVersion,
&ftEnumTime,
i);
if (SUCCEEDED(hresReturn)) {
DBG_ASSERT(_wcsicmp(pszEnumLocation, pszMDBackupLocation) == 0);
if ((dwEnumVersion == dwMDVersion) ||
(dwMDVersion == MD_BACKUP_HIGHEST_VERSION))
{
break;
}
}
}
}
if (FAILED(hresReturn)) {
if (hresReturn == RETURNCODETOHRESULT(ERROR_NO_MORE_ITEMS)) {
if(dwRestoreType == RESTORE_HISTORY) {
if(dwMDFlags & MD_HISTORY_LATEST) {
hresReturn = RETURNCODETOHRESULT(ERROR_FILE_NOT_FOUND);
}
else {
hresReturn = RETURNCODETOHRESULT(MD_ERROR_INVALID_VERSION);
}
}
else {
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
}
}
else {
//
// Looks like a valid database
//
if ( IISGetPlatformType() == PtWindows95 ) {
bIsWin95 = TRUE;
}
if (bIsWin95) {
bIsW3svcStarted = IsInetinfoRunning();
if (bIsW3svcStarted) {
W95ShutdownW3SVC();
WaitForW95W3svcStop();
}
}
else {
schSCM = OpenSCManager(NULL,
NULL,
SC_MANAGER_ALL_ACCESS);
if (schSCM == NULL) {
hresReturn = RETURNCODETOHRESULT(GetLastError());
}
else {
schIISADMIN = OpenService(schSCM,
"IISADMIN",
STANDARD_RIGHTS_REQUIRED | SERVICE_ENUMERATE_DEPENDENTS);
if (schIISADMIN == NULL) {
hresReturn = RETURNCODETOHRESULT(GetLastError());
}
else {
if (!EnumDependentServices(schIISADMIN,
SERVICE_ACTIVE,
(LPENUM_SERVICE_STATUS)(bufDependentServices.QueryPtr()),
bufDependentServices.QuerySize(),
&dwBytesNeeded,
&dwNumServices)) {
if (GetLastError() == ERROR_MORE_DATA) {
if (!bufDependentServices.Resize(dwBytesNeeded)) {
hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
}
else {
if (!EnumDependentServices(schIISADMIN,
SERVICE_ACTIVE,
(LPENUM_SERVICE_STATUS)(bufDependentServices.QueryPtr()),
bufDependentServices.QuerySize(),
&dwBytesNeeded,
&dwNumServices)) {
hresReturn = RETURNCODETOHRESULT(GetLastError());
}
}
}
else {
hresReturn = RETURNCODETOHRESULT(GetLastError());
}
}
if (SUCCEEDED(hresReturn)) {
pessDependentServices = (LPENUM_SERVICE_STATUS)(bufDependentServices.QueryPtr());
if (dwNumServices != 0) {
SC_HANDLE schDependent;
//
// Open handles and send service control stop command
//
for (DWORD i = 0; i < dwNumServices; i++) {
//Stop Services
if (pessDependentServices[i].ServiceStatus.dwCurrentState != SERVICE_STOP_PENDING) {
schDependent = OpenService(schSCM,
pessDependentServices[i].lpServiceName,
SERVICE_ALL_ACCESS);
if (schDependent != NULL)
{
ControlService(schDependent, SERVICE_CONTROL_STOP, &ssDependent);
WaitForServiceStatus(schDependent, SERVICE_STOPPED);
CloseServiceHandle(schDependent);
}
}
}
}
}
CloseServiceHandle(schIISADMIN);
}
}
}
if (SUCCEEDED(hresReturn)) {
AdminAclDisableAclCache();
AdminAclFlushCache();
if(dwRestoreType == RESTORE_HISTORY)
{
hresReturn = m_pMdObject->ComMDRestoreHistoryW(pszMDBackupLocation,
dwMDVersion,
dwMDMinorVersion,
dwMDFlags);
}
else
{
if( !pszPasswd )
{
hresReturn = m_pMdObject->ComMDRestoreW(pszMDBackupLocation,
dwMDVersion,
dwMDFlags);
}
else
{
hresReturn = m_pMdObject->ComMDRestoreWithPasswdW(pszMDBackupLocation,
dwMDVersion,
dwMDFlags,
pszPasswd);
}
}
AdminAclEnableAclCache();
}
if (bIsWin95) {
if (bIsW3svcStarted) {
W95StartW3SVC();
//
// No good way to wait for service to start, so just
// sleep a little while
//
Sleep(SLEEP_INTERVAL);
}
}
else {
if (dwNumServices != 0) {
SC_HANDLE schDependent;
//
// Open handles and start services
// Use reverse order, since EnumServices orders
// list by dependencies
//
for (long i = (long)dwNumServices - 1; i >= 0; i--) {
//Stop Services
if (pessDependentServices[i].ServiceStatus.dwCurrentState != SERVICE_STOP_PENDING) {
schDependent = OpenService(schSCM,
pessDependentServices[i].lpServiceName,
SERVICE_ALL_ACCESS);
if (schDependent != NULL)
{
StartService(schDependent, 0, NULL);
WaitForServiceStatus(schDependent, SERVICE_RUNNING);
CloseServiceHandle(schDependent);
}
}
}
}
if (schSCM != NULL) {
CloseServiceHandle(schSCM);
}
}
//
// Issue TaylorW 4/10/2001
//
// After the restore, notify clients, as data has changed
// and all handles have become invalid
//
// Windows Bug 82423
//
}
}
}
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CADMCOMW::Backup(
/* [string][in][unique] */ LPCWSTR pszMDBackupLocation,
/* [in] */ DWORD dwMDVersion,
/* [in] */ DWORD dwMDFlags)
{
return BackupHelper( pszMDBackupLocation,
dwMDVersion,
dwMDFlags
);
}
HRESULT STDMETHODCALLTYPE
CADMCOMW::BackupWithPasswd(
/* [string][in][unique] */ LPCWSTR pszMDBackupLocation,
/* [in] */ DWORD dwMDVersion,
/* [in] */ DWORD dwMDFlags,
/* [defaultvalue][string][in][unique] */ LPCWSTR pszPasswd
)
{
return BackupHelper( pszMDBackupLocation,
dwMDVersion,
dwMDFlags,
pszPasswd
);
}
HRESULT STDMETHODCALLTYPE
CADMCOMW::Restore(
/* [string][in][unique] */ LPCWSTR pszMDBackupLocation,
/* [in] */ DWORD dwMDVersion,
/* [in] */ DWORD dwMDFlags)
{
return RestoreHelper( pszMDBackupLocation,
dwMDVersion,
0,
NULL,
dwMDFlags,
RESTORE_BACKUP
);
}
HRESULT STDMETHODCALLTYPE
CADMCOMW::RestoreWithPasswd(
/* [string][in][unique] */ LPCWSTR pszMDBackupLocation,
/* [in] */ DWORD dwMDVersion,
/* [in] */ DWORD dwMDFlags,
/* [defaultvalue][string][in][unique] */ LPCWSTR pszPasswd)
{
return RestoreHelper( pszMDBackupLocation,
dwMDVersion,
0,
pszPasswd,
dwMDFlags,
RESTORE_BACKUP
);
}
HRESULT STDMETHODCALLTYPE
CADMCOMW::EnumBackups(
/* [size_is][out][in] */ LPWSTR pszMDBackupLocation,
/* [out] */ DWORD __RPC_FAR *pdwMDVersion,
/* [out] */ PFILETIME pftMDBackupTime,
/* [in] */ DWORD dwMDEnumIndex)
{
HRESULT hresReturn = MD_ERROR_NOT_INITIALIZED;
if ( !AdminAclAccessCheck( m_pMdObject,
(LPVOID)this,
METADATA_MASTER_ROOT_HANDLE,
L"",
0,
METADATA_PERMISSION_READ,
&g_ohMasterRootHandle ) )
{
DBGPRINTF(( DBG_CONTEXT,
"[CADMCOMW::EnumBackups AdminAclAccessCheck failed, error %lx\n",
GetLastError() ));
hresReturn = RETURNCODETOHRESULT( GetLastError() );
}
else {
//
// call metadata com api
//
hresReturn = m_pMdObject->ComMDEnumBackupsW(pszMDBackupLocation,
pdwMDVersion,
pftMDBackupTime,
dwMDEnumIndex);
}
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CADMCOMW::DeleteBackup(
/* [string][in][unique] */ LPCWSTR pszMDBackupLocation,
/* [in] */ DWORD dwMDVersion)
{
HRESULT hresReturn = MD_ERROR_NOT_INITIALIZED;
if ( !AdminAclAccessCheck( m_pMdObject,
(LPVOID)this,
METADATA_MASTER_ROOT_HANDLE,
L"",
0,
METADATA_PERMISSION_WRITE,
&g_ohMasterRootHandle ) )
{
DBGPRINTF(( DBG_CONTEXT,
"[CADMCOMW::DeleteBackup] AdminAclAccessCheck failed, error %lx\n",
GetLastError() ));
hresReturn = RETURNCODETOHRESULT( GetLastError() );
}
else {
//
// call metadata com api
//
hresReturn = m_pMdObject->ComMDDeleteBackupW(pszMDBackupLocation,
dwMDVersion);
}
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CADMCOMW::Export(
/* [string][in][unique] */ LPCWSTR i_wszPasswd,
/* [string][in][unique] */ LPCWSTR i_wszFileName,
/* [string][in][unique] */ LPCWSTR i_wszSourcePath,
/* [in] */ DWORD i_dwMDFlags)
{
HRESULT hresReturn = MD_ERROR_NOT_INITIALIZED;
HRESULT hresWarning = MD_ERROR_NOT_INITIALIZED;
METADATA_HANDLE mdh = 0;
METADATA_HANDLE mdhActual = 0;
COpenHandle* pohActual = NULL;
HANDLE_TYPE mdHandleType;
//
// parameter validation
//
if (i_wszFileName == NULL || i_wszSourcePath == NULL) {
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
return hresReturn;
}
hresReturn = OpenKeyHelper(METADATA_MASTER_ROOT_HANDLE,
i_wszSourcePath,
METADATA_PERMISSION_READ,
DEFAULT_SAVE_TIMEOUT,
&mdh);
//
// pohActual refCount = 2 after Lookup.
//
if(SUCCEEDED(hresReturn)) {
hresReturn = Lookup(mdh, &mdhActual, &mdHandleType, &pohActual);
hresReturn = RETURNCODETOHRESULT(hresReturn);
}
if(SUCCEEDED(hresReturn)) {
//
// Move refCount down to 1.
//
pohActual->Release(this);
if( !AdminAclAccessCheck( m_pMdObject,
(LPVOID)this,
mdh,
L"",
0,
METADATA_PERMISSION_READ,
pohActual ) )
{
DBGPRINTF(( DBG_CONTEXT,
"[CADMCOMW::Export] AdminAclAccessCheck failed, error %lx\n",
GetLastError() ));
hresReturn = RETURNCODETOHRESULT( GetLastError() );
}
else
{
// call metadata com api
hresReturn = m_pMdObject->ComMDExportW(mdhActual,
i_wszPasswd,
i_wszFileName,
i_wszSourcePath,
i_dwMDFlags);
}
// close key
if( mdHandleType == NSEPM_HANDLE ) {
// call nse com api
hresWarning = m_pNseObject->ComMDCloseMetaObject( mdhActual );
}
else {
// call metadata com api
hresWarning = m_pMdObject->ComMDCloseMetaObject( mdhActual );
}
pohActual->Release(this);
}
if(SUCCEEDED(hresReturn)) {
hresReturn = hresWarning;
}
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CADMCOMW::Import(
/* [string][in][unique] */ LPCWSTR i_wszPasswd,
/* [string][in][unique] */ LPCWSTR i_wszFileName,
/* [string][in][unique] */ LPCWSTR i_wszSourcePath,
/* [string][in][unique] */ LPCWSTR i_wszDestPath,
/* [in] */ DWORD i_dwMDFlags)
/*++
Synopsis:
Arguments: [i_wszPasswd] -
[i_wszFileName] -
[i_wszSourcePath] - Absolute metabase path
[i_wszDestPath] - Absolute metabase path
[i_dwMDFlags] -
Return Value:
--*/
{
HRESULT hresReturn = MD_ERROR_NOT_INITIALIZED;
HRESULT hresWarning = MD_ERROR_NOT_INITIALIZED;
METADATA_HANDLE mdh = 0;
METADATA_HANDLE mdhActual = 0;
COpenHandle* pohActual = NULL;
HANDLE_TYPE mdHandleType;
LPWSTR wszDeepest = NULL;
LONG cchDeepest = 0;
LPWSTR wszEnd = NULL;
LONG idx = 0;
WCHAR wszKeyType[METADATA_MAX_STRING_LEN] = {0};
DWORD dwRequiredSize = 0;
METADATA_RECORD mr = {
MD_KEY_TYPE,
METADATA_NO_ATTRIBUTES,
IIS_MD_UT_SERVER,
STRING_METADATA,
METADATA_MAX_STRING_LEN*sizeof(WCHAR),
(LPBYTE)wszKeyType,
0
};
//
// parameter validation
//
if (i_wszFileName == NULL || i_wszSourcePath == NULL || i_wszDestPath == NULL)
{
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
return hresReturn;
}
if (i_wszPasswd == NULL)
{
i_wszPasswd = L"";
}
//
// else we can move on, but FreeInUse() must be called before exiting this
// function. this is done in exit section.
//
//
// Copy i_wszDestPath to wszDeepest
// Remove trailing slashes
//
cchDeepest = wcslen(i_wszDestPath);
wszDeepest = new WCHAR[1+cchDeepest];
if(!wszDeepest)
{
hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
goto exit;
}
memcpy(wszDeepest, i_wszDestPath, sizeof(WCHAR)*(cchDeepest+1));
while( cchDeepest > 0 && IS_MD_PATH_DELIM(wszDeepest[cchDeepest-1]) )
{
cchDeepest--;
}
//
// Open the deepest level key possible
//
wszEnd = wszDeepest + cchDeepest;
for(idx = cchDeepest; idx >= 0; idx--)
{
if(idx == 0 || idx == cchDeepest || IS_MD_PATH_DELIM(*wszEnd))
{
*wszEnd = L'\0';
hresReturn = OpenKeyHelper(
METADATA_MASTER_ROOT_HANDLE,
wszDeepest,
METADATA_PERMISSION_WRITE | METADATA_PERMISSION_READ,
DEFAULT_SAVE_TIMEOUT,
&mdh);
if( FAILED(hresReturn) &&
hresReturn != RETURNCODETOHRESULT(ERROR_PATH_NOT_FOUND) )
{
goto exit;
}
else if(SUCCEEDED(hresReturn))
{
break;
}
}
wszEnd--;
}
if(FAILED(hresReturn))
{
goto exit;
}
//
// If we are here, we now have an Open metabase handle
//
hresReturn = Lookup(mdh, &mdhActual, &mdHandleType, &pohActual);
hresReturn = RETURNCODETOHRESULT(hresReturn);
if(FAILED(hresReturn))
{
//
// Yes, an open key does not get closed, but Lookup really should
// not fail if mdh is a valid key.
//
goto exit;
}
pohActual->Release(this); // Decrements refcount from 2 to 1.
if( !AdminAclAccessCheck( m_pMdObject,
(LPVOID)this,
mdh,
L"",
0,
METADATA_PERMISSION_WRITE | METADATA_PERMISSION_READ,
pohActual ) )
{
DBGPRINTF(( DBG_CONTEXT,
"[CADMCOMW::Import] AdminAclAccessCheck failed, error %lx\n",
GetLastError() ));
hresReturn = RETURNCODETOHRESULT( GetLastError() );
goto exit;
}
//
// Get the keytype
// If the node does not exist, or node exists but keytype doesn't, we
// will not set wszKeytype and hence ComMDImport will not attempt to match
// the source and dest keytype
//
hresReturn = m_pMdObject->ComMDGetMetaDataW(
mdhActual,
i_wszDestPath+idx,
&mr,
&dwRequiredSize);
if(hresReturn == RETURNCODETOHRESULT(ERROR_PATH_NOT_FOUND))
{
hresReturn = S_OK;
}
else if(hresReturn == MD_ERROR_DATA_NOT_FOUND)
{
hresReturn = S_OK;
}
if(FAILED(hresReturn))
{
DBGPRINTF((DBG_CONTEXT, "Error trying to retrieve keytype for %ws\n", i_wszDestPath+idx));
goto exit;
}
//
// Call Import
//
hresReturn = m_pMdObject->ComMDImportW(
mdhActual,
i_wszDestPath+idx,
wszKeyType,
i_wszPasswd,
i_wszFileName,
i_wszSourcePath,
i_dwMDFlags);
if(FAILED(hresReturn))
{
goto exit;
}
exit:
if(pohActual != NULL)
{
//
// Close Key
//
if( mdHandleType == NSEPM_HANDLE )
{
// call nse com api
hresWarning = m_pNseObject->ComMDCloseMetaObject( mdhActual );
}
else
{
// call metadata com api
hresWarning = m_pMdObject->ComMDCloseMetaObject( mdhActual );
}
pohActual->Release(this);
pohActual = NULL;
}
delete [] wszDeepest;
return (FAILED(hresReturn)) ? hresReturn : hresWarning;
}
HRESULT STDMETHODCALLTYPE
CADMCOMW::RestoreHistory(
/* [unique][in][string] */ LPCWSTR pszMDHistoryLocation,
/* [in] */ DWORD dwMDMajorVersion,
/* [in] */ DWORD dwMDMinorVersion,
/* [in] */ DWORD dwMDFlags)
{
HRESULT hresReturn = ERROR_SUCCESS;
if( (dwMDFlags & ~MD_HISTORY_LATEST) != 0 &&
dwMDFlags != 0 )
{
return HRESULT_FROM_WIN32(ERROR_INVALID_FLAGS);
}
if( (dwMDFlags & MD_HISTORY_LATEST) &&
(dwMDMajorVersion != 0 || dwMDMinorVersion != 0) )
{
return E_INVALIDARG;
}
//
// parameter validation done in here.
//
hresReturn = RestoreHelper(pszMDHistoryLocation,
dwMDMajorVersion,
dwMDMinorVersion,
NULL,
dwMDFlags,
RESTORE_HISTORY);
return hresReturn;
}
HRESULT STDMETHODCALLTYPE
CADMCOMW::EnumHistory(
/* [size_is][out][in] */ LPWSTR io_wszMDHistoryLocation,
/* [out] */ DWORD __RPC_FAR *o_pdwMDMajorVersion,
/* [out] */ DWORD __RPC_FAR *o_pdwMDMinorVersion,
/* [out] */ PFILETIME o_pftMDHistoryTime,
/* [in] */ DWORD i_dwMDEnumIndex)
{
HRESULT hresReturn = MD_ERROR_NOT_INITIALIZED;
if (io_wszMDHistoryLocation == NULL ||
o_pdwMDMajorVersion == NULL ||
o_pdwMDMinorVersion == NULL ||
o_pftMDHistoryTime == NULL) {
return RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
if ( !AdminAclAccessCheck( m_pMdObject,
(LPVOID)this,
METADATA_MASTER_ROOT_HANDLE,
L"",
0,
METADATA_PERMISSION_READ,
&g_ohMasterRootHandle ) )
{
DBGPRINTF(( DBG_CONTEXT,
"[CADMCOMW::EnumHistory AdminAclAccessCheck failed, error %lx\n",
GetLastError() ));
hresReturn = RETURNCODETOHRESULT( GetLastError() );
}
else {
//
// call metadata com api
//
hresReturn = m_pMdObject->ComMDEnumHistoryW(io_wszMDHistoryLocation,
o_pdwMDMajorVersion,
o_pdwMDMinorVersion,
o_pftMDHistoryTime,
i_dwMDEnumIndex);
}
return hresReturn;
}
VOID
CADMCOMW::ReleaseNode(
IN HANDLE_TABLE *phndTable
)
{
if ( phndTable )
{
m_rHandleResource.Unlock();
}
}
HRESULT
CADMCOMW::AddKeyHelper(
IN METADATA_HANDLE hMDHandle,
IN LPCWSTR pszMDPath
)
/*++
Routine Description:
Add meta object and adds it to the list of child objects for the object
specified by Path.
Arguments:
hMDHandle - open handle
pszMDPath - path of the object to be added
Return Value:
Status.
--*/
{
HRESULT hresReturn = MD_ERROR_NOT_INITIALIZED;
if ((pszMDPath == NULL) ||
(*pszMDPath == (WCHAR)'\0')) {
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
else {
METADATA_HANDLE hActualHandle;
HANDLE_TYPE HandleType;
//
// lookup and access check
//
hresReturn = LookupAndAccessCheck(hMDHandle,
&hActualHandle,
&HandleType,
pszMDPath,
0,
METADATA_PERMISSION_WRITE);
if (SUCCEEDED(hresReturn)) {
if( HandleType == NSEPM_HANDLE ) {
//
// call nse com api
//
hresReturn = m_pNseObject->ComMDAddMetaObjectW( hActualHandle,
pszMDPath );
}
else {
//
// call metadata com api
//
hresReturn = m_pMdObject->ComMDAddMetaObjectW( hActualHandle,
pszMDPath );
}
}
}
return hresReturn;
}
HRESULT
CADMCOMW::OpenKeyHelper(
/* [in] */ METADATA_HANDLE hMDHandle,
/* [string][in] */ LPCWSTR pszMDPath,
/* [in] */ DWORD dwMDAccessRequested,
/* [in] */ DWORD dwMDTimeOut,
/* [out] */ PMETADATA_HANDLE phMDNewHandle
)
/*++
Routine Description:
Opens a meta object for read and/or write access.
- This is used by Export.
Arguments:
hMDHandle - open handle
pszMDPath - path of the object to be opened
dwMDAccessRequested - permissions requested
dwMDTimeOut - time to block waiting for open to succeed, in miliseconds.
phMDNewHandle - handle to be passed to other MD routines
Return Value:
Status.
--*/
{
HRESULT hresReturn = MD_ERROR_NOT_INITIALIZED;
if ((phMDNewHandle == NULL) ||
((dwMDAccessRequested & (METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE)) == 0)) {
hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
else {
METADATA_HANDLE hNewHandle;
METADATA_HANDLE hActualHandle;
HANDLE_TYPE HandleType;
DWORD RetCode;
HANDLE_TABLE *phtNode;
UINT cL;
COpenHandle *pohParent;
//
// Map Admin Handle to Actual Handle
//
//
// This Addrefs pohParent, which makes sure it doesn't do away
// pohParent is needed by AddNode
//
RetCode = Lookup( hMDHandle,
&hActualHandle,
&HandleType,
&pohParent);
if( RetCode == ERROR_SUCCESS) {
if(HandleType == NSEPM_HANDLE || (HandleType == ALL_HANDLE &&
pszMDPath != NULL && IsValidNsepmPath( pszMDPath )) ) {
//
// call nse com api
//
hresReturn = m_pNseObject->ComMDOpenMetaObjectW( hActualHandle,
pszMDPath,
dwMDAccessRequested,
dwMDTimeOut,
&hNewHandle );
if( SUCCEEDED(hresReturn) ) {
hresReturn = AddNode( hNewHandle,
pohParent,
NSEPM_HANDLE,
phMDNewHandle,
pszMDPath );
if (FAILED(hresReturn)) {
m_pNseObject->ComMDCloseMetaObject( hNewHandle );
}
}
}
else {
DBG_ASSERT( HandleType == META_HANDLE || HandleType == ALL_HANDLE );
//
// call metadata com api
//
hresReturn = m_pMdObject->ComMDOpenMetaObjectW( hActualHandle,
pszMDPath,
dwMDAccessRequested,
dwMDTimeOut,
&hNewHandle );
if( SUCCEEDED(hresReturn) ) {
hresReturn = AddNode( hNewHandle,
pohParent,
META_HANDLE,
phMDNewHandle,
pszMDPath );
if (FAILED(hresReturn)) {
m_pMdObject->ComMDCloseMetaObject( hNewHandle );
}
}
}
pohParent->Release(this);
}
else {
hresReturn = RETURNCODETOHRESULT(RetCode);
}
}
return hresReturn;
}
DWORD
CADMCOMW::Lookup(
IN METADATA_HANDLE hHandle,
OUT METADATA_HANDLE *phActualHandle,
OUT HANDLE_TYPE *HandleType,
OUT COpenHandle **ppohHandle
)
{
HANDLE_TABLE *phtNode;
DWORD dwReturn = ERROR_INVALID_HANDLE;
if( hHandle == METADATA_MASTER_ROOT_HANDLE ) {
*phActualHandle = g_MasterRoot.hActualHandle;
*HandleType = g_MasterRoot.HandleType;
if (ppohHandle != NULL) {
*ppohHandle = g_MasterRoot.pohHandle;
(*ppohHandle)->AddRef();
}
dwReturn = ERROR_SUCCESS;
}
else {
m_rHandleResource.Lock(TSRES_LOCK_READ);
for( phtNode = m_hashtab[(DWORD)hHandle % HASHSIZE]; phtNode != NULL;
phtNode = phtNode->next ) {
if( phtNode->hAdminHandle == hHandle ) {
*phActualHandle = phtNode->hActualHandle;
*HandleType = phtNode->HandleType;
if (ppohHandle != NULL) {
*ppohHandle = phtNode->pohHandle;
(*ppohHandle)->AddRef();
}
dwReturn = ERROR_SUCCESS;
break;
}
}
m_rHandleResource.Unlock();
}
return dwReturn;
}
VOID
CADMCOMW::DisableAllHandles(
)
{
HANDLE_TABLE *phtNode;
DWORD i;
//
// At this point, all metadata handles should be closed because a retore
// just happened. So don't need to close these handles.
//
//
// Can't just delete them, becuase of syncronization problems
// with CloseKey and Lookup. Set the hande to an invalid value
// So Lookup won't use them.
//
m_rHandleResource.Lock(TSRES_LOCK_WRITE);
for( i = 0; i < HASHSIZE; i++ ) {
for( phtNode = m_hashtab[i]; phtNode != NULL; phtNode = phtNode->next ) {
phtNode->hAdminHandle = INVALID_ADMINHANDLE_VALUE;
}
}
if ( m_pNseObject ) {
m_pNseObject->ComMDRestoreW( NULL,
0,
0 );
}
m_rHandleResource.Unlock();
}
HRESULT
CADMCOMW::LookupAndAccessCheck(
IN METADATA_HANDLE hHandle,
OUT METADATA_HANDLE *phActualHandle,
OUT HANDLE_TYPE *pHandleType,
IN LPCWSTR pszPath,
IN DWORD dwId, // check for MD_ADMIN_ACL, must have special right to write them
IN DWORD dwAccess, // METADATA_PERMISSION_*
OUT LPBOOL pfEnableSecureAccess
)
{
DWORD dwReturn = ERROR_SUCCESS;
COpenHandle *pohParent;
//
// Map Admin Handle to Actual Handle
//
//
// This Addrefs pohParent, which makes sure it doesn't go away
// until AdminAclAccessCheck is done
//
dwReturn = Lookup( hHandle,
phActualHandle,
pHandleType,
&pohParent);
if (dwReturn == ERROR_SUCCESS) {
if (!AdminAclAccessCheck(m_pMdObject,
(LPVOID)this,
hHandle,
pszPath,
dwId,
dwAccess,
pohParent,
pfEnableSecureAccess)) {
dwReturn = GetLastError();
}
pohParent->Release(this);
}
return RETURNCODETOHRESULT(dwReturn);
}
DWORD
CADMCOMW::LookupActualHandle(
IN METADATA_HANDLE hHandle
)
{
HANDLE_TABLE *phtNode;
DWORD i;
DWORD dwReturn = ERROR_INVALID_HANDLE;
m_rHandleResource.Lock(TSRES_LOCK_READ);
for( i = 0; (i < HASHSIZE) && (dwReturn != ERROR_SUCCESS); i++ ) {
for( phtNode = m_hashtab[i]; (phtNode != NULL) && (dwReturn != ERROR_SUCCESS); phtNode = phtNode->next ) {
if( phtNode->hActualHandle == hHandle ) {
dwReturn = ERROR_SUCCESS;
}
}
}
m_rHandleResource.Unlock();
return dwReturn;
}
HRESULT
CADMCOMW::AddNode(
METADATA_HANDLE hActualHandle,
COpenHandle *pohParentHandle,
enum HANDLE_TYPE HandleType,
PMETADATA_HANDLE phAdminHandle,
LPCWSTR pszPath
)
{
HANDLE_TABLE *phtNode = (HANDLE_TABLE *)LocalAlloc(LMEM_FIXED, sizeof(*phtNode));
DWORD hashVal;
HRESULT hresReturn = ERROR_SUCCESS;
COpenHandle * pohHandle = new COpenHandle;
METADATA_HANDLE hParentActualHandle;
HANDLE_TYPE htParentType;
if ((phtNode == NULL) ||
(pohHandle == NULL)) {
hresReturn = E_OUTOFMEMORY;
if( phtNode )
{
LocalFree(phtNode);
}
if( pohHandle )
{
delete pohHandle;
}
}
else {
m_rHandleResource.Lock(TSRES_LOCK_WRITE);
hresReturn = pohHandle->Init(m_dwHandleValue,
pszPath,
pohParentHandle->GetPath(),
(HandleType == NSEPM_HANDLE) ? TRUE : FALSE);
if (FAILED(hresReturn)) {
LocalFree(phtNode);
delete pohHandle;
}
else {
phtNode->pohHandle = pohHandle;
phtNode->hAdminHandle = m_dwHandleValue;
*phAdminHandle = m_dwHandleValue++;
phtNode->hActualHandle = hActualHandle;
phtNode->HandleType = HandleType;
hashVal = (phtNode->hAdminHandle) % HASHSIZE;
phtNode->next = m_hashtab[hashVal];
m_hashtab[hashVal] = phtNode;
}
m_rHandleResource.Unlock();
}
return hresReturn;
}
DWORD
CADMCOMW::DeleteNode(
METADATA_HANDLE hHandle
)
{
HANDLE_TABLE *phtNode;
HANDLE_TABLE *phtDelNode;
DWORD HashValue = (DWORD)hHandle % HASHSIZE;
if( hHandle == METADATA_MASTER_ROOT_HANDLE ) {
return ERROR_SUCCESS;
}
m_rHandleResource.Lock(TSRES_LOCK_WRITE);
phtNode = m_hashtab[HashValue];
//
// check single node linked list
//
if( phtNode->hAdminHandle == hHandle ) {
m_hashtab[HashValue] = phtNode->next;
delete phtNode->pohHandle;
LocalFree(phtNode);
}
else {
for( ; phtNode != NULL; phtNode = phtNode->next ) {
phtDelNode = phtNode->next;
if( phtDelNode != NULL ) {
if( phtDelNode->hAdminHandle == hHandle ) {
phtNode->next = phtDelNode->next;
delete phtDelNode->pohHandle;
LocalFree(phtDelNode);
break;
}
}
}
}
m_rHandleResource.Unlock();
return ERROR_SUCCESS;
}
//---------------
/*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
Method: COPaper::NotifySinks
Summary: Internal utility method of this COM object used to fire event
notification calls to all listening connection sinks in the
client.
Args: PAPER_EVENT PaperEvent
Type of notification event.
SHORT nX
X cordinate. Value is 0 unless event needs it.
SHORT nY
Y cordinate. Value is 0 unless event needs it.
SHORT nInkWidth
Ink Width. Value is 0 unless event needs it.
SHORT crInkColor
COLORREF RGB color value. Value is 0 unless event needs it.
Modifies: ...
Returns: HRESULT
Standard OLE result code. NOERROR for success.
M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
HRESULT
CADMCOMW::NotifySinks(
/* [in] */ METADATA_HANDLE hMDHandle,
/* [in] */ DWORD dwMDNumElements,
/* [size_is][in] */ MD_CHANGE_OBJECT_W __RPC_FAR pcoChangeList[ ],
/* [in] */ BOOL bIsMainNotification)
{
// DBGPRINTF(( DBG_CONTEXT, "[CADMCOMW::NotifySink]\n" ));
HRESULT hr = NOERROR;
IConnectionPoint* pIConnectionPoint;
IEnumConnections* pIEnum;
CONNECTDATA ConnData;
HRESULT hrTemp;
HANDLE_TABLE *node;
m_rSinkResource.Lock(TSRES_LOCK_READ);
if (m_bCallSinks) {
//
// if the meta handle is for this object, return ERROR_SUCCESS to
// the caller (admin's sink);
//
if( !bIsMainNotification || (LookupActualHandle( hMDHandle ) != ERROR_SUCCESS) ) {
//
// Correct broken connections.
// It's not likely to be a high number so
// save a memory allocation by using an array.
//
DWORD pdwLostConnections[MAX_SINK_CALLS_TOBE_REMOVED];
DWORD dwNumLostConnections = 0;
// If there was a paper event, broadcast appropriate notifications to
// all Sinks connected to each connection point.
// if (PAPER_EVENT_NONE != PaperEvent)
{
// Here is the section for the PaperSink connection point--currently
// this is the only connection point offered by COPaper objects.
pIConnectionPoint = m_aConnectionPoints[ADM_CONNPOINT_WRITESINK];
if (NULL != pIConnectionPoint)
{
pIConnectionPoint->AddRef();
hr = pIConnectionPoint->EnumConnections(&pIEnum);
if (SUCCEEDED(hr)) {
// Loop thru the connection point's connections and if the
// listening connection supports IPaperSink (ie, PaperSink events)
// then dispatch the PaperEvent event notification to that sink.
while (NOERROR == pIEnum->Next(1, &ConnData, NULL))
{
IMSAdminBaseSinkW *pIADMCOMSINKW_Synchro = NULL;
AsyncIMSAdminBaseSinkW *pIADMCOMSINKW_Async = NULL;
ICallFactory *pCF = NULL;
HRESULT hr ;
hr = ConnData.pUnk->QueryInterface(IID_ICallFactory, (void **)&pCF);
if (SUCCEEDED(hr))
{
hr = pCF->CreateCall(IID_AsyncIMSAdminBaseSink_W, NULL, IID_AsyncIMSAdminBaseSink_W,
(IUnknown **)&pIADMCOMSINKW_Async);
if (SUCCEEDED(hr))
{
if (bIsMainNotification) {
hr = pIADMCOMSINKW_Async->Begin_SinkNotify(dwMDNumElements,
pcoChangeList);
}
else {
hr = pIADMCOMSINKW_Async->Begin_ShutdownNotify();
}
pIADMCOMSINKW_Async->Release();
}
else
{
DBGPRINTF(( DBG_CONTEXT, "Failled in CreateCall to ICallFactory !!!!\n" ));
}
pCF->Release();
}
else
{
hr = ConnData.pUnk->QueryInterface(IID_IMSAdminBaseSink_W,
(PPVOID)&pIADMCOMSINKW_Synchro);
if (SUCCEEDED(hr))
{
if (bIsMainNotification) {
hr = pIADMCOMSINKW_Synchro->SinkNotify(dwMDNumElements,
pcoChangeList);
}
else {
hr= pIADMCOMSINKW_Synchro->ShutdownNotify();
}
pIADMCOMSINKW_Synchro->Release();
}
else
{
DBGPRINTF(( DBG_CONTEXT, "Failled in QueryInterface for synchro version of IID_IMSAdminBaseSink_W\n" ));
}
}
if (FAILED(hr)) {
if ((HRESULT_CODE(hr) == RPC_S_SERVER_UNAVAILABLE) ||
((HRESULT_CODE(hr) >= RPC_S_NO_CALL_ACTIVE) &&
(HRESULT_CODE(hr) <= RPC_S_CALL_FAILED_DNE))) {
if (dwNumLostConnections < MAX_SINK_CALLS_TOBE_REMOVED) {
pdwLostConnections[dwNumLostConnections++] = ConnData.dwCookie;
}
}
}
ConnData.pUnk->Release();
}
pIEnum->Release();
}
while (dwNumLostConnections > 0) {
m_rSinkResource.Convert(TSRES_CONV_WRITE);
((COConnectionPoint *)pIConnectionPoint)->Unadvise_Worker(
pdwLostConnections[--dwNumLostConnections]);
}
pIConnectionPoint->Release();
}
}
}
}
m_rSinkResource.Unlock();
return hr;
}
//
// Stubs for routine that clients shouldn't be calling anyway.
//
HRESULT
CADMCOMW::KeyExchangePhase1()
{
return E_FAIL;
}
HRESULT
CADMCOMW::KeyExchangePhase2()
{
return E_FAIL;
}
HRESULT STDMETHODCALLTYPE
CADMCOMW::GetServerGuid( void)
{
return E_FAIL;
}
HRESULT STDMETHODCALLTYPE
CADMCOMW::UnmarshalInterface(
/* [out] */ IMSAdminBaseW __RPC_FAR *__RPC_FAR *piadmbwInterface)
{
AddRef(); // Always return interfaces addref'ed
*piadmbwInterface = (IMSAdminBaseW *)this;
return(NOERROR);
}
BOOL
CADMCOMW::CheckGetAttributes(DWORD dwAttributes)
{
DWORD dwReturn = TRUE;
if ((dwAttributes & METADATA_REFERENCE) ||
((dwAttributes & METADATA_PARTIAL_PATH) &&
!(dwAttributes & METADATA_INHERIT))) {
dwReturn = FALSE;
}
return dwReturn;
}
VOID
WaitForW95W3svcStop()
{
DWORD dwSleepTotal = 0;
while (dwSleepTotal < MAX_SLEEP) {
if (!IsInetinfoRunning()) {
break;
}
else {
//
// Still pending...
//
Sleep(SLEEP_INTERVAL);
dwSleepTotal += SLEEP_INTERVAL;
}
}
}
VOID
WaitForServiceStatus(SC_HANDLE schDependent, DWORD dwDesiredServiceState)
{
DWORD dwSleepTotal = 0;
SERVICE_STATUS ssDependent;
while (dwSleepTotal < MAX_SLEEP) {
if (QueryServiceStatus(schDependent, &ssDependent)) {
if (ssDependent.dwCurrentState == dwDesiredServiceState) {
break;
}
else {
//
// Still pending...
//
Sleep(SLEEP_INTERVAL);
dwSleepTotal += SLEEP_INTERVAL;
}
}
else {
break;
}
}
}
DWORD
CADMCOMW::IsReadAccessGranted(
METADATA_HANDLE hHandle,
LPWSTR pszPath,
METADATA_RECORD* pmdRecord
)
/*++
Routine Description:
Check if read access to property granted based on ACL visible at point in metabase
where property is stored ( as opposed as check made by AdminAclAccessCheck which uses
the ACL visible at path specified during data access )
Arguments:
hHandle - DCOM metabase handle
pszPath - path relative to hHandle
pmdRecord - metadata info to access property
Returns:
ERROR_SUCCESS if access granted, otherwise error code
--*/
{
DWORD dwStatus = ERROR_SUCCESS;
LPWSTR pszPropPath;
//
// If property is not inherited then we already checked the correct ACL
//
if ( !(pmdRecord->dwMDAttributes & METADATA_ISINHERITED) )
{
return dwStatus;
}
// determine from where we got it
// do AccessCheck
if ( (dwStatus = FindClosestProp( hHandle,
pszPath,
&pszPropPath,
pmdRecord->dwMDIdentifier,
pmdRecord->dwMDDataType,
pmdRecord->dwMDUserType,
METADATA_SECURE,
TRUE )) == ERROR_SUCCESS )
{
if ( pszPropPath ) // i.e such a property exist
{
dwStatus = AdminAclAccessCheck( m_pMdObject,
(LPVOID)this,
METADATA_MASTER_ROOT_HANDLE,
pszPropPath,
pmdRecord->dwMDIdentifier,
METADATA_PERMISSION_READ,
&g_ohMasterRootHandle ) ?
ERROR_SUCCESS :
GetLastError();
LocalFree( pszPropPath );
}
else
{
dwStatus = MD_ERROR_DATA_NOT_FOUND;
//
// Should not happen unless handle is master root :
// if we are here then we succeeded accessing data and as we have a read handle
// nobody should be able to delete it
// if master root handle we don't have such protection, so property could
// have been deleted.
//
DBG_ASSERT ( METADATA_MASTER_ROOT_HANDLE == hHandle );
}
}
return dwStatus;
}
DWORD
CADMCOMW::FindClosestProp(
METADATA_HANDLE hHandle,
LPWSTR pszRelPath,
LPWSTR* ppszPropPath,
DWORD dwPropId,
DWORD dwDataType,
DWORD dwUserType,
DWORD dwAttr,
BOOL fSkipCurrentNode
)
/*++
Routine Description:
Find the closest path where the specified property exist ( in the direction of
the root ) in metabase
Arguments:
hHandle - DCOM metabase handle
pszRelPath - path relative to hHandle
ppszPropPath - updated with path to property or NULL if property not found
dwPropId - property ID
dwDataType - property data type
dwUserType - property user type
dwAttr - property attribute
fSkipCurrentNode - TRUE to skip current node while scanning for property
Returns:
TRUE if success ( including property not found ), otherwise FALSE
--*/
{
DWORD dwReturn;
LPWSTR pszParentPath;
METADATA_HANDLE hActualHandle;
HANDLE_TYPE HandleType;
COpenHandle * pohParent;
HRESULT hRes;
METADATA_RECORD mdRecord;
DWORD dwRequiredLen;
LPWSTR pszPath;
BOOL fFound;
dwReturn = Lookup( hHandle,
&hActualHandle,
&HandleType,
&pohParent);
if ( dwReturn != ERROR_SUCCESS )
{
return dwReturn;
}
pszParentPath = pohParent->GetPath();
if (pszRelPath == NULL) {
pszRelPath = L"";
}
DBG_ASSERT(pszParentPath != NULL);
DBG_ASSERT((*pszParentPath == (WCHAR)'\0') ||
ISPATHDELIMW(*pszParentPath));
//
// Strip front slash now, add it in later
//
if (ISPATHDELIMW(*pszRelPath)) {
pszRelPath++;
}
DWORD dwRelPathLen = wcslen(pszRelPath);
DWORD dwParentPathLen = wcslen(pszParentPath);
DBG_ASSERT((dwParentPathLen == 0) ||
(!ISPATHDELIMW(pszParentPath[dwParentPathLen -1])));
//
// Get rid of trailing slash for good
//
if ((dwRelPathLen > 0) && (ISPATHDELIMW(pszRelPath[dwRelPathLen -1]))) {
dwRelPathLen--;
}
//
// Include space for mid slash if Relpath exists
// Include space for termination
//
DWORD dwTotalSize =
(dwRelPathLen + dwParentPathLen + 1 + ((dwRelPathLen > 0) ? 1 : 0)) * sizeof(WCHAR);
*ppszPropPath = pszPath = (LPWSTR)LocalAlloc(LMEM_FIXED, dwTotalSize);
if (pszPath == NULL) {
dwReturn = GetLastError();
}
else {
//
// OK to always copy the first part
//
memcpy(pszPath,
pszParentPath,
dwParentPathLen * sizeof(WCHAR));
//
// Don't need slash if there is no RelPath
//
if (dwRelPathLen > 0) {
pszPath[dwParentPathLen] = (WCHAR)'/';
memcpy(pszPath + dwParentPathLen + 1,
pszRelPath,
dwRelPathLen * sizeof(WCHAR));
}
pszPath[(dwTotalSize / sizeof(WCHAR)) - 1] = (WCHAR)'\0';
//
// Now convert \ to / for string compares
//
LPWSTR pszPathIndex = pszPath;
while ((pszPathIndex = wcschr(pszPathIndex, (WCHAR)'\\')) != NULL) {
*pszPathIndex = (WCHAR)'/';
}
// scan for property
pszPathIndex = pszPath + wcslen(pszPath);
while ( TRUE )
{
if ( !fSkipCurrentNode )
{
// check prop exist
mdRecord.dwMDIdentifier = dwPropId;
mdRecord.dwMDAttributes = dwAttr;
mdRecord.dwMDUserType = dwUserType;
mdRecord.dwMDDataType = dwDataType;
mdRecord.dwMDDataLen = 0;
mdRecord.pbMDData = NULL;
mdRecord.dwMDDataTag = NULL;
hRes = m_pMdObject->ComMDGetMetaDataW( METADATA_MASTER_ROOT_HANDLE,
pszPath,
&mdRecord,
&dwRequiredLen );
if ( hRes == RETURNCODETOHRESULT(ERROR_INSUFFICIENT_BUFFER) )
{
break;
}
}
// scan backward for delimiter
fFound = FALSE;
if ( pszPathIndex > pszPath )
{
do {
if ( *--pszPathIndex == L'/' )
{
*pszPathIndex = L'\0';
fFound = TRUE;
break;
}
} while ( pszPathIndex > pszPath );
}
if ( !fFound )
{
// Property not found, return OK status with NULL string
*ppszPropPath = NULL;
LocalFree( pszPath );
break;
}
fSkipCurrentNode = FALSE;
}
}
pohParent->Release( this );
return dwReturn;
}
BOOL
MakeParentPath(
LPWSTR pszPath
)
/*++
Routine Description:
Make the path points to parent
Arguments:
pszPath - path to adjust
Returns:
TRUE if success, otherwise FALSE ( no parent )
--*/
{
LPWSTR pszPathIndex = pszPath + wcslen( pszPath );
BOOL fFound = FALSE;
while ( pszPathIndex > pszPath )
{
if ( *--pszPathIndex == L'/' )
{
*pszPathIndex = L'\0';
fFound = TRUE;
break;
}
}
return fFound;
}
BOOL
IsValidNsepmPath(
LPCWSTR pszMDPath
)
/*++
Routine Description:
Determine if pszMDPath is a valid NSEPM path.
Really the following are the only valid path forms, but we are going
to do a simpler test and just reject paths that have "Root" before the
<nsepm>.
/lm/<service>/<nsepm>
/lm/<service>/<#>/<nsepm>
Arguments:
psMDPath - the path to validate
Return Value:
TRUE if path is valid
--*/
{
BOOL ValidPath = FALSE;
LPWSTR pszNsepmTag;
if( pszNsepmTag = wcsstr( pszMDPath, L"<nsepm>" ) )
{
DWORD cchPrefix = DIFF( pszNsepmTag - pszMDPath );
LPWSTR pszPrefix = (LPWSTR)LocalAlloc( LPTR, (cchPrefix + 1) * sizeof(WCHAR) );
if( pszPrefix )
{
memcpy( pszPrefix, pszMDPath, cchPrefix * sizeof(WCHAR) );
pszPrefix[cchPrefix] = 0;
_wcsupr( pszPrefix );
if( wcsstr( pszPrefix, L"ROOT" ) == NULL )
{
ValidPath = TRUE;
}
LocalFree( pszPrefix );
}
}
return ValidPath;
}