Source code of Windows XP (NT5)
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.

2036 lines
64 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name :
  4. admutil.cpp
  5. Abstract:
  6. IADMCOM interface WRAPPER functions implemetation
  7. Environment:
  8. Win32 User Mode
  9. Author:
  10. jaroslad (jan 1997)
  11. --*/
  12. #define INITGUID
  13. #include <tchar.h>
  14. #include <afx.h>
  15. #ifdef UNICODE
  16. #include <iadmw.h>
  17. #define IADM_PBYTE
  18. #else
  19. #include "ansimeta.h"
  20. //convert when using ANSI interface
  21. #define IADM_PBYTE (PBYTE)
  22. #endif
  23. #include <iiscnfg.h>
  24. #include <ole2.h>
  25. #include <ctype.h> //import toupper
  26. #include <stdlib.h>
  27. #include <stdio.h>
  28. #include <conio.h>
  29. #include "admutil.h"
  30. #include "tables.h"
  31. #include <jd_misc.h>
  32. //////////////////////////////
  33. //global variable definition
  34. DWORD g_dwTIMEOUT_VALUE =30000;
  35. DWORD g_dwDELAY_AFTER_OPEN_VALUE=0;
  36. //////////////////////////////
  37. //*********************
  38. CString FindCommonPath(CString a_strPath1, CString a_strPath2)
  39. {
  40. CString strCommonPath=_TEXT("");
  41. int MinLength=a_strPath1.GetLength();
  42. int i;
  43. //find shorter from strings
  44. if(a_strPath2.GetLength() < MinLength)
  45. MinLength=a_strPath2.GetLength();
  46. for(i=0; i<MinLength; i++)
  47. {
  48. if(a_strPath1.GetAt(i)!=a_strPath2.GetAt(i) )
  49. // common path cannot be any longer;
  50. break;
  51. }
  52. // now find the previous '/' and all before '/' is the common path
  53. for(i=i-1; i>=0;i--)
  54. {
  55. if(a_strPath1.GetAt(i)==_T('/'))
  56. {
  57. strCommonPath=a_strPath1.Left(i+1);//take the trailing '/' with you
  58. //strRelSrcPath=strPath1.Mid(i+1);
  59. //strRelDstPath=strPath2.Mid(i+1);
  60. break;
  61. }
  62. }
  63. return strCommonPath;
  64. }
  65. //**********************************************************************
  66. //IMPLEMENTATION of CAdmNode
  67. //**********************************************************************
  68. //return the position of '/' that is iSeqNumber in the order
  69. //e.g: GetSlashIndex("aaa/bbb/ccc/ddd",2) returns position of 2nd index that equals 7)
  70. INT CAdmNode::GetSlashIndex(const CString& strPath, INT iSeqNumber)
  71. {
  72. INT count=0;
  73. if (iSeqNumber==0)
  74. return 0;
  75. for(INT i=0; i<strPath.GetLength();i++)
  76. {
  77. if(strPath[i]==_T('/'))
  78. if((++count)==iSeqNumber)
  79. return i;
  80. }
  81. return -1;
  82. }
  83. //return the count of '/' in strPath
  84. INT CAdmNode::GetCountOfSlashes(const CString& strPath)
  85. {
  86. INT count=0;
  87. for(INT i=0; i<strPath.GetLength();i++)
  88. {
  89. if(strPath[i]==_T('/'))
  90. count++;
  91. }
  92. return count;
  93. }
  94. //return selement within the given string with sequence number wIndex
  95. //e.g.: GetPartOfPath("aaa/bbb/ccc",1,1) will return "bbb"
  96. //e.g.: GetPartOfPath("aaa/bbb/ccc",1) will return "bbb/ccc"
  97. //e.g.: GetPartOfPath("aaa/bbb/ccc",0,1) will return "aaa/bbb"
  98. //iStart- sequence number of first slash
  99. //iEnd- sequence number of last slash
  100. CString CAdmNode::GetPartOfPath(const CString& strPath, INT iStart, INT iEnd)
  101. {
  102. if(iEnd!=-1 && iEnd <= iStart)
  103. return _TEXT("");
  104. INT i=0;
  105. INT iPosBegin = GetSlashIndex(strPath,iStart);
  106. if(iPosBegin==-1) //not found (exceeds number of slashes available in strPath
  107. {
  108. return _TEXT("");
  109. }
  110. iPosBegin+=((iStart==0)?0:1); //adjust iPosBegin
  111. INT iPosEnd = GetSlashIndex(strPath,iEnd);
  112. CString strToReturn;
  113. if(iEnd==-1 || iPosEnd==-1)
  114. strToReturn = strPath.Mid(iPosBegin);
  115. else
  116. strToReturn = strPath.Mid(iPosBegin,iPosEnd-iPosBegin);
  117. if(iStart==0 && strToReturn==_TEXT("") && strPath!=_TEXT(""))
  118. return _TEXT("/"); //this had to be root
  119. else
  120. return strToReturn;
  121. }
  122. //within path can be given computer name, service, instance number
  123. // function will split the path to Computer, Service, Instance, Path relative to instance
  124. //
  125. void CAdmNode::SetPath(CString a_strPath)
  126. {
  127. if(a_strPath.IsEmpty())
  128. return;
  129. // change backslashes
  130. for(int i=0; i<a_strPath.GetLength(); i++)
  131. {
  132. // skip DBCS
  133. if(IsDBCSLeadByte(a_strPath[i]))
  134. {
  135. i++;
  136. continue;
  137. }
  138. if(a_strPath[i]==_T('\\'))
  139. a_strPath.SetAt(i,_T('/'));
  140. }
  141. //trim leading '/'
  142. while (a_strPath.GetLength()!=0 && a_strPath[0]==_T('/'))
  143. a_strPath=a_strPath.Mid(1);
  144. int iSvc=-1;
  145. if( IsServiceName(GetPartOfPath(a_strPath,1,2))) //get the second name within path
  146. { //if second is service then first has to be computer name
  147. strComputer = GetPartOfPath(a_strPath,0,1);
  148. strService = GetPartOfPath(a_strPath,1,2);
  149. if( IsNumber(GetPartOfPath(a_strPath,2,3))) {
  150. strInstance = GetPartOfPath(a_strPath,2,3);
  151. strIPath = GetPartOfPath(a_strPath,3); //store the rest
  152. }
  153. else {
  154. strIPath = GetPartOfPath(a_strPath,2); //store the rest
  155. }
  156. }
  157. else if( IsServiceName(GetPartOfPath(a_strPath,0,1))) //get the second name within path
  158. { //if second is service then first has to be computer name
  159. strComputer = _TEXT("");
  160. strService = GetPartOfPath(a_strPath,0,1);
  161. if( IsNumber(GetPartOfPath(a_strPath,1,2))) {
  162. strInstance = GetPartOfPath(a_strPath,1,2);
  163. strIPath = GetPartOfPath(a_strPath,2); //store the rest
  164. }
  165. else {
  166. strIPath = GetPartOfPath(a_strPath,1); //store the rest
  167. }
  168. }
  169. else
  170. {
  171. strIPath = a_strPath;
  172. }
  173. //in IPath there can be Property name at the end
  174. INT iCount= GetCountOfSlashes(strIPath);
  175. CString LastName= GetPartOfPath(strIPath,iCount); //get last name within path;
  176. if(MapPropertyNameToCode(LastName)!=NAME_NOT_FOUND)
  177. { //the Last name in the path is valid Property name
  178. strProperty = LastName;
  179. strIPath = GetPartOfPath(strIPath,0,iCount); //Strip Last name from IPath
  180. }
  181. }
  182. CString CAdmNode::GetLMRootPath(void)
  183. {
  184. return _T("/")+CString(IIS_MD_LOCAL_MACHINE_PATH);
  185. }
  186. CString CAdmNode::GetLMServicePath(void)
  187. {
  188. if(strService.IsEmpty())
  189. return GetLMRootPath();
  190. else
  191. return GetLMRootPath()+_T("/")+strService;
  192. }
  193. CString CAdmNode::GetLMInstancePath(void)
  194. {
  195. if(strInstance.IsEmpty())
  196. return GetLMServicePath();
  197. else
  198. return GetLMServicePath()+_T("/")+strInstance;
  199. }
  200. CString CAdmNode::GetLMNodePath(void)
  201. {
  202. if(strIPath.IsEmpty())
  203. return GetLMInstancePath();
  204. else
  205. return GetLMInstancePath()+_T("/")+strIPath;
  206. }
  207. CString CAdmNode::GetServicePath(void)
  208. {
  209. if(strService.IsEmpty())
  210. return _TEXT("");
  211. else
  212. return _T("/")+strService;
  213. }
  214. CString CAdmNode::GetInstancePath(void)
  215. {
  216. if(!strInstance.IsEmpty())
  217. return GetServicePath() + _T("/")+ strInstance;
  218. else
  219. return GetServicePath();
  220. }
  221. CString CAdmNode::GetNodePath(void)
  222. {
  223. if(!strIPath.IsEmpty())
  224. return GetInstancePath() + _T("/")+ strIPath;
  225. else
  226. return GetInstancePath();
  227. }
  228. CString CAdmNode::GetParentNodePath(void)
  229. {
  230. CString strNodePath;
  231. strNodePath = GetNodePath();
  232. if(strNodePath.IsEmpty())
  233. return strNodePath;
  234. else
  235. {
  236. int i= strNodePath.GetLength()-1; //point to the end of strNodePath
  237. if (strNodePath.Right(1)==_T("/"))
  238. i--;
  239. for(; i>=0; i--)
  240. {
  241. if(strNodePath.GetAt(i)==_T('/'))
  242. return strNodePath.Left(i+1);
  243. }
  244. return _TEXT("");
  245. }
  246. }
  247. //can return _TEXT("") for nonamed
  248. CString CAdmNode::GetCurrentNodeName(void)
  249. {
  250. CString strNodePath;
  251. strNodePath = GetNodePath();
  252. if(strNodePath.IsEmpty())
  253. return strNodePath;
  254. else
  255. {
  256. int i= strNodePath.GetLength()-1; //point to the end of strNodePath
  257. if (strNodePath.Right(1)==_T("/"))
  258. i--;
  259. for(int count=0; i>=0; i--, count++) //search backward for '/'
  260. {
  261. if(strNodePath.GetAt(i)==_T('/'))
  262. return strNodePath.Mid(i+1,count);
  263. }
  264. return strNodePath;
  265. }
  266. }
  267. CString CAdmNode::GetRelPathFromService(void)
  268. {
  269. CString str=strService;
  270. if (!strInstance.IsEmpty())
  271. str=str+_T("/")+strInstance;
  272. if (!strIPath.IsEmpty())
  273. str=str+_T("/")+strIPath;
  274. return str;
  275. }
  276. CString CAdmNode::GetRelPathFromInstance(void)
  277. {
  278. if(strInstance.IsEmpty())
  279. return strIPath;
  280. else
  281. return strInstance+_T("/")+strIPath;
  282. }
  283. //**********************************************************************
  284. //**********************************************************************
  285. //IMPLEMENTATION of CAdmProp object
  286. //**********************************************************************
  287. //**********************************************************************
  288. CAdmProp::CAdmProp(METADATA_RECORD &a_mdr)
  289. {
  290. memcpy (&mdr,&a_mdr,sizeof(METADATA_RECORD));
  291. }
  292. void CAdmProp::SetValue(DWORD a_dwValue)
  293. {
  294. if(mdr.pbMDData!=0)
  295. delete mdr.pbMDData;
  296. mdr.dwMDDataLen= sizeof(DWORD);
  297. mdr.pbMDData = (PBYTE) new char[mdr.dwMDDataLen];
  298. memcpy(mdr.pbMDData,&a_dwValue,mdr.dwMDDataLen);
  299. }
  300. void CAdmProp::SetValue(CString a_strValue)
  301. {
  302. if(mdr.pbMDData!=0)
  303. delete mdr.pbMDData;
  304. mdr.dwMDDataLen = (a_strValue.GetLength()+1)*sizeof(_TCHAR);
  305. mdr.pbMDData = (PBYTE) new _TCHAR [mdr.dwMDDataLen/sizeof(_TCHAR)];
  306. memcpy(mdr.pbMDData,LPCTSTR(a_strValue),(mdr.dwMDDataLen-1)*sizeof(_TCHAR));
  307. ((_TCHAR *)mdr.pbMDData)[mdr.dwMDDataLen/sizeof(_TCHAR)-1]=0; //terminate with zero
  308. }
  309. void CAdmProp::SetValue(LPCTSTR *a_lplpszValue, DWORD a_dwValueCount)
  310. {
  311. if(mdr.pbMDData!=NULL)
  312. {
  313. delete mdr.pbMDData;
  314. mdr.pbMDData=0;
  315. }
  316. mdr.dwMDDataLen=0;
  317. for(DWORD i=0; i< a_dwValueCount; i++)
  318. {
  319. if(a_lplpszValue[i]==NULL)
  320. break;
  321. mdr.dwMDDataLen += (_tcslen(a_lplpszValue[i])+1)*sizeof(_TCHAR);
  322. }
  323. mdr.dwMDDataLen+=sizeof(_TCHAR); // two 0 at the end
  324. mdr.pbMDData = (PBYTE) new char[mdr.dwMDDataLen];
  325. //merge strings in one area of memory
  326. DWORD j=0; //index to destination where stings will be merged
  327. for( i=0; i< a_dwValueCount; i++) //index to aray of strings
  328. {
  329. if(a_lplpszValue[i]==NULL)
  330. break;
  331. DWORD k=0; //index within string
  332. while(a_lplpszValue[i][k]!=0)
  333. ((_TCHAR *)mdr.pbMDData)[j++]=a_lplpszValue[i][k++];
  334. ((_TCHAR *)mdr.pbMDData)[j++]=0;
  335. }
  336. ((_TCHAR *)mdr.pbMDData)[j++]=0;
  337. }
  338. void
  339. CAdmProp::SetValue(
  340. LPBYTE pbValue,
  341. DWORD dwValueLength
  342. )
  343. {
  344. if( mdr.pbMDData != NULL )
  345. {
  346. delete mdr.pbMDData;
  347. }
  348. mdr.dwMDDataLen = dwValueLength;
  349. mdr.pbMDData = (PBYTE) new BYTE[mdr.dwMDDataLen];
  350. memcpy( mdr.pbMDData, pbValue, mdr.dwMDDataLen );
  351. }
  352. //sets the value depending on GetDataType()
  353. BOOL CAdmProp::SetValueByDataType(LPCTSTR *a_lplpszPropValue, DWORD* a_lpdwPropValueLength, WORD a_wPropValueCount)
  354. {
  355. //process the value
  356. WORD i;
  357. if(a_wPropValueCount!=0)
  358. { DWORD dwValue=0;
  359. switch(GetDataType())
  360. {
  361. case DWORD_METADATA:
  362. {
  363. for (i=0;i<a_wPropValueCount;i++)
  364. {
  365. if( _tcslen(a_lplpszPropValue[i]) > 2 && a_lplpszPropValue[i][0]==_T('0') && _toupper(a_lplpszPropValue[i][1])==_T('X'))
  366. { _TCHAR * lpszX;
  367. dwValue += _tcstoul(a_lplpszPropValue[i]+2, &lpszX, 16);
  368. }
  369. else if(IsNumber(a_lplpszPropValue[i]))
  370. dwValue += _ttol(a_lplpszPropValue[i]);
  371. else
  372. {
  373. DWORD dwMapped=MapValueNameToCode(a_lplpszPropValue[i],GetIdentifier());
  374. if(dwMapped==NAME_NOT_FOUND)
  375. {
  376. Print(_TEXT("value not resolved: %s\n"),a_lplpszPropValue[i]);
  377. return FALSE;
  378. }
  379. else
  380. // it has to be checked if adding can be performed
  381. dwValue |= dwMapped;
  382. }
  383. }
  384. SetValue(dwValue);
  385. }
  386. break;
  387. case STRING_METADATA:
  388. case EXPANDSZ_METADATA:
  389. {
  390. CString strValue=_TEXT("");
  391. for (i=0;i<a_wPropValueCount;i++)
  392. {
  393. strValue += a_lplpszPropValue[i];
  394. }
  395. SetValue(strValue);
  396. }
  397. break;
  398. case MULTISZ_METADATA:
  399. {
  400. SetValue(a_lplpszPropValue, a_wPropValueCount);
  401. }
  402. break;
  403. case BINARY_METADATA:
  404. SetValue( (LPBYTE)a_lplpszPropValue[0], a_lpdwPropValueLength[0] );
  405. break;
  406. default:
  407. return FALSE;
  408. }
  409. }
  410. return TRUE;
  411. }
  412. void CAdmProp::Print(const _TCHAR * format,...)
  413. {
  414. _TCHAR buffer[2000];
  415. va_list marker;
  416. va_start( marker, format ); /* Initialize variable arguments. */
  417. _vstprintf(buffer,format, marker);
  418. _tprintf(_TEXT("%s"),buffer);
  419. va_end( marker ); /* Reset variable arguments. */
  420. }
  421. void CAdmProp::PrintProperty(void)
  422. {
  423. CString strPropName=tPropertyNameTable::MapCodeToName(mdr.dwMDIdentifier);
  424. BOOL fSecure =(mdr.dwMDAttributes&METADATA_SECURE);
  425. //print code or name of property
  426. if(strPropName.IsEmpty())
  427. Print(_TEXT("%-30ld: "), mdr.dwMDIdentifier);
  428. else
  429. {
  430. if(getenv("MDUTIL_PRINT_ID")!=NULL) //let's print out Identifier numeric values when environment variable is set
  431. Print(_TEXT("%ld %-25s: "), mdr.dwMDIdentifier,LPCTSTR(strPropName));
  432. else
  433. Print(_TEXT("%-30s: "), LPCTSTR(strPropName));
  434. }
  435. CString strFlagsToPrint=_TEXT("");
  436. strFlagsToPrint+=_TEXT("[");
  437. if(mdr.dwMDAttributes&METADATA_INHERIT)
  438. strFlagsToPrint+=_TEXT("I");
  439. if(mdr.dwMDAttributes&METADATA_SECURE)
  440. strFlagsToPrint+=_TEXT("P");
  441. if(mdr.dwMDAttributes&METADATA_REFERENCE)
  442. strFlagsToPrint+=_TEXT("R");
  443. if(mdr.dwMDUserType==IIS_MD_UT_SERVER)
  444. strFlagsToPrint+=_TEXT("S");
  445. if(mdr.dwMDUserType==IIS_MD_UT_FILE)
  446. strFlagsToPrint+=_TEXT("F");
  447. if(mdr.dwMDUserType==IIS_MD_UT_WAM)
  448. strFlagsToPrint+=_TEXT("W");
  449. if(mdr.dwMDUserType==ASP_MD_UT_APP)
  450. strFlagsToPrint+=_TEXT("A");
  451. strFlagsToPrint+=_TEXT("]");
  452. Print(_TEXT("%-8s"),LPCTSTR(strFlagsToPrint));
  453. //print property value
  454. DWORD i;
  455. switch (mdr.dwMDDataType) {
  456. case DWORD_METADATA:
  457. #ifndef SHOW_SECURE
  458. if ( fSecure )
  459. {
  460. Print(_TEXT("(DWORD) ********"), *(DWORD *)(mdr.pbMDData));
  461. }
  462. else
  463. #endif
  464. {
  465. Print(_TEXT("(DWORD) 0x%x"), *(DWORD *)(mdr.pbMDData));
  466. // try to convert to readable info
  467. CString strNiceContent;
  468. strNiceContent=tValueTable::MapValueContentToString(*(DWORD *)(mdr.pbMDData), mdr.dwMDIdentifier);
  469. if(!strNiceContent.IsEmpty())
  470. Print(_TEXT("={%s}"),LPCTSTR(strNiceContent));
  471. else //at least decimal value can be useful
  472. Print(_TEXT("={%ld}"),*(DWORD *)(mdr.pbMDData));
  473. }
  474. break;
  475. case BINARY_METADATA:
  476. Print(_TEXT("(BINARY) 0x"));
  477. for (i = 0; i < mdr.dwMDDataLen; i++) {
  478. #ifndef SHOW_SECURE
  479. if ( fSecure )
  480. {
  481. Print(_TEXT(" * " ));
  482. }
  483. else
  484. #endif
  485. {
  486. Print(_TEXT("%02x "), ((PBYTE)(mdr.pbMDData))[i]);
  487. }
  488. }
  489. break;
  490. case STRING_METADATA:
  491. case EXPANDSZ_METADATA:
  492. if(mdr.dwMDDataType==STRING_METADATA)
  493. Print(_TEXT("(STRING) "));
  494. else
  495. Print(_TEXT("(EXPANDSZ) "));
  496. #ifndef SHOW_SECURE
  497. if( fSecure )
  498. { //do not expose the length of secure data
  499. Print( _TEXT("\"********************\"" ));
  500. }
  501. else
  502. #endif
  503. {
  504. Print(_TEXT("\""));
  505. for (i = 0; i < mdr.dwMDDataLen/sizeof(_TCHAR); i++) {
  506. if(((_TCHAR *)(mdr.pbMDData))[i]==0)
  507. {
  508. if( i+1 == mdr.dwMDDataLen/sizeof(_TCHAR))
  509. { //we are at the end print only terminating "
  510. Print(_TEXT("\""));
  511. }
  512. else
  513. {
  514. Print(_TEXT("\" \""));
  515. }
  516. }
  517. if(((_TCHAR *)(mdr.pbMDData))[i]=='\r')
  518. Print(_TEXT("\t"));
  519. else
  520. {
  521. // if(mdr.dwMDAttributes&METADATA_SECURE)
  522. // {
  523. // Print( _TEXT("*" ));
  524. // }
  525. // else
  526. // {
  527. Print( _TEXT("%c"), ((_TCHAR *)(mdr.pbMDData))[i]);
  528. // }
  529. }
  530. }
  531. }
  532. break;
  533. case MULTISZ_METADATA:
  534. Print(_TEXT("(MULTISZ) ")); //0 should be separator of mulisz strings
  535. #ifndef SHOW_SECURE
  536. if( fSecure )
  537. { //do not expose the length of secure data
  538. Print( _TEXT("\"********************\"" ));
  539. }
  540. else
  541. #endif
  542. {
  543. Print(_TEXT("\""));
  544. for (i = 0; i < mdr.dwMDDataLen/sizeof(_TCHAR); i++) {
  545. if(((_TCHAR *)(mdr.pbMDData))[i]==0)
  546. {
  547. if( i+1 == mdr.dwMDDataLen/sizeof(_TCHAR) || (mdr.dwMDDataLen/sizeof(_TCHAR)-i==2 && ((_TCHAR *)(mdr.pbMDData))[i]==0 && ((_TCHAR *)(mdr.pbMDData))[i+1]==0))
  548. { //we are at the end print only terminating "
  549. Print(_TEXT("\"")); break;
  550. }
  551. else
  552. {
  553. Print(_TEXT("\" \""));
  554. }
  555. }
  556. else
  557. Print(_TEXT("%c"),((_TCHAR *)(mdr.pbMDData))[i]);
  558. }
  559. }
  560. break;
  561. default:
  562. Print(_TEXT("(UNKNOWN) "));
  563. break;
  564. }
  565. Print(_TEXT("\n"));
  566. }
  567. //**********************************************************************
  568. //**********************************************************************
  569. //IMPLEMENTATION of CAdmUtil object
  570. //**********************************************************************
  571. //**********************************************************************
  572. //nesting for recursive enumeration
  573. static void nest_print(BYTE bLevel)
  574. {
  575. for(int i=0; i<=bLevel;i++)
  576. _tprintf(_T(" "));
  577. }
  578. CAdmUtil::CAdmUtil (const CString & strComputer)
  579. {
  580. EnablePrint(); // by default print error messages
  581. pcAdmCom=0;
  582. m_hmd=0;
  583. pbDataBuffer=new BYTE [DEFAULTBufferSize];
  584. wDataBufferSize=DEFAULTBufferSize;
  585. #if UNICODE
  586. pcAdmCom=0;
  587. #else
  588. pcAdmCom=new ANSI_smallIMSAdminBase; //we will access metabase through wrapper class
  589. #endif
  590. //Open (strComputer);
  591. }
  592. void CAdmUtil::Open (const CString & strComputer)
  593. {
  594. IClassFactory * pcsfFactory = NULL;
  595. COSERVERINFO csiMachineName;
  596. COSERVERINFO *pcsiParam = NULL;
  597. OLECHAR rgchMachineName[MAX_PATH];
  598. #if UNICODE
  599. //release previous interface if needed
  600. if(pcAdmCom!=0)
  601. {
  602. if (m_hmd!=0) CloseObject(m_hmd);
  603. m_hmd=0;
  604. pcAdmCom->Release();
  605. pcAdmCom=0;
  606. }
  607. //convert to OLECHAR[];
  608. if (!strComputer.IsEmpty())
  609. {
  610. wsprintf( rgchMachineName, L"%s", LPCTSTR(strComputer));
  611. #else
  612. //release previous interface if needed
  613. if(pcAdmCom!=0 &&pcAdmCom->m_pcAdmCom!=0)
  614. {
  615. if (m_hmd!=0) CloseObject(m_hmd);
  616. m_hmd=0;
  617. pcAdmCom->m_pcAdmCom->Release();
  618. pcAdmCom->m_pcAdmCom=0;
  619. }
  620. //convert to OLECHAR[];
  621. if (!strComputer.IsEmpty())
  622. {
  623. wsprintfW( rgchMachineName, L"%S", LPCTSTR(strComputer));
  624. #endif
  625. }
  626. //fill the structure for CoGetClassObject
  627. ZeroMemory( &csiMachineName, sizeof(csiMachineName) );
  628. // csiMachineName.pAuthInfo = NULL;
  629. // csiMachineName.dwFlags = 0;
  630. // csiMachineName.pServerInfoExt = NULL;
  631. pcsiParam = &csiMachineName;
  632. csiMachineName.pwszName = (strComputer.IsEmpty())?NULL:rgchMachineName;
  633. hresError = CoGetClassObject(GETAdminBaseCLSID(TRUE), CLSCTX_SERVER, pcsiParam,
  634. IID_IClassFactory, (void**) &pcsfFactory);
  635. if (FAILED(hresError))
  636. {
  637. Error(_TEXT("CoGetClassObject"));
  638. }
  639. else {
  640. hresError = pcsfFactory->CreateInstance(NULL, IID_IMSAdminBase,
  641. #if UNICODE
  642. (void **) &pcAdmCom);
  643. #else
  644. (void **) &pcAdmCom->m_pcAdmCom);
  645. #endif
  646. if (FAILED(hresError)) Error(_TEXT("CreateInstance"));
  647. pcsfFactory->Release();
  648. }
  649. }
  650. void CAdmUtil::Close (void)
  651. {
  652. //release the interface
  653. #if UNICODE
  654. if(pcAdmCom!=0)
  655. {
  656. if (m_hmd!=0) CloseObject(m_hmd);
  657. m_hmd=0;
  658. pcAdmCom->Release();
  659. pcAdmCom=0;
  660. }
  661. #else
  662. if(pcAdmCom!=0 &&pcAdmCom->m_pcAdmCom!=0)
  663. {
  664. if (m_hmd!=0) CloseObject(m_hmd);
  665. m_hmd=0;
  666. pcAdmCom->m_pcAdmCom->Release();
  667. pcAdmCom->m_pcAdmCom=0;
  668. }
  669. #endif
  670. }
  671. CAdmUtil::~CAdmUtil (void)
  672. {
  673. //release the interface
  674. if(pbDataBuffer!=NULL)
  675. delete [] pbDataBuffer;
  676. //the following may fail if class is static
  677. #if UNICODE
  678. if(pcAdmCom!=0)
  679. {
  680. if (m_hmd!=0) CloseObject(m_hmd);
  681. m_hmd=0;
  682. pcAdmCom->Release();
  683. pcAdmCom=0;
  684. }
  685. #else
  686. if(pcAdmCom!=0 &&pcAdmCom->m_pcAdmCom!=0)
  687. {
  688. if (m_hmd!=0) CloseObject(m_hmd);
  689. m_hmd=0;
  690. pcAdmCom->m_pcAdmCom->Release();
  691. pcAdmCom->m_pcAdmCom=0;
  692. }
  693. #endif
  694. }
  695. //*******************************************************************************
  696. //with fCreate set to TRUE the node will be created if it doesn't exist
  697. METADATA_HANDLE CAdmUtil::OpenObject(CAdmNode & a_AdmNode, DWORD dwPermission, BOOL fCreate)
  698. {
  699. METADATA_HANDLE hmdToReturn = 0;
  700. //try to open the full path
  701. CString strPathToOpen=a_AdmNode.GetLMNodePath();
  702. hresError = pcAdmCom->OpenKey(METADATA_MASTER_ROOT_HANDLE,
  703. IADM_PBYTE LPCTSTR(strPathToOpen), dwPermission, g_dwTIMEOUT_VALUE, &hmdToReturn);
  704. if (FAILED(hresError)) {
  705. if ( ((dwPermission==(dwPermission|METADATA_PERMISSION_READ)) || fCreate==FALSE) ||(hresError != RETURNCODETOHRESULT(ERROR_PATH_NOT_FOUND))) {
  706. CString strErrMsg=_TEXT("OpenKey");
  707. strErrMsg += _TEXT("(\"")+a_AdmNode.GetNodePath()+_TEXT("\")");
  708. Error(LPCTSTR(strErrMsg));
  709. }
  710. else {
  711. //!!!!!!!!!!!!!Place the dialog to ask to create the path
  712. // open the service object for write
  713. METADATA_HANDLE hmdServicePathHandle;
  714. hresError = pcAdmCom->OpenKey(METADATA_MASTER_ROOT_HANDLE,
  715. IADM_PBYTE LPCTSTR(a_AdmNode.GetLMServicePath()), METADATA_PERMISSION_WRITE, g_dwTIMEOUT_VALUE, &hmdServicePathHandle);
  716. if (FAILED(hresError))
  717. {
  718. CString strErrMsg=_TEXT("OpenKey");
  719. strErrMsg += _TEXT("(\"")+a_AdmNode.GetServicePath()+_TEXT(",WRITE")+_TEXT("\")");
  720. Error(LPCTSTR(strErrMsg));
  721. }
  722. else {
  723. // create the node
  724. hresError = pcAdmCom->AddKey(hmdServicePathHandle,
  725. IADM_PBYTE LPCTSTR(a_AdmNode.GetRelPathFromInstance()));
  726. if (FAILED(hresError)) {
  727. CString strErrMsg=_TEXT("AddKey");
  728. strErrMsg += _TEXT("(\"")+a_AdmNode.GetRelPathFromInstance()+_TEXT("\")");
  729. Error(LPCTSTR(strErrMsg));
  730. }
  731. //close the service object
  732. pcAdmCom->CloseKey(hmdServicePathHandle);
  733. if (FAILED(hresError)) Error(_TEXT("CloseKey"));
  734. else {
  735. // now finally we can open the full path
  736. hresError = pcAdmCom->OpenKey(METADATA_MASTER_ROOT_HANDLE,
  737. IADM_PBYTE LPCTSTR(strPathToOpen), dwPermission, g_dwTIMEOUT_VALUE, &hmdToReturn);
  738. if (FAILED(hresError))
  739. {
  740. CString strErrMsg=_TEXT("OpenKey");
  741. strErrMsg += _TEXT("(\"")+a_AdmNode.GetServicePath()+_TEXT(",WRITE")+_TEXT("\")");
  742. Error(LPCTSTR(strErrMsg));
  743. }
  744. }
  745. }
  746. }
  747. }
  748. Sleep(g_dwDELAY_AFTER_OPEN_VALUE);
  749. return hmdToReturn;
  750. }
  751. //*******************************************************************************
  752. void CAdmUtil::CloseObject(METADATA_HANDLE hmd)
  753. {
  754. HRESULT hresStore=hresError;
  755. hresError=pcAdmCom->CloseKey(hmd);
  756. if (FAILED(hresError)) Error(_TEXT("CloseData"));
  757. else hresError=hresStore; //restore the previous hresError
  758. }
  759. //*******************************************************************************
  760. void CAdmUtil::CreateObject(CAdmNode & a_AdmNode)
  761. {
  762. OpenObjectTo_hmd(a_AdmNode, METADATA_PERMISSION_WRITE, TRUE/* fCreate*/);
  763. }
  764. #if 0
  765. METADATA_HANDLE hmdToReturn = 0;
  766. //try to open the full path
  767. CString strPathToOpen=a_AdmNode.GetLMNodePath();
  768. METADATA_HANDLE hmdServicePathHandle;
  769. hresError = pcAdmCom->OpenKey(METADATA_MASTER_ROOT_HANDLE,
  770. IADM_PBYTE LPCTSTR(a_AdmNode.GetLMServicePath()), METADATA_PERMISSION_WRITE, g_dwTIMEOUT_VALUE, &hmdServicePathHandle);
  771. if (FAILED(hresError))
  772. {
  773. CString strErrMsg=_TEXT("OpenKey");
  774. strErrMsg += _TEXT("(\"")+a_AdmNode.GetServicePath()+_TEXT(",WRITE")+_TEXT("\")");
  775. Error(LPCTSTR(strErrMsg));
  776. }
  777. else
  778. {
  779. // create the node
  780. hresError = pcAdmCom->AddKey(hmdServicePathHandle,
  781. IADM_PBYTE LPCTSTR(a_AdmNode.GetRelPathFromInstance()));
  782. if (FAILED(hresError)) {
  783. CString strErrMsg=_TEXT("AddKey");
  784. strErrMsg += _TEXT("(\"")+a_AdmNode.GetRelPathFromInstance()+_TEXT("\")");
  785. Error(LPCTSTR(strErrMsg));
  786. }
  787. //close the service object
  788. CloseObject(hmdServicePathHandle);
  789. }
  790. #endif
  791. // This function enables to reuse open handles in order to improve performance
  792. // !!it supports only one acticve handle (otherwise the processing may fail)
  793. METADATA_HANDLE CAdmUtil::OpenObjectTo_hmd(CAdmNode & a_AdmNode, DWORD dwPermission, BOOL fCreate)
  794. {
  795. CString strPathToOpen=a_AdmNode.GetLMNodePath();
  796. if(m_hmd!=0 && strPathToOpen.CompareNoCase(m_strNodePath)==0 && m_dwPermissionOfhmd == dwPermission )
  797. { //we can reuse already opened node
  798. }
  799. else
  800. {
  801. if(m_hmd != 0)
  802. {
  803. CloseObject(m_hmd);
  804. m_hmd=0;
  805. }
  806. m_hmd = OpenObject(a_AdmNode, dwPermission, fCreate);
  807. m_dwPermissionOfhmd = dwPermission;
  808. m_strNodePath = strPathToOpen;
  809. }
  810. return m_hmd;
  811. }
  812. void CAdmUtil::CloseObject_hmd(void)
  813. {
  814. if(m_hmd != 0)
  815. {
  816. CloseObject(m_hmd);
  817. m_hmd=0;
  818. }
  819. }
  820. //*******************************************************************************
  821. void CAdmUtil::GetProperty(CAdmNode& a_AdmNode, CAdmProp& a_AdmProp)
  822. {
  823. DWORD dwRequiredDataLen=0;
  824. WORD wDataBufferSize=0;
  825. PBYTE DataBuffer=0;
  826. DWORD dwPropertyCode=a_AdmProp.GetIdentifier();
  827. if(dwPropertyCode==0) Error(_TEXT("Property name not found"));
  828. else
  829. {
  830. //MD_SET_DATA_RECORD(&a_AdmProp.mdr,
  831. // 0,
  832. // METADATA_INHERIT | METADATA_PARTIAL_PATH,
  833. // 0,
  834. // 0,
  835. // wDataBufferSize,
  836. // pbDataBuffer);
  837. //a_AdmProp.SetIdentifier(dwPropertyCode); //has to be set beforehand
  838. a_AdmProp.SetDataType(0);
  839. a_AdmProp.SetUserType(0);
  840. a_AdmProp.SetAttrib(0);
  841. METADATA_HANDLE hmd = OpenObjectTo_hmd(a_AdmNode,
  842. METADATA_PERMISSION_READ);
  843. if (SUCCEEDED(hresError))
  844. {
  845. hresError = pcAdmCom->GetData(hmd,
  846. IADM_PBYTE _TEXT(""),
  847. &a_AdmProp.mdr, &dwRequiredDataLen);
  848. if (FAILED(hresError)) {
  849. if (hresError == RETURNCODETOHRESULT(ERROR_INSUFFICIENT_BUFFER)) {
  850. /////////// delete []pbDataBuffer;
  851. pbDataBuffer=new BYTE[dwRequiredDataLen];
  852. if (pbDataBuffer==0) {
  853. hresError = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
  854. Error(_TEXT("Buffer resize failed"));
  855. }
  856. else {
  857. a_AdmProp.mdr.dwMDDataLen = dwRequiredDataLen;
  858. a_AdmProp.mdr.pbMDData = pbDataBuffer;
  859. hresError = pcAdmCom->GetData(hmd,
  860. IADM_PBYTE _TEXT(""), &a_AdmProp.mdr, &dwRequiredDataLen);
  861. if (FAILED(hresError)) Error(_TEXT("GetData"));
  862. }
  863. }
  864. else
  865. Error(_TEXT("GetData"));;
  866. }
  867. //CloseObject (hmd); we might reuse it
  868. }
  869. }
  870. }
  871. //if lplpszPropertyValue[1]==NULL it means there is only one value (it is not a multistring)
  872. void CAdmUtil::SetProperty(CAdmNode& a_AdmNode, CAdmProp& a_AdmProp)
  873. {
  874. METADATA_HANDLE hmd = OpenObjectTo_hmd(a_AdmNode,
  875. METADATA_PERMISSION_WRITE,TRUE/*create node if doesn't exist*/);
  876. if (SUCCEEDED(hresError))
  877. {
  878. SetProperty(&a_AdmProp.mdr,hmd);
  879. //CloseObject(hmd); we will reuse it
  880. }
  881. }
  882. void CAdmUtil::SetProperty(PMETADATA_RECORD a_pmdrData,METADATA_HANDLE a_hmd)
  883. {
  884. hresError = pcAdmCom->SetData(a_hmd,
  885. IADM_PBYTE _TEXT(""), a_pmdrData);
  886. if (FAILED(hresError)) Error(_TEXT("SetData"));
  887. }
  888. void CAdmUtil::SaveData(void)
  889. {
  890. if (m_hmd!=0)
  891. { //we have to close reusable handle in order to save successfully
  892. CloseObject(m_hmd);
  893. m_hmd=0;
  894. }
  895. hresError = pcAdmCom->SaveData();
  896. if (FAILED(hresError)) Error(_TEXT("SaveData"));
  897. }
  898. //****************************************************************************
  899. //DELETE PROPERTY
  900. void CAdmUtil::DeleteProperty(CAdmNode& a_AdmNode, CAdmProp& a_AdmProp)
  901. {
  902. METADATA_HANDLE hmd = OpenObjectTo_hmd(a_AdmNode,
  903. METADATA_PERMISSION_WRITE,TRUE/*create node if doesn't exist*/);
  904. if (SUCCEEDED(hresError))
  905. {
  906. DeleteProperty(&a_AdmProp.mdr,hmd);
  907. // CloseObject(hmd); we will reuse it
  908. }
  909. }
  910. void CAdmUtil::DeleteProperty(PMETADATA_RECORD a_pmdrData,METADATA_HANDLE a_hmd)
  911. {
  912. hresError = pcAdmCom->DeleteData(a_hmd,
  913. IADM_PBYTE _TEXT(""), a_pmdrData->dwMDIdentifier,ALL_METADATA);
  914. if (FAILED(hresError)) Error(_TEXT("DeleteData"));
  915. }
  916. //****************************************************************************
  917. //DELETE OBJECT
  918. void CAdmUtil::DeleteObject(CAdmNode& a_AdmNode, CAdmProp& a_AdmProp)
  919. {
  920. CAdmNode NodeToOpen = a_AdmNode.GetParentNodePath();
  921. METADATA_HANDLE hmd = OpenObjectTo_hmd(NodeToOpen,
  922. METADATA_PERMISSION_WRITE,FALSE/*create node if doesn't exist*/);
  923. if (SUCCEEDED(hresError))
  924. {
  925. CString strToDelete=a_AdmNode.GetCurrentNodeName();
  926. if(strToDelete==_TEXT(""))
  927. strToDelete=_TEXT("//"); //empty name has to be wrapped with '/'
  928. DeleteObject(hmd,strToDelete);
  929. //CloseObject(hmd); we will reuse it
  930. }
  931. }
  932. void CAdmUtil::DeleteObject(METADATA_HANDLE a_hmd, CString& a_strObjectName)
  933. {
  934. hresError = pcAdmCom->DeleteKey(a_hmd, IADM_PBYTE LPCTSTR(a_strObjectName));
  935. if (FAILED(hresError)) Error(_TEXT("DeleteKey"));
  936. }
  937. void CAdmUtil::EnumPropertiesAndPrint(CAdmNode& a_AdmNode,
  938. CAdmProp a_AdmProp, //cannot be passed by reference
  939. BYTE bRecurLevel,
  940. METADATA_HANDLE a_hmd,
  941. CString & a_strRelPath)
  942. {
  943. CAdmProp mdrData=a_AdmProp;
  944. DWORD dwRequiredDataLen=0;
  945. PBYTE DataBuffer=0;
  946. METADATA_HANDLE hmdMain;
  947. if(a_hmd==0) //if handle was not passed then open one
  948. {
  949. hmdMain = OpenObjectTo_hmd(a_AdmNode, METADATA_PERMISSION_READ);
  950. if (FAILED(hresError))
  951. return;
  952. }
  953. else
  954. hmdMain = a_hmd;
  955. for (int j=0;;j++) { //cycle for properties
  956. MD_SET_DATA_RECORD(&mdrData.mdr,
  957. 0,
  958. a_AdmProp.mdr.dwMDAttributes,
  959. a_AdmProp.mdr.dwMDUserType,
  960. a_AdmProp.mdr.dwMDDataType,
  961. dwRequiredDataLen,
  962. pbDataBuffer);
  963. hresError = pcAdmCom->EnumData(hmdMain,
  964. IADM_PBYTE LPCTSTR(a_strRelPath), &mdrData.mdr,j, &dwRequiredDataLen);
  965. if (FAILED(hresError))
  966. {
  967. if(hresError == RETURNCODETOHRESULT(ERROR_NO_MORE_ITEMS))
  968. {
  969. hresError=0; //NO MORE ITEMS IS NOT ERROR FOR US
  970. break; //end of items
  971. }
  972. else if (hresError == RETURNCODETOHRESULT(ERROR_INSUFFICIENT_BUFFER))
  973. {
  974. delete pbDataBuffer;
  975. pbDataBuffer=new BYTE[dwRequiredDataLen];
  976. if (pbDataBuffer==0)
  977. {
  978. hresError = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
  979. Error(_TEXT("Buffer resize failed"));
  980. }
  981. else
  982. {
  983. mdrData.mdr.dwMDDataLen = dwRequiredDataLen;
  984. mdrData.mdr.pbMDData = pbDataBuffer;
  985. hresError = pcAdmCom->EnumData(hmdMain,
  986. IADM_PBYTE LPCTSTR(a_strRelPath), &mdrData.mdr,j, &dwRequiredDataLen);
  987. if (FAILED(hresError)) Error(_TEXT("GetData"));
  988. }
  989. }
  990. else
  991. Error(_TEXT("EnumData"));
  992. }
  993. //else
  994. // Error(_TEXT("EnumData"));
  995. if(SUCCEEDED(hresError)) //we enumerated successfully, let's print
  996. {
  997. nest_print(bRecurLevel+1);
  998. mdrData.PrintProperty();
  999. }
  1000. else
  1001. {
  1002. break;
  1003. }
  1004. } //end for j - cycle for properties
  1005. //if(a_hmd==0)
  1006. // CloseObject(hmdMain); we will reuse it //close only if we opened at the beginning
  1007. }
  1008. void CAdmUtil::EnumAndPrint(CAdmNode& a_AdmNode,
  1009. CAdmProp& a_AdmProp,
  1010. BOOL a_fRecursive,
  1011. BYTE a_bRecurLevel,
  1012. METADATA_HANDLE a_hmd,
  1013. CString& a_strRelPath)
  1014. {
  1015. _TCHAR NameBuf[METADATA_MAX_NAME_LEN];
  1016. METADATA_HANDLE hmdMain;
  1017. if(a_hmd==0) //if handle was not passed then open one
  1018. {
  1019. hmdMain = OpenObjectTo_hmd(a_AdmNode, METADATA_PERMISSION_READ);
  1020. if (FAILED(hresError))
  1021. return;
  1022. }
  1023. else
  1024. hmdMain = a_hmd;
  1025. //printf("[RELATIVE PATH : \"%s\"]\n",LPCTSTR(a_strRelPath));
  1026. //print the properties of the node
  1027. EnumPropertiesAndPrint(a_AdmNode,a_AdmProp,a_bRecurLevel,hmdMain,a_strRelPath);
  1028. for (int i=0; ;i++) { //cycle for subnodes
  1029. hresError = pcAdmCom->EnumKeys(hmdMain,
  1030. IADM_PBYTE LPCTSTR(a_strRelPath), IADM_PBYTE NameBuf, i);
  1031. if(FAILED(hresError)) {
  1032. if(hresError == RETURNCODETOHRESULT(ERROR_NO_MORE_ITEMS)) {
  1033. hresError=0; //NO MORE ITEMS IS NOT ERROR FOR US
  1034. break; //end of cycle
  1035. }
  1036. else
  1037. {
  1038. Error(_TEXT("EnumKeys"));
  1039. break;
  1040. }
  1041. }
  1042. else {
  1043. //process and print node info
  1044. CString strNewRelPath( a_strRelPath );
  1045. if(NameBuf[0]==0) //empty name
  1046. strNewRelPath+=_TEXT("//"); //add two slashes -> this is required by metabase
  1047. else
  1048. {
  1049. UINT nLen;
  1050. //if(strNewRelPath.GetLength()>=1 && strNewRelPath.Right(1)==_TEXT("/")) {
  1051. if( (nLen=strNewRelPath.GetLength())>=1 && (strNewRelPath.GetAt(nLen-1)=='/') ) {
  1052. }
  1053. else {
  1054. strNewRelPath+=_TEXT("/"); //add only if it is not at the end of string.
  1055. }
  1056. strNewRelPath+=NameBuf;
  1057. }
  1058. CString strStringToPrint( a_AdmNode.GetNodePath() );
  1059. UINT nLen = strStringToPrint.GetLength();
  1060. //if (strStringToPrint.Right(2)==_TEXT("//"))
  1061. if ((nLen > 2) && strStringToPrint.GetAt(nLen-1)=='/'
  1062. && strStringToPrint.GetAt(nLen-2)=='/' )
  1063. {
  1064. strStringToPrint += strNewRelPath.Mid(1); //strip first '/'
  1065. }
  1066. else
  1067. {
  1068. strStringToPrint += strNewRelPath;
  1069. }
  1070. LPCTSTR lpszStr=LPCTSTR(strStringToPrint);
  1071. this->Print(_TEXT("[%s]\n"),lpszStr );
  1072. if(a_fRecursive)
  1073. {
  1074. EnumAndPrint(a_AdmNode,a_AdmProp ,a_fRecursive, a_bRecurLevel+1, hmdMain,strNewRelPath);
  1075. }
  1076. else
  1077. { //no recursion
  1078. }
  1079. }
  1080. } //end for i - cycle for nodes
  1081. //if(a_hmd==0)
  1082. // CloseObject(hmdMain); //we will reuse it //close only if we opened at the beginning
  1083. }
  1084. //****************************************************************
  1085. // the following function is somehow complicated because
  1086. // metadata copy function doesn't support copying of one object to another place with different name
  1087. // e.g. ComAdmCopyKey will copy /W3SVC/1//scripts/oldscripts1 /W3SVC/1//oldscripts2
  1088. // will create /W3SVC/1//oldscripts2/oldscripts1
  1089. //
  1090. void CAdmUtil::CopyObject(CAdmNode& a_AdmNode,
  1091. CAdmNode& a_AdmNodeDst)
  1092. {
  1093. CString strSrcPath=a_AdmNode.GetNodePath();
  1094. CString strDstPath=a_AdmNodeDst.GetNodePath();
  1095. CString strCommonPath; //=_TEXT("");
  1096. CString strRelSrcPath=strSrcPath; //relative to common path
  1097. CString strRelDstPath=strDstPath; //relative to common path
  1098. //we cannot open Source Path for reading because if will diable wrining to all parent nodes
  1099. //e.g. copy /W3SVC/1//scripts/oldscripts /W3SVC/1//oldscripts would fail
  1100. //It is necessary to find common partial path and open metabase object for that common partial path for READ/WRITE
  1101. //!!!!!!!!!!!!!!!!! assume that paths are not case sensitive
  1102. int MinLength=strSrcPath.GetLength();
  1103. int i;
  1104. //find shorter from strings
  1105. if(strDstPath.GetLength() < MinLength)
  1106. MinLength=strDstPath.GetLength();
  1107. for(i=0; i<MinLength; i++)
  1108. {
  1109. if(strSrcPath.GetAt(i)!=strDstPath.GetAt(i) )
  1110. // common path cannot be any longer;
  1111. break;
  1112. }
  1113. // now find the previous '/' and all before '/' is the common path
  1114. for(i=i-1; i>=0;i--)
  1115. {
  1116. if(strSrcPath.GetAt(i)==_T('/'))
  1117. {
  1118. strCommonPath=strSrcPath.Left(i+1);//take the trailing '/' with you
  1119. strRelSrcPath=strSrcPath.Mid(i+1);
  1120. strRelDstPath=strDstPath.Mid(i+1);
  1121. break;
  1122. }
  1123. }
  1124. _TCHAR NameBuf[METADATA_MAX_NAME_LEN];
  1125. METADATA_HANDLE hmdCommon=0;
  1126. CAdmNode CommonNode;
  1127. CommonNode.SetPath(strCommonPath);
  1128. hmdCommon = OpenObjectTo_hmd(CommonNode, METADATA_PERMISSION_READ+METADATA_PERMISSION_WRITE);
  1129. if (FAILED(hresError))
  1130. return;
  1131. // Altered by Adam Stone on 30-Jan-97 The following code was changed to comply with
  1132. // the changes to the metabase ComMDCopyKey function.
  1133. // Copy the metadata to the destination
  1134. hresError = pcAdmCom->CopyKey (hmdCommon,
  1135. IADM_PBYTE LPCTSTR(strRelSrcPath),
  1136. hmdCommon,
  1137. IADM_PBYTE LPCTSTR(strRelDstPath),
  1138. FALSE, // Do NOT overwrite
  1139. TRUE); // Copy do NOT move
  1140. if (FAILED(hresError)) // if the node already exists, it is error
  1141. {
  1142. CString strErrMsg=_TEXT("CopyKey");
  1143. strErrMsg += _TEXT("(\"")+a_AdmNodeDst.GetRelPathFromInstance()+_TEXT("\")");
  1144. Error(LPCTSTR(strErrMsg));
  1145. }
  1146. // All of the commented out code has become unneccessary as of 30-Jan-97 because of a change
  1147. // in the metabase. ComMDCopyKey now copies to the destination, overwriting if
  1148. // requested. It used to copy to a child of the destination object.
  1149. /* // create the node
  1150. * hresError = pcAdmCom->AddKey(hmdCommon,
  1151. * IADM_PBYTE LPCTSTR(strRelDstPath));
  1152. * if (FAILED(hresError)) { //if the node exists, it is error)
  1153. * CString strErrMsg=_TEXT("AddKey");
  1154. * strErrMsg += _TEXT("(\"")+a_AdmNodeDst.GetRelPathFromInstance()+_TEXT("\")");
  1155. * Error(LPCTSTR(strErrMsg));
  1156. * }
  1157. * else //no error when creating new node
  1158. * {
  1159. * for (i=0; ;i++) { //cycle for subnodes
  1160. * hresError = pcAdmCom->EnumKeys(hmdCommon,
  1161. * IADM_PBYTE LPCTSTR(strRelSrcPath), (PBYTE)NameBuf, i);
  1162. * if(FAILED(hresError)) {
  1163. * if(hresError == RETURNCODETOHRESULT(ERROR_NO_MORE_ITEMS)) {
  1164. * hresError=0; //this is not an error
  1165. * break; //end of cycle
  1166. * }
  1167. * else
  1168. * {
  1169. * Error(_TEXT("EnumKeys"));
  1170. * break;
  1171. * }
  1172. *
  1173. * }
  1174. * else {
  1175. *
  1176. * //process and copy node child node
  1177. *
  1178. * CString strNewRelSrcPath=strRelSrcPath;
  1179. * if(NameBuf[0]==0) //empty name
  1180. * strNewRelSrcPath+=_TEXT("//"); //add two slashes -> this is required by metabase
  1181. * else
  1182. * { if(strNewRelSrcPath.GetLength()>=1 && strNewRelSrcPath.Right(1)==_TEXT("/")) {
  1183. * }
  1184. * else {
  1185. * strNewRelSrcPath+=_TEXT("/"); //add only if it is not at the end of string.
  1186. * }
  1187. * strNewRelSrcPath+=NameBuf;
  1188. * }
  1189. * hresError = pcAdmCom->CopyKey(
  1190. * hmdCommon, (PBYTE) LPCTSTR(strNewRelSrcPath),
  1191. * hmdCommon, (PBYTE) LPCTSTR(strRelDstPath),TRUE,TRUE);
  1192. * if(FAILED(hresError)) {
  1193. * Error(_TEXT("CopyKey"));
  1194. * }
  1195. *
  1196. *
  1197. * }
  1198. * } //end for i - cycle for nodes
  1199. *
  1200. *
  1201. * //WE COPIED ALL NODES, COPY PARAMETERS NOW
  1202. * CAdmProp mdrData;
  1203. * DWORD dwRequiredDataLen=0;
  1204. * PBYTE DataBuffer=0;
  1205. *
  1206. *
  1207. *
  1208. * for (int j=0;;j++) { //cycle for properties
  1209. * MD_SET_DATA_RECORD(&mdrData.mdr,
  1210. * 0,
  1211. * 0,
  1212. * 0,
  1213. * 0,
  1214. * dwRequiredDataLen,
  1215. * pbDataBuffer);
  1216. *
  1217. * hresError = pcAdmCom->EnumData(hmdCommon,
  1218. * (PBYTE) LPCTSTR(strRelSrcPath)
  1219. * , &mdrData.mdr,j, &dwRequiredDataLen);
  1220. * if (FAILED(hresError))
  1221. * {
  1222. * if(hresError == RETURNCODETOHRESULT(ERROR_NO_MORE_ITEMS))
  1223. * {
  1224. * hresError=0; //NO MORE ITEMS IS NOT ERROR FOR US
  1225. * break; //end of items
  1226. * }
  1227. * else if (hresError == RETURNCODETOHRESULT(ERROR_INSUFFICIENT_BUFFER))
  1228. * {
  1229. /////////// delete pbDataBuffer;
  1230. * pbDataBuffer=new BYTE[dwRequiredDataLen];
  1231. * if (pbDataBuffer==0)
  1232. * {
  1233. * hresError = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
  1234. * Error(_TEXT("Buffer resize failed"));
  1235. * }
  1236. * else
  1237. * {
  1238. * mdrData.mdr.dwMDDataLen = dwRequiredDataLen;
  1239. * mdrData.mdr.pbMDData = pbDataBuffer;
  1240. * hresError = pcAdmCom->EnumData(hmdCommon,
  1241. * (PBYTE) LPCTSTR(strRelSrcPath)
  1242. * , &mdrData.mdr,j, &dwRequiredDataLen);
  1243. * if (FAILED(hresError)) Error(_TEXT("GetData"));
  1244. * }
  1245. * }
  1246. * else
  1247. * Error(_TEXT("EnumData"));
  1248. * }
  1249. * else
  1250. * Error(_TEXT("EnumData"));
  1251. *
  1252. * if(SUCCEEDED(hresError)) //we enumerated successfully, let's print
  1253. * {
  1254. * hresError = pcAdmCom->SetData(hmdCommon, (PBYTE) LPCTSTR(strRelDstPath),&mdrData.mdr);
  1255. * if (FAILED(hresError)) Error(_TEXT("SetData"));
  1256. * }
  1257. * else
  1258. * {
  1259. * break;
  1260. * }
  1261. * } //end for j - cycle for properties
  1262. * }
  1263. */
  1264. //CloseObject(hmdCommon); //we will reuse handle //close only if we opened at the beginning
  1265. }
  1266. void CAdmUtil::RenameObject(CAdmNode& a_AdmNode,
  1267. CAdmNode& a_AdmNodeDst)
  1268. {
  1269. CString strSrcPath=a_AdmNode.GetNodePath();
  1270. CString strDstPath=a_AdmNodeDst.GetNodePath();
  1271. CString strCommonPath=_TEXT("");
  1272. CString strRelSrcPath=strSrcPath; //relative to common path
  1273. CString strRelDstPath=strDstPath; //relative to common path
  1274. //we cannot open Source Path for reading because if will diable wrining to all parent nodes
  1275. //e.g. copy /W3SVC/1//scripts/oldscripts /W3SVC/1//oldscripts would fail
  1276. //It is necessary to find common partial path and open metabase object for that common partial path for READ/WRITE
  1277. //!!!!!!!!!!!!!!!!! assume that paths are not case sensitive
  1278. int MinLength=strSrcPath.GetLength();
  1279. int i;
  1280. //find shorter from strings
  1281. if(strDstPath.GetLength() < MinLength)
  1282. MinLength=strDstPath.GetLength();
  1283. for(i=0; i<MinLength; i++)
  1284. {
  1285. if(strSrcPath.GetAt(i)!=strDstPath.GetAt(i) )
  1286. // common path cannot be any longer;
  1287. break;
  1288. }
  1289. // now find the previous '/' and all before '/' is the common path
  1290. for(i=i-1; i>=0;i--)
  1291. {
  1292. if(strSrcPath.GetAt(i)==_T('/'))
  1293. {
  1294. strCommonPath=strSrcPath.Left(i+1);//take the trailing '/' with you
  1295. strRelSrcPath=strSrcPath.Mid(i); // keep the trailing '/' in case it's "//"
  1296. strRelDstPath=strDstPath.Mid(i+1);
  1297. break;
  1298. }
  1299. }
  1300. _TCHAR NameBuf[METADATA_MAX_NAME_LEN];
  1301. METADATA_HANDLE hmdCommon=0;
  1302. CAdmNode CommonNode;
  1303. CommonNode.SetPath(strCommonPath);
  1304. hmdCommon = OpenObjectTo_hmd(CommonNode, METADATA_PERMISSION_READ+METADATA_PERMISSION_WRITE);
  1305. if (FAILED(hresError))
  1306. return;
  1307. hresError = pcAdmCom->RenameKey (hmdCommon,
  1308. IADM_PBYTE LPCTSTR(strRelSrcPath),
  1309. IADM_PBYTE LPCTSTR(strRelDstPath)
  1310. );
  1311. if (FAILED(hresError)) // if the node already exists, it is error
  1312. {
  1313. CString strErrMsg=_TEXT("RenameKey");
  1314. strErrMsg += _TEXT("(\"")+a_AdmNodeDst.GetRelPathFromInstance()+_TEXT("\")");
  1315. Error(LPCTSTR(strErrMsg));
  1316. }
  1317. //CloseObject(hmdCommon); //we will reuse it//close only if we opened at the beginning
  1318. }
  1319. //**********************************************************************
  1320. //IMPLEMENTATION of AdmUtil
  1321. //**********************************************************************
  1322. void CAdmUtil::Run(CString& strCommand, CAdmNode& a_AdmNode, CAdmProp& a_AdmProp, CAdmNode& a_AdmDstNode,
  1323. LPCTSTR *a_lplpszPropValue,
  1324. DWORD *a_lpdwPropValueLength,
  1325. WORD wPropValueCount)
  1326. {
  1327. DWORD dwCommandCode=0;
  1328. dwCommandCode = tCommandNameTable::MapNameToCode(strCommand);
  1329. switch(dwCommandCode)
  1330. {
  1331. case CMD_SAVE:
  1332. SaveData();
  1333. if (FAILED(hresError)) {}
  1334. else{
  1335. Print(_TEXT("saved\n"));
  1336. }
  1337. break;
  1338. case CMD_CREATE:
  1339. {
  1340. if (a_AdmNode.GetProperty()!=_TEXT("")) //property name cannot be used
  1341. Error(_TEXT("property name for CREATE not supported"));
  1342. // else if (a_AdmNode.GetService()==_TEXT("")) //property name cannot be used
  1343. // Error(_TEXT("service name for CREATE is missing"));
  1344. else
  1345. {
  1346. CreateObject(a_AdmNode);
  1347. if( SUCCEEDED(QueryLastHresError()))
  1348. {
  1349. // SaveData(); //end of transaction
  1350. if( SUCCEEDED(QueryLastHresError()))
  1351. {
  1352. Print(_TEXT("created \"%s\"\n"), LPCTSTR(a_AdmNode.GetNodePath()));
  1353. }
  1354. }
  1355. }
  1356. }
  1357. break;
  1358. case CMD_SET:
  1359. {
  1360. CAdmProp AdmPropToGet;
  1361. AdmPropToGet = a_AdmProp;
  1362. AdmPropToGet.SetAttrib(0);
  1363. AdmPropToGet.SetUserType(0);
  1364. AdmPropToGet.SetDataType(0);
  1365. DisablePrint(); //do not print any error message
  1366. GetProperty(a_AdmNode, AdmPropToGet);
  1367. EnablePrint(); //continue printing error messages
  1368. //*************************SETTING ATTRIB, DATATYPE, USERTYPE
  1369. // if the parameter exists in the metabase, then existing ATTRIB, DATATYPE, USERTYPE
  1370. // will be used , but this can be overwritten from a_AdmProp
  1371. // if the parameter doesn't exists in the metabase, then default ATTRIB, DATATYPE, USERTYPE
  1372. // (see tables.cpp) will be used , but this can be overwritten from a_AdmProp
  1373. if(FAILED(QueryLastHresError()))
  1374. { //store the value to be set into a_AdmProp
  1375. //FIND DEFAULT SETTINGS
  1376. DWORD dwPropCode=a_AdmProp.GetIdentifier();
  1377. tPropertyNameTable * PropNameTableRecord = tPropertyNameTable::FindRecord(dwPropCode);
  1378. if (PropNameTableRecord!=NULL)
  1379. {
  1380. AdmPropToGet.SetIdentifier(PropNameTableRecord->dwCode);
  1381. AdmPropToGet.SetAttrib(PropNameTableRecord->dwDefAttributes) ;
  1382. AdmPropToGet.SetUserType(PropNameTableRecord->dwDefUserType);
  1383. AdmPropToGet.SetDataType(PropNameTableRecord->dwDefDataType);
  1384. }
  1385. }
  1386. else
  1387. { //reuse the existing settings
  1388. if( a_AdmProp.GetDataType()!=0 &&(a_AdmProp.GetDataType()!= AdmPropToGet.GetDataType()))
  1389. {
  1390. Error(_TEXT("Cannot redefine data type from %s to %s"),
  1391. tDataTypeNameTable::MapCodeToName(AdmPropToGet.GetDataType()),
  1392. tDataTypeNameTable::MapCodeToName(a_AdmProp.GetDataType()));
  1393. break;
  1394. }
  1395. }
  1396. // use settings passed to the function if set
  1397. if(!a_AdmProp.IsSetDataType())
  1398. a_AdmProp.SetDataType(AdmPropToGet.GetDataType()); //reuse existing data type
  1399. if(!a_AdmProp.IsSetUserType())
  1400. a_AdmProp.SetUserType(AdmPropToGet.GetUserType()); //reuse existing user type
  1401. if(!a_AdmProp.IsSetAttrib())
  1402. a_AdmProp.SetAttrib(AdmPropToGet.GetAttrib()); //reuse exixting attrib
  1403. if(a_AdmProp.SetValueByDataType( (LPCTSTR *)a_lplpszPropValue, a_lpdwPropValueLength, wPropValueCount)==0)
  1404. Error(_TEXT("SetValueByDataType failed"));
  1405. else
  1406. {
  1407. // if (a_AdmNode.GetService()==_TEXT("")) //property name cannot be used
  1408. // Error(_TEXT("service name for SET is missing"));
  1409. // else
  1410. if (a_AdmNode.GetProperty()!=_TEXT(""))
  1411. {
  1412. SetProperty(a_AdmNode, a_AdmProp);
  1413. if( SUCCEEDED(QueryLastHresError()))
  1414. {
  1415. //SaveData(); //end of transaction
  1416. if( SUCCEEDED(QueryLastHresError()))
  1417. {
  1418. GetProperty(a_AdmNode, a_AdmProp);
  1419. if(SUCCEEDED(QueryLastHresError()))
  1420. a_AdmProp.PrintProperty();
  1421. }
  1422. }
  1423. }else
  1424. Error(_TEXT("property name missing for SET command"));
  1425. }
  1426. break;
  1427. }
  1428. case CMD_DELETE:
  1429. //if (a_AdmNode.GetService()==_TEXT("")) //property name cannot be used
  1430. // Error(_TEXT("service name for DELETE is missing"));
  1431. if (IsServiceName(a_AdmNode.GetService()) && a_AdmNode.GetInstance()==_TEXT("") && a_AdmNode.GetIPath()==_TEXT("") && a_AdmNode.GetProperty()==_TEXT(""))
  1432. Error(_TEXT("cannot delete service"));
  1433. else if (a_AdmNode.GetInstance()==_TEXT("1") && a_AdmNode.GetIPath()==_TEXT("") && a_AdmNode.GetProperty()==_TEXT("")) //property name cannot be used
  1434. Error(_TEXT("cannot delete 1. instance"));
  1435. else if (a_AdmNode.GetProperty()!=_TEXT(""))
  1436. {
  1437. DeleteProperty(a_AdmNode, a_AdmProp);
  1438. }
  1439. else
  1440. {
  1441. DeleteObject(a_AdmNode, a_AdmProp);
  1442. }
  1443. //if( SUCCEEDED(QueryLastHresError()))
  1444. //{
  1445. // GetProperty(a_AdmNode, a_AdmProp);
  1446. // if(SUCCEEDED(QueryLastHresError()))
  1447. // a_AdmProp.PrintProperty();
  1448. //}
  1449. if(SUCCEEDED(QueryLastHresError()))
  1450. {
  1451. //SaveData(); //end of transaction
  1452. if( SUCCEEDED(QueryLastHresError()))
  1453. {
  1454. Print(_TEXT("deleted \"%s"), LPCTSTR(a_AdmNode.GetNodePath()));
  1455. if(a_AdmNode.GetProperty()!=_TEXT(""))
  1456. Print(_TEXT("%s"),LPCTSTR(((a_AdmNode.GetNodePath().Right(1)==_TEXT("/"))?_TEXT(""):_TEXT("/"))+
  1457. a_AdmNode.GetProperty()));
  1458. Print(_TEXT("\"\n"));
  1459. }
  1460. }
  1461. break;
  1462. case CMD_GET:
  1463. // if (a_AdmNode.GetService()==_TEXT("")) //property name cannot be used
  1464. // Error(_TEXT("service name for GET is missing"));
  1465. // else
  1466. if (a_AdmNode.GetProperty()!=_TEXT(""))
  1467. {
  1468. GetProperty(a_AdmNode, a_AdmProp);
  1469. if(SUCCEEDED(QueryLastHresError()))
  1470. a_AdmProp.PrintProperty();
  1471. }
  1472. else
  1473. {
  1474. EnumPropertiesAndPrint(a_AdmNode, a_AdmProp);
  1475. }
  1476. break;
  1477. case CMD_COPY:
  1478. if(a_AdmDstNode.GetNodePath()==_TEXT(""))
  1479. Error(_TEXT("destination path is missing"));
  1480. else if(a_AdmNode.GetProperty()!=_TEXT("") || a_AdmDstNode.GetProperty()!=_TEXT(""))
  1481. Error(_TEXT("copying of properties (parameters) not supported\n"));
  1482. //else if (a_AdmNode.GetService()==_TEXT("")) //property name cannot be used
  1483. // Error(_TEXT("service name in source path for COPY is missing"));
  1484. //else if (a_AdmDstNode.GetService()==_TEXT("")) //property name cannot be used
  1485. // Error(_TEXT("service name for destination path COPY is missing"));
  1486. //else if (a_AdmNode.GetInstance()==_TEXT("")) //property name cannot be used
  1487. // Error(_TEXT("instance number in source path for COPY is missing"));
  1488. //else if (a_AdmDstNode.GetInstance()==_TEXT("")) //property name cannot be used
  1489. // Error(_TEXT("instance number in destination path for COPY is missing"));
  1490. else
  1491. {
  1492. CopyObject(a_AdmNode,a_AdmDstNode);
  1493. if(SUCCEEDED(QueryLastHresError()))
  1494. {
  1495. //SaveData(); //end of transaction
  1496. if( SUCCEEDED(QueryLastHresError()))
  1497. {
  1498. Print(_TEXT("copied from %s to %s\n"), LPCTSTR(a_AdmNode.GetNodePath()),LPCTSTR(a_AdmDstNode.GetNodePath()));
  1499. }
  1500. }
  1501. break;
  1502. }
  1503. break;
  1504. case CMD_RENAME:
  1505. if(a_AdmDstNode.GetNodePath()==_TEXT(""))
  1506. Error(_TEXT("destination path is missing"));
  1507. else if(a_AdmNode.GetProperty()!=_TEXT("") || a_AdmDstNode.GetProperty()!=_TEXT(""))
  1508. Error(_TEXT("renaming of properties (parameters) not supported"));
  1509. //else if (a_AdmNode.GetService()==_TEXT("")) //property name cannot be used
  1510. // Error(_TEXT("service name in source path for RENAME is missing"));
  1511. //else if (a_AdmDstNode.GetService()==_TEXT(""))
  1512. // Error(_TEXT("service name for destination path RENAME is missing"));
  1513. //else if (a_AdmNode.GetInstance()==_TEXT(""))
  1514. // Error(_TEXT("instance number in source path for RENAME is missing"));
  1515. //else if (a_AdmDstNode.GetInstance()==_TEXT(""))
  1516. // Error(_TEXT("instance number in destination path for RENAME is missing"));
  1517. else if (a_AdmNode.GetInstance()==_TEXT("1") && a_AdmNode.GetIPath()==_TEXT(""))
  1518. Error(_TEXT("cannot rename 1. instance"));
  1519. else if (a_AdmNode.GetRelPathFromService().CompareNoCase(a_AdmDstNode.GetRelPathFromService())==0)
  1520. Error(_TEXT("cannot rename to itself"));
  1521. else
  1522. { //check if one of the paths is not the child of the other one
  1523. CString str1=a_AdmNode.GetRelPathFromService();
  1524. CString str2=a_AdmDstNode.GetRelPathFromService();
  1525. CString strCommonPath=FindCommonPath(str1,str2);
  1526. if(strCommonPath.CompareNoCase(str1)==0 ||
  1527. strCommonPath.CompareNoCase(str1)==0)
  1528. Error(_TEXT("cannot rename - one path is the child of the other"));
  1529. else
  1530. { //O.K.
  1531. //CopyObject(a_AdmNode,a_AdmDstNode);
  1532. //if(SUCCEEDED(QueryLastHresError()))
  1533. //{
  1534. // DeleteObject(a_AdmNode,a_AdmProp);
  1535. // if(SUCCEEDED(QueryLastHresError()))
  1536. // {
  1537. // // SaveData(); //end of transaction
  1538. // if( SUCCEEDED(QueryLastHresError()))
  1539. // {
  1540. // Print("renamed from %s to %s\n", LPCTSTR(a_AdmNode.GetNodePath()),LPCTSTR(a_AdmDstNode.GetNodePath()));
  1541. // }
  1542. // }
  1543. // }
  1544. RenameObject(a_AdmNode,a_AdmDstNode);
  1545. if(SUCCEEDED(QueryLastHresError()))
  1546. {
  1547. // SaveData(); //end of transaction
  1548. if( SUCCEEDED(QueryLastHresError()))
  1549. {
  1550. Print(_TEXT("renamed from %s to %s\n"), LPCTSTR(a_AdmNode.GetNodePath()),LPCTSTR(a_AdmDstNode.GetNodePath()));
  1551. }
  1552. }
  1553. }
  1554. }
  1555. break;
  1556. case CMD_ENUM:
  1557. EnumAndPrint(a_AdmNode, a_AdmProp, FALSE/*no recursion*/);
  1558. break;
  1559. case CMD_ENUM_ALL:
  1560. EnumAndPrint(a_AdmNode, a_AdmProp,TRUE/*no recursion*/);
  1561. break;
  1562. case CMD_APPCREATEINPROC:
  1563. AppCreateInProc(LPCTSTR(a_AdmNode.GetLMNodePath()),a_AdmNode.GetComputer());
  1564. break;
  1565. case CMD_APPDELETE:
  1566. AppDelete(LPCTSTR(a_AdmNode.GetLMNodePath()),a_AdmNode.GetComputer());
  1567. break;
  1568. case CMD_APPRENAME:
  1569. AppRename(a_AdmNode,a_AdmDstNode,a_AdmNode.GetComputer());
  1570. break;
  1571. case CMD_APPCREATEOUTPROC:
  1572. AppCreateOutProc(LPCTSTR(a_AdmNode.GetLMNodePath()),a_AdmNode.GetComputer());
  1573. break;
  1574. case CMD_APPGETSTATUS:
  1575. AppGetStatus(LPCTSTR(a_AdmNode.GetLMNodePath()),a_AdmNode.GetComputer());
  1576. break;
  1577. case CMD_APPUNLOAD:
  1578. AppUnLoad(LPCTSTR(a_AdmNode.GetLMNodePath()),a_AdmNode.GetComputer());
  1579. break;
  1580. default:
  1581. Print(_TEXT("Command not recognized: %s\n"),strCommand);
  1582. hresError=RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
  1583. return ;
  1584. }
  1585. return;
  1586. }
  1587. //if hresError is 0, we will set it to invalid parameter
  1588. void CAdmUtil::Error(const _TCHAR * format,...)
  1589. {
  1590. _TCHAR buffer[2000];
  1591. va_list marker;
  1592. va_start( marker, format ); /* Initialize variable arguments. */
  1593. int x=_vstprintf(buffer, format, marker);
  1594. va_end( marker ); /* Reset variable arguments. */
  1595. if(hresError==0)
  1596. {
  1597. if(fPrint)
  1598. {
  1599. _ftprintf(stderr,_TEXT("Error: %s\n"),buffer);
  1600. }
  1601. hresError=RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER); //little trick
  1602. }
  1603. else
  1604. {
  1605. if(fPrint)
  1606. {
  1607. _ftprintf(stderr,_TEXT("Error: %s - HRES(0x%x) %s\n"), buffer, hresError/*, ConvertHresToDword(hresError),ConvertHresToDword(hresError)*/,ConvertReturnCodeToString(ConvertHresToDword(hresError)));
  1608. if(getenv("MDUTIL_ASCENT_LOG")!=NULL)
  1609. {
  1610. //we got to do some ascent logging
  1611. FILE *fpAscent;
  1612. fpAscent=fopen("Ascent.log","a");
  1613. if (fpAscent)
  1614. {
  1615. //new variation description
  1616. fprintf(fpAscent,"Variation1: METADATA ACCESS (by mdutil.exe)\n");
  1617. fprintf(fpAscent,"Explain: READ OR WRITE OPERATION TO METADATA \n");
  1618. //variation summary
  1619. fprintf(fpAscent,"Attempted: 1 \n");
  1620. fprintf(fpAscent,"Passed: 0 \n");
  1621. fprintf(fpAscent,"Failed: 1 \n");
  1622. _ftprintf(fpAscent,_TEXT("Error: Operation failed with HRES(0x%x)\n"), hresError);
  1623. fclose(fpAscent);
  1624. }
  1625. }
  1626. }
  1627. }
  1628. if(fPrint)
  1629. {
  1630. if(getenv("MDUTIL_BLOCK_ON_ERROR")!=NULL && hresError!=0x80070003) //path not found
  1631. {
  1632. _ftprintf(stdout,_TEXT("\nHit SPACE to continue or Ctrl-C to abort.\n"));
  1633. while(1)
  1634. {
  1635. while(!_kbhit())
  1636. {
  1637. ;
  1638. }
  1639. if(_getch()==' ')
  1640. {
  1641. _ftprintf(stdout,_TEXT("Continuing...\n"));
  1642. break;
  1643. }
  1644. }
  1645. }
  1646. }
  1647. }
  1648. void CAdmUtil::Print(const _TCHAR * format,...)
  1649. {
  1650. va_list marker;
  1651. va_start( marker, format ); /* Initialize variable arguments. */
  1652. if(fPrint)
  1653. _vtprintf(format, marker);
  1654. va_end( marker ); /* Reset variable arguments. */
  1655. }
  1656. LPTSTR ConvertReturnCodeToString(DWORD ReturnCode)
  1657. {
  1658. LPTSTR RetCode = NULL;
  1659. switch (ReturnCode) {
  1660. case ERROR_SUCCESS:
  1661. RetCode = _TEXT("ERROR_SUCCESS");
  1662. break;
  1663. case ERROR_PATH_NOT_FOUND:
  1664. RetCode = _TEXT("ERROR_PATH_NOT_FOUND");
  1665. break;
  1666. case ERROR_INVALID_HANDLE:
  1667. RetCode = _TEXT("ERROR_INVALID_HANDLE");
  1668. break;
  1669. case ERROR_INVALID_DATA:
  1670. RetCode =_TEXT("ERROR_INVALID_DATA");
  1671. break;
  1672. case ERROR_INVALID_PARAMETER:
  1673. RetCode =_TEXT("ERROR_INVALID_PARAMETER");
  1674. break;
  1675. case ERROR_NOT_SUPPORTED:
  1676. RetCode =_TEXT("ERROR_NOT_SUPPORTED");
  1677. break;
  1678. case ERROR_ACCESS_DENIED:
  1679. RetCode =_TEXT("ERROR_ACCESS_DENIED");
  1680. break;
  1681. case ERROR_NOT_ENOUGH_MEMORY:
  1682. RetCode =_TEXT("ERROR_NOT_ENOUGH_MEMORY");
  1683. break;
  1684. case ERROR_FILE_NOT_FOUND:
  1685. RetCode =_TEXT("ERROR_FILE_NOT_FOUND");
  1686. break;
  1687. case ERROR_DUP_NAME:
  1688. RetCode =_TEXT("ERROR_DUP_NAME");
  1689. break;
  1690. case ERROR_PATH_BUSY:
  1691. RetCode =_TEXT("ERROR_PATH_BUSY");
  1692. break;
  1693. case ERROR_NO_MORE_ITEMS:
  1694. RetCode =_TEXT("ERROR_NO_MORE_ITEMS");
  1695. break;
  1696. case ERROR_INSUFFICIENT_BUFFER:
  1697. RetCode =_TEXT("ERROR_INSUFFICIENT_BUFFER");
  1698. break;
  1699. case ERROR_PROC_NOT_FOUND:
  1700. RetCode =_TEXT("ERROR_PROC_NOT_FOUND");
  1701. break;
  1702. case ERROR_INTERNAL_ERROR:
  1703. RetCode =_TEXT("ERROR_INTERNAL_ERROR");
  1704. break;
  1705. case MD_ERROR_NOT_INITIALIZED:
  1706. RetCode =_TEXT("MD_ERROR_NOT_INITIALIZED");
  1707. break;
  1708. case MD_ERROR_DATA_NOT_FOUND:
  1709. RetCode =_TEXT("MD_ERROR_DATA_NOT_FOUND");
  1710. break;
  1711. case ERROR_ALREADY_EXISTS:
  1712. RetCode =_TEXT("ERROR_ALREADY_EXISTS");
  1713. break;
  1714. case MD_WARNING_PATH_NOT_FOUND:
  1715. RetCode =_TEXT("MD_WARNING_PATH_NOT_FOUND");
  1716. break;
  1717. case MD_WARNING_DUP_NAME:
  1718. RetCode =_TEXT("MD_WARNING_DUP_NAME");
  1719. break;
  1720. case MD_WARNING_INVALID_DATA:
  1721. RetCode =_TEXT("MD_WARNING_INVALID_DATA");
  1722. break;
  1723. case ERROR_INVALID_NAME:
  1724. RetCode =_TEXT("ERROR_INVALID_NAME");
  1725. break;
  1726. default:
  1727. RetCode= _TEXT("");//RetCode = "Unrecognized Error Code");
  1728. break;
  1729. }
  1730. return (RetCode);
  1731. }
  1732. DWORD ConvertHresToDword(HRESULT hRes)
  1733. {
  1734. return HRESULTTOWIN32(hRes);
  1735. }
  1736. LPTSTR ConvertHresToString(HRESULT hRes)
  1737. {
  1738. LPTSTR strReturn = NULL;
  1739. if ((HRESULT_FACILITY(hRes) == FACILITY_WIN32) ||
  1740. (HRESULT_FACILITY(hRes) == FACILITY_ITF) ||
  1741. (hRes == 0)) {
  1742. strReturn = ConvertReturnCodeToString(ConvertHresToDword(hRes));
  1743. }
  1744. else {
  1745. switch (hRes) {
  1746. case CO_E_SERVER_EXEC_FAILURE:
  1747. strReturn =_TEXT("CO_E_SERVER_EXEC_FAILURE");
  1748. break;
  1749. default:
  1750. strReturn =_TEXT("Unrecognized hRes facility");
  1751. }
  1752. }
  1753. return(strReturn);
  1754. }