Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1805 lines
47 KiB

/*++
Copyright (c) 2000-2001 Microsoft Corporation
Module Name:
SecConLib.cpp
Abstract:
Implementation of:
CSecConLib
Author:
Brent R. Midwood Apr-2002
Revision History:
--*/
#include "secconlib.h"
#include "debug.h"
#include "iiscnfg.h"
#define BAIL_ON_FAILURE(hr) if (FAILED(hr)) { goto done; }
#define DEFAULT_TIMEOUT_VALUE 30000
#define SEMICOLON_STRING L";"
#define SEMICOLON_CHAR L';'
#define COMMA_STRING L","
#define COMMA_CHAR L','
#define ZERO_STRING L"0"
#define ZERO_CHAR L'0'
#define ONE_STRING L"1"
#define ONE_CHAR L'1'
CSecConLib::CSecConLib()
{
m_bInit = false;
}
CSecConLib::CSecConLib(
IMSAdminBase* pIABase)
{
SC_ASSERT(pIABase != NULL);
m_spIABase = pIABase;
m_bInit = true;
}
CSecConLib::~CSecConLib()
{
}
HRESULT
CSecConLib::InternalInitIfNecessary()
{
HRESULT hr = S_OK;
CSafeLock csSafe(m_SafeCritSec);
if(m_bInit)
{
return hr;
}
hr = csSafe.Lock();
hr = HRESULT_FROM_WIN32(hr);
if(FAILED(hr))
{
return hr;
}
if(!m_bInit)
{
hr = CoCreateInstance(
CLSID_MSAdminBase,
NULL,
CLSCTX_ALL,
IID_IMSAdminBase,
(void**)&m_spIABase);
if(FAILED(hr))
{
m_bInit = false;
}
else
{
m_bInit = true;
}
}
csSafe.Unlock();
return hr;
}
STDMETHODIMP CSecConLib::EnableApplication(
/* [in] */ LPCWSTR wszApplication,
/* [in] */ LPCWSTR wszPath)
{
DWORD dwAppNameSz = 0;
WCHAR *pwszAppProp = NULL;
DWORD dwAppPropSz = 0;
HRESULT hr = S_OK;
bool bFound = false;
WCHAR *pTop = NULL;
// compute arg length
dwAppNameSz = (DWORD)wcslen(wszApplication);
hr = InternalInitIfNecessary();
if (FAILED(hr))
{
BAIL_ON_FAILURE(hr);
}
// get the current property value for applicationdep list
hr = GetMultiSZPropVal(wszPath, MD_APP_DEPENDENCIES, &pwszAppProp, &dwAppPropSz);
BAIL_ON_FAILURE(hr);
if (NULL == pwszAppProp)
{
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
pTop = pwszAppProp;
// go thru the apps one by one
while (pwszAppProp[0])
{
DWORD dwTokSz = (DWORD)wcslen(pwszAppProp) + 1;
// check to see if the app matches
if (!_wcsnicmp(wszApplication, pwszAppProp, dwAppNameSz) &&
pwszAppProp[dwAppNameSz] == SEMICOLON_CHAR)
{
bFound = true;
WCHAR *pGroups = &pwszAppProp[dwAppNameSz + ((DWORD)sizeof(SEMICOLON_CHAR) / (DWORD)sizeof(WCHAR))];
while (pGroups)
{
WCHAR *pTemp = wcschr(pGroups, COMMA_CHAR);
if (pTemp)
{
*pTemp = 0; // replace comma w/ null
}
hr = EnableWebServiceExtension(pGroups, wszPath);
BAIL_ON_FAILURE(hr);
if (pTemp)
{
pGroups = pTemp + 1; // go past comma
}
else
{
pGroups = NULL;
}
}
}
pwszAppProp += dwTokSz; // go to the next part of the multisz
}
if (!bFound)
{
BAIL_ON_FAILURE(hr = MD_ERROR_DATA_NOT_FOUND);
}
done:
if (pTop)
{
delete [] pTop;
}
return hr;
}
HRESULT CSecConLib::SetMultiSZPropVal(
LPCWSTR wszPath,
DWORD dwMetaId,
WCHAR *pBuffer,
DWORD dwBufSize)
{
HRESULT hr = S_OK;
METADATA_RECORD mdrMDData;
METADATA_HANDLE hObjHandle = NULL;
hr = m_spIABase->OpenKey(
METADATA_MASTER_ROOT_HANDLE,
wszPath,
METADATA_PERMISSION_WRITE,
DEFAULT_TIMEOUT_VALUE,
&hObjHandle
);
BAIL_ON_FAILURE(hr);
if (!pBuffer)
{
hr = m_spIABase->DeleteData(
hObjHandle,
(LPWSTR)L"",
dwMetaId,
ALL_METADATA
);
BAIL_ON_FAILURE(hr);
}
else
{
MD_SET_DATA_RECORD(&mdrMDData,
dwMetaId,
METADATA_NO_ATTRIBUTES,
IIS_MD_UT_SERVER,
MULTISZ_METADATA,
dwBufSize * sizeof(WCHAR),
pBuffer);
hr = m_spIABase->SetData(
hObjHandle,
L"",
&mdrMDData
);
BAIL_ON_FAILURE(hr);
}
done:
m_spIABase->CloseKey(hObjHandle);
return hr;
}
HRESULT CSecConLib::GetMultiSZPropVal(
LPCWSTR wszPath,
DWORD dwMetaId,
WCHAR **ppBuffer,
DWORD *dwBufSize)
{
HRESULT hr = S_OK;
DWORD dwBufferSize = 0;
METADATA_RECORD mdrMDData;
WCHAR *pBuffer = NULL;
METADATA_HANDLE hObjHandle = NULL;
hr = m_spIABase->OpenKey(
METADATA_MASTER_ROOT_HANDLE,
wszPath,
METADATA_PERMISSION_READ,
DEFAULT_TIMEOUT_VALUE,
&hObjHandle
);
BAIL_ON_FAILURE(hr);
MD_SET_DATA_RECORD(&mdrMDData,
dwMetaId,
METADATA_NO_ATTRIBUTES,
IIS_MD_UT_SERVER,
MULTISZ_METADATA,
dwBufferSize,
pBuffer);
hr = m_spIABase->GetData(
hObjHandle,
L"",
&mdrMDData,
&dwBufferSize
);
if (dwBufferSize > 0)
{
*dwBufSize = dwBufferSize / sizeof(WCHAR);
pBuffer = (WCHAR*) new BYTE[dwBufferSize];
if (!pBuffer) {
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
MD_SET_DATA_RECORD(&mdrMDData,
dwMetaId,
METADATA_NO_ATTRIBUTES,
IIS_MD_UT_SERVER,
MULTISZ_METADATA,
dwBufferSize,
pBuffer);
hr = m_spIABase->GetData(
hObjHandle,
L"",
&mdrMDData,
&dwBufferSize
);
}
BAIL_ON_FAILURE(hr);
*ppBuffer = pBuffer;
hr = m_spIABase->CloseKey(hObjHandle);
return hr;
done:
if (pBuffer) {
delete [] pBuffer;
}
m_spIABase->CloseKey(hObjHandle);
return hr;
}
STDMETHODIMP CSecConLib::RemoveApplication(
/* [in] */ LPCWSTR wszApplication,
/* [in] */ LPCWSTR wszPath)
{
DWORD dwAppNameSz = 0;
WCHAR *pwszOrig = NULL;
WCHAR *pTopOrig = NULL;
WCHAR *pwszAppProp = NULL;
DWORD dwAppPropSz = 0;
HRESULT hr = S_OK;
bool bFound = false;
// compute arg length
dwAppNameSz = (DWORD)wcslen(wszApplication);
hr = InternalInitIfNecessary();
if (FAILED(hr))
{
BAIL_ON_FAILURE(hr);
}
// get the current property value for applicationdep list
hr = GetMultiSZPropVal(wszPath, MD_APP_DEPENDENCIES, &pwszAppProp, &dwAppPropSz);
BAIL_ON_FAILURE(hr);
// remove the application
// copy the property
pwszOrig = new WCHAR[dwAppPropSz];
pTopOrig = pwszOrig;
if (!pwszOrig)
{
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
memcpy(pwszOrig, pwszAppProp, dwAppPropSz * sizeof(WCHAR));
dwAppPropSz = 1; //reset size to contain one for the last null
WCHAR* pMidBuf = pwszAppProp;
// copy the old apps one by one
while (pwszOrig[0])
{
DWORD dwTokSz = (DWORD)wcslen(pwszOrig) + 1;
// check to see if the app already exists
if (!_wcsnicmp(wszApplication, pwszOrig, dwAppNameSz) &&
pwszOrig[dwAppNameSz] == SEMICOLON_CHAR)
{
bFound = true;
}
else
{
// copy it in
if (NULL == pMidBuf)
{
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
wcscpy(pMidBuf, pwszOrig);
pMidBuf += dwTokSz; // advance past null
*pMidBuf = 0; // add the last null
dwAppPropSz += dwTokSz;
}
pwszOrig += dwTokSz; // go to the next part of the multisz
}
if (!bFound)
{
BAIL_ON_FAILURE(hr = MD_ERROR_DATA_NOT_FOUND);
}
// set the new property value for property
if (dwAppPropSz < 3)
{
// handle deleting the last one
hr = SetMultiSZPropVal(wszPath, MD_APP_DEPENDENCIES, NULL, 0);
}
else
{
hr = SetMultiSZPropVal(wszPath, MD_APP_DEPENDENCIES, pwszAppProp, dwAppPropSz);
}
BAIL_ON_FAILURE(hr);
done:
if (pTopOrig)
{
delete [] pTopOrig;
}
if (pwszAppProp)
{
delete [] pwszAppProp;
}
return hr;
}
STDMETHODIMP CSecConLib::QueryGroupIDStatus(
/* [in] */ LPCWSTR wszPath,
/* [in] */ LPCWSTR wszGroupID,
/* [out] */ WCHAR **pszBuffer, // MULTI_SZ - allocated in here, caller should delete
/* [out] */ DWORD *pdwBufferSize) // length includes double null
{
WCHAR *pwszAppProp = NULL;
DWORD dwAppPropSz = 0;
WCHAR *pList = NULL;
WCHAR *pTempList = NULL;
DWORD dwListLen = 1; // one for the extra null at the end
DWORD dwOldListLen = 1;
HRESULT hr = S_OK;
WCHAR *pTop = NULL;
hr = InternalInitIfNecessary();
if (FAILED(hr))
{
BAIL_ON_FAILURE(hr);
}
// get the current property value for applicationdep list
hr = GetMultiSZPropVal(wszPath, MD_APP_DEPENDENCIES, &pwszAppProp, &dwAppPropSz);
BAIL_ON_FAILURE(hr);
if (NULL == pwszAppProp)
{
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
pTop = pwszAppProp;
// iterate through the apps
while (pwszAppProp[0])
{
// reset bFound
bool bFound = false;
WCHAR* pMidBuf = wcschr(pwszAppProp, SEMICOLON_CHAR);
if (!pMidBuf)
{
BAIL_ON_FAILURE(hr = E_FAIL);
}
// null the semicolon and go past it
*pMidBuf = 0;
*pMidBuf++;
// does this app have a dependency on the GroupID that got passed in?
WCHAR* pGroupID = NULL;
WCHAR* pGroups = new WCHAR[(DWORD)wcslen(pMidBuf) + 1];
if (!pGroups)
{
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
// copy in the GroupIDs
wcscpy(pGroups, pMidBuf);
// look at each GroupID
pGroupID = wcstok(pGroups, COMMA_STRING);
while (pGroupID && !bFound)
{
if (!wcscmp(pGroupID, wszGroupID))
{
bFound = true;
}
pGroupID = wcstok(NULL, COMMA_STRING);
}
if (pGroups)
{
delete [] pGroups;
}
// do we want to add this app to the list?
if (bFound)
{
// allocate the memory
dwListLen += (DWORD)wcslen(pwszAppProp) + 1; // for the null
pTempList = new WCHAR[dwListLen];
if (!pTempList)
{
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
if (pList)
{
// copy the previous list
memcpy(pTempList, pList, dwOldListLen * sizeof(WCHAR));
delete [] pList;
}
// copy on the app name
wcscpy(&pTempList[dwOldListLen - 1], pwszAppProp);
pTempList[dwListLen-1] = 0;
pTempList[dwListLen-2] = 0;
pList = pTempList;
dwOldListLen = dwListLen;
}
// now go to the next application
pwszAppProp = pMidBuf + (DWORD)wcslen(pMidBuf) + 1;
}
*pszBuffer = pList;
*pdwBufferSize = dwListLen;
done:
if (pTop)
{
delete [] pTop;
}
return hr;
}
STDMETHODIMP CSecConLib::ListApplications(
/* [in] */ LPCWSTR wszPath,
/* [out] */ WCHAR **pszBuffer, // MULTI_SZ - allocated in here, caller should delete
/* [out] */ DWORD *pdwBufferSize) // length includes double null
{
WCHAR *pwszAppProp = NULL;
DWORD dwAppPropSz = 0;
WCHAR *pList = NULL;
WCHAR *pTempList = NULL;
DWORD dwListLen = 1; // one for the extra null at the end
DWORD dwOldListLen = 1;
HRESULT hr = S_OK;
WCHAR *pTop = NULL;
hr = InternalInitIfNecessary();
if (FAILED(hr))
{
BAIL_ON_FAILURE(hr);
}
// get the current property value for applicationdep list
hr = GetMultiSZPropVal(wszPath, MD_APP_DEPENDENCIES, &pwszAppProp, &dwAppPropSz);
BAIL_ON_FAILURE(hr);
if (NULL == pwszAppProp)
{
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
pTop = pwszAppProp;
// iterate through the apps
while (pwszAppProp[0])
{
WCHAR* pMidBuf = wcschr(pwszAppProp, SEMICOLON_CHAR);
if (!pMidBuf)
{
BAIL_ON_FAILURE(hr = E_FAIL);
}
// null the semicolon and go past it
*pMidBuf = 0;
*pMidBuf++;
// allocate the memory
dwListLen += (DWORD)wcslen(pwszAppProp) + 1; // for the null
pTempList = new WCHAR[dwListLen];
if (!pTempList)
{
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
if (pList)
{
// copy the previous list
memcpy(pTempList, pList, dwOldListLen * sizeof(WCHAR));
delete [] pList;
}
// copy on the app name
wcscpy(&pTempList[dwOldListLen - 1], pwszAppProp);
pTempList[dwListLen-1] = 0;
pTempList[dwListLen-2] = 0;
pList = pTempList;
dwOldListLen = dwListLen;
// now go to the next application
pwszAppProp = pMidBuf + (DWORD)wcslen(pMidBuf) + 1;
}
if (!pList)
{
// make it a valid empty multisz
dwListLen = 2;
pList = new WCHAR[dwListLen];
if (!pList)
{
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
wmemset(pList, 0, dwListLen);
}
*pszBuffer = pList;
*pdwBufferSize = dwListLen;
done:
if (pTop)
{
delete [] pTop;
}
return hr;
}
STDMETHODIMP CSecConLib::AddDependency(
/* [in] */ LPCWSTR wszApplication,
/* [in] */ LPCWSTR wszGroupID,
/* [in] */ LPCWSTR wszPath)
{
WCHAR *pwszAppProp = NULL;
WCHAR *pwszOrig = NULL;
WCHAR *pwszTopOrig = NULL;
DWORD dwAppPropSz = 0;
DWORD dwAppNameSz = 0;
DWORD dwGroupIDSz = 0;
HRESULT hr = S_OK;
bool bDone = false;
// compute arg length
dwAppNameSz = (DWORD)wcslen(wszApplication);
dwGroupIDSz = (DWORD)wcslen(wszGroupID);
hr = InternalInitIfNecessary();
if (FAILED(hr))
{
BAIL_ON_FAILURE(hr);
}
// get the current property value for applicationdep list
hr = GetMultiSZPropVal(wszPath, MD_APP_DEPENDENCIES, &pwszAppProp, &dwAppPropSz);
if (MD_ERROR_DATA_NOT_FOUND == hr)
{
// this is okay, we just need to create the property.
hr = S_OK;
dwAppPropSz = 0;
}
BAIL_ON_FAILURE(hr);
// add the dependency
if (!dwAppPropSz)
{
// create the property
// size of the property = len(App) + 1(semicolon) + len(GID) + 2(double null MULTISZ)
dwAppPropSz = dwAppNameSz + (DWORD)wcslen(SEMICOLON_STRING) + dwGroupIDSz + 2;
// No Leak
// pwszAppProp never got alloced since we didn't get any value back,
// so no need to delete first...
pwszAppProp = new WCHAR[dwAppPropSz];
if (!pwszAppProp)
{
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
wcscpy(pwszAppProp, wszApplication);
wcscat(pwszAppProp, SEMICOLON_STRING);
wcscat(pwszAppProp, wszGroupID);
// add the double null
pwszAppProp[dwAppPropSz-1] = 0;
pwszAppProp[dwAppPropSz-2] = 0;
}
else
{
// property already exists
// copy the property
pwszOrig = new WCHAR[dwAppPropSz];
pwszTopOrig = pwszOrig;
if (!pwszOrig)
{
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
memcpy(pwszOrig, pwszAppProp, dwAppPropSz * sizeof(WCHAR));
// resize the new property to the biggest possible
if (pwszAppProp)
{
delete [] pwszAppProp;
}
// max new size is old size + len(app) + 1(semicolon) + len(GID) + null
dwAppPropSz = dwAppPropSz + dwAppNameSz + (DWORD)wcslen(SEMICOLON_STRING) +
dwGroupIDSz + 1;
pwszAppProp = new WCHAR[dwAppPropSz];
if (!pwszAppProp)
{
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
WCHAR* pMidBuf = pwszAppProp;
// copy the old dependencies one by one
while (pwszOrig[0])
{
wcscpy(pMidBuf, pwszOrig);
// check to see if the app already exists
if (!_wcsnicmp(wszApplication, pMidBuf, dwAppNameSz) &&
pMidBuf[dwAppNameSz] == SEMICOLON_CHAR)
{
// since we're not adding the app, subtract the size of the app and trailing null
dwAppPropSz = dwAppPropSz - dwAppNameSz - 1;
// this is the correct app, so now look for the GroupID
pMidBuf += dwAppNameSz + 1; // go to the first GroupID
// need a temp copy, sinc wcstok modifies the string
WCHAR* pTokTemp = new WCHAR[(DWORD)wcslen(pMidBuf) + 1];
if (!pTokTemp)
{
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
wcscpy(pTokTemp, pMidBuf);
WCHAR* token = wcstok( pTokTemp, COMMA_STRING );
while (token && !bDone)
{
if (!_wcsicmp(token, wszGroupID))
{
// we found the group ID, so the user is trying
// to add a dependency that is already there
if (pTokTemp)
{
delete [] pTokTemp;
}
BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(ERROR_DUP_NAME));
}
token = wcstok( NULL, COMMA_STRING );
}
if (pTokTemp)
{
delete [] pTokTemp;
}
pMidBuf += (DWORD)wcslen(pMidBuf); // go to the null at the end of this part
if (!bDone)
{
// we didn't find the GroupID, so add it
wcscat(pMidBuf, COMMA_STRING);
wcscat(pMidBuf, wszGroupID);
pMidBuf += (DWORD)wcslen(pMidBuf); // go to the null at the end of this part
bDone = true;
}
pMidBuf++; // go to the next char and make it a null
pMidBuf[0] = 0;
}
else // no change here, move pMidBuf along...
{
pMidBuf += (DWORD)wcslen(pMidBuf) + 1; // go past the null
}
pwszOrig += (DWORD)wcslen(pwszOrig) + 1; // go to the next part of the multisz
}
if (!bDone)
{
// we didn't even find the application, so add both app & groupID
wcscpy(pMidBuf, wszApplication);
wcscat(pMidBuf, SEMICOLON_STRING);
wcscat(pMidBuf, wszGroupID);
pMidBuf[(DWORD)wcslen(pMidBuf)+1] = 0; // add the last null
}
}
// set the new property value for property
hr = SetMultiSZPropVal(wszPath, MD_APP_DEPENDENCIES, pwszAppProp, dwAppPropSz);
BAIL_ON_FAILURE(hr);
done:
if (pwszTopOrig)
{
delete [] pwszTopOrig;
}
if (pwszAppProp)
{
delete [] pwszAppProp;
}
return hr;
}
STDMETHODIMP CSecConLib::RemoveDependency(
/* [in] */ LPCWSTR wszApplication,
/* [in] */ LPCWSTR wszGroupID,
/* [in] */ LPCWSTR wszPath)
{
HRESULT hr = S_OK;
WCHAR *pwszOrig = NULL;
WCHAR *pwszTopOrig = NULL;
WCHAR *pwszAppProp = NULL;
WCHAR *pStartStr = NULL;
DWORD dwAppPropSz = 0;
DWORD dwAppNameSz = 0;
DWORD dwGroupIDSz = 0;
bool bFound = false;
bool bOtherGIDs = false;
// compute arg length
dwAppNameSz = (DWORD)wcslen(wszApplication);
dwGroupIDSz = (DWORD)wcslen(wszGroupID);
hr = InternalInitIfNecessary();
if (FAILED(hr))
{
BAIL_ON_FAILURE(hr);
}
// get the current property value for applicationdep list
hr = GetMultiSZPropVal(wszPath, MD_APP_DEPENDENCIES, &pwszAppProp, &dwAppPropSz);
BAIL_ON_FAILURE(hr);
// remove the dependency
// copy the property
pwszOrig = new WCHAR[dwAppPropSz];
pwszTopOrig = pwszOrig;
if (!pwszOrig)
{
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
memcpy(pwszOrig, pwszAppProp, dwAppPropSz * sizeof(WCHAR));
WCHAR* pMidBuf = pwszAppProp;
// copy the old dependencies one by one
while (pwszOrig[0])
{
// check to see if the app already exists
if (!_wcsnicmp(wszApplication, pwszOrig, dwAppNameSz) &&
pwszOrig[dwAppNameSz] == SEMICOLON_CHAR)
{
pStartStr = pMidBuf;
// this is the correct app, so now look for the GroupID
pMidBuf += dwAppNameSz + 1; // go to the first GroupID
// need a temp copy, sinc wcstok modifies the string
WCHAR* pTokTemp = new WCHAR[(DWORD)wcslen(pMidBuf) + 1];
if (!pTokTemp)
{
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
wcscpy(pTokTemp, pMidBuf);
WCHAR* token = wcstok( pTokTemp, COMMA_STRING );
while (token)
{
if (bOtherGIDs)
{
wcscpy(pMidBuf, COMMA_STRING);
pMidBuf += (DWORD)wcslen(pMidBuf);
}
if (!wcscmp(token, wszGroupID))
{
// we found the group ID
bFound = true;
// adjust the final length = no comma, no GID
dwAppPropSz = dwAppPropSz - (DWORD)wcslen(COMMA_STRING) - dwGroupIDSz;
if (bOtherGIDs)
{
// need to backup over the last comma we inserted
pMidBuf -= (DWORD)wcslen(COMMA_STRING);
*pMidBuf = 0;
}
}
else
{
bOtherGIDs = true;
wcscpy(pMidBuf, token);
pMidBuf += (DWORD)wcslen(pMidBuf);
}
token = wcstok( NULL, COMMA_STRING );
}
if (pTokTemp)
{
delete [] pTokTemp;
}
if (!bOtherGIDs)
{
// deleted last dependency, so delete the app
pMidBuf = pStartStr;
dwAppPropSz = dwAppPropSz - dwAppNameSz - 1; // account for null
}
else
{
pMidBuf++;
*pMidBuf = 0;
}
}
else // no change here, move pMidBuf along...
{
if (NULL == pMidBuf)
{
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
wcscpy(pMidBuf, pwszOrig); // copy the part without mods
pMidBuf += (DWORD)wcslen(pMidBuf) + 1; // go past the null
}
pwszOrig += (DWORD)wcslen(pwszOrig) + 1; // go to the next part of the multisz
}
if (!bFound)
{
// user is trying to remove a non-existent dependency
BAIL_ON_FAILURE(hr = MD_ERROR_DATA_NOT_FOUND);
}
*pMidBuf = 0;
// set the new property value for property
if (dwAppPropSz < 3)
{
// handle deleting the last one
hr = SetMultiSZPropVal(wszPath, MD_APP_DEPENDENCIES, NULL, 0);
}
else
{
hr = SetMultiSZPropVal(wszPath, MD_APP_DEPENDENCIES, pwszAppProp, dwAppPropSz);
}
BAIL_ON_FAILURE(hr);
done:
if (pwszTopOrig)
{
delete [] pwszTopOrig;
}
if (pwszAppProp)
{
delete [] pwszAppProp;
}
return hr;
}
STDMETHODIMP CSecConLib::EnableWebServiceExtension(
/* [in] */ LPCWSTR wszExtension,
/* [in] */ LPCWSTR wszPath)
{
HRESULT hr = S_OK;
hr = InternalInitIfNecessary();
if (FAILED(hr))
{
BAIL_ON_FAILURE(hr);
}
hr = StatusWServEx(true, wszExtension, wszPath);
if (FAILED(hr))
{
BAIL_ON_FAILURE(hr);
}
done:
return hr;
}
STDMETHODIMP CSecConLib::DisableWebServiceExtension(
/* [in] */ LPCWSTR wszExtension,
/* [in] */ LPCWSTR wszPath)
{
HRESULT hr = S_OK;
hr = InternalInitIfNecessary();
if (FAILED(hr))
{
BAIL_ON_FAILURE(hr);
}
hr = StatusWServEx(false, wszExtension, wszPath);
if (FAILED(hr))
{
BAIL_ON_FAILURE(hr);
}
done:
return hr;
}
STDMETHODIMP CSecConLib::ListWebServiceExtensions(
/* [in] */ LPCWSTR wszPath,
/* [out] */ WCHAR **pszBuffer, // MULTI_SZ - allocated in here, caller should delete
/* [out] */ DWORD *pdwBufferSize) // length includes double null
{
WCHAR *pwszRListProp = NULL;
DWORD dwRListPropSz = 0;
WCHAR *pList = NULL;
WCHAR *pTempList = NULL;
DWORD dwListLen = 1; // one for the extra null at the end
DWORD dwOldListLen = 1;
HRESULT hr = S_OK;
WCHAR *pTop = NULL;
WCHAR *pMidBuf = NULL;
bool bFound = false;
bool bSpecial = false;
hr = InternalInitIfNecessary();
if (FAILED(hr))
{
BAIL_ON_FAILURE(hr);
}
// get the current property value for applicationdep list
hr = GetMultiSZPropVal(wszPath, MD_WEB_SVC_EXT_RESTRICTION_LIST, &pwszRListProp, &dwRListPropSz);
BAIL_ON_FAILURE(hr);
if (NULL == pwszRListProp)
{
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
pTop = pwszRListProp;
// iterate through the files
while (pwszRListProp[0])
{
// get to the group ID
for (int i=0; i<3; i++)
{
pMidBuf = wcschr(pwszRListProp, COMMA_CHAR);
if (!pMidBuf)
{
// don't fail. just treat this as a special case and break out
bSpecial = true;
pMidBuf = pwszRListProp;
break;
}
// null the comma and go past it
*pMidBuf = 0;
*pMidBuf++;
pwszRListProp = pMidBuf;
}
if (COMMA_CHAR == pMidBuf[0])
{
bSpecial = true;
pMidBuf = pwszRListProp;
}
if (!bSpecial)
{
// now we're looking at the group ID
pMidBuf = wcschr(pwszRListProp, COMMA_CHAR);
// if we can't find the comma, just treat the whole thing as a GroupID
// otherwise, the GroupID ends at the comma
if (pMidBuf)
{
// null the comma and go past it
*pMidBuf = 0;
*pMidBuf++;
}
// check to see if the entry is in the list already
WCHAR *pCheck = pList;
while (pCheck && *pCheck)
{
if (!_wcsicmp(pCheck, pwszRListProp))
{
bFound = true;
pCheck = NULL;
}
else
{
pCheck += (DWORD)wcslen(pCheck) + 1;
}
}
if (!bFound)
{
// allocate the memory
dwListLen += (DWORD)wcslen(pwszRListProp) + 1; // for the null
pTempList = new WCHAR[dwListLen];
if (!pTempList)
{
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
if (pList)
{
// copy the previous list
memcpy(pTempList, pList, dwOldListLen * sizeof(WCHAR));
delete [] pList;
}
// copy on the file name
wcscpy(&pTempList[dwOldListLen - 1], pwszRListProp);
pTempList[dwListLen-1] = 0;
pTempList[dwListLen-2] = 0;
pList = pTempList;
dwOldListLen = dwListLen;
}
}
// now go to the next application
pwszRListProp = pMidBuf + (DWORD)wcslen(pMidBuf) + 1;
bFound = false;
bSpecial = false;
}
if (!pList)
{
// make it a valid empty multisz
dwListLen = 2;
pList = new WCHAR[dwListLen];
if (!pList)
{
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
wmemset(pList, 0, dwListLen);
}
*pszBuffer = pList;
*pdwBufferSize = dwListLen;
done:
if (pTop)
{
delete [] pTop;
}
return hr;
}
STDMETHODIMP CSecConLib::EnableExtensionFile(
/* [in] */ LPCWSTR wszExFile,
/* [in] */ LPCWSTR wszPath)
{
HRESULT hr = S_OK;
hr = InternalInitIfNecessary();
if (FAILED(hr))
{
BAIL_ON_FAILURE(hr);
}
hr = StatusExtensionFile(true, wszExFile, wszPath);
if (FAILED(hr))
{
BAIL_ON_FAILURE(hr);
}
done:
return hr;
}
STDMETHODIMP CSecConLib::DisableExtensionFile(
/* [in] */ LPCWSTR wszExFile,
/* [in] */ LPCWSTR wszPath)
{
HRESULT hr = S_OK;
hr = InternalInitIfNecessary();
if (FAILED(hr))
{
BAIL_ON_FAILURE(hr);
}
hr = StatusExtensionFile(false, wszExFile, wszPath);
if (FAILED(hr))
{
BAIL_ON_FAILURE(hr);
}
done:
return hr;
}
HRESULT CSecConLib::StatusWServEx(
/* [in] */ bool bEnable,
/* [in] */ LPCWSTR wszWServEx,
/* [in] */ LPCWSTR wszPath)
{
WCHAR *pwszRListProp = NULL;
WCHAR *pTop = NULL;
DWORD dwRListPropSz = 0;
HRESULT hr = S_OK;
DWORD dwWServExSz = 0;
bool bFound = false;
// compute arg length
dwWServExSz = (DWORD)wcslen(wszWServEx);
// get the current property value for restriction list
hr = GetMultiSZPropVal(wszPath, MD_WEB_SVC_EXT_RESTRICTION_LIST, &pwszRListProp, &dwRListPropSz);
BAIL_ON_FAILURE(hr);
if (NULL == pwszRListProp)
{
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
pTop = pwszRListProp;
// look at the files one by one
while (pwszRListProp[0])
{
DWORD dwTokSz = (DWORD)wcslen(pwszRListProp) + 1;
WCHAR *pFileTemp = new WCHAR[dwTokSz];
WCHAR *pToken;
if (!pFileTemp)
{
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
// check to see if we're at the right group
wcscpy(pFileTemp, pwszRListProp);
pToken = wcstok( pFileTemp, COMMA_STRING );
// look at the group ID
for (int i=0; i<3; i++)
{
if (pToken)
{
pToken = wcstok( NULL, COMMA_STRING );
}
}
if (pToken && (!wcscmp(pToken, wszWServEx)))
{
bFound = true;
if (bEnable)
{
pwszRListProp[0] = ONE_CHAR;
}
else
{
pwszRListProp[0] = ZERO_CHAR;
}
}
pwszRListProp += dwTokSz; // go to the next part of the multisz
if (pFileTemp)
{
delete [] pFileTemp;
}
}
if (!bFound)
{
BAIL_ON_FAILURE(hr = MD_ERROR_DATA_NOT_FOUND);
}
// set the new property value for property
hr = SetMultiSZPropVal(wszPath, MD_WEB_SVC_EXT_RESTRICTION_LIST, pTop, dwRListPropSz);
BAIL_ON_FAILURE(hr);
done:
if (pTop)
{
delete [] pTop;
}
return hr;
}
HRESULT CSecConLib::StatusExtensionFile(
/* [in] */ bool bEnable,
/* [in] */ LPCWSTR wszExFile,
/* [in] */ LPCWSTR wszPath)
{
WCHAR *pwszRListProp = NULL;
WCHAR *pTop = NULL;
DWORD dwRListPropSz = 0;
HRESULT hr = S_OK;
DWORD dwFileNameSz = 0;
bool bFound = false;
// compute arg length
dwFileNameSz = (DWORD)wcslen(wszExFile);
// get the current property value for restriction list
hr = GetMultiSZPropVal(wszPath, MD_WEB_SVC_EXT_RESTRICTION_LIST, &pwszRListProp, &dwRListPropSz);
BAIL_ON_FAILURE(hr);
if (NULL == pwszRListProp)
{
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
pTop = pwszRListProp;
// look at the files one by one
while (pwszRListProp[0])
{
DWORD dwTokSz = (DWORD)wcslen(pwszRListProp) + 1;
// check to see if we're at the right file
// look past the bool(1) + comma(sizof_comma_char)
DWORD dwTemp = (DWORD)sizeof(COMMA_CHAR) / (DWORD)sizeof(WCHAR);
if ((!_wcsnicmp(wszExFile, &pwszRListProp[1 + dwTemp], dwFileNameSz)) &&
((pwszRListProp[dwFileNameSz + dwTemp + 1] == COMMA_CHAR) ||
(pwszRListProp[dwFileNameSz + dwTemp + 1] == NULL)
)
)
{
bFound = true;
if (bEnable)
{
pwszRListProp[0] = ONE_CHAR;
}
else
{
pwszRListProp[0] = ZERO_CHAR;
}
}
pwszRListProp += dwTokSz; // go to the next part of the multisz
}
if (!bFound)
{
BAIL_ON_FAILURE(hr = MD_ERROR_DATA_NOT_FOUND);
}
// set the new property value for property
hr = SetMultiSZPropVal(wszPath, MD_WEB_SVC_EXT_RESTRICTION_LIST, pTop, dwRListPropSz);
BAIL_ON_FAILURE(hr);
done:
if (pTop)
{
delete [] pTop;
}
return hr;
}
STDMETHODIMP CSecConLib::AddExtensionFile(
/* [in] */ LPCWSTR bstrExtensionFile,
/* [in] */ bool bAccess,
/* [in] */ LPCWSTR bstrGroupID,
/* [in] */ bool bCanDelete,
/* [in] */ LPCWSTR bstrDescription,
/* [in] */ LPCWSTR wszPath)
{
HRESULT hr = S_OK;
WCHAR *pwszRListProp = NULL;
WCHAR *pwszOrig = NULL;
WCHAR *pwszTopOrig = NULL;
DWORD dwRListPropSz = 0;
DWORD dwFileNameSz = 0;
DWORD dwGroupIDSz = 0;
DWORD dwDescSz = 0;
// compute arg length
dwFileNameSz = (DWORD)wcslen(bstrExtensionFile);
dwGroupIDSz = (DWORD)wcslen(bstrGroupID);
dwDescSz = (DWORD)wcslen(bstrDescription);
hr = InternalInitIfNecessary();
if (FAILED(hr))
{
BAIL_ON_FAILURE(hr);
}
// get the current property value for restriction list
hr = GetMultiSZPropVal(wszPath, MD_WEB_SVC_EXT_RESTRICTION_LIST, &pwszRListProp, &dwRListPropSz);
if (MD_ERROR_DATA_NOT_FOUND == hr)
{
// this is okay, we just need to create the property.
hr = S_OK;
dwRListPropSz = 0;
}
BAIL_ON_FAILURE(hr);
if (!dwRListPropSz)
{
// create the property
// size of the property = 1(0 or 1) + 1(comma) + len(file) + 1(comma) + 1(0 or 1) +
// 1(comma) + len(GID) + 1(comma) + len(descr) + 2(double null MULTISZ)
dwRListPropSz = 1 + (DWORD)wcslen(COMMA_STRING) + dwFileNameSz + (DWORD)wcslen(COMMA_STRING) +
1 + (DWORD)wcslen(COMMA_STRING) + dwGroupIDSz + (DWORD)wcslen(COMMA_STRING) + dwDescSz + 2;
// No Leak
// pwszRListProp never got alloced since we didn't get any value back,
// so no need to delete first...
pwszRListProp = new WCHAR[dwRListPropSz];
if (!pwszRListProp)
{
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
if (bAccess)
{
wcscpy(pwszRListProp, ONE_STRING);
}
else
{
wcscpy(pwszRListProp, ZERO_STRING);
}
wcscat(pwszRListProp, COMMA_STRING);
wcscat(pwszRListProp, bstrExtensionFile);
wcscat(pwszRListProp, COMMA_STRING);
if (bCanDelete)
{
wcscat(pwszRListProp, ONE_STRING);
}
else
{
wcscat(pwszRListProp, ZERO_STRING);
}
wcscat(pwszRListProp, COMMA_STRING);
wcscat(pwszRListProp, bstrGroupID);
wcscat(pwszRListProp, COMMA_STRING);
wcscat(pwszRListProp, bstrDescription);
// add the double null
pwszRListProp[dwRListPropSz-1] = 0;
pwszRListProp[dwRListPropSz-2] = 0;
}
else
{
// property already exists
// copy the property
pwszOrig = new WCHAR[dwRListPropSz];
pwszTopOrig = pwszOrig;
if (!pwszOrig)
{
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
memcpy(pwszOrig, pwszRListProp, dwRListPropSz * sizeof(WCHAR));
// resize the new property to the biggest possible
if (pwszRListProp)
{
delete [] pwszRListProp;
}
// max new size is old size + new stuff
// new stuff = 1(0 or 1) + 1(comma) + len(file) + 1(comma) + 1(0 or 1) +
// 1(comma) + len(GID) + 1(comma) + len(descr) + 1(null)
dwRListPropSz = dwRListPropSz +
1 + (DWORD)wcslen(COMMA_STRING) + dwFileNameSz + (DWORD)wcslen(COMMA_STRING) +
1 + (DWORD)wcslen(COMMA_STRING) + dwGroupIDSz + (DWORD)wcslen(COMMA_STRING) + dwDescSz + 1;
pwszRListProp = new WCHAR[dwRListPropSz];
if (!pwszRListProp)
{
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
WCHAR* pMidBuf = pwszRListProp;
// copy the old list entries one by one
while (pwszOrig[0])
{
wcscpy(pMidBuf, pwszOrig);
// skip over the #,
pMidBuf += 1 + (DWORD)wcslen(COMMA_STRING);
// check to see if the app already exists
if ((!_wcsnicmp(bstrExtensionFile, pMidBuf, dwFileNameSz)) &&
((pMidBuf[dwFileNameSz] == COMMA_CHAR) ||
(pMidBuf[dwFileNameSz] == NULL)
)
)
{
BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(ERROR_DUP_NAME));
}
pwszOrig += (DWORD)wcslen(pwszOrig) + 1; // go to the next part of the multisz
pMidBuf += (DWORD)wcslen(pMidBuf) + 1; // go past the null
}
// now copy the new file entry on
if (bAccess)
{
wcscpy(pMidBuf, ONE_STRING);
}
else
{
wcscpy(pMidBuf, ZERO_STRING);
}
wcscat(pMidBuf, COMMA_STRING);
wcscat(pMidBuf, bstrExtensionFile);
wcscat(pMidBuf, COMMA_STRING);
if (bCanDelete)
{
wcscat(pMidBuf, ONE_STRING);
}
else
{
wcscat(pMidBuf, ZERO_STRING);
}
wcscat(pMidBuf, COMMA_STRING);
wcscat(pMidBuf, bstrGroupID);
wcscat(pMidBuf, COMMA_STRING);
wcscat(pMidBuf, bstrDescription);
// add the last null
pMidBuf += (DWORD)wcslen(pMidBuf) + 1;
*pMidBuf = 0;
}
// set the new property value for property
hr = SetMultiSZPropVal(wszPath, MD_WEB_SVC_EXT_RESTRICTION_LIST, pwszRListProp, dwRListPropSz);
BAIL_ON_FAILURE(hr);
done:
if (pwszTopOrig)
{
delete [] pwszTopOrig;
}
if (pwszRListProp)
{
delete [] pwszRListProp;
}
return hr;
}
STDMETHODIMP CSecConLib::DeleteExtensionFileRecord(
/* [in] */ LPCWSTR wszExFile,
/* [in] */ LPCWSTR wszPath)
{
HRESULT hr = S_OK;
WCHAR *pwszRListProp = NULL;
WCHAR *pwszOrig = NULL;
WCHAR *pTopOrig = NULL;
DWORD dwRListPropSz = 0;
DWORD dwFileNameSz = 0;
bool bFound = false;
// compute arg length
dwFileNameSz = (DWORD)wcslen(wszExFile);
hr = InternalInitIfNecessary();
if (FAILED(hr))
{
BAIL_ON_FAILURE(hr);
}
// get the current property value for applicationdep list
hr = GetMultiSZPropVal(wszPath, MD_WEB_SVC_EXT_RESTRICTION_LIST, &pwszRListProp, &dwRListPropSz);
BAIL_ON_FAILURE(hr);
// remove the application
// copy the property
pwszOrig = new WCHAR[dwRListPropSz];
pTopOrig = pwszOrig;
if (!pwszOrig)
{
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
memcpy(pwszOrig, pwszRListProp, dwRListPropSz * sizeof(WCHAR));
dwRListPropSz = 1; //reset size to contain one for the last null
WCHAR* pMidBuf = pwszRListProp;
// copy the old apps one by one
while (pwszOrig[0])
{
DWORD dwTokSz = (DWORD)wcslen(pwszOrig) + 1;
// check to see if we're at the right file
// look past the bool(1) + comma(sizof_comma_char)
DWORD dwTemp = (DWORD)sizeof(COMMA_CHAR) / (DWORD)sizeof(WCHAR);
if (!_wcsnicmp(wszExFile, &pwszOrig[1 + dwTemp], dwFileNameSz) &&
pwszOrig[dwFileNameSz + dwTemp + 1] == COMMA_CHAR)
{
bFound = true;
// we don't want to do this... spec change in progress
// check if this is deletable or not - if not, bail with an error
//if (pwszOrig[dwFileNameSz + 1 + (2 * dwTemp)] == ZERO_CHAR)
//{
// BAIL_ON_FAILURE(hr = E_FAIL);
//}
}
else
{
// copy it in
wcscpy(pMidBuf, pwszOrig);
pMidBuf += dwTokSz; // advance past null
*pMidBuf = 0; // add the last null
dwRListPropSz += dwTokSz;
}
pwszOrig += dwTokSz; // go to the next part of the multisz
}
if (!bFound)
{
BAIL_ON_FAILURE(hr = MD_ERROR_DATA_NOT_FOUND);
}
// set the new property value for property
if (dwRListPropSz < 3)
{
// handle deleting the last one
hr = SetMultiSZPropVal(wszPath, MD_WEB_SVC_EXT_RESTRICTION_LIST, NULL, 0);
}
else
{
hr = SetMultiSZPropVal(wszPath, MD_WEB_SVC_EXT_RESTRICTION_LIST, pwszRListProp, dwRListPropSz);
}
BAIL_ON_FAILURE(hr);
done:
if (pTopOrig)
{
delete [] pTopOrig;
}
if (pwszRListProp)
{
delete [] pwszRListProp;
}
return hr;
}
STDMETHODIMP CSecConLib::ListExtensionFiles(
/* [in] */ LPCWSTR wszPath,
/* [out] */ WCHAR **pszBuffer, // MULTI_SZ - allocated in here, caller should delete
/* [out] */ DWORD *pdwBufferSize) // length includes double null
{
WCHAR *pwszRListProp = NULL;
DWORD dwRListPropSz = 0;
WCHAR *pList = NULL;
WCHAR *pTempList = NULL;
DWORD dwListLen = 1; // one for the extra null at the end
DWORD dwOldListLen = 1;
HRESULT hr = S_OK;
WCHAR *pTop = NULL;
hr = InternalInitIfNecessary();
if (FAILED(hr))
{
BAIL_ON_FAILURE(hr);
}
// get the current property value for applicationdep list
hr = GetMultiSZPropVal(wszPath, MD_WEB_SVC_EXT_RESTRICTION_LIST, &pwszRListProp, &dwRListPropSz);
BAIL_ON_FAILURE(hr);
if (NULL == pwszRListProp)
{
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
pTop = pwszRListProp;
// iterate through the files
while (pwszRListProp[0])
{
pwszRListProp += 1 + ((DWORD)sizeof(COMMA_CHAR)/(DWORD)sizeof(WCHAR));
WCHAR* pMidBuf = wcschr(pwszRListProp, COMMA_CHAR);
if (pMidBuf)
{
// null the comma and go past it
*pMidBuf = 0;
*pMidBuf++;
// allocate the memory
dwListLen += (DWORD)wcslen(pwszRListProp) + 1; // for the null
pTempList = new WCHAR[dwListLen];
if (!pTempList)
{
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
if (pList)
{
// copy the previous list
memcpy(pTempList, pList, dwOldListLen * sizeof(WCHAR));
delete [] pList;
}
// copy on the file name
wcscpy(&pTempList[dwOldListLen - 1], pwszRListProp);
pTempList[dwListLen-1] = 0;
pTempList[dwListLen-2] = 0;
pList = pTempList;
dwOldListLen = dwListLen;
}
else
{
pMidBuf = pwszRListProp + (DWORD)wcslen(pwszRListProp) + 1;
}
// now go to the next application
pwszRListProp = pMidBuf + (DWORD)wcslen(pMidBuf) + 1;
}
if (!pList)
{
// make it a valid empty multisz
dwListLen = 2;
pList = new WCHAR[dwListLen];
if (!pList)
{
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
wmemset(pList, 0, dwListLen);
}
*pszBuffer = pList;
*pdwBufferSize = dwListLen;
done:
if (pTop)
{
delete [] pTop;
}
return hr;
}