/*++ Copyright (c) 1997 Microsoft Corporation Module Name : admutil.cpp Abstract: IADMCOM interface WRAPPER functions implemetation Environment: Win32 User Mode Author: jaroslad (jan 1997) --*/ #define INITGUID #include #include #include #ifdef UNICODE #include #define IADM_PBYTE #else #include "ansimeta.h" //convert when using ANSI interface #define IADM_PBYTE (PBYTE) #endif //#define SPECIAL_SHOW_ALL_METABASE #include #include #include //import toupper #include #include #include #include "admutil.h" #include "tables.h" #include #undef SHOW_SECURE ////////////////////////////// //global variable definition DWORD g_dwTIMEOUT_VALUE =30000; DWORD g_dwDELAY_AFTER_OPEN_VALUE=0; ////////////////////////////// //********************* CString FindCommonPath(CString a_strPath1, CString a_strPath2) { CString strCommonPath=_TEXT(""); int MinLength=a_strPath1.GetLength(); int i; //find shorter from strings if(a_strPath2.GetLength() < MinLength) MinLength=a_strPath2.GetLength(); for(i=0; i=0;i--) { if(a_strPath1.GetAt(i)==_T('/')) { strCommonPath=a_strPath1.Left(i+1);//take the trailing '/' with you //strRelSrcPath=strPath1.Mid(i+1); //strRelDstPath=strPath2.Mid(i+1); break; } } return strCommonPath; } //********************************************************************** //IMPLEMENTATION of CAdmNode //********************************************************************** //return the position of '/' that is iSeqNumber in the order //e.g: GetSlashIndex("aaa/bbb/ccc/ddd",2) returns position of 2nd index that equals 7) INT CAdmNode::GetSlashIndex(const CString& strPath, INT iSeqNumber) { INT count=0; if (iSeqNumber==0) return 0; for(INT i=0; i=0; i--) { if(strNodePath.GetAt(i)==_T('/')) return strNodePath.Left(i+1); } return _TEXT(""); } } //can return _TEXT("") for nonamed CString CAdmNode::GetCurrentNodeName(void) { CString strNodePath; strNodePath = GetNodePath(); if(strNodePath.IsEmpty()) return strNodePath; else { INT i= strNodePath.GetLength()-1; //point to the end of strNodePath if (strNodePath.Right(1)==_T("/")) i--; for(int count=0; i>=0; i--, count++) //search backward for '/' { if(strNodePath.GetAt(i)==_T('/')) return strNodePath.Mid(i+1,count); } return strNodePath; } } CString CAdmNode::GetRelPathFromService(void) { CString str=strService; if (!strInstance.IsEmpty()) str=str+_T("/")+strInstance; if (!strIPath.IsEmpty()) str=str+_T("/")+strIPath; return str; } CString CAdmNode::GetRelPathFromInstance(void) { if(strInstance.IsEmpty()) return strIPath; else return strInstance+_T("/")+strIPath; } //********************************************************************** //********************************************************************** //IMPLEMENTATION of CAdmProp object //********************************************************************** //********************************************************************** CAdmProp::CAdmProp(METADATA_RECORD &a_mdr) { memcpy (&mdr,&a_mdr,sizeof(METADATA_RECORD)); } void CAdmProp::SetValue(DWORD a_dwValue) { if(mdr.pbMDData!=0) delete mdr.pbMDData; mdr.dwMDDataLen= sizeof(DWORD); mdr.pbMDData = (PBYTE) new char[mdr.dwMDDataLen]; memcpy(mdr.pbMDData,&a_dwValue,mdr.dwMDDataLen); } void CAdmProp::SetValue(CString a_strValue) { if(mdr.pbMDData!=0) delete mdr.pbMDData; mdr.dwMDDataLen = (a_strValue.GetLength()+1)*sizeof(_TCHAR); mdr.pbMDData = (PBYTE) new _TCHAR [mdr.dwMDDataLen/sizeof(_TCHAR)]; memcpy(mdr.pbMDData,LPCTSTR(a_strValue),mdr.dwMDDataLen-sizeof(_TCHAR)); ((_TCHAR *)mdr.pbMDData)[mdr.dwMDDataLen/sizeof(_TCHAR)-1]=0; //terminate with zero } void CAdmProp::SetValue(LPCTSTR *a_lplpszValue, DWORD a_dwValueCount) { if(mdr.pbMDData!=NULL) { delete mdr.pbMDData; mdr.pbMDData=0; } mdr.dwMDDataLen=0; for(DWORD i=0; i< a_dwValueCount; i++) { if(a_lplpszValue[i]==NULL) break; mdr.dwMDDataLen += (DWORD)(_tcslen(a_lplpszValue[i])+1)*sizeof(_TCHAR); } mdr.dwMDDataLen+=sizeof(_TCHAR); // two 0 at the end mdr.pbMDData = (PBYTE) new char[mdr.dwMDDataLen]; //merge strings in one area of memory DWORD j=0; //index to destination where stings will be merged for( i=0; i< a_dwValueCount; i++) //index to aray of strings { if(a_lplpszValue[i]==NULL) break; DWORD k=0; //index within string while(a_lplpszValue[i][k]!=0) ((_TCHAR *)mdr.pbMDData)[j++]=a_lplpszValue[i][k++]; ((_TCHAR *)mdr.pbMDData)[j++]=0; } ((_TCHAR *)mdr.pbMDData)[j++]=0; } void CAdmProp::SetValue( LPBYTE pbValue, DWORD dwValueLength ) { if( mdr.pbMDData != NULL ) { delete mdr.pbMDData; } mdr.dwMDDataLen = dwValueLength; mdr.pbMDData = (PBYTE) new BYTE[mdr.dwMDDataLen]; memcpy( mdr.pbMDData, pbValue, mdr.dwMDDataLen ); } //sets the value depending on GetDataType() BOOL CAdmProp::SetValueByDataType(LPCTSTR *a_lplpszPropValue, DWORD* a_lpdwPropValueLength, WORD a_wPropValueCount) { //process the value WORD i; if(a_wPropValueCount!=0) { DWORD dwValue=0; switch(GetDataType()) { case DWORD_METADATA: { for (i=0;i 2 && a_lplpszPropValue[i][0]==_T('0') && _toupper(a_lplpszPropValue[i][1])==_T('X')) { _TCHAR * lpszX; dwValue += _tcstoul(a_lplpszPropValue[i]+2, &lpszX, 16); } else if(IsNumber(a_lplpszPropValue[i])) dwValue += _ttol(a_lplpszPropValue[i]); else { DWORD dwMapped=MapValueNameToCode(a_lplpszPropValue[i],GetIdentifier()); if(dwMapped==NAME_NOT_FOUND) { printf/*Print*/(_TEXT("value not resolved: %s\n"),a_lplpszPropValue[i]); return FALSE; } else // it has to be checked if adding can be performed dwValue |= dwMapped; } } SetValue(dwValue); } break; case STRING_METADATA: case EXPANDSZ_METADATA: { CString strValue=_TEXT(""); for (i=0;iRelease(); pcAdmCom=0; } //convert to OLECHAR[]; if (!strComputer.IsEmpty()) { wsprintf( rgchMachineName, L"%s", LPCTSTR(strComputer)); #else //release previous interface if needed if(pcAdmCom!=0 &&pcAdmCom->m_pcAdmCom!=0) { if (m_hmd!=0) CloseObject(m_hmd); m_hmd=0; pcAdmCom->m_pcAdmCom->Release(); pcAdmCom->m_pcAdmCom=0; } //convert to OLECHAR[]; if (!strComputer.IsEmpty()) { wsprintfW( rgchMachineName, L"%S", LPCTSTR(strComputer)); #endif } //fill the structure for CoGetClassObject ZeroMemory( &csiMachineName, sizeof(csiMachineName) ); // csiMachineName.pAuthInfo = NULL; // csiMachineName.dwFlags = 0; // csiMachineName.pServerInfoExt = NULL; pcsiParam = &csiMachineName; csiMachineName.pwszName = (strComputer.IsEmpty())?NULL:rgchMachineName; hresError = CoGetClassObject(GETAdminBaseCLSID(TRUE), CLSCTX_SERVER, pcsiParam, IID_IClassFactory, (void**) &pcsfFactory); if (FAILED(hresError)) { Error(_TEXT("CoGetClassObject")); } else { hresError = pcsfFactory->CreateInstance(NULL, IID_IMSAdminBase, #if UNICODE (void **) &pcAdmCom); #else (void **) &pcAdmCom->m_pcAdmCom); #endif if (FAILED(hresError)) Error(_TEXT("CreateInstance")); pcsfFactory->Release(); } } void CAdmUtil::Close (void) { //release the interface #if UNICODE if(pcAdmCom!=0) { if (m_hmd!=0) CloseObject(m_hmd); m_hmd=0; pcAdmCom->Release(); pcAdmCom=0; } #else if(pcAdmCom!=0 &&pcAdmCom->m_pcAdmCom!=0) { if (m_hmd!=0) CloseObject(m_hmd); m_hmd=0; pcAdmCom->m_pcAdmCom->Release(); pcAdmCom->m_pcAdmCom=0; } #endif } CAdmUtil::~CAdmUtil (void) { //release the interface if(pbDataBuffer!=NULL) delete [] pbDataBuffer; //the following may fail if class is static #if UNICODE if(pcAdmCom!=0) { if (m_hmd!=0) CloseObject(m_hmd); m_hmd=0; pcAdmCom->Release(); pcAdmCom=0; } #else if(pcAdmCom!=0 &&pcAdmCom->m_pcAdmCom!=0) { if (m_hmd!=0) CloseObject(m_hmd); m_hmd=0; pcAdmCom->m_pcAdmCom->Release(); pcAdmCom->m_pcAdmCom=0; } #endif } //******************************************************************************* //with fCreate set to TRUE the node will be created if it doesn't exist METADATA_HANDLE CAdmUtil::OpenObject(CAdmNode & a_AdmNode, DWORD dwPermission, BOOL fCreate) { METADATA_HANDLE hmdToReturn = 0; //try to open the full path CString strPathToOpen=a_AdmNode.GetLMNodePath(); hresError = pcAdmCom->OpenKey(METADATA_MASTER_ROOT_HANDLE, IADM_PBYTE LPCTSTR(strPathToOpen), dwPermission, g_dwTIMEOUT_VALUE, &hmdToReturn); if (FAILED(hresError)) { if ( ((dwPermission==(dwPermission|METADATA_PERMISSION_READ)) || fCreate==FALSE) ||(hresError != RETURNCODETOHRESULT(ERROR_PATH_NOT_FOUND))) { CString strErrMsg=_TEXT("OpenKey"); strErrMsg += _TEXT("(\"")+a_AdmNode.GetNodePath()+_TEXT("\")"); Error(LPCTSTR(strErrMsg)); } else { //!!!!!!!!!!!!!Place the dialog to ask to create the path // open the service object for write METADATA_HANDLE hmdServicePathHandle; hresError = pcAdmCom->OpenKey(METADATA_MASTER_ROOT_HANDLE, IADM_PBYTE LPCTSTR(a_AdmNode.GetLMServicePath()), METADATA_PERMISSION_WRITE, g_dwTIMEOUT_VALUE, &hmdServicePathHandle); if (FAILED(hresError)) { CString strErrMsg=_TEXT("OpenKey"); strErrMsg += _TEXT("(\"")+a_AdmNode.GetServicePath()+_TEXT(",WRITE")+_TEXT("\")"); Error(LPCTSTR(strErrMsg)); } else { // create the node hresError = pcAdmCom->AddKey(hmdServicePathHandle, IADM_PBYTE LPCTSTR(a_AdmNode.GetRelPathFromInstance())); if (FAILED(hresError)) { CString strErrMsg=_TEXT("AddKey"); strErrMsg += _TEXT("(\"")+a_AdmNode.GetRelPathFromInstance()+_TEXT("\")"); Error(LPCTSTR(strErrMsg)); } //close the service object pcAdmCom->CloseKey(hmdServicePathHandle); if (FAILED(hresError)) Error(_TEXT("CloseKey")); else { // now finally we can open the full path hresError = pcAdmCom->OpenKey(METADATA_MASTER_ROOT_HANDLE, IADM_PBYTE LPCTSTR(strPathToOpen), dwPermission, g_dwTIMEOUT_VALUE, &hmdToReturn); if (FAILED(hresError)) { CString strErrMsg=_TEXT("OpenKey"); strErrMsg += _TEXT("(\"")+a_AdmNode.GetServicePath()+_TEXT(",WRITE")+_TEXT("\")"); Error(LPCTSTR(strErrMsg)); } } } } } Sleep(g_dwDELAY_AFTER_OPEN_VALUE); return hmdToReturn; } //******************************************************************************* void CAdmUtil::CloseObject(METADATA_HANDLE hmd) { HRESULT hresStore=hresError; hresError=pcAdmCom->CloseKey(hmd); if (FAILED(hresError)) Error(_TEXT("CloseData")); else hresError=hresStore; //restore the previous hresError } //******************************************************************************* void CAdmUtil::CreateObject(CAdmNode & a_AdmNode) { OpenObjectTo_hmd(a_AdmNode, METADATA_PERMISSION_WRITE, TRUE/* fCreate*/); } #if 0 METADATA_HANDLE hmdToReturn = 0; //try to open the full path CString strPathToOpen=a_AdmNode.GetLMNodePath(); METADATA_HANDLE hmdServicePathHandle; hresError = pcAdmCom->OpenKey(METADATA_MASTER_ROOT_HANDLE, IADM_PBYTE LPCTSTR(a_AdmNode.GetLMServicePath()), METADATA_PERMISSION_WRITE, g_dwTIMEOUT_VALUE, &hmdServicePathHandle); if (FAILED(hresError)) { CString strErrMsg=_TEXT("OpenKey"); strErrMsg += _TEXT("(\"")+a_AdmNode.GetServicePath()+_TEXT(",WRITE")+_TEXT("\")"); Error(LPCTSTR(strErrMsg)); } else { // create the node hresError = pcAdmCom->AddKey(hmdServicePathHandle, IADM_PBYTE LPCTSTR(a_AdmNode.GetRelPathFromInstance())); if (FAILED(hresError)) { CString strErrMsg=_TEXT("AddKey"); strErrMsg += _TEXT("(\"")+a_AdmNode.GetRelPathFromInstance()+_TEXT("\")"); Error(LPCTSTR(strErrMsg)); } //close the service object CloseObject(hmdServicePathHandle); } #endif // This function enables to reuse open handles in order to improve performance // !!it supports only one acticve handle (otherwise the processing may fail) METADATA_HANDLE CAdmUtil::OpenObjectTo_hmd(CAdmNode & a_AdmNode, DWORD dwPermission, BOOL fCreate) { CString strPathToOpen=a_AdmNode.GetLMNodePath(); if(m_hmd!=0 && strPathToOpen.CompareNoCase(m_strNodePath)==0 && m_dwPermissionOfhmd == dwPermission ) { //we can reuse already opened node } else { if(m_hmd != 0) { CloseObject(m_hmd); m_hmd=0; } m_hmd = OpenObject(a_AdmNode, dwPermission, fCreate); m_dwPermissionOfhmd = dwPermission; m_strNodePath = strPathToOpen; } return m_hmd; } void CAdmUtil::CloseObject_hmd(void) { if(m_hmd != 0) { CloseObject(m_hmd); m_hmd=0; } } //******************************************************************************* void CAdmUtil::GetProperty(CAdmNode& a_AdmNode, CAdmProp& a_AdmProp) { DWORD dwRequiredDataLen=0; WORD wDataBufferSize=0; PBYTE DataBuffer=0; DWORD dwPropertyCode=a_AdmProp.GetIdentifier(); if(dwPropertyCode==0) Error(_TEXT("Property name not found")); else { //MD_SET_DATA_RECORD(&a_AdmProp.mdr, // 0, // METADATA_INHERIT | METADATA_PARTIAL_PATH, // 0, // 0, // wDataBufferSize, // pbDataBuffer); //a_AdmProp.SetIdentifier(dwPropertyCode); //has to be set beforehand a_AdmProp.SetDataType(0); a_AdmProp.SetUserType(0); a_AdmProp.SetAttrib(0); METADATA_HANDLE hmd = OpenObjectTo_hmd(a_AdmNode, METADATA_PERMISSION_READ); if (SUCCEEDED(hresError)) { hresError = pcAdmCom->GetData(hmd, IADM_PBYTE _TEXT(""), &a_AdmProp.mdr, &dwRequiredDataLen); if (FAILED(hresError)) { if (hresError == RETURNCODETOHRESULT(ERROR_INSUFFICIENT_BUFFER)) { /////////// delete []pbDataBuffer; pbDataBuffer=new BYTE[dwRequiredDataLen]; if (pbDataBuffer==0) { hresError = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY); Error(_TEXT("Buffer resize failed")); } else { a_AdmProp.mdr.dwMDDataLen = dwRequiredDataLen; a_AdmProp.mdr.pbMDData = pbDataBuffer; hresError = pcAdmCom->GetData(hmd, IADM_PBYTE _TEXT(""), &a_AdmProp.mdr, &dwRequiredDataLen); if (FAILED(hresError)) Error(_TEXT("GetData")); } } else Error(_TEXT("GetData"));; } //CloseObject (hmd); we might reuse it } } } //if lplpszPropertyValue[1]==NULL it means there is only one value (it is not a multistring) void CAdmUtil::SetProperty(CAdmNode& a_AdmNode, CAdmProp& a_AdmProp) { METADATA_HANDLE hmd = OpenObjectTo_hmd(a_AdmNode, METADATA_PERMISSION_WRITE,TRUE/*create node if doesn't exist*/); if (SUCCEEDED(hresError)) { SetProperty(&a_AdmProp.mdr,hmd); //CloseObject(hmd); we will reuse it } } void CAdmUtil::SetProperty(PMETADATA_RECORD a_pmdrData,METADATA_HANDLE a_hmd) { hresError = pcAdmCom->SetData(a_hmd, IADM_PBYTE _TEXT(""), a_pmdrData); if (FAILED(hresError)) Error(_TEXT("SetData")); } void CAdmUtil::SaveData(void) { if (m_hmd!=0) { //we have to close reusable handle in order to save successfully CloseObject(m_hmd); m_hmd=0; } hresError = pcAdmCom->SaveData(); if (FAILED(hresError)) Error(_TEXT("SaveData")); } //**************************************************************************** //DELETE PROPERTY void CAdmUtil::DeleteProperty(CAdmNode& a_AdmNode, CAdmProp& a_AdmProp) { METADATA_HANDLE hmd = OpenObjectTo_hmd(a_AdmNode, METADATA_PERMISSION_WRITE,TRUE/*create node if doesn't exist*/); if (SUCCEEDED(hresError)) { DeleteProperty(&a_AdmProp.mdr,hmd); // CloseObject(hmd); we will reuse it } } void CAdmUtil::DeleteProperty(PMETADATA_RECORD a_pmdrData,METADATA_HANDLE a_hmd) { hresError = pcAdmCom->DeleteData(a_hmd, IADM_PBYTE _TEXT(""), a_pmdrData->dwMDIdentifier,ALL_METADATA); if (FAILED(hresError)) Error(_TEXT("DeleteData")); } //**************************************************************************** //DELETE OBJECT void CAdmUtil::DeleteObject(CAdmNode& a_AdmNode, CAdmProp& a_AdmProp) { CAdmNode NodeToOpen = a_AdmNode.GetParentNodePath(); METADATA_HANDLE hmd = OpenObjectTo_hmd(NodeToOpen, METADATA_PERMISSION_WRITE,FALSE/*create node if doesn't exist*/); UNREFERENCED_PARM(a_AdmProp); if (SUCCEEDED(hresError)) { CString strToDelete=a_AdmNode.GetCurrentNodeName(); if(strToDelete==_TEXT("")) strToDelete=_TEXT("//"); //empty name has to be wrapped with '/' DeleteObject(hmd,strToDelete); //CloseObject(hmd); we will reuse it } } void CAdmUtil::DeleteObject(METADATA_HANDLE a_hmd, CString& a_strObjectName) { hresError = pcAdmCom->DeleteKey(a_hmd, IADM_PBYTE LPCTSTR(a_strObjectName)); if (FAILED(hresError)) Error(_TEXT("DeleteKey")); } void CAdmUtil::EnumPropertiesAndPrint(CAdmNode& a_AdmNode, CAdmProp a_AdmProp, //cannot be passed by reference BYTE bRecurLevel, METADATA_HANDLE a_hmd, CString & a_strRelPath) { CAdmProp mdrData=a_AdmProp; DWORD dwRequiredDataLen=0; PBYTE DataBuffer=0; METADATA_HANDLE hmdMain; if(a_hmd==0) //if handle was not passed then open one { hmdMain = OpenObjectTo_hmd(a_AdmNode, METADATA_PERMISSION_READ); if (FAILED(hresError)) return; } else hmdMain = a_hmd; for (int j=0;;j++) { //cycle for properties MD_SET_DATA_RECORD(&mdrData.mdr, 0, a_AdmProp.mdr.dwMDAttributes, a_AdmProp.mdr.dwMDUserType, a_AdmProp.mdr.dwMDDataType, dwRequiredDataLen, pbDataBuffer); hresError = pcAdmCom->EnumData(hmdMain, IADM_PBYTE LPCTSTR(a_strRelPath), &mdrData.mdr,j, &dwRequiredDataLen); if (FAILED(hresError)) { if(hresError == RETURNCODETOHRESULT(ERROR_NO_MORE_ITEMS)) { hresError=0; //NO MORE ITEMS IS NOT ERROR FOR US break; //end of items } else if (hresError == RETURNCODETOHRESULT(ERROR_INSUFFICIENT_BUFFER)) { delete pbDataBuffer; pbDataBuffer=new BYTE[dwRequiredDataLen]; if (pbDataBuffer==0) { hresError = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY); Error(_TEXT("Buffer resize failed")); } else { mdrData.mdr.dwMDDataLen = dwRequiredDataLen; mdrData.mdr.pbMDData = pbDataBuffer; hresError = pcAdmCom->EnumData(hmdMain, IADM_PBYTE LPCTSTR(a_strRelPath), &mdrData.mdr,j, &dwRequiredDataLen); if (FAILED(hresError)) Error(_TEXT("GetData")); } } else Error(_TEXT("EnumData")); } //else // Error(_TEXT("EnumData")); if(SUCCEEDED(hresError)) //we enumerated successfully, let's print { nest_print(bRecurLevel+1); mdrData.PrintProperty(); } else { break; } } //end for j - cycle for properties //if(a_hmd==0) // CloseObject(hmdMain); we will reuse it //close only if we opened at the beginning } void CAdmUtil::EnumAndPrint(CAdmNode& a_AdmNode, CAdmProp& a_AdmProp, BOOL a_fRecursive, BYTE a_bRecurLevel, METADATA_HANDLE a_hmd, CString& a_strRelPath) { _TCHAR NameBuf[METADATA_MAX_NAME_LEN]; METADATA_HANDLE hmdMain; if(a_hmd==0) //if handle was not passed then open one { hmdMain = OpenObjectTo_hmd(a_AdmNode, METADATA_PERMISSION_READ); if (FAILED(hresError)) return; } else hmdMain = a_hmd; //printf("[RELATIVE PATH : \"%s\"]\n",LPCTSTR(a_strRelPath)); //print the properties of the node EnumPropertiesAndPrint(a_AdmNode,a_AdmProp,a_bRecurLevel,hmdMain,a_strRelPath); for (int i=0; ;i++) { //cycle for subnodes hresError = pcAdmCom->EnumKeys(hmdMain, IADM_PBYTE LPCTSTR(a_strRelPath), IADM_PBYTE NameBuf, i); if(FAILED(hresError)) { if(hresError == RETURNCODETOHRESULT(ERROR_NO_MORE_ITEMS)) { hresError=0; //NO MORE ITEMS IS NOT ERROR FOR US break; //end of cycle } else { Error(_TEXT("EnumKeys")); break; } } else { //process and print node info CString strNewRelPath( a_strRelPath ); if(NameBuf[0]==0) //empty name strNewRelPath+=_TEXT("//"); //add two slashes -> this is required by metabase else { UINT nLen; //if(strNewRelPath.GetLength()>=1 && strNewRelPath.Right(1)==_TEXT("/")) { if( (nLen=strNewRelPath.GetLength())>=1 && (strNewRelPath.GetAt(nLen-1)=='/') ) { } else { strNewRelPath+=_TEXT("/"); //add only if it is not at the end of string. } strNewRelPath+=NameBuf; } CString strStringToPrint( a_AdmNode.GetNodePath() ); UINT nLen = strStringToPrint.GetLength(); //if (strStringToPrint.Right(2)==_TEXT("//")) if ((nLen > 2) && strStringToPrint.GetAt(nLen-1)=='/' && strStringToPrint.GetAt(nLen-2)=='/' ) { strStringToPrint += strNewRelPath.Mid(1); //strip first '/' } else { strStringToPrint += strNewRelPath; } LPCTSTR lpszStr=LPCTSTR(strStringToPrint); this->Print(_TEXT("[%s]\n"),lpszStr ); if(a_fRecursive) { EnumAndPrint(a_AdmNode,a_AdmProp ,a_fRecursive, a_bRecurLevel+1, hmdMain,strNewRelPath); } else { //no recursion } } } //end for i - cycle for nodes //if(a_hmd==0) // CloseObject(hmdMain); //we will reuse it //close only if we opened at the beginning } //**************************************************************** // the following function is somehow complicated because // metadata copy function doesn't support copying of one object to another place with different name // e.g. ComAdmCopyKey will copy /W3SVC/1//scripts/oldscripts1 /W3SVC/1//oldscripts2 // will create /W3SVC/1//oldscripts2/oldscripts1 // void CAdmUtil::CopyObject(CAdmNode& a_AdmNode, CAdmNode& a_AdmNodeDst) { CString strSrcPath=a_AdmNode.GetNodePath(); CString strDstPath=a_AdmNodeDst.GetNodePath(); CString strCommonPath; //=_TEXT(""); CString strRelSrcPath=strSrcPath; //relative to common path CString strRelDstPath=strDstPath; //relative to common path //we cannot open Source Path for reading because if will diable wrining to all parent nodes //e.g. copy /W3SVC/1//scripts/oldscripts /W3SVC/1//oldscripts would fail //It is necessary to find common partial path and open metabase object for that common partial path for READ/WRITE //!!!!!!!!!!!!!!!!! assume that paths are not case sensitive int MinLength=strSrcPath.GetLength(); int i; //find shorter from strings if(strDstPath.GetLength() < MinLength) MinLength=strDstPath.GetLength(); for(i=0; i=0;i--) { if(strSrcPath.GetAt(i)==_T('/')) { strCommonPath=strSrcPath.Left(i+1);//take the trailing '/' with you strRelSrcPath=strSrcPath.Mid(i+1); strRelDstPath=strDstPath.Mid(i+1); break; } } METADATA_HANDLE hmdCommon=0; CAdmNode CommonNode; CommonNode.SetPath(strCommonPath); hmdCommon = OpenObjectTo_hmd(CommonNode, METADATA_PERMISSION_READ+METADATA_PERMISSION_WRITE); if (FAILED(hresError)) return; // Altered by Adam Stone on 30-Jan-97 The following code was changed to comply with // the changes to the metabase ComMDCopyKey function. // Copy the metadata to the destination hresError = pcAdmCom->CopyKey (hmdCommon, IADM_PBYTE LPCTSTR(strRelSrcPath), hmdCommon, IADM_PBYTE LPCTSTR(strRelDstPath), FALSE, // Do NOT overwrite TRUE); // Copy do NOT move if (FAILED(hresError)) // if the node already exists, it is error { CString strErrMsg=_TEXT("CopyKey"); strErrMsg += _TEXT("(\"")+a_AdmNodeDst.GetRelPathFromInstance()+_TEXT("\")"); Error(LPCTSTR(strErrMsg)); } // All of the commented out code has become unneccessary as of 30-Jan-97 because of a change // in the metabase. ComMDCopyKey now copies to the destination, overwriting if // requested. It used to copy to a child of the destination object. /* // create the node * hresError = pcAdmCom->AddKey(hmdCommon, * IADM_PBYTE LPCTSTR(strRelDstPath)); * if (FAILED(hresError)) { //if the node exists, it is error) * CString strErrMsg=_TEXT("AddKey"); * strErrMsg += _TEXT("(\"")+a_AdmNodeDst.GetRelPathFromInstance()+_TEXT("\")"); * Error(LPCTSTR(strErrMsg)); * } * else //no error when creating new node * { * for (i=0; ;i++) { //cycle for subnodes * hresError = pcAdmCom->EnumKeys(hmdCommon, * IADM_PBYTE LPCTSTR(strRelSrcPath), (PBYTE)NameBuf, i); * if(FAILED(hresError)) { * if(hresError == RETURNCODETOHRESULT(ERROR_NO_MORE_ITEMS)) { * hresError=0; //this is not an error * break; //end of cycle * } * else * { * Error(_TEXT("EnumKeys")); * break; * } * * } * else { * * //process and copy node child node * * CString strNewRelSrcPath=strRelSrcPath; * if(NameBuf[0]==0) //empty name * strNewRelSrcPath+=_TEXT("//"); //add two slashes -> this is required by metabase * else * { if(strNewRelSrcPath.GetLength()>=1 && strNewRelSrcPath.Right(1)==_TEXT("/")) { * } * else { * strNewRelSrcPath+=_TEXT("/"); //add only if it is not at the end of string. * } * strNewRelSrcPath+=NameBuf; * } * hresError = pcAdmCom->CopyKey( * hmdCommon, (PBYTE) LPCTSTR(strNewRelSrcPath), * hmdCommon, (PBYTE) LPCTSTR(strRelDstPath),TRUE,TRUE); * if(FAILED(hresError)) { * Error(_TEXT("CopyKey")); * } * * * } * } //end for i - cycle for nodes * * * //WE COPIED ALL NODES, COPY PARAMETERS NOW * CAdmProp mdrData; * DWORD dwRequiredDataLen=0; * PBYTE DataBuffer=0; * * * * for (int j=0;;j++) { //cycle for properties * MD_SET_DATA_RECORD(&mdrData.mdr, * 0, * 0, * 0, * 0, * dwRequiredDataLen, * pbDataBuffer); * * hresError = pcAdmCom->EnumData(hmdCommon, * (PBYTE) LPCTSTR(strRelSrcPath) * , &mdrData.mdr,j, &dwRequiredDataLen); * if (FAILED(hresError)) * { * if(hresError == RETURNCODETOHRESULT(ERROR_NO_MORE_ITEMS)) * { * hresError=0; //NO MORE ITEMS IS NOT ERROR FOR US * break; //end of items * } * else if (hresError == RETURNCODETOHRESULT(ERROR_INSUFFICIENT_BUFFER)) * { /////////// delete pbDataBuffer; * pbDataBuffer=new BYTE[dwRequiredDataLen]; * if (pbDataBuffer==0) * { * hresError = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY); * Error(_TEXT("Buffer resize failed")); * } * else * { * mdrData.mdr.dwMDDataLen = dwRequiredDataLen; * mdrData.mdr.pbMDData = pbDataBuffer; * hresError = pcAdmCom->EnumData(hmdCommon, * (PBYTE) LPCTSTR(strRelSrcPath) * , &mdrData.mdr,j, &dwRequiredDataLen); * if (FAILED(hresError)) Error(_TEXT("GetData")); * } * } * else * Error(_TEXT("EnumData")); * } * else * Error(_TEXT("EnumData")); * * if(SUCCEEDED(hresError)) //we enumerated successfully, let's print * { * hresError = pcAdmCom->SetData(hmdCommon, (PBYTE) LPCTSTR(strRelDstPath),&mdrData.mdr); * if (FAILED(hresError)) Error(_TEXT("SetData")); * } * else * { * break; * } * } //end for j - cycle for properties * } */ //CloseObject(hmdCommon); //we will reuse handle //close only if we opened at the beginning } void CAdmUtil::RenameObject(CAdmNode& a_AdmNode, CAdmNode& a_AdmNodeDst) { CString strSrcPath=a_AdmNode.GetNodePath(); CString strDstPath=a_AdmNodeDst.GetNodePath(); CString strCommonPath=_TEXT(""); CString strRelSrcPath=strSrcPath; //relative to common path CString strRelDstPath=strDstPath; //relative to common path //we cannot open Source Path for reading because if will diable wrining to all parent nodes //e.g. copy /W3SVC/1//scripts/oldscripts /W3SVC/1//oldscripts would fail //It is necessary to find common partial path and open metabase object for that common partial path for READ/WRITE //!!!!!!!!!!!!!!!!! assume that paths are not case sensitive int MinLength=strSrcPath.GetLength(); int i; //find shorter from strings if(strDstPath.GetLength() < MinLength) MinLength=strDstPath.GetLength(); for(i=0; i=0;i--) { if(strSrcPath.GetAt(i)==_T('/')) { strCommonPath=strSrcPath.Left(i+1);//take the trailing '/' with you strRelSrcPath=strSrcPath.Mid(i); // keep the trailing '/' in case it's "//" strRelDstPath=strDstPath.Mid(i+1); break; } } METADATA_HANDLE hmdCommon=0; CAdmNode CommonNode; CommonNode.SetPath(strCommonPath); hmdCommon = OpenObjectTo_hmd(CommonNode, METADATA_PERMISSION_READ+METADATA_PERMISSION_WRITE); if (FAILED(hresError)) return; hresError = pcAdmCom->RenameKey (hmdCommon, IADM_PBYTE LPCTSTR(strRelSrcPath), IADM_PBYTE LPCTSTR(strRelDstPath) ); if (FAILED(hresError)) // if the node already exists, it is error { CString strErrMsg=_TEXT("RenameKey"); strErrMsg += _TEXT("(\"")+a_AdmNodeDst.GetRelPathFromInstance()+_TEXT("\")"); Error(LPCTSTR(strErrMsg)); } //CloseObject(hmdCommon); //we will reuse it//close only if we opened at the beginning } //********************************************************************** //IMPLEMENTATION of AdmUtil //********************************************************************** void CAdmUtil::Run(CString& strCommand, CAdmNode& a_AdmNode, CAdmProp& a_AdmProp, CAdmNode& a_AdmDstNode, LPCTSTR *a_lplpszPropValue, DWORD *a_lpdwPropValueLength, WORD wPropValueCount) { DWORD dwCommandCode=0; dwCommandCode = tCommandNameTable::MapNameToCode(strCommand); switch(dwCommandCode) { case CMD_SAVE: SaveData(); if (FAILED(hresError)) {} else{ printf/*Print*/(_TEXT("saved\n")); } break; case CMD_CREATE: { if (a_AdmNode.GetProperty()!=_TEXT("")) //property name cannot be used Error(_TEXT("property name for CREATE not supported")); // else if (a_AdmNode.GetService()==_TEXT("")) //property name cannot be used // Error(_TEXT("service name for CREATE is missing")); else { CreateObject(a_AdmNode); if( SUCCEEDED(QueryLastHresError())) { // SaveData(); //end of transaction if( SUCCEEDED(QueryLastHresError())) { printf/*Print*/(_TEXT("created \"%s\"\n"), LPCTSTR(a_AdmNode.GetNodePath())); } } } } break; case CMD_SET: { CAdmProp AdmPropToGet; AdmPropToGet = a_AdmProp; AdmPropToGet.SetAttrib(0); AdmPropToGet.SetUserType(0); AdmPropToGet.SetDataType(0); DisablePrint(); //do not print any error message GetProperty(a_AdmNode, AdmPropToGet); EnablePrint(); //continue printing error messages //*************************SETTING ATTRIB, DATATYPE, USERTYPE // if the parameter exists in the metabase, then existing ATTRIB, DATATYPE, USERTYPE // will be used , but this can be overwritten from a_AdmProp // if the parameter doesn't exists in the metabase, then default ATTRIB, DATATYPE, USERTYPE // (see tables.cpp) will be used , but this can be overwritten from a_AdmProp if(FAILED(QueryLastHresError())) { //store the value to be set into a_AdmProp //FIND DEFAULT SETTINGS DWORD dwPropCode=a_AdmProp.GetIdentifier(); tPropertyNameTable * PropNameTableRecord = tPropertyNameTable::FindRecord(dwPropCode); if (PropNameTableRecord!=NULL) { AdmPropToGet.SetIdentifier(PropNameTableRecord->dwCode); AdmPropToGet.SetAttrib(PropNameTableRecord->dwDefAttributes) ; AdmPropToGet.SetUserType(PropNameTableRecord->dwDefUserType); AdmPropToGet.SetDataType(PropNameTableRecord->dwDefDataType); } } else { //reuse the existing settings if( a_AdmProp.GetDataType()!=0 &&(a_AdmProp.GetDataType()!= AdmPropToGet.GetDataType())) { Error(_TEXT("Cannot redefine data type from %s to %s"), tDataTypeNameTable::MapCodeToName(AdmPropToGet.GetDataType()), tDataTypeNameTable::MapCodeToName(a_AdmProp.GetDataType())); break; } } // use settings passed to the function if set if(!a_AdmProp.IsSetDataType()) a_AdmProp.SetDataType(AdmPropToGet.GetDataType()); //reuse existing data type if(!a_AdmProp.IsSetUserType()) a_AdmProp.SetUserType(AdmPropToGet.GetUserType()); //reuse existing user type if(!a_AdmProp.IsSetAttrib()) a_AdmProp.SetAttrib(AdmPropToGet.GetAttrib()); //reuse exixting attrib if(a_AdmProp.SetValueByDataType( (LPCTSTR *)a_lplpszPropValue, a_lpdwPropValueLength, wPropValueCount)==0) Error(_TEXT("SetValueByDataType failed")); else { // if (a_AdmNode.GetService()==_TEXT("")) //property name cannot be used // Error(_TEXT("service name for SET is missing")); // else if (a_AdmNode.GetProperty()!=_TEXT("")) { SetProperty(a_AdmNode, a_AdmProp); if( SUCCEEDED(QueryLastHresError())) { //SaveData(); //end of transaction if( SUCCEEDED(QueryLastHresError())) { GetProperty(a_AdmNode, a_AdmProp); if(SUCCEEDED(QueryLastHresError())) a_AdmProp.PrintProperty(); } } }else Error(_TEXT("property name missing for SET command")); } break; } case CMD_DELETE: //if (a_AdmNode.GetService()==_TEXT("")) //property name cannot be used // Error(_TEXT("service name for DELETE is missing")); if (IsServiceName(a_AdmNode.GetService()) && a_AdmNode.GetInstance()==_TEXT("") && a_AdmNode.GetIPath()==_TEXT("") && a_AdmNode.GetProperty()==_TEXT("")) Error(_TEXT("cannot delete service")); else if (a_AdmNode.GetInstance()==_TEXT("1") && a_AdmNode.GetIPath()==_TEXT("") && a_AdmNode.GetProperty()==_TEXT("")) //property name cannot be used Error(_TEXT("cannot delete 1. instance")); else if (a_AdmNode.GetProperty()!=_TEXT("")) { DeleteProperty(a_AdmNode, a_AdmProp); } else { DeleteObject(a_AdmNode, a_AdmProp); } //if( SUCCEEDED(QueryLastHresError())) //{ // GetProperty(a_AdmNode, a_AdmProp); // if(SUCCEEDED(QueryLastHresError())) // a_AdmProp.PrintProperty(); //} if(SUCCEEDED(QueryLastHresError())) { //SaveData(); //end of transaction if( SUCCEEDED(QueryLastHresError())) { printf/*Print*/(_TEXT("deleted \"%s"), LPCTSTR(a_AdmNode.GetNodePath())); if(a_AdmNode.GetProperty()!=_TEXT("")) printf/*Print*/(_TEXT("%s"),LPCTSTR(((a_AdmNode.GetNodePath().Right(1)==_TEXT("/"))?_TEXT(""):_TEXT("/"))+ a_AdmNode.GetProperty())); printf/*Print*/(_TEXT("\"\n")); } } break; case CMD_GET: // if (a_AdmNode.GetService()==_TEXT("")) //property name cannot be used // Error(_TEXT("service name for GET is missing")); // else if (a_AdmNode.GetProperty()!=_TEXT("")) { GetProperty(a_AdmNode, a_AdmProp); if(SUCCEEDED(QueryLastHresError())) a_AdmProp.PrintProperty(); } else { CString strT(""); EnumPropertiesAndPrint(a_AdmNode, a_AdmProp, 0 , 0, strT); } break; case CMD_COPY: if(a_AdmDstNode.GetNodePath()==_TEXT("")) Error(_TEXT("destination path is missing")); else if(a_AdmNode.GetProperty()!=_TEXT("") || a_AdmDstNode.GetProperty()!=_TEXT("")) Error(_TEXT("copying of properties (parameters) not supported\n")); //else if (a_AdmNode.GetService()==_TEXT("")) //property name cannot be used // Error(_TEXT("service name in source path for COPY is missing")); //else if (a_AdmDstNode.GetService()==_TEXT("")) //property name cannot be used // Error(_TEXT("service name for destination path COPY is missing")); //else if (a_AdmNode.GetInstance()==_TEXT("")) //property name cannot be used // Error(_TEXT("instance number in source path for COPY is missing")); //else if (a_AdmDstNode.GetInstance()==_TEXT("")) //property name cannot be used // Error(_TEXT("instance number in destination path for COPY is missing")); else { CopyObject(a_AdmNode,a_AdmDstNode); if(SUCCEEDED(QueryLastHresError())) { //SaveData(); //end of transaction if( SUCCEEDED(QueryLastHresError())) { printf/*Print*/(_TEXT("copied from %s to %s\n"), LPCTSTR(a_AdmNode.GetNodePath()),LPCTSTR(a_AdmDstNode.GetNodePath())); } } break; } break; case CMD_RENAME: if(a_AdmDstNode.GetNodePath()==_TEXT("")) Error(_TEXT("destination path is missing")); else if(a_AdmNode.GetProperty()!=_TEXT("") || a_AdmDstNode.GetProperty()!=_TEXT("")) Error(_TEXT("renaming of properties (parameters) not supported")); //else if (a_AdmNode.GetService()==_TEXT("")) //property name cannot be used // Error(_TEXT("service name in source path for RENAME is missing")); //else if (a_AdmDstNode.GetService()==_TEXT("")) // Error(_TEXT("service name for destination path RENAME is missing")); //else if (a_AdmNode.GetInstance()==_TEXT("")) // Error(_TEXT("instance number in source path for RENAME is missing")); //else if (a_AdmDstNode.GetInstance()==_TEXT("")) // Error(_TEXT("instance number in destination path for RENAME is missing")); else if (a_AdmNode.GetInstance()==_TEXT("1") && a_AdmNode.GetIPath()==_TEXT("")) Error(_TEXT("cannot rename 1. instance")); else if (a_AdmNode.GetRelPathFromService().CompareNoCase(a_AdmDstNode.GetRelPathFromService())==0) Error(_TEXT("cannot rename to itself")); else { //check if one of the paths is not the child of the other one CString str1=a_AdmNode.GetRelPathFromService(); CString str2=a_AdmDstNode.GetRelPathFromService(); CString strCommonPath=FindCommonPath(str1,str2); if(strCommonPath.CompareNoCase(str1)==0 || strCommonPath.CompareNoCase(str1)==0) Error(_TEXT("cannot rename - one path is the child of the other")); else { //O.K. //CopyObject(a_AdmNode,a_AdmDstNode); //if(SUCCEEDED(QueryLastHresError())) //{ // DeleteObject(a_AdmNode,a_AdmProp); // if(SUCCEEDED(QueryLastHresError())) // { // // SaveData(); //end of transaction // if( SUCCEEDED(QueryLastHresError())) // { // printf/*Print*/("renamed from %s to %s\n", LPCTSTR(a_AdmNode.GetNodePath()),LPCTSTR(a_AdmDstNode.GetNodePath())); // } // } // } RenameObject(a_AdmNode,a_AdmDstNode); if(SUCCEEDED(QueryLastHresError())) { // SaveData(); //end of transaction if( SUCCEEDED(QueryLastHresError())) { printf/*Print*/(_TEXT("renamed from %s to %s\n"), LPCTSTR(a_AdmNode.GetNodePath()),LPCTSTR(a_AdmDstNode.GetNodePath())); } } } } break; case CMD_ENUM: { CString strT(""); EnumAndPrint(a_AdmNode, a_AdmProp, FALSE/*no recursion*/, 0, 0, strT); } break; case CMD_ENUM_ALL: { CString strT(""); EnumAndPrint(a_AdmNode, a_AdmProp,TRUE/*no recursion*/, 0, 0, strT); } break; case CMD_APPCREATEINPROC: AppCreateInProc(LPCTSTR(a_AdmNode.GetLMNodePath()),a_AdmNode.GetComputer()); break; case CMD_APPCREATEOUTPOOL: AppCreateOutPool(LPCTSTR(a_AdmNode.GetLMNodePath()),a_AdmNode.GetComputer()); break; case CMD_APPDELETE: AppDelete(LPCTSTR(a_AdmNode.GetLMNodePath()),a_AdmNode.GetComputer()); break; case CMD_APPRENAME: AppRename(a_AdmNode,a_AdmDstNode,a_AdmNode.GetComputer()); break; case CMD_APPCREATEOUTPROC: AppCreateOutProc(LPCTSTR(a_AdmNode.GetLMNodePath()),a_AdmNode.GetComputer()); break; case CMD_APPGETSTATUS: AppGetStatus(LPCTSTR(a_AdmNode.GetLMNodePath()),a_AdmNode.GetComputer()); break; case CMD_APPUNLOAD: AppUnLoad(LPCTSTR(a_AdmNode.GetLMNodePath()),a_AdmNode.GetComputer()); break; default: printf/*Print*/(_TEXT("Command not recognized: %s\n"),strCommand.operator LPCTSTR()); hresError=RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER); return ; } return; } //if hresError is 0, we will set it to invalid parameter void CAdmUtil::Error(const _TCHAR * format,...) { _TCHAR buffer[2000]; va_list marker; va_start( marker, format ); /* Initialize variable arguments. */ int x=_vstprintf(buffer, format, marker); va_end( marker ); /* Reset variable arguments. */ if(hresError==0) { if(fPrint) { _ftprintf(stderr,_TEXT("Error: %s\n"),buffer); } hresError=RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER); //little trick } else { if(fPrint) { _ftprintf(stderr,_TEXT("Error: %s - HRES(0x%x) %s\n"), buffer, hresError/*, ConvertHresToDword(hresError),ConvertHresToDword(hresError)*/,ConvertReturnCodeToString(ConvertHresToDword(hresError))); if(getenv("MDUTIL_ASCENT_LOG")!=NULL) { //we got to do some ascent logging FILE *fpAscent; fpAscent=fopen("Ascent.log","a"); if (fpAscent) { //new variation description fprintf(fpAscent,"Variation1: METADATA ACCESS (by mdutil.exe)\n"); fprintf(fpAscent,"Explain: READ OR WRITE OPERATION TO METADATA \n"); //variation summary fprintf(fpAscent,"Attempted: 1 \n"); fprintf(fpAscent,"Passed: 0 \n"); fprintf(fpAscent,"Failed: 1 \n"); _ftprintf(fpAscent,_TEXT("Error: Operation failed with HRES(0x%x)\n"), hresError); fclose(fpAscent); } } } } if(fPrint) { if(getenv("MDUTIL_BLOCK_ON_ERROR")!=NULL && hresError!=0x80070003) //path not found { _ftprintf(stdout,_TEXT("\nHit SPACE to continue or Ctrl-C to abort.\n")); while(1) { while(!_kbhit()) { ; } if(_getch()==' ') { _ftprintf(stdout,_TEXT("Continuing...\n")); break; } } } } } void CAdmUtil::Print(const _TCHAR * format,...) { va_list marker; va_start( marker, format ); /* Initialize variable arguments. */ if(fPrint) _vtprintf(format, marker); va_end( marker ); /* Reset variable arguments. */ } LPTSTR ConvertReturnCodeToString(DWORD ReturnCode) { LPTSTR RetCode = NULL; switch (ReturnCode) { case ERROR_SUCCESS: RetCode = _TEXT("ERROR_SUCCESS"); break; case ERROR_PATH_NOT_FOUND: RetCode = _TEXT("ERROR_PATH_NOT_FOUND"); break; case ERROR_INVALID_HANDLE: RetCode = _TEXT("ERROR_INVALID_HANDLE"); break; case ERROR_INVALID_DATA: RetCode =_TEXT("ERROR_INVALID_DATA"); break; case ERROR_INVALID_PARAMETER: RetCode =_TEXT("ERROR_INVALID_PARAMETER"); break; case ERROR_NOT_SUPPORTED: RetCode =_TEXT("ERROR_NOT_SUPPORTED"); break; case ERROR_ACCESS_DENIED: RetCode =_TEXT("ERROR_ACCESS_DENIED"); break; case ERROR_NOT_ENOUGH_MEMORY: RetCode =_TEXT("ERROR_NOT_ENOUGH_MEMORY"); break; case ERROR_FILE_NOT_FOUND: RetCode =_TEXT("ERROR_FILE_NOT_FOUND"); break; case ERROR_DUP_NAME: RetCode =_TEXT("ERROR_DUP_NAME"); break; case ERROR_PATH_BUSY: RetCode =_TEXT("ERROR_PATH_BUSY"); break; case ERROR_NO_MORE_ITEMS: RetCode =_TEXT("ERROR_NO_MORE_ITEMS"); break; case ERROR_INSUFFICIENT_BUFFER: RetCode =_TEXT("ERROR_INSUFFICIENT_BUFFER"); break; case ERROR_PROC_NOT_FOUND: RetCode =_TEXT("ERROR_PROC_NOT_FOUND"); break; case ERROR_INTERNAL_ERROR: RetCode =_TEXT("ERROR_INTERNAL_ERROR"); break; case MD_ERROR_NOT_INITIALIZED: RetCode =_TEXT("MD_ERROR_NOT_INITIALIZED"); break; case MD_ERROR_DATA_NOT_FOUND: RetCode =_TEXT("MD_ERROR_DATA_NOT_FOUND"); break; case ERROR_ALREADY_EXISTS: RetCode =_TEXT("ERROR_ALREADY_EXISTS"); break; case MD_WARNING_PATH_NOT_FOUND: RetCode =_TEXT("MD_WARNING_PATH_NOT_FOUND"); break; case MD_WARNING_DUP_NAME: RetCode =_TEXT("MD_WARNING_DUP_NAME"); break; case MD_WARNING_INVALID_DATA: RetCode =_TEXT("MD_WARNING_INVALID_DATA"); break; case ERROR_INVALID_NAME: RetCode =_TEXT("ERROR_INVALID_NAME"); break; default: RetCode= _TEXT("");//RetCode = "Unrecognized Error Code"); break; } return (RetCode); } DWORD ConvertHresToDword(HRESULT hRes) { return HRESULTTOWIN32(hRes); } LPTSTR ConvertHresToString(HRESULT hRes) { LPTSTR strReturn = NULL; if ((HRESULT_FACILITY(hRes) == FACILITY_WIN32) || (HRESULT_FACILITY(hRes) == FACILITY_ITF) || (hRes == 0)) { strReturn = ConvertReturnCodeToString(ConvertHresToDword(hRes)); } else { switch (hRes) { case CO_E_SERVER_EXEC_FAILURE: strReturn =_TEXT("CO_E_SERVER_EXEC_FAILURE"); break; default: strReturn =_TEXT("Unrecognized hRes facility"); } } return(strReturn); }