|
|
/*++
Copyright (c) 1994-2001 Microsoft Corporation
Module Name : mdkeys.cpp
Abstract: Metabase key wrapper class
Author: Ronald Meijer (ronaldm) Sergei Antonov (sergeia)
Project: Internet Services Manager
Revision History:
--*/
//
// Include Files
//
#include "stdafx.h"
#include "common.h"
#include "idlg.h"
#include "mdkeys.h"
//#include <acsmb.h>
//#include <iisrf.h>
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__; #endif
#define new DEBUG_NEW
extern HINSTANCE hDLLInstance;
//
// Constants
//
#define MB_TIMEOUT (15000) // Timeout in milliseconds
#define MB_INIT_BUFF_SIZE ( 256) // Initial buffer size
//
// CComAuthInfo implementation
//
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
/* static */ BOOL CComAuthInfo::SplitUserNameAndDomain( IN OUT CString & strUserName, IN CString & strDomainName ) /*++
Routine Description:
Split the user name and domain from the given username, which is in the format "domain\user".
Return TRUE if the user name contained a domain FALSE if it did not
Arguments:
CString & strUserName : User name which may contain a domain name CString & strDomainName : Output domain name ("." if local)
Return Value:
TRUE if a domain is split off
--*/ { //
// Assume local
//
strDomainName = _T("."); int nSlash = strUserName.Find(_T("\\"));
if (nSlash >= 0) { strDomainName = strUserName.Left(nSlash); strUserName = strUserName.Mid(nSlash + 1);
return TRUE; }
return FALSE; }
/* static */ DWORD CComAuthInfo::VerifyUserPassword( IN LPCTSTR lpstrUserName, IN LPCTSTR lpstrPassword ) /*++
Routine Description:
Verify the usernamer password combo checks out
Arguments:
LPCTSTR lpstrUserName : Domain/username combo LPCTSTR lpstrPassword : Password
Return Value:
ERROR_SUCCESS if the password checks out, an error code otherwise.
--*/ { CString strDomain; CString strUser(lpstrUserName); CString strPassword(lpstrPassword);
SplitUserNameAndDomain(strUser, strDomain);
//
// In order to look up an account name, this process
// must first be granted the privilege of doing so.
//
CError err; { HANDLE hToken; LUID AccountLookupValue; TOKEN_PRIVILEGES tkp;
do { if (!::OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken) ) { err.GetLastWinError(); break; }
if (!::LookupPrivilegeValue(NULL, SE_TCB_NAME, &AccountLookupValue)) { err.GetLastWinError(); break; }
tkp.PrivilegeCount = 1; tkp.Privileges[0].Luid = AccountLookupValue; tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
::AdjustTokenPrivileges( hToken, FALSE, &tkp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL );
err.GetLastWinError();
if (err.Failed()) { break; }
HANDLE hUser = NULL;
if (::LogonUser( strUser.GetBuffer(0), strDomain.GetBuffer(0), strPassword.GetBuffer(0), LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &hUser )) { //
// Success!
//
CloseHandle(hUser); } else { err.GetLastWinError(); }
//
// Remove the privilege
//
} while(FALSE); }
HANDLE hUser = NULL;
if (::LogonUser( strUser.GetBuffer(0), strDomain.GetBuffer(0), strPassword.GetBuffer(0), LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &hUser)) { //
// Success!
//
CloseHandle(hUser); } else { err.GetLastWinError(); }
return err; }
CComAuthInfo::CComAuthInfo( IN LPCOLESTR lpszServerName OPTIONAL, IN LPCOLESTR lpszUserName OPTIONAL, IN LPCOLESTR lpszPassword OPTIONAL ) /*++
Routine Description:
Construct CIIServer object
Argument:
LPCOLESTR lpszServerName : Server name or NULL for local computer LPCOLESTR lpszUserName : User name of blank for no impersonation LPCOLESTR lpszPassword : Password (might be blank or NULL)
Return Value:
N/A
--*/ : m_bstrServerName(), m_bstrUserName(lpszUserName), m_bstrPassword(lpszPassword), m_fLocal(FALSE) { SetComputerName(lpszServerName); }
CComAuthInfo::CComAuthInfo( IN CComAuthInfo & auth ) /*++
Routine Description:
Copy constructor
Arguments:
CComAuthInfo & auth : Source object to copy from
Return Value:
N/A
--*/ : m_bstrServerName(auth.m_bstrServerName), m_bstrUserName(auth.m_bstrUserName), m_bstrPassword(auth.m_bstrPassword), m_fLocal(auth.m_fLocal) { }
CComAuthInfo::CComAuthInfo( IN CComAuthInfo * pAuthInfo OPTIONAL ) /*++
Routine Description:
Copy constructor
Arguments:
CComAuthInfo * pAuthInfo : Source object to copy from (or NULL)
Return Value:
N/A
--*/ : m_bstrServerName(), m_bstrUserName(), m_bstrPassword(), m_fLocal(FALSE) { if (pAuthInfo) { //
// Full authentication information available
//
m_bstrUserName = pAuthInfo->m_bstrUserName; m_bstrPassword = pAuthInfo->m_bstrPassword; m_bstrServerName = pAuthInfo->m_bstrServerName; m_fLocal = pAuthInfo->m_fLocal; } else { //
// Local computer w/o impersonation
//
SetComputerName(NULL); } }
CComAuthInfo & CComAuthInfo::operator =( IN CComAuthInfo & auth ) /*++
Routine Description:
Assignment operator
Arguments:
CComAuthInfo & auth : Source object to copy from
Return Value:
Reference to current object
--*/ { m_bstrServerName = auth.m_bstrServerName; m_bstrUserName = auth.m_bstrUserName; m_bstrPassword = auth.m_bstrPassword; m_fLocal = auth.m_fLocal;
return *this; }
CComAuthInfo & CComAuthInfo::operator =( IN CComAuthInfo * pAuthInfo OPTIONAL ) /*++
Routine Description:
Assignment operator
Arguments:
CComAuthInfo * pAuthInfo : Source object to copy from (or NULL)
Return Value:
Reference to current object
--*/ { if (pAuthInfo) { m_bstrUserName = pAuthInfo->m_bstrUserName; m_bstrPassword = pAuthInfo->m_bstrPassword; SetComputerName(pAuthInfo->m_bstrServerName); } else { //
// Local computer w/o impersonation
//
m_bstrUserName.Empty(); m_bstrPassword.Empty(); SetComputerName(NULL); }
return *this; }
CComAuthInfo & CComAuthInfo::operator =( IN LPCTSTR lpszServerName ) /*++
Routine Description:
Assignment operator. Assign computer name w/o impersonation
Arguments:
LPCTSTR lpszServerName : Source server name
Return Value:
Reference to current object
--*/ { RemoveImpersonation(); SetComputerName(lpszServerName);
return *this; }
void CComAuthInfo::SetComputerName( IN LPCOLESTR lpszServerName OPTIONAL ) /*++
Routine Description:
Store the computer name. Determine if its local.
Arguments:
LPCOLESTR lpszServername : Server name. NULL indicates the local computer
Return Value:
None
--*/ { if (lpszServerName && *lpszServerName) { //
// Specific computer name specified
//
m_bstrServerName = lpszServerName; m_fLocal = ::IsServerLocal(lpszServerName); TRACEEOLID("Computer name " << lpszServerName << " Local: " << m_fLocal); } else { //
// Use local computer name
//
// CODEWORK: Cache static version of computername maybe?
//
TCHAR szLocalServer[MAX_PATH + 1]; DWORD dwSize = MAX_PATH;
VERIFY(::GetComputerName(szLocalServer, &dwSize)); m_bstrServerName = szLocalServer; m_fLocal = TRUE; TRACEEOLID("Using local computer name " << szLocalServer); } }
void CComAuthInfo::SetImpersonation( IN LPCOLESTR lpszUser, IN LPCOLESTR lpszPassword ) /*++
Routine Description:
Set impersonation parameters
Arguments:
LPCOLESTR lpszUser : User name LPCOLESTR lpszPassword : Password
Return Value:
None
--*/ { m_bstrUserName = lpszUser; StorePassword(lpszPassword); }
void CComAuthInfo::RemoveImpersonation() /*++
Routine Description:
Remove impersonation parameters
Arguments:
None
Return Value:
None
--*/ { m_bstrUserName.Empty(); m_bstrPassword.Empty(); }
COSERVERINFO * CComAuthInfo::CreateServerInfoStruct() const { return (CComAuthInfo::CreateServerInfoStruct(RPC_C_AUTHN_LEVEL_CONNECT)); }
COSERVERINFO * CComAuthInfo::CreateServerInfoStruct(DWORD dwAuthnLevel) const /*++
Routine Description:
Create the server info structure. Might return NULL for the no frills case.
Arguments:
NULL
Return Value:
A COSERVERINFO structure, or NULL if the computer is local, and no impersonation is required.
Notes:
Caller must call FreeServerInfoStruct() to prevent memory leaks
--*/ { //
// Be smart about the server name; optimize for local
// computer name.
//
if (m_fLocal && !UsesImpersonation()) { //
// Special, no-frills case.
//
return NULL; }
//
// Create the COM server info for CoCreateInstanceEx
//
COSERVERINFO * pcsiName = NULL;
do { pcsiName = (COSERVERINFO *)AllocMem(sizeof(COSERVERINFO));
if (!pcsiName) { break; }
pcsiName->pwszName = m_bstrServerName;
//
// Set impersonation
//
if (UsesImpersonation()) { COAUTHINFO * pAuthInfo = (COAUTHINFO *)AllocMem(sizeof(COAUTHINFO));
if (!pAuthInfo) { break; }
COAUTHIDENTITY * pAuthIdentityData = (COAUTHIDENTITY *)AllocMem(sizeof(COAUTHIDENTITY));
if (!pAuthIdentityData) { break; }
CString strUserName(m_bstrUserName); CString strPassword(m_bstrPassword); CString strDomain;
//
// Break up domain\username combo
//
SplitUserNameAndDomain(strUserName, strDomain);
pAuthIdentityData->UserLength = strUserName.GetLength();
if (pAuthIdentityData->UserLength) { pAuthIdentityData->User = AllocString( strUserName, strUserName.GetLength() ); }
pAuthIdentityData->DomainLength = strDomain.GetLength();
if (pAuthIdentityData->DomainLength) { pAuthIdentityData->Domain = AllocString( strDomain, strDomain.GetLength() ); }
pAuthIdentityData->PasswordLength = strPassword.GetLength();
if (pAuthIdentityData->PasswordLength) { pAuthIdentityData->Password = AllocString( strPassword, strPassword.GetLength() ); }
// RPC_C_AUTHN_LEVEL_DEFAULT 0
// RPC_C_AUTHN_LEVEL_NONE 1
// RPC_C_AUTHN_LEVEL_CONNECT 2
// RPC_C_AUTHN_LEVEL_CALL 3
// RPC_C_AUTHN_LEVEL_PKT 4
// RPC_C_AUTHN_LEVEL_PKT_INTEGRITY 5
// RPC_C_AUTHN_LEVEL_PKT_PRIVACY 6
// you can only specify stuff stronger than RPC_C_AUTHN_LEVEL_CONNECT
if (dwAuthnLevel >= RPC_C_AUTHN_LEVEL_CONNECT && dwAuthnLevel <= RPC_C_AUTHN_LEVEL_PKT_PRIVACY) { pAuthInfo->dwAuthnLevel = dwAuthnLevel; } else { pAuthInfo->dwAuthnLevel = RPC_C_AUTHN_LEVEL_CONNECT; } pAuthIdentityData->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; pAuthInfo->dwImpersonationLevel = RPC_C_IMP_LEVEL_IMPERSONATE; pAuthInfo->dwAuthnSvc = RPC_C_AUTHN_WINNT; pAuthInfo->dwAuthzSvc = RPC_C_AUTHZ_NONE; pAuthInfo->pwszServerPrincName = NULL; pAuthInfo->dwCapabilities = EOAC_NONE; pAuthInfo->pAuthIdentityData = pAuthIdentityData; pcsiName->pAuthInfo = pAuthInfo; } } while(FALSE);
return pcsiName; }
void CComAuthInfo::FreeServerInfoStruct( IN COSERVERINFO * pServerInfo ) const /*++
Routine Description:
As mentioned above -- free the server info structure
Arguments:
COSERVERINFO * pServerInfo : Server info structure
Return Value:
None
--*/ { if (pServerInfo) { if (pServerInfo->pAuthInfo) { if (pServerInfo->pAuthInfo->pAuthIdentityData) { if (pServerInfo->pAuthInfo->pAuthIdentityData) { SAFE_FREEMEM(pServerInfo->pAuthInfo->pAuthIdentityData->User); SAFE_FREEMEM(pServerInfo->pAuthInfo->pAuthIdentityData->Domain); SAFE_FREEMEM(pServerInfo->pAuthInfo->pAuthIdentityData->Password); FreeMem(pServerInfo->pAuthInfo->pAuthIdentityData); } }
FreeMem(pServerInfo->pAuthInfo); }
FreeMem(pServerInfo); } }
HRESULT CComAuthInfo::ApplyProxyBlanket( IN OUT IUnknown * pInterface ) /*++
Routine Description:
Set security information on the interface. The user name is of the form domain\username.
Arguments:
IUnknown * pInterface : Interface
Return Value:
HRESULT
--*/ { HRESULT hr = S_OK;
COSERVERINFO * pcsiName = CreateServerInfoStruct();
//
// This method should only be called if we're using impersonation.
// so the pcsiName returned should never be NULL.
//
ASSERT(pcsiName && pcsiName->pAuthInfo);
if (pcsiName && pcsiName->pAuthInfo) { hr = ::CoSetProxyBlanket( pInterface, pcsiName->pAuthInfo->dwAuthnSvc, pcsiName->pAuthInfo->dwAuthzSvc, pcsiName->pAuthInfo->pwszServerPrincName, pcsiName->pAuthInfo->dwAuthnLevel, pcsiName->pAuthInfo->dwImpersonationLevel, pcsiName->pAuthInfo->pAuthIdentityData, pcsiName->pAuthInfo->dwCapabilities );
FreeServerInfoStruct(pcsiName); }
return hr; }
//
// CMetabasePath implemention
//
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
const LPCTSTR CMetabasePath::_cszMachine = SZ_MBN_MACHINE; const LPCTSTR CMetabasePath::_cszRoot = SZ_MBN_ROOT; const LPCTSTR CMetabasePath::_cszSep = SZ_MBN_SEP_STR; const TCHAR CMetabasePath::_chSep = SZ_MBN_SEP_CHAR;
/* static */ LPCTSTR CMetabasePath::ConvertToParentPath( OUT IN CString & strMetaPath ) /*++
Routine Description:
Given the path, convert it to the parent path e.g. "foo/bar/etc" returns "foo/bar"
Arguments:
CString & strMetaPath : Path to be converted
Return value:
Pointer to the converted path, or NULL in case of error
--*/ { TRACEEOLID("Getting parent path of " << strMetaPath);
LPTSTR lpszPath = strMetaPath.GetBuffer(1); LPTSTR lpszTail = lpszPath + lstrlen(lpszPath) - 1; LPTSTR lpszReturn = NULL;
do { if (lpszTail <= lpszPath) { break; }
//
// Strip trailing backslash
//
if (*lpszTail == _chSep) { *lpszTail-- = _T('\0'); }
//
// Search for parent
//
while (lpszTail > lpszPath && *lpszTail != _chSep) { --lpszTail; }
if (lpszTail <= lpszPath) { break; }
*lpszTail = _T('\0');
lpszReturn = lpszPath; } while(FALSE);
strMetaPath.ReleaseBuffer();
TRACEEOLID("Parent path should be " << strMetaPath);
return lpszReturn; }
/* static */ LPCTSTR CMetabasePath::TruncatePath( IN int nLevel, IN LPCTSTR lpszMDPath, OUT CString & strNewPath, OUT CString * pstrRemainder OPTIONAL ) /*++
Routine Description:
Truncate the given metabase path at the given level, that is, the nLevel'th separator in the path, starting at 0, where 0 will always give lpszPath back whether it started with a separator or not.
Examples:
"/lm/w3svc/1/foo" at level 2 returns "/lm/w3svc" as does "lm/w3svc/1/foo". Arguments:
int nLevel 0-based separator count to truncate at. LPTSTR lpszMDPath Fully-qualified metabase path CString & strNewPath Returns truncated path CString * pstrRemainder Optionally returns the remainder past the nLevel'th separator.
Return Value:
The truncated path at the level requested. See examples above. *pstrRemainder returns the remainder of the path. If the path does not contain nLevel worth of separators, the entire path is returned, and the remainder will be blank.
--*/ { ASSERT_PTR(lpszMDPath); ASSERT(nLevel >= 0);
if (!lpszMDPath || nLevel < 0) { TRACEEOLID("TruncatePath: Invalid parameter"); return NULL; }
TRACEEOLID("Source Path: " << lpszMDPath);
//
// Skip the first sep whether it exists or not
//
LPCTSTR lp = *lpszMDPath == _chSep ? lpszMDPath + 1 : lpszMDPath; LPCTSTR lpRem = NULL; int cSeparators = 0;
if (nLevel) { //
// Advance to the requested separator level
//
while (*lp) { if (*lp == _chSep) { if (++cSeparators == nLevel) { break; } }
++lp; }
if (!*lp) { //
// End of path is considered a separator
//
++cSeparators; }
ASSERT(cSeparators <= nLevel);
if (cSeparators == nLevel) { //
// Break up the strings
//
strNewPath = lpszMDPath; strNewPath.ReleaseBuffer((int)(lp - lpszMDPath));
TRACEEOLID("Path truncated at level " << nLevel << ": " << strNewPath);
if (*lp) { lpRem = ++lp; TRACEEOLID("Remainder: " << lpRem); } } }
//
// Return remainder
//
if (pstrRemainder && lpRem) { ASSERT_WRITE_PTR(pstrRemainder); *pstrRemainder = lpRem; }
return strNewPath; }
/* static */ DWORD CMetabasePath::GetInstanceNumber( IN LPCTSTR lpszMDPath ) /*++
Routine Description:
Get the number of the instance referred to in the given metabase path. Examples: "lm/w3svc/1/foo/bar" will return 1 "lm/w3svc/" will return 0 (master instance) "lm/bogus/path/" will return 0xffffffff (error)
Arguments:
LPCTSTR lpszMDPath : A metabase path.
Return Value:
Instance number (0 indicates master instance) or 0xffffffff if the path is in error.
--*/ { TRACEEOLID("Determining instance number of " << lpszMDPath); DWORD dwInstance = 0xffffffff;
CString strService, strInst;
if (GetServicePath(lpszMDPath, strService, &strInst)) { if (strInst.IsEmpty()) { dwInstance = MASTER_INSTANCE; } else { if (_istdigit(strInst.GetAt(0))) { dwInstance = _ttol(strInst); } } }
return dwInstance; }
/* static */ LPCTSTR CMetabasePath::GetLastNodeName( IN LPCTSTR lpszMDPath, OUT CString & strNodeName ) /*++
Routine Description:
Get the last nodename off the metabase path
Example:
"/lm/foo/bar/" returns "bar"
Arguments:
LPCTSTR lpszMDPath : Metabase path
Return Value:
Pointer to the node name or NULL in case of a malformed path.
--*/ { ASSERT_PTR(lpszMDPath);
if (!lpszMDPath || !*lpszMDPath) { return NULL; }
TRACEEOLID("Getting last node name from " << lpszMDPath);
LPCTSTR lp; LPCTSTR lpTail; lp = lpTail = lpszMDPath + lstrlen(lpszMDPath) - 1;
//
// Skip trailing separator
//
if (*lp == _chSep) { --lpTail; --lp; }
strNodeName.Empty();
while (*lp && *lp != _chSep) { strNodeName += *(lp--); }
strNodeName.MakeReverse();
TRACEEOLID("Node is " << strNodeName); return strNodeName; }
/* static */ void CMetabasePath::SplitMetaPathAtInstance( IN LPCTSTR lpszMDPath, OUT CString & strParent, OUT CString & strAlias ) /*++
Routine Description:
Split the given path into parent metabase root and alias, with the root being the instance path, and the alias everything following the instance.
Arguments:
LPCTSTR lpszMDPath : Input path CString & strParent : Outputs the parent path CString & strAlias : Outputs the alias name
Return Value:
None.
--*/ { ASSERT_PTR(lpszMDPath);
TRACEEOLID("Source Path " << lpszMDPath);
strParent = lpszMDPath; strAlias.Empty();
LPTSTR lp = strParent.GetBuffer(0); ASSERT_PTR(lp);
if (!lp) { //
// This is just about impossible
//
return; }
int cSeparators = 0; int iChar = 0;
//
// Looking for "LM/sss/ddd/" <-- 3d slash:
//
while (*lp && cSeparators < 2) { if (*lp++ == _chSep) { ++cSeparators; }
++iChar; }
if (!*lp) { //
// Bogus format
//
ASSERT_MSG("Bogus Format"); return; }
if (_istdigit(*lp)) { //
// Not at the master instance, skip one more.
//
while (*lp) { ++iChar;
if (*lp++ == _chSep) { break; } }
if (!*lp) { //
// Bogus format
//
ASSERT_MSG("Bogus Format"); return; } }
strAlias = strParent.Mid(iChar); strParent.ReleaseBuffer(--iChar);
TRACEEOLID("Broken up into " << strParent); TRACEEOLID(" and " << strAlias); }
/* static */ BOOL CMetabasePath::IsHomeDirectoryPath( IN LPCTSTR lpszMetaPath ) /*++
Routine Description:
Determine if the path given describes a root directory
Arguments:
LPCTSTR lpszMetaPath : Metabase path
Return Value:
TRUE if the path describes a root directory, FALSE if it does not
--*/ { ASSERT_READ_PTR(lpszMetaPath);
LPTSTR lpNode = lpszMetaPath ? _tcsrchr(lpszMetaPath, _chSep) : NULL;
if (lpNode) { return _tcsicmp(++lpNode, _cszRoot) == 0; }
return FALSE; }
/* static */ BOOL CMetabasePath::IsMasterInstance( IN LPCTSTR lpszMDPath ) /*++
Routine Description:
Determine if the given metabase path points to the master instance (site). This is essentially the service path.
Arguments:
LPCTSTR lpszMDPath : Metabase path.
Return Value:
TRUE if the path is the master instance, FALSE otherwise.
--*/ { ASSERT_READ_PTR(lpszMDPath);
if (!lpszMDPath || !*lpszMDPath) { return FALSE; }
TRACEEOLID("Checking path " << lpszMDPath);
CString strService; CString strRemainder;
LPCTSTR lpPath = TruncatePath(2, lpszMDPath, strService, &strRemainder);
return lpPath && !strService.IsEmpty() && strRemainder.IsEmpty(); }
/* static */ LPCTSTR CMetabasePath::GetServiceInfoPath( IN LPCTSTR lpszMDPath, OUT CString & strInfoPath, IN LPCTSTR lpszDefService OPTIONAL ) /*++
Routine Description:
Generate the appropriate metabase service info path for the given metabase path.
For example:
"lm/w3svc/1/foo/bar" Generates "lm/w3svc/info"
Arguments:
LPCTSTR lpszMDPath : Input metabase path CString & strInfoPath : Returns the info path LPCTSTR lpszDefService : Optionally specifies the default service to use (e.g "w3svc") if no service could be found in the path. Return Value:
The info metabase path or NULL if one could not be generated.
--*/ { //
// Capability info stored off the service path ("lm/w3svc").
//
CString strService; CString strRem; //
// Strip off everything past the service
//
if (!TruncatePath(2, lpszMDPath, strService, &strRem) || strService.IsEmpty()) { if (!lpszDefService) { TRACEEOLID("Unable to generate info path"); return NULL; }
TRACEEOLID("Using default service for info path");
//
// Machine path (no service). Use web as default service to
// look for capability and version info.
//
strService = CMetabasePath(TRUE, lpszDefService); }
strInfoPath = CMetabasePath(FALSE, strService, SZ_MBN_INFO); TRACEEOLID("Using " << strInfoPath << " to look for capability info");
return strInfoPath; }
/* static */ LPCTSTR CMetabasePath::CleanMetaPath( IN OUT CString & strMetaRoot ) /*++
Routine Description:
Clean up the metabase path to one valid for internal consumption. This removes the beginning and trailing slashes off the path.
Arguments:
CString & strMetaRoot : Metabase path to be cleaned up.
Return Value:
Pointer to the metabase path
--*/ { TRACEEOLID("Dirty metapath: " << strMetaRoot);
if (!strMetaRoot.IsEmpty()) { if (strMetaRoot[strMetaRoot.GetLength() - 1] == _chSep) { strMetaRoot.ReleaseBuffer(strMetaRoot.GetLength() - 1); }
if (!strMetaRoot.IsEmpty() && strMetaRoot[0] == _chSep) { strMetaRoot = strMetaRoot.Right(strMetaRoot.GetLength() - 1); } }
TRACEEOLID("Clean metapath: " << strMetaRoot);
return strMetaRoot; }
CMetabasePath::CMetabasePath( IN BOOL fAddBasePath, IN LPCTSTR lpszMDPath, IN LPCTSTR lpszMDPath2 OPTIONAL, IN LPCTSTR lpszMDPath3 OPTIONAL, IN LPCTSTR lpszMDPath4 OPTIONAL ) /*++
Routine Description:
Constructor.
Arguments:
BOOL fAddBasePath : TRUE to prepend base path ("LM") FALSE if the path is complete LPCTSTR lpszMDPath : Metabase path LPCTSTR lpszMDPath2 : Optional child path LPCTSTR lpszMDPath3 : Optional child path LPCTSTR lpszMDPath4 : Optional child path
Return Value:
N/A
--*/ : m_strMetaPath() { ASSERT_READ_PTR(lpszMDPath);
if (fAddBasePath) { m_strMetaPath = _cszMachine; AppendPath(lpszMDPath); } else { m_strMetaPath = lpszMDPath; }
//
// Add optional path components
//
AppendPath(lpszMDPath2); AppendPath(lpszMDPath3); AppendPath(lpszMDPath4); }
CMetabasePath::CMetabasePath( IN LPCTSTR lpszSvc, OPTIONAL IN DWORD dwInstance, OPTIONAL IN LPCTSTR lpszParentPath, OPTIONAL IN LPCTSTR lpszAlias OPTIONAL ) /*++
Routine Description:
Constructor. Construct with path components.
Arguments:
LPCTSTR lpszSvc : Service (may be NULL or "") DWORD dwInstance : Instance number (may be 0 for master) LPCTSTR lpszParentPath : Parent path (may be NULL or "") LPCTSTR lpszAlias : Alias (may be NULL or "")
Return Value:
N/A
--*/ : m_strMetaPath() { BuildMetaPath(lpszSvc, dwInstance, lpszParentPath, lpszAlias); }
void CMetabasePath::AppendPath( IN LPCTSTR lpszPath ) /*++
Routine Description:
Append path to current metabase path
Arguments:
LPCTSTR lpszPath : Metabase path
Return Value:
None
--*/ { if (lpszPath && *lpszPath) { m_strMetaPath += _cszSep; m_strMetaPath += lpszPath; } }
void CMetabasePath::AppendPath( IN DWORD dwInstance ) /*++
Routine Description:
Append path to current metabase path
Arguments:
DWORD dwInstance : Instance path
Return Value:
None
--*/ { if (!IS_MASTER_INSTANCE(dwInstance)) { TCHAR szInstance[] = _T("4000000000"); _ltot(dwInstance, szInstance, 10);
m_strMetaPath += _cszSep; m_strMetaPath += szInstance; } }
void CMetabasePath::BuildMetaPath( IN LPCTSTR lpszSvc OPTIONAL, IN LPCTSTR lpszInstance OPTIONAL, IN LPCTSTR lpszParentPath OPTIONAL, IN LPCTSTR lpszAlias OPTIONAL ) /*++
Routine Description:
Build a complete metapath with the given service name, instance number and optional path components.
Arguments:
LPCTSTR lpszSvc : Service (may be NULL or "") LPCTSTR lpszInstance : Instance (may be NULL or "") LPCTSTR lpszParentPath : Parent path (may be NULL or "") LPCTSTR lpszAlias : Alias (may be NULL or "")
Return Value:
Pointer to internal buffer containing the path.
--*/ { m_strMetaPath = _cszMachine;
AppendPath(lpszSvc); AppendPath(lpszInstance); AppendPath(lpszParentPath);
if (lpszAlias && *lpszAlias) { //
// Special case: If the alias is root, but we're
// at the master instance, ignore this.
//
if (lpszInstance || ::lstrcmpi(_cszRoot, lpszAlias)) { m_strMetaPath += _cszSep; m_strMetaPath += lpszAlias; } }
TRACEEOLID("Generated metapath: " << m_strMetaPath ); }
void CMetabasePath::BuildMetaPath( IN LPCTSTR lpszSvc OPTIONAL, IN DWORD dwInstance OPTIONAL, IN LPCTSTR lpszParentPath OPTIONAL, IN LPCTSTR lpszAlias OPTIONAL ) /*++
Routine Description:
Build a complete metapath with the given service name, instance number and optional path components.
Arguments:
LPCTSTR lpszSvc : Service (may be NULL or "") DWORD dwInstance : Instance number (may be 0 for master) LPCTSTR lpszParentPath : Parent path (may be NULL or "") LPCTSTR lpszAlias : Alias (may be NULL or "")
Return Value:
Pointer to internal buffer containing the path.
--*/ { m_strMetaPath = _cszMachine;
AppendPath(lpszSvc); AppendPath(dwInstance); AppendPath(lpszParentPath);
if (lpszAlias && *lpszAlias) { //
// Special case: If the alias is root, but we're
// at the master instance, ignore this.
//
if (!IS_MASTER_INSTANCE(dwInstance) || ::lstrcmpi(_cszRoot, lpszAlias)) { m_strMetaPath += _cszSep; m_strMetaPath += lpszAlias; } }
TRACEEOLID("Generated metapath: " << m_strMetaPath ); }
//
// CIISInterface class
//
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
CIISInterface::CIISInterface( IN CComAuthInfo * pAuthInfo, OPTIONAL IN HRESULT hrInterface OPTIONAL ) /*++
Routine Description:
Base class constructor.
Arguments:
CComAuthInfo * pAuthInfo : Auth info or NULL for local computer HRESULT hrInterface : Initial error code. S_OK by default.
Return Value:
N/A
--*/ : m_auth(pAuthInfo), m_hrInterface(hrInterface) { }
HRESULT CIISInterface::Create( IN int cInterfaces, IN const IID rgIID[], IN const GUID rgCLSID[], OUT int * pnInterface, OPTIONAL OUT IUnknown ** ppInterface ) /*++
Routine Description:
Create interface. This will try a range of interfaces in order of priority.
Arguments:
int cInterfaces : Number of interfaces in array. const IID * rgIID : Array if IIDs const GUID * rgCLSID : Array of CLSIDs int * pnInterface : Returns the interface index that was successful. or NULL if not interested. IUnknown ** ppInterface : Returns pointer to the interface.
Return Value:
HRESULT
Notes:
This will attempt to create an interface, in order of declaration in the IID and CLSIS arrays. The first successful interface to be created will have its index returned in *pnInterfaces.
--*/ { ASSERT(cInterfaces > 0); ASSERT(rgIID && rgCLSID && ppInterface); COSERVERINFO * pcsiName = m_auth.CreateServerInfoStruct();
MULTI_QI rgmqResults; CError err; int nInterface;
ZeroMemory(&rgmqResults, sizeof(rgmqResults)); //
// Try to create the interface in order
//
for (nInterface = 0; nInterface < cInterfaces; ++nInterface) { rgmqResults.pIID = &rgIID[nInterface];
TRACEEOLID("Attempting to create interface #" << nInterface); err = ::CoCreateInstanceEx( rgCLSID[nInterface], NULL, CLSCTX_SERVER, pcsiName, 1, &rgmqResults );
if (err.Succeeded() || err.Win32Error() == ERROR_ACCESS_DENIED) { break; } ZeroMemory(&rgmqResults, sizeof(rgmqResults)); }
if(err.Succeeded()) { //
// Save the interface pointer
//
ASSERT_PTR(rgmqResults.pItf); *ppInterface = rgmqResults.pItf;
if (pnInterface) { //
// Store successful interface index
//
*pnInterface = nInterface; }
//
// Strangely enough, I now have still have to apply
// the proxy blanket. Apparently this is by design.
//
if (m_auth.UsesImpersonation()) { ApplyProxyBlanket(); } }
//
// Clean up
//
m_auth.FreeServerInfoStruct(pcsiName);
return err; }
//
// CMetaInterface class
//
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
CMetaInterface::CMetaInterface( IN CComAuthInfo * pAuthInfo OPTIONAL ) /*++
Routine Description:
Construct and initialize the interface
Arguments:
CComAuthInfo * pAuthInfo : Authentication info. NULL indicates the local computer.
Return Value:
N/A
--*/ : CIISInterface(pAuthInfo), m_pInterface(NULL), m_iTimeOutValue(MB_TIMEOUT) { //
// Initialize the interface
//
m_hrInterface = Create(); }
CMetaInterface::CMetaInterface( IN CMetaInterface * pInterface ) /*++
Routine Description:
Construct from existing interface (Copy Constructor)
Arguments:
CMetaInterface * pInterface : Existing interface
Return Value:
N/A
Notes: Object will not take ownership of the interface, it will merely add to the reference count, and release it upon destruction
BUGBUG:
if pInterface is NULL, this will AV.
--*/ : CIISInterface(&pInterface->m_auth, pInterface->m_hrInterface), m_pInterface(pInterface->m_pInterface), m_iTimeOutValue(pInterface->m_iTimeOutValue) { ASSERT_READ_PTR(m_pInterface); m_pInterface->AddRef(); }
CMetaInterface::~CMetaInterface() /*++
Routine Description:
Destructor -- releases the interface
Arguments:
N/A
Return Value:
N/A
--*/ { SAFE_RELEASE(m_pInterface); }
//
// CMetaKey class
//
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
//
// Helper macros
//
#define ASSURE_PROPER_INTERFACE()\
if (!HasInterface()) { ASSERT_MSG("No interface"); return MD_ERROR_NOT_INITIALIZED; }
#define ASSURE_OPEN_KEY()\
if (!m_hKey && !m_fAllowRootOperations) { ASSERT_MSG("No open key"); return HRESULT_FROM_WIN32(ERROR_INVALID_HANDLE); }
#define FETCH_PROPERTY_DATA_OR_FAIL(dwID, md)\
ZeroMemory(&md, sizeof(md)); \ if (!GetMDFieldDef(dwID, md.dwMDIdentifier, md.dwMDAttributes, md.dwMDUserType, md.dwMDDataType))\ { ASSERT_MSG("Bad property ID"); return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER); }
//
// Static Initialization
//
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
#define MD_SERVER_PLATFORM (IIS_MD_SERVER_BASE+100 )
#define MD_SERVER_VERSION_MAJOR (IIS_MD_SERVER_BASE+101 )
#define MD_SERVER_VERSION_MINOR (IIS_MD_SERVER_BASE+102 )
#define MD_SERVER_CAPABILITIES (IIS_MD_SERVER_BASE+103 )
//
// Metabase table
//
const CMetaKey::MDFIELDDEF CMetaKey::s_rgMetaTable[] = { ///////////////////////////////////////////////////////////////////////////
//
// !!!IMPORTANT!!! This table must be sorted on dwMDIdentifier. (Will
// ASSERT if not not sorted)
//
{ MD_MAX_BANDWIDTH, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_KEY_TYPE, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, 0 }, { MD_SERVER_COMMAND, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_CONNECTION_TIMEOUT, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, IDS_MD_CONNECTION_TIMEOUT }, { MD_MAX_CONNECTIONS, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, IDS_MD_MAX_CONNECTIONS }, { MD_SERVER_COMMENT, METADATA_INHERIT, IIS_MD_UT_SERVER, STRING_METADATA, IDS_MD_SERVER_COMMENT }, { MD_SERVER_STATE, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_SERVER_AUTOSTART, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_SERVER_SIZE, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, IDS_MD_SERVER_SIZE }, { MD_SERVER_LISTEN_BACKLOG, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, IDS_MD_SERVER_LISTEN_BACKLOG }, { MD_SERVER_LISTEN_TIMEOUT, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, IDS_MD_SERVER_LISTEN_TIMEOUT }, { MD_DOWNLEVEL_ADMIN_INSTANCE, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, IDS_MD_DOWNLEVEL_ADMIN_INSTANCE }, { MD_SERVER_BINDINGS, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, MULTISZ_METADATA, 0 }, { MD_WIN32_ERROR, METADATA_VOLATILE, IIS_MD_UT_FILE, DWORD_METADATA, 0 }, { MD_SERVER_PLATFORM, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_SERVER_VERSION_MAJOR, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_SERVER_VERSION_MINOR, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_SERVER_CAPABILITIES, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_SECURE_BINDINGS, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, MULTISZ_METADATA, 0 }, { MD_FILTER_LOAD_ORDER, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, 0 }, { MD_FILTER_IMAGE_PATH, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, 0 }, { MD_FILTER_STATE, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_FILTER_ENABLED, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_FILTER_FLAGS, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_AUTH_CHANGE_URL, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_AUTH_EXPIRED_URL, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, 0 }, { MD_AUTH_NOTIFY_PWD_EXP_URL, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, 0 }, { MD_ADV_NOTIFY_PWD_EXP_IN_DAYS, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_ADV_CACHE_TTL, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_NET_LOGON_WKS, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_USE_HOST_NAME, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_AUTH_EXPIRED_UNSECUREURL, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, 0 }, { MD_AUTH_CHANGE_FLAGS, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_AUTH_NOTIFY_PWD_EXP_UNSECUREURL, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, 0 }, { MD_FRONTPAGE_WEB, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_MAPCERT, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, 0 }, { MD_MAPNTACCT, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, 0 }, { MD_MAPNAME, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, 0 }, { MD_MAPENABLED, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, 0 }, { MD_MAPREALM, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, 0 }, { MD_MAPPWD, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, 0 }, { MD_ITACCT, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, 0 }, { MD_CPP_CERT11, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, BINARY_METADATA, 0 }, { MD_SERIAL_CERT11, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, BINARY_METADATA, 0 }, { MD_CPP_CERTW, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, BINARY_METADATA, 0 }, { MD_SERIAL_CERTW, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, BINARY_METADATA, 0 }, { MD_CPP_DIGEST, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, BINARY_METADATA, 0 }, { MD_SERIAL_DIGEST, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, BINARY_METADATA, 0 }, { MD_CPP_ITA, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, BINARY_METADATA, 0 }, { MD_SERIAL_ITA, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, BINARY_METADATA, 0 }, { MD_FRONTPAGE_WEB, METADATA_INHERIT, IIS_MD_UT_SERVER, BINARY_METADATA, 0 }, { MD_APP_FRIENDLY_NAME, METADATA_INHERIT, IIS_MD_UT_WAM, STRING_METADATA, IDS_MD_APP_FRIENDLY_NAME }, { MD_APP_ROOT, METADATA_INHERIT, IIS_MD_UT_WAM, STRING_METADATA, IDS_MD_APP_ROOT }, { MD_APP_ISOLATED, METADATA_INHERIT, IIS_MD_UT_WAM, DWORD_METADATA, IDS_MD_APP_ISOLATED }, { MD_CPU_LIMITS_ENABLED, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, IDS_MD_CPU_LIMITS_ENABLED }, { MD_CPU_RESET_INTERVAL, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_CPU_LIMIT_LOGEVENT, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, IDS_MD_CPU_LIMIT_LOGEVENT }, { MD_CPU_LIMIT_PRIORITY, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, IDS_MD_CPU_LIMIT_PRIORITY }, { MD_CPU_LIMIT_PROCSTOP, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, IDS_MD_CPU_LIMIT_PROCSTOP }, { MD_CPU_LIMIT_PAUSE, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, IDS_MD_CPU_LIMIT_PAUSE }, { MD_HC_COMPRESSION_DIRECTORY, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, 0 }, { MD_HC_DO_DYNAMIC_COMPRESSION, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_HC_DO_STATIC_COMPRESSION, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_HC_DO_DISK_SPACE_LIMITING, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_HC_MAX_DISK_SPACE_USAGE, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_VR_PATH, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, IDS_MD_VR_PATH }, { MD_VR_USERNAME, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, IDS_MD_VR_USERNAME }, { MD_VR_PASSWORD, METADATA_INHERIT | METADATA_SECURE, IIS_MD_UT_FILE, STRING_METADATA, IDS_MD_VR_PASSWORD }, { MD_VR_ACL, METADATA_NO_ATTRIBUTES, IIS_MD_UT_FILE, BINARY_METADATA, 0 }, { MD_VR_UPDATE, METADATA_NO_ATTRIBUTES, IIS_MD_UT_FILE, DWORD_METADATA, 0 }, { MD_LOG_TYPE, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, IDS_MD_LOG_TYPE }, { MD_LOGFILE_DIRECTORY, METADATA_INHERIT, IIS_MD_UT_FILE, EXPANDSZ_METADATA,IDS_MD_LOGFILE_DIRECTORY }, { MD_LOGFILE_PERIOD, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, IDS_MD_LOGFILE_PERIOD }, { MD_LOGFILE_TRUNCATE_SIZE, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, IDS_MD_LOGFILE_TRUNCATE_SIZE }, { MD_LOGSQL_DATA_SOURCES, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, IDS_MD_LOGSQL_DATA_SOURCES }, { MD_LOGSQL_TABLE_NAME, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, IDS_MD_LOGSQL_TABLE_NAME }, { MD_LOGSQL_USER_NAME, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, IDS_MD_LOGSQL_USER_NAME }, { MD_LOGSQL_PASSWORD, METADATA_INHERIT | METADATA_SECURE, IIS_MD_UT_FILE, STRING_METADATA, IDS_MD_LOGSQL_PASSWORD }, { MD_LOG_PLUGIN_ORDER, METADATA_INHERIT, IIS_MD_UT_SERVER, STRING_METADATA, IDS_MD_LOG_PLUGIN_ORDER }, { MD_LOGEXT_FIELD_MASK, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, IDS_MD_LOGEXT_FIELD_MASK }, { MD_LOGFILE_LOCALTIME_ROLLOVER, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, IDS_MD_LOGFILE_LOCALTIME_ROLLOVER }, { MD_CPU_LOGGING_MASK, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, IDS_MD_CPU_LOGGING_MASK }, { MD_EXIT_MESSAGE, METADATA_INHERIT, IIS_MD_UT_SERVER, STRING_METADATA, IDS_MD_EXIT_MESSAGE }, { MD_GREETING_MESSAGE, METADATA_INHERIT, IIS_MD_UT_SERVER, MULTISZ_METADATA, IDS_MD_GREETING_MESSAGE }, { MD_MAX_CLIENTS_MESSAGE, METADATA_INHERIT, IIS_MD_UT_SERVER, STRING_METADATA, IDS_MD_MAX_CLIENTS_MESSAGE }, { MD_MSDOS_DIR_OUTPUT, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, IDS_MD_MSDOS_DIR_OUTPUT }, { MD_ALLOW_ANONYMOUS, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, IDS_MD_ALLOW_ANONYMOUS }, { MD_ANONYMOUS_ONLY, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, IDS_MD_ANONYMOUS_ONLY }, { MD_LOG_ANONYMOUS, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, IDS_MD_LOG_ANONYMOUS }, { MD_LOG_NONANONYMOUS, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, IDS_MD_LOG_NONANONYMOUS }, { MD_BANNER_MESSAGE, METADATA_INHERIT, IIS_MD_UT_SERVER, MULTISZ_METADATA, 0 }, { MD_SSL_PUBLIC_KEY, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, BINARY_METADATA, 0 }, { MD_SSL_PRIVATE_KEY, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, BINARY_METADATA, 0 }, { MD_SSL_KEY_PASSWORD, METADATA_SECURE, IIS_MD_UT_SERVER, BINARY_METADATA, 0 }, { MD_SSL_CERT_HASH, METADATA_INHERIT, IIS_MD_UT_SERVER, BINARY_METADATA, 0 }, { MD_SSL_CERT_STORE_NAME, METADATA_INHERIT, IIS_MD_UT_SERVER, STRING_METADATA, 0 }, { MD_SSL_CTL_IDENTIFIER, METADATA_INHERIT, IIS_MD_UT_SERVER, STRING_METADATA, 0 }, { MD_SSL_CTL_STORE_NAME, METADATA_INHERIT, IIS_MD_UT_SERVER, STRING_METADATA, 0 }, { MD_SSL_USE_DS_MAPPER, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_AUTHORIZATION, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, IDS_MD_AUTHORIZATION }, { MD_REALM, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, IDS_MD_REALM }, { MD_HTTP_EXPIRES, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, IDS_MD_HTTP_EXPIRES }, { MD_HTTP_PICS, METADATA_INHERIT, IIS_MD_UT_FILE, MULTISZ_METADATA, IDS_MD_HTTP_PICS }, { MD_HTTP_CUSTOM, METADATA_INHERIT, IIS_MD_UT_FILE, MULTISZ_METADATA, IDS_MD_HTTP_CUSTOM }, { MD_DIRECTORY_BROWSING, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, IDS_MD_DIRECTORY_BROWSING }, { MD_DEFAULT_LOAD_FILE, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, IDS_MD_DEFAULT_LOAD_FILE }, { MD_CONTENT_NEGOTIATION, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, IDS_MD_CONTENT_NEGOTIATION }, { MD_CUSTOM_ERROR, METADATA_INHERIT, IIS_MD_UT_FILE, MULTISZ_METADATA, IDS_MD_CUSTOM_ERROR }, { MD_FOOTER_DOCUMENT, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, IDS_MD_FOOTER_DOCUMENT }, { MD_FOOTER_ENABLED, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, IDS_MD_FOOTER_ENABLED }, { MD_HTTP_REDIRECT, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, IDS_MD_HTTP_REDIRECT }, { MD_DEFAULT_LOGON_DOMAIN, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, IDS_MD_DEFAULT_LOGON_DOMAIN }, { MD_LOGON_METHOD, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, IDS_MD_LOGON_METHOD }, { MD_SCRIPT_MAPS, METADATA_INHERIT, IIS_MD_UT_FILE, MULTISZ_METADATA, IDS_MD_SCRIPT_MAPS }, { MD_MIME_MAP, METADATA_INHERIT, IIS_MD_UT_FILE, MULTISZ_METADATA, IDS_MD_MIME_MAP }, { MD_ACCESS_PERM, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, IDS_MD_ACCESS_PERM }, { MD_IP_SEC, METADATA_INHERIT | METADATA_REFERENCE, IIS_MD_UT_FILE, BINARY_METADATA, IDS_MD_IP_SEC }, { MD_ANONYMOUS_USER_NAME, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, IDS_MD_ANONYMOUS_USER_NAME }, { MD_ANONYMOUS_PWD, METADATA_INHERIT | METADATA_SECURE, IIS_MD_UT_FILE, STRING_METADATA, IDS_MD_ANONYMOUS_PWD }, { MD_ANONYMOUS_USE_SUBAUTH, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, IDS_MD_ANONYMOUS_USE_SUBAUTH }, { MD_DONT_LOG, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, IDS_MD_DONT_LOG }, { MD_ADMIN_ACL, METADATA_INHERIT | METADATA_SECURE | METADATA_REFERENCE,IIS_MD_UT_SERVER, BINARY_METADATA, IDS_MD_ADMIN_ACL }, { MD_SSI_EXEC_DISABLED, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, IDS_MD_SSI_EXEC_DISABLED }, { MD_SSL_ACCESS_PERM, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, IDS_MD_SSL_ACCESS_PERM }, { MD_NTAUTHENTICATION_PROVIDERS, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, IDS_MD_NTAUTHENTICATION_PROVIDERS }, { MD_SCRIPT_TIMEOUT, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, IDS_MD_SCRIPT_TIMEOUT }, { MD_CACHE_EXTENSIONS, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, IDS_MD_CACHE_EXTENSIONS }, { MD_CREATE_PROCESS_AS_USER, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, IDS_MD_CREATE_PROCESS_AS_USER }, { MD_CREATE_PROC_NEW_CONSOLE, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, IDS_MD_CREATE_PROC_NEW_CONSOLE }, { MD_POOL_IDC_TIMEOUT, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, IDS_MD_POOL_IDC_TIMEOUT }, { MD_ALLOW_KEEPALIVES, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, IDS_MD_ALLOW_KEEPALIVES }, { MD_IS_CONTENT_INDEXED, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, IDS_MD_IS_CONTENT_INDEXED }, { MD_ISM_ACCESS_CHECK, METADATA_NO_ATTRIBUTES, IIS_MD_UT_FILE, DWORD_METADATA, 0 }, { MD_ASP_BUFFERINGON, METADATA_INHERIT, ASP_MD_UT_APP, DWORD_METADATA, IDS_ASP_BUFFERINGON }, { MD_ASP_LOGERRORREQUESTS, METADATA_INHERIT, IIS_MD_UT_WAM, DWORD_METADATA, IDS_ASP_LOGERRORREQUESTS }, { MD_ASP_SCRIPTERRORSSENTTOBROWSER, METADATA_INHERIT, ASP_MD_UT_APP, DWORD_METADATA, IDS_ASP_SCRIPTERRORSSENTTOBROWSER }, { MD_ASP_SCRIPTERRORMESSAGE, METADATA_INHERIT, ASP_MD_UT_APP, STRING_METADATA, IDS_ASP_SCRIPTERRORMESSAGE }, { MD_ASP_SCRIPTFILECACHESIZE, METADATA_INHERIT, IIS_MD_UT_WAM, DWORD_METADATA, IDS_ASP_SCRIPTFILECACHESIZE }, { MD_ASP_SCRIPTENGINECACHEMAX, METADATA_INHERIT, IIS_MD_UT_WAM, DWORD_METADATA, IDS_ASP_SCRIPTENGINECACHEMAX }, { MD_ASP_SCRIPTTIMEOUT, METADATA_INHERIT, ASP_MD_UT_APP, DWORD_METADATA, IDS_ASP_SCRIPTTIMEOUT }, { MD_ASP_SESSIONTIMEOUT, METADATA_INHERIT, ASP_MD_UT_APP, DWORD_METADATA, IDS_ASP_SESSIONTIMEOUT }, { MD_ASP_ENABLEPARENTPATHS, METADATA_INHERIT, ASP_MD_UT_APP, DWORD_METADATA, IDS_ASP_ENABLEPARENTPATHS }, { MD_ASP_ALLOWSESSIONSTATE, METADATA_INHERIT, ASP_MD_UT_APP, DWORD_METADATA, IDS_ASP_ALLOWSESSIONSTATE }, { MD_ASP_SCRIPTLANGUAGE, METADATA_INHERIT, ASP_MD_UT_APP, STRING_METADATA, IDS_ASP_SCRIPTLANGUAGE }, { MD_ASP_EXCEPTIONCATCHENABLE, METADATA_INHERIT, IIS_MD_UT_WAM, DWORD_METADATA, IDS_ASP_EXCEPTIONCATCHENABLE }, { MD_ASP_ENABLESERVERDEBUG, METADATA_INHERIT, ASP_MD_UT_APP, DWORD_METADATA, IDS_ASP_ENABLESERVERDEBUG }, { MD_ASP_ENABLECLIENTDEBUG, METADATA_INHERIT, ASP_MD_UT_APP, DWORD_METADATA, IDS_ASP_ENABLECLIENTDEBUG },
{ MD_WAM_USER_NAME, METADATA_INHERIT, IIS_MD_UT_SERVER, STRING_METADATA, 0 }, { MD_WAM_PWD, METADATA_INHERIT, IIS_MD_UT_SERVER, STRING_METADATA, 0 }, //
// IIS6 Application Pools
//
{ MD_APPPOOL_PERIODIC_RESTART_TIME, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_APPPOOL_PERIODIC_RESTART_REQUEST_COUNT, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_APPPOOL_MAX_PROCESS_COUNT, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_APPPOOL_PINGING_ENABLED, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_APPPOOL_IDLE_TIMEOUT, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_APPPOOL_RAPID_FAIL_PROTECTION_ENABLED, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_APPPOOL_ORPHAN_PROCESSES_FOR_DEBUGGING, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_APPPOOL_STARTUP_TIMELIMIT, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_APPPOOL_SHUTDOWN_TIMELIMIT, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_APPPOOL_PING_INTERVAL, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_APPPOOL_ORPHAN_ACTION, METADATA_INHERIT, IIS_MD_UT_SERVER, STRING_METADATA, 0 }, { MD_APPPOOL_UL_APPPOOL_QUEUE_LENGTH, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_APPPOOL_FRIENDLY_NAME, METADATA_INHERIT, IIS_MD_UT_SERVER, STRING_METADATA, 0 }, { MD_APPPOOL_PERIODIC_RESTART_SCHEDULE, METADATA_INHERIT, IIS_MD_UT_SERVER, MULTISZ_METADATA, 0 }, { MD_APPPOOL_IDENTITY_TYPE, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_CPU_ACTION, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_CPU_LIMIT, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_APPPOOL_PERIODIC_RESTART_MEMORY, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_RAPID_FAIL_PROTECTION_INTERVAL, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_RAPID_FAIL_PROTECTION_MAX_CRASHES, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_APP_APPPOOL_ID, METADATA_INHERIT, IIS_MD_UT_SERVER, STRING_METADATA, 0 }, // Global parameters
{ MD_MAX_GLOBAL_BANDWIDTH, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_MAX_GLOBAL_CONNECTIONS, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_GLOBAL_STANDARD_APP_MODE_ENABLED,METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_GLOBAL_LOG_IN_UTF_8, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, { MD_ROOT_ENABLE_EDIT_WHILE_RUNNING, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, 0 }, };
#define NUM_ENTRIES (sizeof(CMetaKey::s_rgMetaTable) / sizeof(CMetaKey::s_rgMetaTable[0]))
/* static */ int CMetaKey::MapMDIDToTableIndex( IN DWORD dwID ) /*++
Routine Description:
Map MD id value to table index. Return -1 if not found
Arguments:
DWORD dwID : MD id value
Return Value:
Index into the table that coresponds to the MD id value
--*/ { #ifdef _DEBUG
{ //
// Do a quick verification that our metadata
// table is sorted correctly.
//
static BOOL fTableChecked = FALSE;
if (!fTableChecked) { for (int n = 1; n < NUM_ENTRIES; ++n) { if (s_rgMetaTable[n].dwMDIdentifier <= s_rgMetaTable[n - 1].dwMDIdentifier) { TRACEEOLID("MD ID Table is out of order: Item is " << n << " " << s_rgMetaTable[n].dwMDIdentifier ); ASSERT_MSG("MD ID Table out of order"); } }
//
// But only once.
//
++fTableChecked; } }
#endif // _DEBUG
//
// Look up the ID in the table using a binary search
//
int nRange = NUM_ENTRIES; int nLow = 0; int nHigh = nRange - 1; int nMid; int nHalf;
while (nLow <= nHigh) { if (0 != (nHalf = nRange / 2)) { nMid = nLow + (nRange & 1 ? nHalf : (nHalf - 1));
if (s_rgMetaTable[nMid].dwMDIdentifier == dwID) { return nMid; } else if (s_rgMetaTable[nMid].dwMDIdentifier > dwID) { nHigh = --nMid; nRange = nRange & 1 ? nHalf : nHalf - 1; } else { nLow = ++nMid; nRange = nHalf; } } else if (nRange) { return s_rgMetaTable[nLow].dwMDIdentifier == dwID ? nLow : -1; } else { break; } }
return -1; }
/* static */ BOOL CMetaKey::GetMDFieldDef( IN DWORD dwID, OUT DWORD & dwMDIdentifier, OUT DWORD & dwMDAttributes, OUT DWORD & dwMDUserType, OUT DWORD & dwMDDataType ) /*++
Routine Description:
Get information about metabase property
Arguments:
DWORD dwID : Meta ID DWORD & dwMDIdentifier : Meta parms DWORD & dwMDAttributes : Meta parms DWORD & dwMDUserType : Meta parms DWORD & dwMDDataType : Meta parms
Return Value:
TRUE for success, FALSE for failure.
--*/ { int nID = MapMDIDToTableIndex(dwID);
if (nID == -1) { //
// Unrecognized meta data ID
//
ASSERT_MSG("Unrecognized meta data id"); return FALSE; }
dwMDIdentifier = s_rgMetaTable[nID].dwMDIdentifier; dwMDAttributes = s_rgMetaTable[nID].dwMDAttributes; dwMDUserType = s_rgMetaTable[nID].dwMDUserType; dwMDDataType = s_rgMetaTable[nID].dwMDDataType;
return TRUE; }
/* static */ BOOL CMetaKey::IsPropertyInheritable( IN DWORD dwID ) /*++
Routine Description:
Check to see if the given property is inheritable
Arguments:
DWORD dwID : Metabase ID
Return Value:
TRUE if the metabase ID is inheritable, FALSE otherwise.
--*/ { int nID = MapMDIDToTableIndex(dwID);
if (nID == -1) { //
// Unrecognized meta data ID
//
ASSERT_MSG("Unrecognized meta data ID"); return FALSE; }
return (s_rgMetaTable[nID].dwMDAttributes & METADATA_INHERIT) != 0; }
/* static */ BOOL CMetaKey::GetPropertyDescription( IN DWORD dwID, OUT CString & strName ) /*++
Routine Description:
Get a description for the given property
Arguments:
DWORD dwID : Property ID CString & strName : Returns friendly property name
Return Value:
TRUE for success, FALSE for failure
--*/ { int nID = MapMDIDToTableIndex(dwID);
if (nID == -1) { //
// Unrecognized meta data ID
//
ASSERT_MSG("Unrecognized meta data ID"); return FALSE; }
UINT uID = s_rgMetaTable[nID].uStringID;
BOOL fResult = TRUE;
if (uID > 0) { fResult = (strName.LoadString(uID) != 0); } else { //
// Don't have a friendly name -- fake it
//
CComBSTR bstrFmt; VERIFY(bstrFmt.LoadString(hDLLInstance, IDS_INHERITANCE_NO_NAME));
strName.Format(bstrFmt, dwID); }
return fResult; }
CMetaKey::CMetaKey( IN CComAuthInfo * pAuthInfo OPTIONAL ) /*++
Routine Description:
Constructor that creates the interface, but does not open the key. This is the ONLY constructor that allows operations from METDATA_MASTER_ROOT_HANDLE (read operations obviously)
Arguments:
CComAuthInfo * pAuthInfo : If NULL, opens interface on local machine
Return Value:
N/A
--*/ : CMetaInterface(pAuthInfo), m_hKey(METADATA_MASTER_ROOT_HANDLE), m_hBase(NULL), m_hrKey(S_OK), m_dwFlags(0L), m_cbInitialBufferSize(MB_INIT_BUFF_SIZE), m_strMetaPath(), m_fAllowRootOperations(TRUE), m_fOwnKey(TRUE) { m_hrKey = CMetaInterface::QueryResult();
//
// Do not open key
//
}
CMetaKey::CMetaKey( IN CMetaInterface * pInterface ) /*++
Routine Description:
Construct with pre-existing interface. Does not open any keys
Arguments:
CMetaInterface * pInterface : Preexisting interface
Return Value:
N/A
--*/ : CMetaInterface(pInterface), m_hKey(NULL), m_hBase(NULL), m_strMetaPath(), m_dwFlags(0L), m_cbInitialBufferSize(MB_INIT_BUFF_SIZE), m_fAllowRootOperations(TRUE), m_fOwnKey(TRUE) { m_hrKey = CMetaInterface::QueryResult(); }
CMetaKey::CMetaKey( IN CComAuthInfo * pAuthInfo, OPTIONAL IN LPCTSTR lpszMDPath, OPTIONAL IN DWORD dwFlags, IN METADATA_HANDLE hkBase ) /*++
Routine Description:
Fully defined constructor that opens a key
Arguments:
CComAuthInfo * pAuthInfo : Auth info or NULL LPCTSTR lpszMDPath : Path or NULL DWORD dwFlags : Open permissions METADATA_HANDLE hkBase : Base key
Return Value:
N/A
--*/ : CMetaInterface(pAuthInfo), m_hKey(NULL), m_hBase(NULL), m_dwFlags(0L), m_cbInitialBufferSize(MB_INIT_BUFF_SIZE), m_fAllowRootOperations(FALSE), m_strMetaPath(), m_fOwnKey(TRUE) { m_hrKey = CMetaInterface::QueryResult();
if (SUCCEEDED(m_hrKey)) { m_hrKey = Open(dwFlags, lpszMDPath, hkBase); } }
CMetaKey::CMetaKey( IN CMetaInterface * pInterface, IN LPCTSTR lpszMDPath, OPTIONAL IN DWORD dwFlags, IN METADATA_HANDLE hkBase ) /*++
Routine Description:
Fully defined constructor that opens a key
Arguments:
CMetaInterface * pInterface : Existing interface DWORD dwFlags : Open permissions METADATA_HANDLE hkBase : Base key LPCTSTR lpszMDPath : Path or NULL
Return Value:
N/A
--*/ : CMetaInterface(pInterface), m_hKey(NULL), m_hBase(NULL), m_strMetaPath(), m_dwFlags(0L), m_cbInitialBufferSize(MB_INIT_BUFF_SIZE), m_fAllowRootOperations(FALSE), m_fOwnKey(TRUE) { m_hrKey = CMetaInterface::QueryResult();
if (SUCCEEDED(m_hrKey)) { m_hrKey = Open(dwFlags, lpszMDPath, hkBase); } }
CMetaKey::CMetaKey( IN BOOL fOwnKey, IN CMetaKey * pKey ) /*++
Routine Description:
Copy constructor.
Arguments:
BOOL fOwnKey : TRUE to take ownership of the key const CMetaKey * pKey : Existing key
Return Value:
N/A
--*/ : CMetaInterface(pKey), m_hKey(pKey->m_hKey), m_hBase(pKey->m_hBase), m_dwFlags(pKey->m_dwFlags), m_cbInitialBufferSize(pKey->m_cbInitialBufferSize), m_fAllowRootOperations(pKey->m_fAllowRootOperations), m_hrKey(pKey->m_hrKey), m_strMetaPath(pKey->m_strMetaPath), m_fOwnKey(fOwnKey) { //
// No provisions for anything else at the moment
//
ASSERT(!m_fOwnKey); }
CMetaKey::~CMetaKey() /*++
Routine Description:
Destructor -- Close the key.
Arguments:
N/A
Return Value:
N/A
--*/ { if (IsOpen() && m_fOwnKey) { Close(); } }
/* virtual */ BOOL CMetaKey::Succeeded() const /*++
Routine Description:
Determine if object was constructed successfully
Arguments:
None
Return Value:
TRUE for success, FALSE for failure
--*/ { return SUCCEEDED(m_hrKey); }
/* virtual */ HRESULT CMetaKey::QueryResult() const /*++
Routine Description:
Return the construction error for this object
Arguments:
None
Return Value:
HRESULT from construction errors
--*/ { return m_hrKey; }
HRESULT CMetaKey::Open( IN DWORD dwFlags, IN LPCTSTR lpszMDPath, OPTIONAL IN METADATA_HANDLE hkBase ) /*++
Routine Description:
Attempt to open a metabase key
Arguments:
DWORD dwFlags : Permission flags LPCTSTR lpszMDPath : Optional path METADATA_HANDLE hkBase : Base metabase key
Return Value:
HRESULT
--*/ { ASSURE_PROPER_INTERFACE();
if (m_hKey != NULL) { ASSERT_MSG("Attempting to open key that already has an open handle");
TRACEEOLID("Closing that key"); Close(); }
//
// Base key is stored for reopen purposes only
//
m_hBase = hkBase; m_strMetaPath = lpszMDPath; m_dwFlags = dwFlags;
return OpenKey(m_hBase, m_strMetaPath, m_dwFlags, &m_hKey); }
HRESULT CMetaKey::CreatePathFromFailedOpen() /*++
Routine Description:
If the path doesn't exist, create it. This method should be called after an Open call failed (because it will have initialized m_strMetaPath.
Arguments:
None
Return Value:
HRESULT
--*/ { CString strParentPath; CString strObjectName; CString strSavePath(m_strMetaPath);
CMetabasePath::SplitMetaPathAtInstance( m_strMetaPath, strParentPath, strObjectName );
CError err(Open( METADATA_PERMISSION_WRITE, strParentPath ));
if (err.Succeeded()) { //
// This really should never fail, because we're opening
// the path at the instance.
//
err = AddKey(strObjectName); }
if (IsOpen()) { Close(); }
//
// The previous open wiped out the path...
//
m_strMetaPath = strSavePath;
return err; }
HRESULT CMetaKey::Close() /*++
Routine Description:
Close the currently open key.
Arguments:
N/A
Return Value:
N/A
--*/ { ASSURE_PROPER_INTERFACE();
HRESULT hr = S_OK;
ASSERT(m_hKey != NULL); ASSERT(m_fOwnKey);
if (m_hKey) { hr = CloseKey(m_hKey);
if (SUCCEEDED(hr)) { m_hKey = NULL; } }
return hr; }
HRESULT CMetaKey::ConvertToParentPath( IN BOOL fImmediate ) /*++
Routine Description:
Change the path to the parent path.
Arguments:
BOOL fImmediate : If TRUE, the immediate parent's path will be used if FALSE, the first parent that really exists
Return Value:
HRESULT
ERROR_INVALID_PARAMETER if there is no valid path
--*/ { BOOL fIsOpen = IsOpen();
if (fIsOpen) { Close(); }
CError err;
FOREVER { if (!CMetabasePath::ConvertToParentPath(m_strMetaPath)) { //
// There is no parent path
//
err = ERROR_INVALID_PARAMETER; break; }
err = ReOpen();
//
// Path not found is the only valid error
// other than success.
//
if (fImmediate || err.Succeeded() || err.Win32Error() != ERROR_PATH_NOT_FOUND) { break; } }
//
// Remember to reset the construction error
// which referred to the parent path.
//
m_hrKey = err;
return err; }
/* protected */ HRESULT CMetaKey::GetPropertyValue( IN DWORD dwID, OUT IN DWORD & dwSize, OPTIONAL OUT IN void *& pvData, OPTIONAL OUT IN DWORD * pdwDataType, OPTIONAL IN BOOL * pfInheritanceOverride, OPTIONAL IN LPCTSTR lpszMDPath, OPTIONAL OUT DWORD * pdwAttributes OPTIONAL ) /*++
Routine Description:
Get metadata on the currently open key.
Arguments:
DWORD dwID : Property ID number DWORD & dwSize : Buffer size (could be 0) void *& pvData : Buffer -- will allocate if NULL DWORD * pdwDataType : NULL or on in contains valid data types, : on out contains actual data type BOOL * pfInheritanceOverride : NULL or on forces inheritance on/off LPCTSTR lpszMDPath : Optional path off the open key DWORD * pdwAttributes : Optionally returns attributes
Return Value:
HRESULT
ERROR_INVALID_HANDLE : If the handle is not open ERROR_INVALID_PARAMETER : If the property id is not found, or the data type doesn't match requested type ERROR_OUTOFMEMORY : Out of memory
--*/ { ASSURE_PROPER_INTERFACE(); ASSURE_OPEN_KEY();
METADATA_RECORD mdRecord; FETCH_PROPERTY_DATA_OR_FAIL(dwID, mdRecord);
//
// If unable to find this property ID in our table, or
// if we specified a desired type, and this type doesn't
// match it, give up.
//
if (pdwDataType && *pdwDataType != ALL_METADATA && *pdwDataType != mdRecord.dwMDDataType) { ASSERT_MSG("Invalid parameter"); return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER); }
//
// Check to see if inheritance behaviour is overridden
//
if (pfInheritanceOverride) { if (*pfInheritanceOverride) { mdRecord.dwMDAttributes |= METADATA_INHERIT; } else { mdRecord.dwMDAttributes &= ~METADATA_INHERIT; } }
//
// This causes a bad parameter error on input otherwise
//
mdRecord.dwMDAttributes &= ~METADATA_REFERENCE;
//
// If we're looking for inheritable properties, the path
// doesn't have to be completely specified.
//
if (mdRecord.dwMDAttributes & METADATA_INHERIT) { mdRecord.dwMDAttributes |= (METADATA_PARTIAL_PATH | METADATA_ISINHERITED); }
ASSERT(dwSize > 0 || pvData == NULL); mdRecord.dwMDDataLen = dwSize; mdRecord.pbMDData = (LPBYTE)pvData;
//
// If no buffer provided, allocate one.
//
HRESULT hr = S_OK; BOOL fBufferTooSmall = FALSE; BOOL fAllocatedMemory = FALSE; DWORD dwInitSize = m_cbInitialBufferSize;
do { if(mdRecord.pbMDData == NULL) { mdRecord.dwMDDataLen = dwInitSize; mdRecord.pbMDData = (LPBYTE)AllocMem(dwInitSize);
if(mdRecord.pbMDData == NULL && dwInitSize > 0) { hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY); break; }
++fAllocatedMemory; }
//
// Get the data
//
DWORD dwRequiredDataLen = 0; hr = GetData(m_hKey, lpszMDPath, &mdRecord, &dwRequiredDataLen);
//
// Re-fetch the buffer if it's too small.
//
fBufferTooSmall = (HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER) && fAllocatedMemory;
if(fBufferTooSmall) { //
// Delete the old buffer, and set up for a re-fetch.
//
FreeMem(mdRecord.pbMDData); mdRecord.pbMDData = NULL; dwInitSize = dwRequiredDataLen; } } while(fBufferTooSmall);
//
// Failed
//
if(FAILED(hr) && fAllocatedMemory) { FreeMem(mdRecord.pbMDData); mdRecord.pbMDData = NULL; }
dwSize = mdRecord.dwMDDataLen; pvData = mdRecord.pbMDData;
if (pdwDataType != NULL) { //
// Return actual data type
//
*pdwDataType = mdRecord.dwMDDataType; }
if (pdwAttributes != NULL) { //
// Return data attributes
//
*pdwAttributes = mdRecord.dwMDAttributes; }
return hr; }
/* protected */ HRESULT CMetaKey::GetDataPaths( OUT CStringListEx & strlDataPaths, IN DWORD dwMDIdentifier, IN DWORD dwMDDataType, IN LPCTSTR lpszMDPath OPTIONAL ) /*++
Routine Description:
Get data paths
Arguments:
Return Value:
HRESULT
--*/ { ASSURE_PROPER_INTERFACE(); ASSURE_OPEN_KEY();
//
// Start with a small buffer
//
DWORD dwMDBufferSize = 1024; LPTSTR lpszBuffer = NULL; CError err;
do { if (lpszBuffer != NULL) { FreeMem(lpszBuffer); }
lpszBuffer = AllocTString(dwMDBufferSize);
if (lpszBuffer == NULL) { err = ERROR_NOT_ENOUGH_MEMORY; break; }
err = CMetaInterface::GetDataPaths( m_hKey, lpszMDPath, dwMDIdentifier, dwMDDataType, dwMDBufferSize, lpszBuffer, &dwMDBufferSize ); } while(err.Win32Error() == ERROR_INSUFFICIENT_BUFFER);
if (err.Win32Error() == ERROR_PATH_NOT_FOUND) { //
// That's ok... this is some sort of physical directory
// that doesn't currently exist in the metabase, and
// which therefore doesn't have any descendants anyway.
//
ZeroMemory(lpszBuffer, dwMDBufferSize); err.Reset(); }
if (err.Succeeded()) { ConvertDoubleNullListToStringList(lpszBuffer, strlDataPaths); FreeMem(lpszBuffer); }
return err; }
HRESULT CMetaKey::CheckDescendants( IN DWORD dwID, IN CComAuthInfo * pAuthInfo, OPTIONAL IN LPCTSTR lpszMDPath OPTIONAL ) /*++
Routine Description:
Check for descendant overrides; If there are any, bring up a dialog that displays them, and give the user the opportunity the remove the overrides.
Arguments:
DWORD dwID : Property ID CComAuthInfo * pAuthInfo : Server or NULL LPCTSTR lpszMDPath : Metabase path or NULL
Return Value:
HRESULT
--*/ { ASSURE_PROPER_INTERFACE();
HRESULT hr = S_OK;
METADATA_RECORD mdRecord; FETCH_PROPERTY_DATA_OR_FAIL(dwID, mdRecord);
if (mdRecord.dwMDAttributes & METADATA_INHERIT) { CStringListEx strlDataPaths;
hr = GetDataPaths( strlDataPaths, mdRecord.dwMDIdentifier, mdRecord.dwMDDataType, lpszMDPath );
if (SUCCEEDED(hr) && !strlDataPaths.IsEmpty()) { //
// Bring up the inheritance override dialog
//
CInheritanceDlg dlg( dwID, FROM_WRITE_PROPERTY, pAuthInfo, lpszMDPath, strlDataPaths );
if (!dlg.IsEmpty()) { dlg.DoModal(); } } }
return hr; }
/* protected */ HRESULT CMetaKey::SetPropertyValue( IN DWORD dwID, IN DWORD dwSize, IN void * pvData, IN BOOL * pfInheritanceOverride, OPTIONAL IN LPCTSTR lpszMDPath OPTIONAL ) /*++
Routine Description:
Set metadata on the open key. The key must have been opened with write permission.
Arguments:
DWORD dwID : Property ID DWORD dwSize : Size of data void * pvData : Data buffer BOOL * pfInheritanceOverride : NULL or forces inheritance on/off LPCTSTR lpszMDPath : Optional path off the open key
Return Value:
HRESULT
ERROR_INVALID_HANDLE : If the handle is not open ERROR_INVALID_PARAMETER : If the property id is not found, or the buffer is NULL or of size 0
--*/ { ASSURE_PROPER_INTERFACE(); ASSURE_OPEN_KEY();
if (pvData == NULL && dwSize != 0) { ASSERT_MSG("No Data"); return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER); }
METADATA_RECORD mdRecord; FETCH_PROPERTY_DATA_OR_FAIL(dwID, mdRecord);
if (pfInheritanceOverride) { if (*pfInheritanceOverride) { mdRecord.dwMDAttributes |= METADATA_INHERIT; } else { mdRecord.dwMDAttributes &= ~METADATA_INHERIT; } }
mdRecord.dwMDDataLen = dwSize; mdRecord.pbMDData = (LPBYTE)pvData;
return SetData(m_hKey, lpszMDPath, &mdRecord); }
/* protected */ HRESULT CMetaKey::GetAllData( IN DWORD dwMDAttributes, IN DWORD dwMDUserType, IN DWORD dwMDDataType, OUT DWORD * pdwMDNumEntries, OUT DWORD * pdwMDDataLen, OUT PBYTE * ppbMDData, IN LPCTSTR lpszMDPath OPTIONAL ) /*++
Routine Description:
Get all data off the open key. Buffer is created automatically.
Arguments:
DWORD dwMDAttributes : Attributes DWORD dwMDUserType : User type to fetch DWORD dwMDDataType : Data type to fetch DWORD * pdwMDNumEntries : Returns number of entries read DWORD * pdwMDDataLen : Returns size of data buffer PBYTE * ppbMDData : Returns data buffer LPCTSTR lpszMDPath : Optional data path
Return Value:
HRESULT
--*/ { ASSURE_PROPER_INTERFACE(); ASSURE_OPEN_KEY();
//
// Check for valid parameters
//
if(!pdwMDDataLen || !ppbMDData || !pdwMDNumEntries) { return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER); }
HRESULT hr = S_OK; BOOL fBufferTooSmall = FALSE; DWORD dwMDDataSetNumber; DWORD dwRequiredBufferSize; DWORD dwInitSize = m_cbInitialBufferSize; *ppbMDData = NULL;
do { *pdwMDDataLen = dwInitSize; *ppbMDData = (LPBYTE)AllocMem(dwInitSize);
if (ppbMDData == NULL && dwInitSize > 0) { hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY); break; }
hr = CMetaInterface::GetAllData( m_hKey, lpszMDPath, dwMDAttributes, dwMDUserType, dwMDDataType, pdwMDNumEntries, &dwMDDataSetNumber, *pdwMDDataLen, *ppbMDData, &dwRequiredBufferSize );
//
// Re-fetch the buffer if it's too small.
//
fBufferTooSmall = (HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER);
if(fBufferTooSmall) { //
// Delete the old buffer, and set up for a re-fetch.
//
SAFE_FREEMEM(*ppbMDData); dwInitSize = dwRequiredBufferSize; } } while (fBufferTooSmall);
if (FAILED(hr)) { //
// No good, be sure we don't leak anything
//
SAFE_FREEMEM(*ppbMDData); dwInitSize = 0L; }
return hr; }
HRESULT CMetaKey::QueryValue( IN DWORD dwID, IN OUT DWORD & dwValue, IN BOOL * pfInheritanceOverride, OPTIONAL IN LPCTSTR lpszMDPath, OPTIONAL OUT DWORD * pdwAttributes OPTIONAL ) /*++
Routine Description:
Fetch data as a DWORD
Arguments:
DWORD dwID : Property ID DWORD & dwValue : Returns the value read in BOOL * pfInheritanceOverride : NULL or forces inheritance on/off LPCTSTR lpszMDPath : Optional path off the open key DWORD * pdwAttributes : Optionally returns attributes
Return Value:
HRESULT
--*/ { DWORD dwSize = sizeof(dwValue); DWORD dwDataType = DWORD_METADATA; void * pvData = &dwValue;
return GetPropertyValue( dwID, dwSize, pvData, &dwDataType, pfInheritanceOverride, lpszMDPath, pdwAttributes ); }
HRESULT CMetaKey::QueryValue( IN DWORD dwID, IN OUT CString & strValue, IN BOOL * pfInheritanceOverride, OPTIONAL IN LPCTSTR lpszMDPath, OPTIONAL OUT DWORD * pdwAttributes OPTIONAL ) /*++
Routine Description:
Fetch data as a string
Arguments:
DWORD dwID : Property ID DWORD & strValue : Returns the value read in BOOL * pfInheritanceOverride : NULL or forces inheritance on/off LPCTSTR lpszMDPath : Optional path off the open key DWORD * pdwAttributes : Optionally returns attributes
Return Value:
HRESULT
--*/ { //
// Get GetData allocate the buffer for us
//
DWORD dwSize = 0; DWORD dwDataType = ALL_METADATA; LPTSTR lpData = NULL;
HRESULT hr = GetPropertyValue( dwID, dwSize, (void *&)lpData, &dwDataType, pfInheritanceOverride, lpszMDPath, pdwAttributes );
if (SUCCEEDED(hr)) { //
// Notes: consider optional auto-expansion on EXPANDSZ_METADATA
// (see registry functions), and data type conversions for DWORD
// or MULTISZ_METADATA or BINARY_METADATA
//
if (dwDataType == EXPANDSZ_METADATA || dwDataType == STRING_METADATA) { try { strValue = lpData; } catch(CMemoryException * e) { hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY); strValue.Empty(); e->Delete(); } } else { hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER); } }
if (lpData) { FreeMem(lpData); }
return hr; }
HRESULT CMetaKey::QueryValue( IN DWORD dwID, IN OUT CComBSTR & strValue, IN BOOL * pfInheritanceOverride, OPTIONAL IN LPCTSTR lpszMDPath, OPTIONAL OUT DWORD * pdwAttributes OPTIONAL ) /*++
Routine Description:
Fetch data as a string
Arguments:
DWORD dwID : Property ID DWORD & CComBSTR : Returns the value read in BOOL * pfInheritanceOverride : NULL or forces inheritance on/off LPCTSTR lpszMDPath : Optional path off the open key DWORD * pdwAttributes : Optionally returns attributes
Return Value:
HRESULT
--*/ { //
// Get GetData allocate the buffer for us
//
DWORD dwSize = 0; DWORD dwDataType = ALL_METADATA; LPTSTR lpData = NULL;
HRESULT hr = GetPropertyValue( dwID, dwSize, (void *&)lpData, &dwDataType, pfInheritanceOverride, lpszMDPath, pdwAttributes );
if (SUCCEEDED(hr)) { //
// Notes: consider optional auto-expansion on EXPANDSZ_METADATA
// (see registry functions), and data type conversions for DWORD
// or MULTISZ_METADATA or BINARY_METADATA
//
if (dwDataType == EXPANDSZ_METADATA || dwDataType == STRING_METADATA) { strValue = lpData; } else { hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER); } }
if (lpData) { FreeMem(lpData); }
return hr; }
HRESULT CMetaKey::QueryValue( IN DWORD dwID, IN OUT CStringListEx & strlValue, IN BOOL * pfInheritanceOverride, OPTIONAL IN LPCTSTR lpszMDPath, OPTIONAL OUT DWORD * pdwAttributes OPTIONAL ) /*++
Routine Description:
Fetch data as a stringlist
Arguments:
DWORD dwID : Property ID DWORD & strlValue : Returns the value read in BOOL * pfInheritanceOverride : NULL or forces inheritance on/off LPCTSTR lpszMDPath : Optional path off the open key DWORD * pdwAttributes : Optionally returns attributes
Return Value:
HRESULT
--*/ { //
// Get GetData allocate the buffer for us
//
DWORD dwSize = 0; DWORD dwDataType = MULTISZ_METADATA; LPTSTR lpData = NULL;
HRESULT hr = GetPropertyValue( dwID, dwSize, (void *&)lpData, &dwDataType, pfInheritanceOverride, lpszMDPath, pdwAttributes );
if (SUCCEEDED(hr)) { //
// Notes: Consider accepting a single STRING
//
ASSERT(dwDataType == MULTISZ_METADATA);
DWORD err = ConvertDoubleNullListToStringList( lpData, strlValue, dwSize / sizeof(TCHAR) ); hr = HRESULT_FROM_WIN32(err); }
if (lpData) { FreeMem(lpData); }
return hr; }
HRESULT CMetaKey::QueryValue( IN DWORD dwID, IN OUT CBlob & blValue, IN BOOL * pfInheritanceOverride, OPTIONAL IN LPCTSTR lpszMDPath, OPTIONAL OUT DWORD * pdwAttributes OPTIONAL ) /*++
Routine Description:
Fetch data as a binary blob
Arguments:
DWORD dwID : Property ID DWORD CBlob & blValue : Returns the binary blob BOOL * pfInheritanceOverride : NULL or forces inheritance on/off LPCTSTR lpszMDPath : Optional path off the open key DWORD * pdwAttributes : Optionally returns attributes
Return Value:
HRESULT
--*/ { //
// Get GetData allocate the buffer for us
//
DWORD dwSize = 0; DWORD dwDataType = BINARY_METADATA; LPBYTE pbData = NULL;
HRESULT hr = GetPropertyValue( dwID, dwSize, (void *&)pbData, &dwDataType, pfInheritanceOverride, lpszMDPath, pdwAttributes );
if (SUCCEEDED(hr)) { //
// Blob takes ownership of the data, so don't free it...
//
ASSERT_READ_PTR2(pbData, dwSize); blValue.SetValue(dwSize, pbData, FALSE); }
return hr; }
HRESULT CMetaKey::SetValue( IN DWORD dwID, IN CStringListEx & strlValue, IN BOOL * pfInheritanceOverride, OPTIONAL IN LPCTSTR lpszMDPath OPTIONAL ) /*++
Routine Description:
Store data as string
Arguments:
DWORD dwID : Property ID CStringListEx & strlValue : Value to be written BOOL * pfInheritanceOverride : NULL or forces inheritance on/off LPCTSTR lpszMDPath : Optional path (or NULL or "")
Return Value:
HRESULT
--*/ { DWORD cCharacters; LPTSTR lpstr = NULL;
//
// Flatten value
//
ConvertStringListToDoubleNullList( strlValue, cCharacters, lpstr );
HRESULT hr = SetPropertyValue( dwID, cCharacters * sizeof(TCHAR), (void *)lpstr, pfInheritanceOverride, lpszMDPath );
SAFE_FREEMEM(lpstr);
return hr; }
HRESULT CMetaKey::SetValue( IN DWORD dwID, IN CBlob & blValue, IN BOOL * pfInheritanceOverride, OPTIONAL IN LPCTSTR lpszMDPath OPTIONAL ) /*++
Routine Description:
Store data as binary
Arguments:
DWORD dwID : Property ID CBlob & blValue : Value to be written BOOL * pfInheritanceOverride : NULL or forces inheritance on/off LPCTSTR lpszMDPath : Optional path (or NULL or "")
Return Value:
HRESULT
--*/ { return SetPropertyValue( dwID, blValue.GetSize(), (void *)blValue.GetData(), pfInheritanceOverride, lpszMDPath ); }
HRESULT CMetaKey::DeleteValue( DWORD dwID, LPCTSTR lpszMDPath OPTIONAL ) /*++
Routine Description:
Delete data
Arguments:
DWORD dwID : Property ID of property to be deleted LPCTSTR lpszMDPath : Optional path (or NULL or "")
Return Value:
HRESULT
--*/ { ASSURE_PROPER_INTERFACE(); ASSURE_OPEN_KEY();
METADATA_RECORD mdRecord; FETCH_PROPERTY_DATA_OR_FAIL(dwID, mdRecord);
return DeleteData( m_hKey, lpszMDPath, mdRecord.dwMDIdentifier, mdRecord.dwMDDataType ); }
HRESULT CMetaKey::DoesPathExist( IN LPCTSTR lpszMDPath ) /*++
Routine Description:
Determine if the path exists
Arguments:
LPCTSTR lpszMDPath : Relative path off the open key
Return Value:
HRESULT, or S_OK if the path exists.
--*/ { ASSURE_PROPER_INTERFACE(); ASSURE_OPEN_KEY();
FILETIME ft;
return GetLastChangeTime(m_hKey, lpszMDPath, &ft, FALSE); }
HRESULT CMetaInterface::Regenerate() /*++
Routine Description:
Attempt to recreate the interface pointer. This assumes that the interface had been successfully created before, but has become invalid at some point afterwards.
Arguments:
None
Return Value:
HRESULT
--*/ { ASSERT_PTR(m_pInterface); // Must have been initialised
SAFE_RELEASE(m_pInterface);
m_hrInterface = Create();
return m_hrInterface; }
//
// CWamInterface class
//
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
CWamInterface::CWamInterface( IN CComAuthInfo * pAuthInfo OPTIONAL ) /*++
Routine Description:
Construct and initialize the interface.
Arguments:
CComAuthInfo * pAuthInfo : Auth info. NULL indicates the local computer.
Return Value:
N/A
--*/ : CIISInterface(pAuthInfo), m_pInterface(NULL), m_fSupportsPooledProc(FALSE) { //
// Initialize the interface
//
m_hrInterface = Create(); }
CWamInterface::CWamInterface( IN CWamInterface * pInterface ) /*++
Routine Description:
Construct from existing interface (copy constructor)
Arguments:
CWamInterface * pInterface : Existing interface
Return Value:
N/A
--*/ : CIISInterface(&pInterface->m_auth, pInterface->m_hrInterface), m_pInterface(pInterface->m_pInterface), m_fSupportsPooledProc(FALSE) { ASSERT_PTR(m_pInterface); m_pInterface->AddRef(); }
CWamInterface::~CWamInterface() /*++
Routine Description:
Destructor -- releases the interface.
Arguments:
N/A
Return Value:
N/A
--*/ { SAFE_RELEASE(m_pInterface); }
/* protected */ HRESULT CWamInterface::Create() /*++
Routine Description: Create the interface with DCOM
Arguments: None
Return Value: HRESULT
Notes: First, it will attempt to create the new interface, if it fails, it will attempt to create the downlevel interface
--*/ { CLSID rgCLSID[2]; IID rgIID[2];
rgCLSID[1] = rgCLSID[0] = CLSID_WamAdmin; rgIID[0] = IID_IWamAdmin2; rgIID[1] = IID_IWamAdmin; ASSERT(ARRAY_SIZE(rgCLSID) == ARRAY_SIZE(rgIID)); int cInterfaces = ARRAY_SIZE(rgCLSID); int iInterface; HRESULT hr = CIISInterface::Create( cInterfaces, rgIID, rgCLSID, &iInterface, (IUnknown **)&m_pInterface );
if (SUCCEEDED(hr)) { //
// Only supported on IWamAdmin2
//
m_fSupportsPooledProc = (rgIID[iInterface] == IID_IWamAdmin2); }
return hr; }
HRESULT CWamInterface::AppCreate( IN LPCTSTR szMDPath, IN DWORD dwAppProtection ) /*++
Routine Description:
Create application
Arguments:
LPCTSTR szMDPath : Metabase path DWORD dwAppProtection : APP_INPROC to create in-proc app APP_OUTOFPROC to create out-of-proc app APP_POOLEDPROC to create a pooled-proc app
Return Value:
HRESULT (ERROR_INVALID_PARAMETER if unsupported protection state is requested)
--*/ { if (m_fSupportsPooledProc) { //
// Interface pointer is really IWamAdmin2, so call the new method
//
return ((IWamAdmin2 *)m_pInterface)->AppCreate2(szMDPath, dwAppProtection); }
//
// Call the downlevel API
//
if (dwAppProtection == APP_INPROC || dwAppProtection == APP_OUTOFPROC) { BOOL fInProc = (dwAppProtection == APP_INPROC); ASSERT_PTR(m_pInterface); return m_pInterface->AppCreate(szMDPath, fInProc); }
return CError(ERROR_INVALID_PARAMETER); }
//
// CMetaback Class
//
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
const LPCTSTR CMetaBack::s_szMasterAppRoot =\ SZ_MBN_SEP_STR SZ_MBN_MACHINE SZ_MBN_SEP_STR SZ_MBN_WEB;
CMetaBack::CMetaBack( IN CComAuthInfo * pAuthInfo OPTIONAL ) /*++
Routine Description:
Constructor for metabase backup/restore operations class. This object is both a WAM interface and a METABASE interface.
Arguments:
CComAuthInfo * pAuthInfo : Auth info. NULL indicates the local computer.
Return Value:
N/A
--*/ : m_dwIndex(0), CMetaInterface(pAuthInfo), CWamInterface(pAuthInfo) { }
/* virtual */ BOOL CMetaBack::Succeeded() const /*++
Routine Description:
Determine if object was constructed successfully.
Arguments:
None
Return Value:
TRUE for success, FALSE for failure
--*/ { return CMetaInterface::Succeeded() && CWamInterface::Succeeded(); }
/* virtual */ HRESULT CMetaBack::QueryResult() const /*++
Routine Description:
Return the construction error for this object
Arguments:
None
Return Value:
HRESULT from construction errors
--*/ { //
// Both interfaces must have constructed successfully
//
HRESULT hr = CMetaInterface::QueryResult();
if (SUCCEEDED(hr)) { hr = CWamInterface::QueryResult(); }
return hr; }
HRESULT CMetaBack::Restore( IN LPCTSTR lpszLocation, IN DWORD dwVersion ) /*++
Routine Description:
Restore metabase
Arguments:
DWORD dwVersion : Backup version LPCTSTR lpszLocation : Backup location
Return Value:
HRESULT
--*/ { //
// Backup and restore the application information from a restore
//
CString strPath(s_szMasterAppRoot); HRESULT hr = AppDeleteRecoverable(strPath, TRUE);
if (SUCCEEDED(hr)) { hr = CMetaInterface::Restore(lpszLocation, dwVersion, 0);
if (SUCCEEDED(hr)) { hr = AppRecover(strPath, TRUE); } }
return hr; }
HRESULT CMetaBack::BackupWithPassword( IN LPCTSTR lpszLocation, IN LPCTSTR lpszPassword ) { return CMetaInterface::BackupWithPassword( lpszLocation, MD_BACKUP_NEXT_VERSION, MD_BACKUP_SAVE_FIRST, lpszPassword ); }
HRESULT CMetaBack::RestoreWithPassword( IN LPCTSTR lpszLocation, IN DWORD dwVersion, IN LPCTSTR lpszPassword ) /*++
Routine Description:
Restore metabase
Arguments:
DWORD dwVersion : Backup version LPCTSTR lpszLocation : Backup location LPCTSTR lpszPassword : Backup password
Return Value:
HRESULT
--*/ { //
// Backup and restore the application information from a restore
//
// BUGBUG: clear it out, why we had an error "parameter is incorrect" from AppDeleteRecoverable
CString strPath(s_szMasterAppRoot); HRESULT hr;// = AppDeleteRecoverable(strPath, TRUE);
// if (SUCCEEDED(hr))
// {
hr = CMetaInterface::RestoreWithPassword(lpszLocation, dwVersion, 0, lpszPassword);
// if (SUCCEEDED(hr))
// {
// hr = AppRecover(strPath, TRUE);
// }
// }
return hr; }
//
// CIISSvcControl class
//
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
CIISSvcControl::CIISSvcControl( IN CComAuthInfo * pAuthInfo OPTIONAL ) /*++
Routine Description:
Construct and initialize the interface.
Arguments:
CComAuthInfo * pAuthInfo : Auth info. NULL indicates the local computer.
Return Value:
N/A
--*/ : CIISInterface(pAuthInfo), m_pInterface(NULL) { //
// Initialize the interface
//
m_hrInterface = Create(); }
CIISSvcControl::CIISSvcControl( IN CIISSvcControl * pInterface ) /*++
Routine Description:
Construct from existing interface (copy constructor)
Arguments:
CIISSvcControl * pInterface : Existing interface
Return Value:
N/A
--*/ : CIISInterface(&pInterface->m_auth, pInterface->m_hrInterface), m_pInterface(pInterface->m_pInterface) { ASSERT_PTR(m_pInterface); m_pInterface->AddRef(); }
CIISSvcControl::~CIISSvcControl() /*++
Routine Description:
Destructor -- releases the interface.
Arguments:
N/A
Return Value:
N/A
--*/ { SAFE_RELEASE(m_pInterface); }
//
// CMetaEnumerator Clas
//
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
CMetaEnumerator::CMetaEnumerator( IN CComAuthInfo * pAuthInfo OPTIONAL, IN LPCTSTR lpszMDPath OPTIONAL, IN METADATA_HANDLE hkBase OPTIONAL ) /*++
Routine Description:
Metabase enumerator constructor. This constructor creates a new interface and opens a key.
Arguments:
CComAuthInfo * pAuthInfo : Auth info. NULL indicates the local computer. LPCTSTR lpszMDPath : Metabase path METADATA_HANDLE hkBase : Metabase handle
Return Value:
N/A
--*/ : CMetaKey(pAuthInfo, lpszMDPath, METADATA_PERMISSION_READ, hkBase), m_dwIndex(0L) { }
CMetaEnumerator::CMetaEnumerator( IN CMetaInterface * pInterface, IN LPCTSTR lpszMDPath, OPTIONAL IN METADATA_HANDLE hkBase OPTIONAL ) /*++
Routine Description:
Metabase enumerator constructor. This constructor uses an existing interface and opens a key.
Arguments:
CMetaInterface * pInterface : Existing interface LPCTSTR lpszMDPath : Metabase path METADATA_HANDLE hkBase : Metabase handle
Return Value:
N/A
--*/ : CMetaKey(pInterface, lpszMDPath, METADATA_PERMISSION_READ, hkBase), m_dwIndex(0L) { }
CMetaEnumerator::CMetaEnumerator( IN BOOL fOwnKey, IN CMetaKey * pKey ) /*++
Routine Description:
Metabase enumerator constructor. This constructor uses an existing interface and open key.
Arguments:
BOOL fOwnKey : TRUE if we own the key (destructor will close) CMetaKey * pKey : Open key
Return Value:
N/A
--*/ : CMetaKey(fOwnKey, pKey), m_dwIndex(0L) { }
HRESULT CMetaEnumerator::Next( OUT CString & strKey, IN LPCTSTR lpszMDPath OPTIONAL ) /*++
Routine Description:
Get the next subkey
Arguments:
CString & str Returns keyname LPCTSTR lpszMDPath Optional subpath
Return Value:
HRESULT
--*/ { ASSURE_PROPER_INTERFACE(); ASSURE_OPEN_KEY();
LPTSTR lpKey = strKey.GetBuffer(MAX_PATH); HRESULT hr = EnumKeys(m_hKey, lpszMDPath, lpKey, m_dwIndex++); strKey.ReleaseBuffer();
return hr; }
HRESULT CMetaEnumerator::Next( OUT DWORD & dwKey, OUT CString & strKey, IN LPCTSTR lpszMDPath OPTIONAL ) /*++
Routine Description:
Get the next subkey as a DWORD. This skips non-numeric keynames (including 0) until the first numeric key name
Arguments:
DWORD & dwKey Numeric key CString & strKey Same key in string format LPCTSTR lpszMDPath Optional subpath
Return Value:
HRESULT
--*/ { ASSURE_PROPER_INTERFACE(); ASSURE_OPEN_KEY();
HRESULT hr = S_OK; BOOL fContinue = TRUE;
while (fContinue) { fContinue = FALSE;
LPTSTR lpKey = strKey.GetBuffer(MAX_PATH); hr = EnumKeys(m_hKey, lpszMDPath, lpKey, m_dwIndex++); strKey.ReleaseBuffer();
if (SUCCEEDED(hr)) { if (FALSE == (dwKey = _ttoi((LPCTSTR)strKey))) { //
// Ignore this one
//
fContinue = TRUE; } } } return hr; }
//
// CIISApplication class
//
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<</
CIISApplication::CIISApplication( IN CComAuthInfo * pAuthInfo OPTIONAL, IN LPCTSTR lpszMetapath ) /*++
Routine Description:
Construct IIS application.
Arguments:
CComAuthInfo * pAuthInfo : Authentication info. NULL indicates the local computer. LPCTSTR lpszMetapath : Metabase path
Return Value:
N/A
--*/ : CWamInterface(pAuthInfo), CMetaKey(pAuthInfo), m_dwProcessProtection(APP_INPROC), m_dwAppState(APPSTATUS_NOTDEFINED), m_strFriendlyName(), m_strAppRoot(), m_strWamPath(lpszMetapath) { CommonConstruct(); }
void CIISApplication::CommonConstruct() /*++
Routine Description:
Perform common construction
Arguments:
None
Return Value:
None
--*/ { //
// Munge the metapath so that WAM doesn't cough up a hairball.
//
//
// BUGBUG: CleanMetaPath() disabled currently
//
if (m_strWamPath[0] != SZ_MBN_SEP_CHAR) { m_strWamPath = SZ_MBN_SEP_CHAR + m_strWamPath; }
do { m_hrApp = CWamInterface::QueryResult();
if (FAILED(m_hrApp)) { break; }
m_hrApp = RefreshAppState();
if (HRESULT_CODE(m_hrApp) == ERROR_PATH_NOT_FOUND) { //
// "Path Not Found" errors are acceptable, since
// the application may not yet exist.
//
m_hrApp = S_OK; } } while(FALSE); }
/* virtual */ BOOL CIISApplication::Succeeded() const /*++
Routine Description:
Determine if object was constructed successfully
Arguments:
None
Return Value:
TRUE for success, FALSE for failure
--*/ { return CMetaInterface::Succeeded() && CWamInterface::Succeeded() && SUCCEEDED(m_hrApp); }
/* virtual */ HRESULT CIISApplication::QueryResult() const /*++
Routine Description:
Return the construction error for this object
Arguments:
None
Return Value:
HRESULT from construction errors
--*/ { //
// Both interfaces must have constructed successfully
//
HRESULT hr = CMetaInterface::QueryResult();
if (SUCCEEDED(hr)) { hr = CWamInterface::QueryResult();
if (SUCCEEDED(hr)) { hr = m_hrApp; } }
return hr; }
HRESULT CIISApplication::RefreshAppState() /*++
Routine Description:
Refresh the application state
Arguments:
None
Return Value:
HRESULT
--*/ { ASSERT(!m_strWamPath.IsEmpty());
HRESULT hr, hrKeys;
hr = AppGetStatus(m_strWamPath, &m_dwAppState);
if (FAILED(hr)) { m_dwAppState = APPSTATUS_NOTDEFINED; }
m_strAppRoot.Empty(); hrKeys = QueryValue(MD_APP_ROOT, m_strAppRoot, NULL, m_strWamPath);
m_dwProcessProtection = APP_INPROC; hrKeys = QueryValue( MD_APP_ISOLATED, m_dwProcessProtection, NULL, m_strWamPath );
hrKeys = QueryValue( MD_APP_APPPOOL_ID, m_strAppPoolId, NULL, m_strWamPath );
m_strFriendlyName.Empty(); hrKeys = QueryValue( MD_APP_FRIENDLY_NAME, m_strFriendlyName, NULL, m_strWamPath );
return hr; }
HRESULT CIISApplication::Create( IN LPCTSTR lpszName, OPTIONAL IN DWORD dwAppProtection ) /*++
Routine Description:
Create the application
Arguments:
LPCTSTR lpszName : Application name DWORD dwAppProtection : APP_INPROC to create in-proc app APP_OUTOFPROC to create out-of-proc app APP_POOLEDPROC to create a pooled-proc app
Return Value:
HRESULT
--*/ { ASSERT(!m_strWamPath.IsEmpty()); HRESULT hr = AppCreate(m_strWamPath, dwAppProtection);
if (SUCCEEDED(hr)) { //
// Write the friendly app name, which we maintain
// ourselves. Empty it first, because we might
// have picked up a name from inheritance.
//
m_strFriendlyName.Empty(); hr = WriteFriendlyName(lpszName);
RefreshAppState(); }
return hr; }
HRESULT CIISApplication::CreatePooled( LPCTSTR name, DWORD mode, LPCTSTR pool_id, BOOL fCreatePool) { ASSERT(!m_strWamPath.IsEmpty()); ASSERT(NULL != pool_id); HRESULT hr = CreateApplication(m_strWamPath, mode, pool_id, fCreatePool); if (SUCCEEDED(hr)) { m_strFriendlyName.Empty(); hr = WriteFriendlyName(name); RefreshAppState(); } return hr; }
HRESULT CIISApplication::WriteFriendlyName( IN LPCTSTR lpszName ) /*++
Routine Description:
Write the friendly name. This will not write anything if the name is the same as it was
Arguments:
LPCTSTR lpszName : New friendly name
Return Value:
HRESULT
--*/ { HRESULT hr = S_OK;
if (m_strFriendlyName.CompareNoCase(lpszName) != 0) { hr = Open(METADATA_PERMISSION_WRITE, m_strWamPath);
if (SUCCEEDED(hr)) { ASSERT_PTR(lpszName);
CString str(lpszName); hr = SetValue(MD_APP_FRIENDLY_NAME, str); Close();
if (SUCCEEDED(hr)) { m_strFriendlyName = lpszName; } } }
return hr; }
HRESULT CIISApplication::WritePoolId(LPCTSTR id) { HRESULT hr = S_OK;
if (m_strAppPoolId.CompareNoCase(id) != 0) { hr = Open(METADATA_PERMISSION_WRITE, m_strWamPath);
if (SUCCEEDED(hr)) { ASSERT_PTR(id);
CString str(id); hr = SetValue(MD_APP_APPPOOL_ID, str); Close();
if (SUCCEEDED(hr)) { m_strAppPoolId = id; } } } return hr; }
/////////////////////////////////////////////////////////
// CIISAppPool class
CIISAppPool::CIISAppPool( IN CComAuthInfo * pAuthInfo OPTIONAL, IN LPCTSTR lpszMetapath ) /*++
Routine Description:
Construct IIS application pool.
Arguments:
CComAuthInfo * pAuthInfo : Authentication info. NULL indicates the local computer. LPCTSTR lpszMetapath : Metabase path
Return Value:
N/A
--*/ : CWamInterface(pAuthInfo), CMetaKey(pAuthInfo), m_dwPoolState(0), m_strFriendlyName(), m_strWamPath(lpszMetapath) { if (m_strWamPath[0] != SZ_MBN_SEP_CHAR) { m_strWamPath = SZ_MBN_SEP_CHAR + m_strWamPath; }
do { if (FAILED(m_hrPool = CWamInterface::QueryResult())) { break; } if (MD_ERROR_DATA_NOT_FOUND == (m_hrPool = RefreshState()) || HRESULT_CODE(m_hrPool) == ERROR_PATH_NOT_FOUND) { //
// "Path Not Found" errors are acceptable, since
// the pool may not yet exist.
//
m_hrPool = S_OK; } } while(FALSE); }
HRESULT CIISAppPool::RefreshState() { ASSERT(!m_strWamPath.IsEmpty());
HRESULT hr;
m_strFriendlyName.Empty(); hr = QueryValue( MD_APPPOOL_FRIENDLY_NAME, m_strFriendlyName, NULL, m_strWamPath );
return hr; }
/* virtual */ HRESULT CIISAppPool::QueryResult() const /*++
Routine Description:
Return the construction error for this object
Arguments:
None
Return Value:
HRESULT from construction errors
--*/ { //
// Both interfaces must have constructed successfully
//
HRESULT hr = CMetaInterface::QueryResult();
if (SUCCEEDED(hr)) { hr = CWamInterface::QueryResult();
if (SUCCEEDED(hr)) { hr = m_hrPool; } }
return hr; }
/* virtual */ BOOL CIISAppPool::Succeeded() const /*++
Routine Description:
Determine if object was constructed successfully
Arguments:
None
Return Value:
TRUE for success, FALSE for failure
--*/ { return CMetaInterface::Succeeded() && CWamInterface::Succeeded() && SUCCEEDED(m_hrPool); }
HRESULT CIISAppPool::EnumerateApplications(CStringListEx& apps) { CString pool; BSTR bstr = NULL;
CMetabasePath::GetLastNodeName(m_strWamPath, pool); CError err = CWamInterface::EnumerateApplicationsInPool( pool, &bstr); if (err.Succeeded()) { ConvertDoubleNullListToStringList(bstr, apps); } #ifdef _DEBUG
err.MessageBoxOnFailure(); #endif
SysFreeString(bstr); return err; }
HRESULT CIISAppPool::Create(LPCTSTR name) { CString id; if (name != NULL) { id = name; } else { CMetabasePath::GetLastNodeName(m_strWamPath, id); } CError err = CWamInterface::CreateApplicationPool(id);
return err; }
HRESULT CIISAppPool::Delete(LPCTSTR id) { CError err = CWamInterface::DeleteApplicationPool(id);
return err; }
|