/*=================================================================== Microsoft IIS Microsoft Confidential. Copyright 1997 Microsoft Corporation. All Rights Reserved. Component: WAMREG File: mdconfig.cpp interface to update/query WAM related properties in metabase. Owner: LeiJin Note: ===================================================================*/ #include "common.h" #include "auxfunc.h" #include "iiscnfgp.h" #include "dbgutil.h" #include "multisz.hxx" // Time out for metabase = 5 seconds const DWORD WamRegMetabaseConfig::m_dwMDDefaultTimeOut = 5*1000; IMSAdminBaseW* WamRegMetabaseConfig::m_pMetabase = NULL; // // Please refer to MDPropItem for definition // Application properties that might be updated by WAMREG // const MDPropItem WamRegMetabaseConfig::m_rgMDPropTemplate[IWMDP_MAX] = { {MD_APP_ROOT, STRING_METADATA, 0, EMD_NONE, E_FAIL}, {MD_APP_ISOLATED, DWORD_METADATA, 0, EMD_NONE, E_FAIL}, {MD_APP_WAM_CLSID, STRING_METADATA, 0, EMD_NONE, E_FAIL}, {MD_APP_PACKAGE_ID, STRING_METADATA, 0, EMD_NONE, E_FAIL}, {MD_APP_PACKAGE_NAME, STRING_METADATA, 0, EMD_NONE, E_FAIL}, {MD_APP_LAST_OUTPROC_PID, STRING_METADATA, 0, EMD_NONE, E_FAIL}, {MD_APP_FRIENDLY_NAME, STRING_METADATA, 0, EMD_NONE, E_FAIL}, {MD_APP_STATE, DWORD_METADATA, 0, EMD_NONE, E_FAIL}, {MD_APP_OOP_RECOVER_LIMIT, DWORD_METADATA, 0, EMD_NONE, E_FAIL}, {MD_APP_APPPOOL_ID, STRING_METADATA, 0, EMD_NONE, E_FAIL} }; /*=================================================================== InitPropItemData Init a metabase item list, prepare for metabase update. Parameter: pMDPropItem: pointer to MDPropItem which is set to the default values. Return: NONE ===================================================================*/ VOID WamRegMetabaseConfig::InitPropItemData(IN OUT MDPropItem* pMDPropItem) { DBG_ASSERT(pMDPropItem != NULL); memcpy(pMDPropItem, (void *)m_rgMDPropTemplate, sizeof(m_rgMDPropTemplate)); return; } /*=================================================================== MetabaseInit Initialize Metabase, and obtain Metabase DCOM interface. Parameter: pMetabase: [out] Metabase DCOM interface pointer. Return: HRESULT Side affect: Create a Metabase object, and get interface pointer. ===================================================================*/ HRESULT WamRegMetabaseConfig::MetabaseInit ( ) { HRESULT hr = NOERROR; m_pMetabase = (IMSAdminBase *)NULL; hr = CoCreateInstance(CLSID_MSAdminBase , NULL , CLSCTX_SERVER , IID_IMSAdminBase , (void**)&(m_pMetabase)); if (FAILED(hr)) goto LErrExit; return hr; LErrExit: RELEASE((m_pMetabase)); return hr; } /*=================================================================== MetabaseUnInit release a metabase interface. Parameter: pMetabase: [in/out] Metabase DCOM interface pointer. Return: HRESULT Side affect: Destroy a metabase object. ===================================================================*/ HRESULT WamRegMetabaseConfig::MetabaseUnInit ( VOID ) { RELEASE((m_pMetabase)); return NOERROR; } /*=================================================================== UpdateMD Update a WAM application property in metabase. Parameter: pMetabase a metabase pointer prgProp contains the info of updating a WAM properties in metabase. refer to the structure definition for more info. dwMDAttributes allows caller specified INHERITABLE attribute. fSaveData perform a IMSAdminBase::SaveData, defaults to false Return: HRESULT Side affect: Release pMetabase. ===================================================================*/ HRESULT WamRegMetabaseConfig::UpdateMD ( IN MDPropItem* prgProp, IN DWORD dwMDAttributes, IN LPCWSTR wszMetabasePath, IN BOOL fSaveData ) { HRESULT hr = NOERROR; INT iItem = 0; METADATA_HANDLE hMetabase = NULL; DBG_ASSERT(m_pMetabase); DBG_ASSERT(prgProp); DBG_ASSERT(wszMetabasePath); // // Open Key // hr = m_pMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, wszMetabasePath, METADATA_PERMISSION_WRITE, m_dwMDDefaultTimeOut, &hMetabase); if (SUCCEEDED(hr)) { METADATA_RECORD recMetaData; // // Update WAM Application Metabase Properties. // for (iItem = 0; iItem < IWMDP_MAX; iItem ++) { if (prgProp[iItem].dwAction == EMD_SET) { DWORD dwUserType = IIS_MD_UT_WAM; if (iItem == IWMDP_ROOT) { dwUserType = IIS_MD_UT_FILE; } if (prgProp[iItem].dwType == STRING_METADATA) { DBG_ASSERT(prgProp[iItem].pwstrVal); MD_SET_DATA_RECORD(&recMetaData, prgProp[iItem].dwMDIdentifier, dwMDAttributes, dwUserType, STRING_METADATA, (wcslen(prgProp[iItem].pwstrVal)+1)*sizeof(WCHAR), (unsigned char *)prgProp[iItem].pwstrVal); } else if (prgProp[iItem].dwType == DWORD_METADATA) { MD_SET_DATA_RECORD(&recMetaData, prgProp[iItem].dwMDIdentifier, dwMDAttributes, dwUserType, DWORD_METADATA, sizeof(DWORD), (unsigned char *)&(prgProp[iItem].dwVal)); } else { DBGPRINTF((DBG_CONTEXT, "Unsupported data type by WAMREG.\n")); DBG_ASSERT(FALSE); } hr = m_pMetabase->SetData(hMetabase, NULL, &recMetaData); prgProp[iItem].hrStatus = hr; if (FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "Metabase SetData failed. Path = %S, id = %08x, error = %08x\n", wszMetabasePath, prgProp[iItem].dwMDIdentifier, hr)); break; } } if (prgProp[iItem].dwAction == EMD_DELETE) { hr = m_pMetabase->DeleteData(hMetabase, NULL, prgProp[iItem].dwMDIdentifier, prgProp[iItem].dwType); } } m_pMetabase->CloseKey(hMetabase); if (SUCCEEDED(hr) && fSaveData == TRUE) { hr = m_pMetabase->SaveData(); if (hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION)) { hr = NOERROR; } if (FAILED(hr)) { DBG_ASSERT((DBG_CONTEXT, "Failed to call metabase->SaveData, Application path = %S," "hr = %08x\n", wszMetabasePath, hr)); DBG_ASSERT(SUCCEEDED(hr)); } } } else { DBGPRINTF((DBG_CONTEXT, "Failed to open metabase path %S, error = %08x\n", wszMetabasePath, hr)); } return hr; } /*=================================================================== MDUpdateIISDefault Write the default IIS package info to metabase under key "/LM/W3SVC". Including IISPackageName IISPackageID WAMCLSID Parameter: szIISPackageName: [in] The Default IIS Package Name. szIISPackageID: [in] The IIS Package ID. szDefaultWAMCLSID: [in] The Default WAM CLSID. Return: HRESULT Side affect: Release pMetabase. ===================================================================*/ HRESULT WamRegMetabaseConfig::MDUpdateIISDefault ( IN LPCWSTR szIISPackageName, IN LPCWSTR szIISPackageID, IN LPCWSTR szDefaultWAMCLSID ) { HRESULT hr = NOERROR; MDPropItem rgProp[IWMDP_MAX]; DBG_ASSERT(szIISPackageName); DBG_ASSERT(szIISPackageID); DBG_ASSERT(szDefaultWAMCLSID); DBG_ASSERT(m_pMetabase != NULL); InitPropItemData(&rgProp[0]); // Update Package Name MDSetPropItem(&rgProp[0], IWMDP_PACKAGE_NAME, szIISPackageName); // Update Package ID MDSetPropItem(&rgProp[0], IWMDP_PACKAGEID, szIISPackageID); // Update DefaultWAMCLSID MDSetPropItem(&rgProp[0], IWMDP_WAMCLSID, szDefaultWAMCLSID); // Update APPRoot MDSetPropItem(&rgProp[0], IWMDP_ROOT, WamRegGlobal::g_szMDW3SVCRoot); //Update AppIsolated MDSetPropItem(&rgProp[0], IWMDP_ISOLATED, (DWORD)0); MDSetPropItem(&rgProp[0], IWMDP_LAST_OUTPROC_PID, L""); MDSetPropItem(&rgProp[0], IWMDP_FRIENDLY_NAME, L""); // // The default WAM Application is not inherited. // Set Metadata attributes to METADATA_NO_ATTRIBUTES // The allows us to have a way to turn the approot off, since this is above the // level of the server, every root dir of every server is part of application, // and there is no way to turn this off. Set the default application not inheritable, // we have a way to turn off the approot. People should have to mark an application in // order to run ASP & ISAPI. // UpdateMD at L"/LM/W3SVC/" // hr = UpdateMD(rgProp, METADATA_NO_ATTRIBUTES, WamRegGlobal::g_szMDAppPathPrefix, TRUE); // Removed AbortUpdateMD code. Why would we want to ensure that things // won't work now? return hr; } /*=================================================================== AbortUpdateMD Abort the last update to the metabase, based on the info embeded in prgProp. Parameter: pMetabase a metabase pointer prgProp contains the info of updating a WAM properties in metabase. refer to the structure definition for more info. Return: HRESULT Side affect: Release pMetabase. ===================================================================*/ HRESULT WamRegMetabaseConfig::AbortUpdateMD ( IN MDPropItem* prgProp, IN LPCWSTR wszMetabasePath ) { HRESULT hr = NOERROR; INT iItem = 0; METADATA_HANDLE hMetabase = NULL; DBG_ASSERT(m_pMetabase); DBG_ASSERT(prgProp); DBGPRINTF((DBG_CONTEXT, "WAMREG Abort Update metabase.\n")); // // Open Key // hr = m_pMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, wszMetabasePath, METADATA_PERMISSION_WRITE, m_dwMDDefaultTimeOut, &hMetabase); if (SUCCEEDED(hr)) { METADATA_RECORD recMetaData; // // Update WAM Application Metabase Properties. // for (iItem = 0; iItem < IWMDP_MAX; iItem ++) { if (prgProp[iItem].dwAction == EMD_SET) { if (prgProp[iItem].hrStatus == NOERROR) { hr = m_pMetabase->DeleteData(hMetabase, NULL, prgProp[iItem].dwMDIdentifier, prgProp[iItem].dwType); if (FAILED(hr) && hr != MD_ERROR_DATA_NOT_FOUND) { DBGPRINTF((DBG_CONTEXT, "Metabase Delete failed. Path = %S, id = %08x, error = %08x\n", wszMetabasePath, prgProp[iItem].dwMDIdentifier, hr)); } } } } m_pMetabase->CloseKey(hMetabase); if (SUCCEEDED(hr)) { hr = m_pMetabase->SaveData(); if (hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION)) { hr = NOERROR; } } } else { DBGPRINTF((DBG_CONTEXT, "Failed to open metabase path %S, error = %08x\n", wszMetabasePath, hr)); } return hr; } HRESULT WamRegMetabaseConfig::MDSetStringProperty ( IN IMSAdminBase * pMetabaseIn, IN LPCWSTR szMetabasePath, IN DWORD dwMetabaseProperty, IN LPCWSTR szMetabaseValue, IN DWORD dwMDUserType /* = IIS_MD_UT_WAM */ ) /*=================================================================== MDSetProperty Set a value of a property at the given path. Parameters: pMetabaseIn : [in] optional metabase interface szMetabasePath : [in] metabase key dwMetabaseProperty : [in] Property to set szMetabaseValue : [in] Value to set on property dwMDUserType : [in, optional] UserType to set on property Return: BOOL ===================================================================*/ { HRESULT hr = S_OK; IMSAdminBase* pMetabase = NULL; METADATA_HANDLE hMetabase = NULL; METADATA_RECORD mdrData; ZeroMemory(&mdrData, sizeof(mdrData)); DBG_ASSERT(szMetabasePath); if (pMetabaseIn) { pMetabase = pMetabaseIn; } else { pMetabase = m_pMetabase; } DBG_ASSERT(pMetabase); hr = pMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, szMetabasePath, METADATA_PERMISSION_WRITE, m_dwMDDefaultTimeOut, &hMetabase); if (FAILED(hr)) { goto done; } MD_SET_DATA_RECORD(&mdrData, dwMetabaseProperty, METADATA_NO_ATTRIBUTES, dwMDUserType, STRING_METADATA, (wcslen(szMetabaseValue)+1)*sizeof(WCHAR), szMetabaseValue); hr = pMetabase->SetData(hMetabase, L"/", &mdrData); if (FAILED(hr)) { goto done; } hr = S_OK; done: if (pMetabase && hMetabase) { pMetabase->CloseKey(hMetabase); } return hr; } HRESULT WamRegMetabaseConfig::MDSetKeyType ( IN IMSAdminBase * pMetabaseIn, IN LPCWSTR szMetabasePath, IN LPCWSTR szKeyType ) { HRESULT hr = S_OK; IMSAdminBase* pMetabase = NULL; METADATA_HANDLE hMetabase = NULL; METADATA_RECORD mdrData; ZeroMemory(&mdrData, sizeof(mdrData)); DBG_ASSERT(szMetabasePath); if (pMetabaseIn) { pMetabase = pMetabaseIn; } else { pMetabase = m_pMetabase; } DBG_ASSERT(pMetabase); hr = pMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, szMetabasePath, METADATA_PERMISSION_WRITE, m_dwMDDefaultTimeOut, &hMetabase); if (FAILED(hr)) { goto done; } MD_SET_DATA_RECORD(&mdrData, MD_KEY_TYPE, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (wcslen(szKeyType)+1)*sizeof(WCHAR), szKeyType); hr = pMetabase->SetData(hMetabase, L"/", &mdrData); if (FAILED(hr)) { goto done; } hr = S_OK; done: if (pMetabase && hMetabase) { pMetabase->CloseKey(hMetabase); } return hr; } HRESULT WamRegMetabaseConfig::MDDeleteKey ( IN IMSAdminBase * pMetabaseIn, IN LPCWSTR szMetabasePath, IN LPCWSTR szKey ) { HRESULT hr = S_OK; IMSAdminBase* pMetabase = NULL; METADATA_HANDLE hMetabase = NULL; DBG_ASSERT(szMetabasePath); DBG_ASSERT(szKey); if (pMetabaseIn) { pMetabase = pMetabaseIn; } else { pMetabase = m_pMetabase; } DBG_ASSERT(pMetabase); hr = pMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, szMetabasePath, METADATA_PERMISSION_WRITE, m_dwMDDefaultTimeOut, &hMetabase); if (FAILED(hr)) { goto done; } hr = pMetabase->DeleteKey(hMetabase, szKey); if (FAILED(hr)) { goto done; } hr = S_OK; done: if (pMetabase && hMetabase) { pMetabase->CloseKey(hMetabase); } return hr; } BOOL WamRegMetabaseConfig::MDDoesPathExist ( IN IMSAdminBase * pMetabaseIn, IN LPCWSTR szMetabasePath ) /*=================================================================== MDDoesPathExist Determine if a given path exists in the metabase Parameters: pMetabaseIn : [in] optional metabase interface szMetabasePath : [in] metabase key Return: BOOL ===================================================================*/ { BOOL fRet = FALSE; HRESULT hr = S_OK; IMSAdminBase* pMetabase = NULL; METADATA_HANDLE hMetabase = NULL; DBG_ASSERT(szMetabasePath); if (pMetabaseIn) { pMetabase = pMetabaseIn; } else { pMetabase = m_pMetabase; } DBG_ASSERT(pMetabase); hr = pMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, szMetabasePath, METADATA_PERMISSION_READ, m_dwMDDefaultTimeOut, &hMetabase); if (SUCCEEDED(hr)) { fRet = TRUE; pMetabase->CloseKey(hMetabase); } else { fRet = FALSE; } return fRet; } /*=================================================================== MDCreatePath Create a metabase path.(szMetabasePath) Parameter: szMetabasePath : [in] metabase key Return: HRESULT Note: fill in the pdwAppMode, memory buffer provided by the caller. ===================================================================*/ HRESULT WamRegMetabaseConfig::MDCreatePath ( IN IMSAdminBase *pMetabaseIn, IN LPCWSTR szMetabasePath ) { HRESULT hr; IMSAdminBase *pMetabase = NULL; WCHAR *pwszApplicationPath = NULL; METADATA_HANDLE hMetabase = NULL; DBG_ASSERT(szMetabasePath); if (pMetabaseIn) { pMetabase = pMetabaseIn; } else { pMetabase = m_pMetabase; } if (_wcsnicmp(szMetabasePath, L"\\LM\\W3SVC\\", 10) == 0 || _wcsnicmp(szMetabasePath, WamRegGlobal::g_szMDAppPathPrefix, WamRegGlobal::g_cchMDAppPathPrefix) == 0) { pwszApplicationPath = (WCHAR *)(szMetabasePath + 10); } else { hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER); return hr; } // Open Key hr = pMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, (LPCWSTR)WamRegGlobal::g_szMDAppPathPrefix, METADATA_PERMISSION_WRITE, m_dwMDDefaultTimeOut, &hMetabase); if (FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "Failed to Open metabase key, path is /LM/W3SVC, hr = %08x\n", hr)); } else { hr = pMetabase->AddKey(hMetabase, (LPCWSTR)pwszApplicationPath); if (FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "Failed to AddKey to metabase, path is %S, hr = %08x\n", szMetabasePath, hr)); } pMetabase->CloseKey(hMetabase); } return hr; } /*=================================================================== MDGetDWORD Get a DWORD type property from Metabase Key(szMetabasePath) Parameter: szMetabasePath : [in] metabase key dwMDIdentifier : [in] indentifier Return: HRESULT ===================================================================*/ HRESULT WamRegMetabaseConfig::MDGetDWORD ( IN LPCWSTR szMetabasePath, IN DWORD dwMDIdentifier, OUT DWORD *pdwData ) { HRESULT hr; METADATA_HANDLE hMetabase = NULL; METADATA_RECORD recMetaData; DWORD dwRequiredLen; IMSAdminBase *pMetabase = NULL; DBG_ASSERT(pdwData); DBG_ASSERT(szMetabasePath); pMetabase = m_pMetabase; // Open Key hr = pMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, (LPCWSTR)szMetabasePath, METADATA_PERMISSION_READ, m_dwMDDefaultTimeOut, &hMetabase); if (SUCCEEDED(hr)) { MD_SET_DATA_RECORD( &recMetaData, dwMDIdentifier, METADATA_NO_ATTRIBUTES, IIS_MD_UT_WAM, DWORD_METADATA, sizeof(DWORD), (unsigned char *)pdwData); hr = pMetabase->GetData(hMetabase, NULL, &recMetaData, &dwRequiredLen); if (FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "Get MD_APP_ISOLATED failed on MD path %S, id %d, error = %08x\n", szMetabasePath, dwMDIdentifier, hr)); } pMetabase->CloseKey(hMetabase); } return hr; } /*=================================================================== MDSetAppState Set an application state. (i.e. If APPSTATE_PAUSE is set, then, the runtime W3SVC can not launch the application). Parameter: szMetabasePath : [in] metabase key dwState : App state to be set. Return: HRESULT ===================================================================*/ HRESULT WamRegMetabaseConfig::MDSetAppState ( IN LPCWSTR szMetabasePath, IN DWORD dwState ) { METADATA_RECORD recMetaData; HRESULT hr; METADATA_HANDLE hMetabase; DBG_ASSERT(m_pMetabase); // Open Key hr = m_pMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, (LPWSTR)szMetabasePath, METADATA_PERMISSION_WRITE, m_dwMDDefaultTimeOut, &hMetabase); if (SUCCEEDED(hr)) { MD_SET_DATA_RECORD( &recMetaData, MD_APP_STATE, METADATA_INHERIT, IIS_MD_UT_WAM, DWORD_METADATA, sizeof(DWORD), (unsigned char *)&dwState); hr = m_pMetabase->SetData(hMetabase, NULL, &recMetaData); m_pMetabase->CloseKey(hMetabase); } return hr; } HRESULT WamRegMetabaseConfig::MDGetWAMCLSID ( IN LPCWSTR szMetabasePath, IN OUT LPWSTR szWAMCLSID ) { HRESULT hr; METADATA_HANDLE hMetabase = NULL; METADATA_RECORD recMetaData; DWORD dwRequiredLen; DBG_ASSERT(szWAMCLSID); DBG_ASSERT(szMetabasePath); szWAMCLSID[0] = NULL; // Open Key hr = m_pMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, (LPWSTR)szMetabasePath, METADATA_PERMISSION_READ, m_dwMDDefaultTimeOut, &hMetabase); if (SUCCEEDED(hr)) { MD_SET_DATA_RECORD( &recMetaData, MD_APP_WAM_CLSID, METADATA_NO_ATTRIBUTES, IIS_MD_UT_WAM, STRING_METADATA, uSizeCLSID*sizeof(WCHAR), (unsigned char *)szWAMCLSID); hr = m_pMetabase->GetData(hMetabase, NULL, &recMetaData, &dwRequiredLen); if (HRESULTTOWIN32(hr) == ERROR_INSUFFICIENT_BUFFER) { DBG_ASSERT(FALSE); } m_pMetabase->CloseKey(hMetabase); } return hr; } /*=================================================================== MDGetIdentity Get pakcage Identity from Metabase Key(szMetabasePath) (WamUserName & WamPassword) Parameter: szIdentity: a string buffer for WamUserName. cbIdneity: size of the string buffer for szIdentity. szPwd: a string buffer for WamPassword. cbPwd: size of the string buffer for szPwd. Return: HRESULT ===================================================================*/ HRESULT WamRegMetabaseConfig::MDGetIdentity ( IN LPWSTR szIdentity, IN DWORD cbIdentity, IN LPWSTR szPwd, IN DWORD cbPwd ) { HRESULT hr; METADATA_HANDLE hMetabase = NULL; METADATA_RECORD recMetaData; DWORD dwRequiredLen; DBG_ASSERT(szIdentity); szIdentity[0] = NULL; // Open Key hr = m_pMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, (LPWSTR)WamRegGlobal::g_szMDAppPathPrefix, METADATA_PERMISSION_READ, m_dwMDDefaultTimeOut, &hMetabase); if (SUCCEEDED(hr)) { // Get WAM user name MD_SET_DATA_RECORD( &recMetaData, MD_WAM_USER_NAME, METADATA_NO_ATTRIBUTES, IIS_MD_UT_WAM, STRING_METADATA, cbIdentity, (unsigned char *)szIdentity); hr = m_pMetabase->GetData(hMetabase, NULL, &recMetaData, &dwRequiredLen); if (HRESULTTOWIN32(hr) == ERROR_INSUFFICIENT_BUFFER) { DBGPRINTF((DBG_CONTEXT, "Insufficient buffer for WAM user name. Required size is %d\n", dwRequiredLen)); DBG_ASSERT(FALSE); } // Get WAM user password MD_SET_DATA_RECORD( &recMetaData, MD_WAM_PWD, METADATA_NO_ATTRIBUTES, IIS_MD_UT_WAM, STRING_METADATA, cbPwd, (unsigned char *)szPwd); hr = m_pMetabase->GetData(hMetabase, NULL, &recMetaData, &dwRequiredLen); if (HRESULTTOWIN32(hr) == ERROR_INSUFFICIENT_BUFFER) { DBGPRINTF((DBG_CONTEXT, "Insufficient buffer for WAM user password. Required size is %d\n", dwRequiredLen)); DBG_ASSERT(FALSE); } m_pMetabase->CloseKey(hMetabase); } return hr; } HRESULT WamRegMetabaseConfig::MDGetAppName ( IN LPCWSTR szMetaPath, OUT LPWSTR * ppszAppName ) /*++ Function: Retrieve the MD_APP_PACKAGE_NAME from the metabase. Parameters: ppszAppName - value of MD_APP_PACKAGE_NAME allocated with new[] free with delete[] Return: {MD_APP_PACKAGE_NAME, STRING_METADATA, 0, EMD_NONE, E_FAIL}, --*/ { return MDGetStringAttribute(szMetaPath, MD_APP_PACKAGE_NAME, ppszAppName); } HRESULT WamRegMetabaseConfig::MDGetStringAttribute ( IN LPCWSTR szMetaPath, DWORD dwMDIdentifier, OUT LPWSTR * ppszBuffer ) { DBG_ASSERT( ppszBuffer ); DBG_ASSERT( m_pMetabase ); HRESULT hr = NOERROR; WCHAR * pwcMetaData = NULL; DWORD cbData = 0; METADATA_HANDLE hKey = NULL; METADATA_RECORD mdr; *ppszBuffer = NULL; hr = m_pMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, szMetaPath, METADATA_PERMISSION_READ, m_dwMDDefaultTimeOut, &hKey); if( SUCCEEDED(hr) ) { MD_SET_DATA_RECORD( &mdr, dwMDIdentifier, METADATA_INHERIT, IIS_MD_UT_WAM, STRING_METADATA, cbData, (LPBYTE)pwcMetaData ); hr = m_pMetabase->GetData( hKey, NULL, &mdr, &cbData ); if( HRESULTTOWIN32(hr) == ERROR_INSUFFICIENT_BUFFER ) { pwcMetaData = new WCHAR[ cbData / sizeof(WCHAR) ]; if( pwcMetaData != NULL ) { mdr.pbMDData = (LPBYTE)pwcMetaData; mdr.dwMDDataLen = cbData; hr = m_pMetabase->GetData( hKey, NULL, &mdr, &cbData ); } else { hr = E_OUTOFMEMORY; } } m_pMetabase->CloseKey( hKey ); } // // Return AppName // if( SUCCEEDED(hr) ) { DBG_ASSERT( pwcMetaData != NULL ); *ppszBuffer = pwcMetaData; } else { DBG_ASSERT( *ppszBuffer == NULL ); delete [] pwcMetaData; } return hr; } #ifdef _IIS_6_0 HRESULT WamRegMetabaseConfig::MDGetAllSiteRoots ( OUT LPWSTR * ppszBuffer ) { DBG_ASSERT( m_pMetabase ); DBG_ASSERT(ppszBuffer); *ppszBuffer = NULL; HRESULT hr = S_OK; METADATA_HANDLE hKey = NULL; DWORD dwEnumKeyIndex = 0; WCHAR szMDName[METADATA_MAX_NAME_LEN] = {0}; MULTISZ mszSiteRoots; // Loop through all keys below /LM/W3SVC hr = m_pMetabase->EnumKeys(METADATA_MASTER_ROOT_HANDLE, L"/LM/W3SVC/", szMDName, dwEnumKeyIndex ); while(SUCCEEDED(hr)) { int i = _wtoi(szMDName); // if this is a site if(0 != i) { // have a valid site number WCHAR pTempBuf[METADATA_MAX_NAME_LEN] = {0}; wcscpy(pTempBuf, L"/LM/W3SVC/"); wcscat(pTempBuf, szMDName); wcscat(pTempBuf, L"/ROOT/"); if (FALSE == mszSiteRoots.Append(pTempBuf)) { hr = E_OUTOFMEMORY; goto done; } } dwEnumKeyIndex++; hr = m_pMetabase->EnumKeys(METADATA_MASTER_ROOT_HANDLE, L"/LM/W3SVC/", szMDName, dwEnumKeyIndex ); } // data is in MULTISZ move to out buffer { UINT cchMulti = 0; DWORD dwBufferSize = 0; cchMulti = mszSiteRoots.QueryCCH(); *ppszBuffer = new WCHAR[cchMulti]; if (NULL == *ppszBuffer) { hr = E_OUTOFMEMORY; goto done; } dwBufferSize = cchMulti; mszSiteRoots.CopyToBuffer(*ppszBuffer, &dwBufferSize); } hr = S_OK; done: return hr; } #endif //_IIS_6_0 /*=================================================================== MDGetIdentity Get WAMCLSID, Wam PackageID, and fAppIsolated from a metabase path. Parameter: szMetabasepath : get info from this path. szWAMCLSID: buffer for WAMCLSID(fixed length buffer). szPackageID: buffer for Wam PackageID(fixed length buffer). fAppIsolated: if InProc(TRUE), do not retrieve szPackageID. Return: HRESULT ===================================================================*/ HRESULT WamRegMetabaseConfig::MDGetIDs ( IN LPCWSTR szMetabasePath, OUT LPWSTR szWAMCLSID, OUT LPWSTR szPackageID, IN DWORD dwAppMode ) { HRESULT hr; METADATA_HANDLE hMetabase = NULL; METADATA_RECORD recMetaData; DWORD dwRequiredLen; DBG_ASSERT(m_pMetabase); DBG_ASSERT(szWAMCLSID); DBG_ASSERT(szPackageID); DBG_ASSERT(szMetabasePath); szPackageID[0] = NULL; szWAMCLSID[0] = NULL; // Open Key hr = m_pMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, (LPWSTR)szMetabasePath, METADATA_PERMISSION_READ, m_dwMDDefaultTimeOut, &hMetabase); if (SUCCEEDED(hr)) { MD_SET_DATA_RECORD( &recMetaData, MD_APP_WAM_CLSID, METADATA_NO_ATTRIBUTES, IIS_MD_UT_WAM, STRING_METADATA, uSizeCLSID*sizeof(WCHAR), (unsigned char *)szWAMCLSID); hr = m_pMetabase->GetData(hMetabase, NULL, &recMetaData, &dwRequiredLen); if (HRESULTTOWIN32(hr) == ERROR_INSUFFICIENT_BUFFER) { DBG_ASSERT(FALSE); } if (SUCCEEDED(hr)) { if (dwAppMode == static_cast(eAppRunOutProcIsolated)) { MD_SET_DATA_RECORD( &recMetaData, MD_APP_PACKAGE_ID, METADATA_NO_ATTRIBUTES, IIS_MD_UT_WAM, STRING_METADATA, uSizeCLSID*sizeof(WCHAR), (unsigned char *)szPackageID); hr = m_pMetabase->GetData(hMetabase, NULL, &recMetaData, &dwRequiredLen); if (HRESULTTOWIN32(hr) == ERROR_INSUFFICIENT_BUFFER) { DBG_ASSERT(FALSE); } } else if (dwAppMode == static_cast(eAppRunInProc)) { wcsncpy(szPackageID, g_WamRegGlobal.g_szIISInProcPackageID, uSizeCLSID); } else { wcsncpy(szPackageID, g_WamRegGlobal.g_szIISOOPPoolPackageID, uSizeCLSID); } } m_pMetabase->CloseKey(hMetabase); } return hr; } /*=================================================================== MDRemoveProperty Remove one MD property. Parameter: pwszMetabasePath dwIdentifier the MD indentifier to be removed. dwType the MD indietifier data type. Return: HRESULT ===================================================================*/ HRESULT WamRegMetabaseConfig::MDRemoveProperty ( IN LPCWSTR pwszMetabasePath, DWORD dwIdentifier, DWORD dwType ) { METADATA_RECORD recMetaData; HRESULT hr; METADATA_HANDLE hMetabase; hr = m_pMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, (LPWSTR)pwszMetabasePath, METADATA_PERMISSION_WRITE, m_dwMDDefaultTimeOut, &hMetabase); if (SUCCEEDED(hr)) { hr = m_pMetabase->DeleteData(hMetabase, NULL, dwIdentifier, dwType); m_pMetabase->CloseKey(hMetabase); } return hr; } /*=================================================================== MDGetLastOutProcPackageID Get LastOutProcPackageID from Metabase Key(szMetabasePath) Parameter: szMetabasePath : [in] metabase key szLastOutProcPackageID : [in] a pointer to LastOutProcPackageID buffer Return: HRESULT Note: fill in the LastOutProcPackageID, memory buffer provided by the caller. ===================================================================*/ HRESULT WamRegMetabaseConfig::MDGetLastOutProcPackageID ( IN LPCWSTR szMetabasePath, IN OUT LPWSTR szLastOutProcPackageID ) { HRESULT hr; METADATA_HANDLE hMetabase = NULL; METADATA_RECORD recMetaData; DWORD dwRequiredLen; DBG_ASSERT(szLastOutProcPackageID); DBG_ASSERT(szMetabasePath); szLastOutProcPackageID[0] = NULL; // Open Key hr = m_pMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, (LPWSTR)szMetabasePath, METADATA_PERMISSION_READ, m_dwMDDefaultTimeOut, &hMetabase); if (SUCCEEDED(hr)) { MD_SET_DATA_RECORD( &recMetaData, MD_APP_LAST_OUTPROC_PID, METADATA_NO_ATTRIBUTES, IIS_MD_UT_WAM, STRING_METADATA, uSizeCLSID*sizeof(WCHAR), (unsigned char *)szLastOutProcPackageID); hr = m_pMetabase->GetData(hMetabase, NULL, &recMetaData, &dwRequiredLen); if (HRESULTTOWIN32(hr) == ERROR_INSUFFICIENT_BUFFER) { DBG_ASSERT(FALSE); } m_pMetabase->CloseKey(hMetabase); } return hr; } /*=================================================================== GetWebServerName Look the WebServerName(ServerComment) property under the key (szMetabasePath). Parameter: None Return: HRESULT Note: fill in the szWebServerName, memory buffer provided by the caller. ===================================================================*/ HRESULT WamRegMetabaseConfig::GetWebServerName ( IN LPCWSTR wszMetabasePath, IN OUT LPWSTR wszWebServerName, IN UINT cBuffer ) { HRESULT hr; METADATA_HANDLE hMetabase = NULL; METADATA_RECORD recMetaData; DWORD dwRequiredLen; DBG_ASSERT(wszMetabasePath); DBG_ASSERT(wszWebServerName); // Open Key hr = m_pMetabase->OpenKey( METADATA_MASTER_ROOT_HANDLE, wszMetabasePath, METADATA_PERMISSION_READ, m_dwMDDefaultTimeOut, &hMetabase ); if (SUCCEEDED(hr)) { MD_SET_DATA_RECORD( &recMetaData, MD_SERVER_COMMENT, METADATA_INHERIT, IIS_MD_UT_SERVER, STRING_METADATA, cBuffer, (unsigned char *)wszWebServerName ); hr = m_pMetabase->GetData(hMetabase, L"", &recMetaData, &dwRequiredLen); if (HRESULTTOWIN32(hr) == ERROR_INSUFFICIENT_BUFFER) { DBGPRINTF((DBG_CONTEXT, "Insuffcient buffer for WebServerName. Path = %S\n", wszMetabasePath)); DBG_ASSERT(FALSE); } // // If property MD_SERVER_COMMENT not found, null out the WebServerName. // if (hr == MD_ERROR_DATA_NOT_FOUND) { wszWebServerName[0] = L'\0'; hr = NOERROR; } if (FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "Failed to read Metabase for WebServerName. Path = %S, error = %08x\n", wszMetabasePath, hr)); } m_pMetabase->CloseKey(hMetabase); } else { DBGPRINTF((DBG_CONTEXT, "Failed to read Metabase for WebServerName. Path = %S, error = %08x\n", wszMetabasePath, hr)); } return hr; } /*=================================================================== GetSignatureOnPath Get an application signature(AppRoot & AppIsolated) on a metabase path. Parameter: pwszMetabasePath pdwSignature Return: HRESULT Note: Signature is returned via pdwSignature. ===================================================================*/ HRESULT WamRegMetabaseConfig::GetSignatureOnPath ( IN LPCWSTR pwszMetabasePath, OUT DWORD* pdwSignature ) { HRESULT hr = NOERROR; WCHAR szWAMCLSID[uSizeCLSID]; WCHAR szPackageID[uSizeCLSID]; DWORD dwResult = 0; DWORD cSize = 0; DWORD dwAppMode = 0; DBG_ASSERT(pwszMetabasePath); hr = MDGetDWORD(pwszMetabasePath, MD_APP_ISOLATED, &dwAppMode); if (SUCCEEDED(hr)) { hr = MDGetIDs(pwszMetabasePath, szWAMCLSID, szPackageID, (BOOL)dwAppMode); if (SUCCEEDED(hr)) { cSize = wcslen(pwszMetabasePath); dwResult = WamRegChkSum(pwszMetabasePath, cSize); dwResult ^= WamRegChkSum(szWAMCLSID, uSizeCLSID); if (dwAppMode == eAppRunOutProcIsolated) { dwResult ^= WamRegChkSum(szPackageID, uSizeCLSID); } } } if (SUCCEEDED(hr)) { *pdwSignature = dwResult; } else { *pdwSignature = 0; } return NOERROR; } /*=================================================================== WamRegChkSum Give a wchar string, calculate a chk sum. Parameter: pszKey wchar string cchKey wcslen(of wchar ) string Return: ChkSum. ===================================================================*/ DWORD WamRegMetabaseConfig::WamRegChkSum ( IN LPCWSTR pszKey, IN DWORD cchKey ) { DWORD hash = 0, g; while (*pszKey) { hash = (hash << 4) + *pszKey++; if (g = hash & 0xf0000000) { hash ^= g >> 24; } hash &= ~g; } return hash; } /*=================================================================== MDGetPropPaths Get an array of metabase paths that contains a specific property. Parameter: szMetabasePath dwMDIdentifier pBuffer a pointer to a buffer pdwBufferSize contains actual buffer size allocated for pBuffer Return: HRESULT Side Affect: Allocate memory for return result use new. Caller needs to free pBuffer use delete[]. ===================================================================*/ HRESULT WamRegMetabaseConfig::MDGetPropPaths ( IN LPCWSTR szMetabasePath, IN DWORD dwMDIdentifier, OUT WCHAR** pBuffer, OUT DWORD* pdwBufferSize ) { HRESULT hr = NOERROR; METADATA_HANDLE hMetabase = NULL; // Metabase Handle WCHAR wchTemp; // One char buffer, no real usage. WCHAR *pTemp = &wchTemp; // Start with some buffer, otherwise, // will get RPC_X_NULL_REF_POINTER DWORD dwMDBufferSize = 0; DWORD dwMDRequiredBufferSize = 0; if (NULL != szMetabasePath) { // Open Key hr = m_pMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, (LPWSTR)szMetabasePath, METADATA_PERMISSION_READ, m_dwMDDefaultTimeOut, &hMetabase); } else { hMetabase = METADATA_MASTER_ROOT_HANDLE; } if (SUCCEEDED(hr)) { hr = m_pMetabase->GetDataPaths(hMetabase, NULL, dwMDIdentifier, ALL_METADATA, dwMDBufferSize, pTemp, &dwMDRequiredBufferSize); if (HRESULTTOWIN32(hr) == ERROR_INSUFFICIENT_BUFFER) { if (dwMDRequiredBufferSize > 0) { pTemp = new WCHAR[dwMDRequiredBufferSize]; if (pTemp == NULL) { hr = E_OUTOFMEMORY; DBGPRINTF((DBG_CONTEXT, "Out of memory. \n")); } else { dwMDBufferSize = dwMDRequiredBufferSize; hr = m_pMetabase->GetDataPaths(hMetabase, NULL, dwMDIdentifier, ALL_METADATA, dwMDBufferSize, (LPWSTR)pTemp, &dwMDRequiredBufferSize); if (FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "GetDataPaths failed with identitifier %d, path %S, hr = %08x\n", dwMDIdentifier, szMetabasePath, hr)); } else { *pBuffer = pTemp; *pdwBufferSize = dwMDBufferSize; } } } } else { DBGPRINTF((DBG_CONTEXT, "GetDataPaths failed with identitifier %d, path %S, hr = %08x\n", dwMDIdentifier, szMetabasePath, hr)); } if (hMetabase) { m_pMetabase->CloseKey(hMetabase); } } else { DBGPRINTF((DBG_CONTEXT, "Failed to open metabase path %S, hr = %08x\n", szMetabasePath, hr)); } return hr; } /*=================================================================== HasAdminAccess Determine if the user has appropriate access to the metabase. We'll use the same, somewhat hacky, method of determining this that the UI uses. Basically we set a dummy property in the MB that only an admin has access to. MB will use the call context to validate this. Parameter: Return: BOOL - True if user has admin access to the MB Side Affect: ===================================================================*/ BOOL WamRegMetabaseConfig::HasAdminAccess ( VOID ) { HRESULT hr = NOERROR; METADATA_HANDLE hMetabase = NULL; DBG_ASSERT(m_pMetabase); hr = m_pMetabase->OpenKey( METADATA_MASTER_ROOT_HANDLE, WamRegGlobal::g_szMDW3SVCRoot, METADATA_PERMISSION_WRITE, m_dwMDDefaultTimeOut, &hMetabase ); if( SUCCEEDED(hr) ) { DWORD dwDummyValue = 0x1234; METADATA_RECORD mdr; MD_SET_DATA_RECORD( &mdr, MD_ISM_ACCESS_CHECK, METADATA_NO_ATTRIBUTES, IIS_MD_UT_FILE, DWORD_METADATA, sizeof(DWORD), &dwDummyValue ); hr = m_pMetabase->SetData( hMetabase, L"", &mdr ); DBG_REQUIRE( SUCCEEDED(m_pMetabase->CloseKey( hMetabase )) ); } return SUCCEEDED(hr); }