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.

1051 lines
35 KiB

  1. /* utl2idl.cpp
  2. *
  3. * UTL2IDL Tool translates the Service Description of a device to IDL interface.
  4. *
  5. * Owner: Guru
  6. *
  7. * Copyright 1986-2000 Microsoft Corporation, All Rights Reserved.
  8. */
  9. #include "pch.h"
  10. #pragma hdrstop
  11. #include <msxml2.h>
  12. #include "stdio.h"
  13. #include "Rpcdce.h"
  14. #define MAXSTRLEN 2048
  15. #define MAXSTATEVARIABLES 1024
  16. #define MAXALLOWEDRETVAL 1
  17. #define XMLSTATEVARIABLETAG "stateVariable"
  18. #define CHECKHR(x) {hr = x; if (FAILED(hr)) {callAbort();}}
  19. #define CHECKHRTRACE(x,ERRORMSG) { hr = x ; if ( FAILED(hr) ) { TraceError(ERRORMSG,hr);/*HrPrintError(ERRORMSG,hr);*/ return hr ;} }
  20. #define CHECKNULL(x,ERRORMSG) { if ( x == NULL ) { hr = E_FAIL; TraceError(ERRORMSG,hr);/*HrPrintError(ERRORMSG,hr);*/ return hr ; }}
  21. #define SAFERELEASE(p) {if (p) {(p)->Release(); p = NULL;}}
  22. // struct definition for XML to IDL DataType mapping
  23. typedef struct {
  24. BSTR m_XMLDataType ;
  25. BSTR m_IDLDataType ;
  26. } DTMAPPING ;
  27. // struct definition for maintaing State Variables and its DataType
  28. typedef struct {
  29. BSTR m_StVarName ;
  30. BSTR m_StVarType ;
  31. } STATEVARIABLE ;
  32. typedef STATEVARIABLE* PSTATEVARIABLE;
  33. typedef struct {
  34. STATEVARIABLE **rgStateVariable ;
  35. long cStVars ;
  36. } STATEVARIABLEINFO ;
  37. STATEVARIABLEINFO g_StateVariableInfo ;
  38. PCWSTR g_pszOutFileName = NULL;
  39. PCWSTR g_pszInputFileName = NULL ;
  40. HANDLE g_hOutFileHandle = NULL;
  41. char g_pszdumpStr[MAXSTRLEN];
  42. unsigned long g_methodID = 0 ;
  43. // XML to IDL DataType Mapping
  44. // XML datatypes are sorted in ascending order
  45. static CONST DTMAPPING g_dataTypeConvtTable[] =
  46. {
  47. {OLESTR("bin.base64"),OLESTR("SAFEARRAY")}, // check this data type
  48. {OLESTR("bin.hex"),OLESTR("SAFEARRAY")},
  49. {OLESTR("boolean"),OLESTR("VARIANT_BOOL")},
  50. {OLESTR("char"),OLESTR("wchar_t")},
  51. {OLESTR("date"),OLESTR("DATE")},
  52. {OLESTR("dateTime"),OLESTR("DATE")},
  53. {OLESTR("dateTime.tz"),OLESTR("DATE")},
  54. {OLESTR("fixed.14.4"),OLESTR("CY")},
  55. {OLESTR("float"),OLESTR("float")},
  56. {OLESTR("i1"),OLESTR("char")},
  57. {OLESTR("i2"),OLESTR("short")},
  58. {OLESTR("i4"),OLESTR("long")},
  59. {OLESTR("int"),OLESTR("long")},
  60. {OLESTR("number"),OLESTR("BSTR")},
  61. {OLESTR("r4"),OLESTR("float")},
  62. {OLESTR("r8"),OLESTR("double")},
  63. {OLESTR("string"),OLESTR("BSTR")},
  64. {OLESTR("time"),OLESTR("DATE")},
  65. {OLESTR("time.tz"),OLESTR("DATE")},
  66. {OLESTR("ui1"),OLESTR("unsigned char")},
  67. {OLESTR("ui2"),OLESTR("unsigned short")},
  68. {OLESTR("ui4"),OLESTR("unsigned long")},
  69. {OLESTR("uri"),OLESTR("BSTR")},
  70. {OLESTR("uuid"),OLESTR("BSTR")}
  71. } ;
  72. HRESULT HrInit(IXMLDOMDocument *pXDMDoc)
  73. {
  74. HRESULT hr = S_OK;
  75. long cNumStateVariables = 0 ;
  76. BSTR bstrStVar = NULL;
  77. IXMLDOMNodeList *pXDNLStVars = NULL;
  78. bstrStVar = SysAllocString(OLESTR("stateVariable"));
  79. if( bstrStVar )
  80. {
  81. CHECKHRTRACE(pXDMDoc->getElementsByTagName(bstrStVar,&pXDNLStVars),"HrInit() :" );
  82. CHECKHRTRACE(pXDNLStVars->get_length(&cNumStateVariables),"HrInit() : get_length() Failed");
  83. g_StateVariableInfo.rgStateVariable = new PSTATEVARIABLE[cNumStateVariables];
  84. g_StateVariableInfo.cStVars = 0 ;
  85. }
  86. else
  87. hr = E_FAIL;
  88. return hr;
  89. }
  90. /*
  91. * Function: HrPrintError()
  92. *
  93. * Description: Helper function to print errors
  94. *
  95. * Arguments: [in] char* - error msg
  96. * [in] HRESULT
  97. *
  98. * Returns: HRESULT
  99. */
  100. HRESULT HrPrintError(char *err, HRESULT hr )
  101. {
  102. fprintf(stderr,"Error - %s\n",err);
  103. return hr ;
  104. }
  105. // Aborts the program
  106. void callAbort()
  107. {
  108. DWORD pLen = 0;
  109. printf("ERROR: Aborting !!\n");
  110. sprintf(g_pszdumpStr,"// UTL2IDL generation failed !!\r\n");
  111. WriteFile(g_hOutFileHandle,g_pszdumpStr,strlen(g_pszdumpStr),&pLen,NULL);
  112. CloseHandle(g_hOutFileHandle);
  113. CoUninitialize();
  114. exit(0);
  115. }
  116. // Error report helper function
  117. HRESULT HrReportError(IXMLDOMParseError *pXMLError)
  118. {
  119. long line, linePos;
  120. LONG errorCode;
  121. BSTR pBURL, pBReason;
  122. HRESULT hr;
  123. CHECKHR(pXMLError->get_line(&line));
  124. CHECKHR(pXMLError->get_linepos(&linePos));
  125. CHECKHR(pXMLError->get_errorCode(&errorCode));
  126. CHECKHR(pXMLError->get_url(&pBURL));
  127. CHECKHR(pXMLError->get_reason(&pBReason));
  128. fprintf(stderr, "%S", pBReason);
  129. if (line > 0)
  130. {
  131. fprintf(stderr, "Error on line %d, position %d in \"%S\".\n",
  132. line, linePos, pBURL);
  133. }
  134. SysFreeString(pBURL);
  135. SysFreeString(pBReason);
  136. return E_FAIL;
  137. }
  138. HRESULT HrGetElementValue(IXMLDOMNode *pXDNNode , VARIANT **vNodeValue )
  139. {
  140. IXMLDOMNode *pXDNCldNode ;
  141. HRESULT hr = S_OK ;
  142. CHECKHRTRACE(pXDNNode->get_firstChild(&pXDNCldNode),"HrGetElementValue() : failed");
  143. CHECKHRTRACE(pXDNCldNode->get_nodeValue(*vNodeValue),"HrGetElementValue() : failed");
  144. return hr ;
  145. }
  146. HRESULT HrGenEnumTags(IXMLDOMDocument *pXDMDoc, PCWSTR pszEnumName)
  147. {
  148. HRESULT hr = S_OK ;
  149. IXMLDOMNodeList *pXDNLStVarTable = NULL ;
  150. IXMLDOMNode *pXDNStVarNode = NULL ;
  151. IXMLDOMNodeList *pXDNLActionList = NULL ;
  152. IXMLDOMNode *pXDNActionListNode = NULL ;
  153. IXMLDOMNodeList *pXDNLAllStVars = NULL ;
  154. IXMLDOMNode *pXDNStVar = NULL ;
  155. long nLen = 0 ;
  156. BSTR pszbStVarName = SysAllocString(OLESTR("serviceStateTable"));
  157. IXMLDOMNodeList *pXDNLAllActions = NULL ;
  158. IXMLDOMNode *pXDNAction = NULL ;
  159. BSTR pszActionName = SysAllocString(OLESTR("actionList"));
  160. BOOL first = true ;
  161. DWORD pLen = 0 ;
  162. WCHAR *pszwTmpName = new WCHAR[wcslen(pszEnumName) + 1];
  163. if ( pszwTmpName == NULL )
  164. callAbort();
  165. wcscpy(pszwTmpName,pszEnumName);
  166. CHECKHRTRACE(pXDMDoc->getElementsByTagName(pszbStVarName,&pXDNLStVarTable),"HrGenEnumTags() : failed");
  167. CHECKHRTRACE(pXDNLStVarTable->get_item(0,&pXDNStVarNode),"HrGenEnumTags() : failed");
  168. CHECKNULL(pXDNStVarNode,"HrGenEnumTags() : failed");
  169. CHECKHRTRACE(pXDNStVarNode->selectNodes(OLESTR("stateVariable/name"),&pXDNLAllStVars),"HrGenEnumTags() : failed");
  170. CHECKHRTRACE(pXDNLAllStVars->get_length(&nLen),"HrGenEnumTags() : failed");
  171. sprintf(g_pszdumpStr,"typedef [v1_enum] enum %S_DISPIDS\r\n{\r\n\t",_wcsupr((wchar_t *)pszwTmpName));
  172. CHECKNULL(WriteFile(g_hOutFileHandle,g_pszdumpStr,strlen(g_pszdumpStr),&pLen,NULL),"HrGenEnumTags() : Write to File failed");
  173. for( int i = 0 ; i < nLen ; i++ )
  174. {
  175. VARIANT vNodeName ;
  176. VARIANT *pvName = NULL ;
  177. VariantInit(&vNodeName);
  178. pvName = &vNodeName ;
  179. CHECKHRTRACE(pXDNLAllStVars->get_item(i,&pXDNStVar),"HrGenEnumTags() : failed");
  180. CHECKHRTRACE(HrGetElementValue(pXDNStVar,&pvName),"HrGenEnumTags() : failed");
  181. sprintf(g_pszdumpStr," DISPID_%S",_wcsupr(V_BSTR(&vNodeName)));
  182. CHECKNULL(WriteFile(g_hOutFileHandle,g_pszdumpStr,strlen(g_pszdumpStr),&pLen,NULL),"HrGenEnumTags() : Write to File failed");
  183. if ( first )
  184. {
  185. sprintf(g_pszdumpStr," = 1");
  186. CHECKNULL(WriteFile(g_hOutFileHandle,g_pszdumpStr,strlen(g_pszdumpStr),&pLen,NULL),"HrGenEnumTags() : Write to File failed");
  187. first = false ;
  188. }
  189. if ( i < nLen-1 )
  190. {
  191. sprintf(g_pszdumpStr,",\r\n\t");
  192. CHECKNULL(WriteFile(g_hOutFileHandle,g_pszdumpStr,strlen(g_pszdumpStr),&pLen,NULL),"HrGenEnumTags() : Write to File failed");
  193. }
  194. VariantClear(&vNodeName);
  195. }
  196. CHECKHRTRACE(pXDMDoc->getElementsByTagName(pszActionName,&pXDNLActionList),"HrGenEnumTags() : failed");
  197. CHECKHRTRACE(pXDNLActionList->get_item(0,&pXDNActionListNode),"HrGenEnumTags() : failed");
  198. nLen = 0 ;
  199. if ( pXDNActionListNode )
  200. {
  201. CHECKNULL(pXDNActionListNode,"HrGenEnumTags() : failed");
  202. CHECKHRTRACE(pXDNActionListNode->selectNodes(OLESTR("action/name"),&pXDNLAllActions),"HrGenEnumTags() : 4 failed");
  203. CHECKHRTRACE(pXDNLAllActions->get_length(&nLen),"HrGenEnumTags() : failed");
  204. }
  205. if ( nLen )
  206. {
  207. sprintf(g_pszdumpStr,",\r\n\t");
  208. CHECKNULL(WriteFile(g_hOutFileHandle,g_pszdumpStr,strlen(g_pszdumpStr),&pLen,NULL),"HrGenEnumTags() : Write to File failed");
  209. }
  210. for( int i = 0 ; i < nLen ; i++ )
  211. {
  212. VARIANT vActionName ;
  213. VARIANT *pvActName = NULL ;
  214. VariantInit(&vActionName);
  215. pvActName = &vActionName;
  216. CHECKHRTRACE(pXDNLAllActions->get_item(i,&pXDNAction),"HrGenEnumTags() : failed");
  217. CHECKHRTRACE(HrGetElementValue(pXDNAction,&pvActName),"HrGenEnumTags() : failed");
  218. sprintf(g_pszdumpStr," DISPID_%S",_wcsupr(V_BSTR(&vActionName)));
  219. CHECKNULL(WriteFile(g_hOutFileHandle,g_pszdumpStr,strlen(g_pszdumpStr),&pLen,NULL),"HrGenEnumTags() : Write to File failed");
  220. if ( first )
  221. {
  222. sprintf(g_pszdumpStr," = 1");
  223. CHECKNULL(WriteFile(g_hOutFileHandle,g_pszdumpStr,strlen(g_pszdumpStr),&pLen,NULL),"HrGenEnumTags() : Write to File failed");
  224. first = false ;
  225. }
  226. if ( i < nLen-1 )
  227. {
  228. sprintf(g_pszdumpStr,",\r\n\t");
  229. CHECKNULL(WriteFile(g_hOutFileHandle,g_pszdumpStr,strlen(g_pszdumpStr),&pLen,NULL),"HrGenEnumTags() : Write to File failed");
  230. }
  231. VariantClear(&vActionName);
  232. }
  233. sprintf(g_pszdumpStr,"\r\n\r\n} %S_DISPIDS;\r\n\r\n",_wcsupr((wchar_t *)pszwTmpName));
  234. CHECKNULL(WriteFile(g_hOutFileHandle,g_pszdumpStr,strlen(g_pszdumpStr),&pLen,NULL),"HrGenEnumTags() : Write to File failed");
  235. delete pszwTmpName ;
  236. SysFreeString(pszActionName);
  237. SysFreeString(pszbStVarName);
  238. return hr ;
  239. }
  240. /*
  241. * Function: HrgenGUIDHDR()
  242. *
  243. * Description: Generates the IDL interface Header
  244. *
  245. * Arguments: [in] PCWSTR - Help String for the interface
  246. *
  247. * Returns: HRESULT
  248. */
  249. HRESULT HrgenGUIDHDR(PCWSTR pszHelpStr, BOOL fDual) {
  250. HRESULT hr = S_OK ;
  251. UUID pUUID ;
  252. unsigned char *arUUID ;
  253. DWORD pLen = 0 ;
  254. RPC_STATUS status ;
  255. status = UuidCreate(&pUUID);
  256. if ( status != RPC_S_OK )
  257. callAbort();
  258. status = UuidToString(&pUUID,(unsigned short **)&arUUID);
  259. if ( status != RPC_S_OK )
  260. callAbort();
  261. sprintf(g_pszdumpStr,"[\r\n\t uuid(%S),\r\n\t %S,\r\n\t pointer_default(unique)\r\n]\r\n",arUUID,(fDual)?OLESTR("dual"):OLESTR("oleautomation"));
  262. CHECKNULL(WriteFile(g_hOutFileHandle,g_pszdumpStr,strlen(g_pszdumpStr),&pLen,NULL),"HrgenGUIDHDR() : Write to File failed");
  263. RpcStringFree((unsigned short **)&arUUID);
  264. return hr ;
  265. }
  266. /*
  267. * Function: HrCheckLoad()
  268. *
  269. * Description: Cheks if the XML document is loaded successfully
  270. *
  271. * Arguments: [in] IXMLDOMDocument* - XML document handle
  272. *
  273. * Returns: HRESULT
  274. */
  275. HRESULT HrCheckLoad(IXMLDOMDocument* pXDMDoc)
  276. {
  277. IXMLDOMParseError *pXMLError = NULL;
  278. LONG errorCode = E_FAIL;
  279. HRESULT hr;
  280. CHECKHR(pXDMDoc->get_parseError(&pXMLError));
  281. CHECKHR(pXMLError->get_errorCode(&errorCode));
  282. if (errorCode != 0)
  283. {
  284. hr = HrReportError(pXMLError);
  285. SAFERELEASE(pXMLError);
  286. }
  287. else
  288. {
  289. fprintf(stderr, "XML document loaded successfully\n");
  290. }
  291. SAFERELEASE(pXMLError);
  292. return errorCode;
  293. }
  294. /*
  295. * Function: HrLoadDocument()
  296. *
  297. * Description: Loads XML Document
  298. *
  299. * Arguments: [in] IXMLDOMDocument* - XML document handle
  300. * [in] BSTR - the location of XML file
  301. *
  302. * Returns: HRESULT
  303. */
  304. HRESULT HrLoadDocument(IXMLDOMDocument *pXDMDoc, BSTR pBURL)
  305. {
  306. VARIANT vURL;
  307. VARIANT_BOOL vb;
  308. HRESULT hr;
  309. CHECKHR(pXDMDoc->put_async(VARIANT_FALSE));
  310. // Load xml document from the given URL or file path
  311. VariantInit(&vURL);
  312. vURL.vt = VT_BSTR;
  313. V_BSTR(&vURL) = pBURL;
  314. CHECKHR(pXDMDoc->load(vURL, &vb));
  315. CHECKHR(HrCheckLoad(pXDMDoc));
  316. return hr;
  317. }
  318. /*
  319. * Function: getRelatedDataType()
  320. *
  321. * Description: The data types of the action arguments is specified in terms of its related state variable
  322. * This function gets the data type of the action argument from the related state variable
  323. *
  324. * Arguments: [in] BSTR - related state variable
  325. *
  326. * Returns: [retval] BSTR - data type of the state variable
  327. * NULL if there is no corresponding state variable
  328. */
  329. BSTR getRelatedDataType(BSTR relatedStateVariable )
  330. {
  331. for(int i = 0 ; i < g_StateVariableInfo.cStVars ; i++ )
  332. {
  333. if( wcscmp(relatedStateVariable,g_StateVariableInfo.rgStateVariable[i]->m_StVarName) == 0 )
  334. return SysAllocString(g_StateVariableInfo.rgStateVariable[i]->m_StVarType);
  335. }
  336. return NULL ;
  337. }
  338. /*
  339. * Function: getIDLDataType()
  340. *
  341. * Description: This functions maps the XML data type to the equivalent IDL data type
  342. *
  343. * Arguments: [in] BSTR - XML data type
  344. *
  345. * Returns: [retval] BSTR - IDL data type
  346. * NULL - if the XML data type is invalid
  347. */
  348. BSTR getIDLDataType(BSTR xmlDataType)
  349. {
  350. CONST int nSize = celems(g_dataTypeConvtTable);
  351. int i ;
  352. for( i = 0 ; i < nSize ; i++ )
  353. {
  354. if ( _wcsicmp(xmlDataType , g_dataTypeConvtTable[i].m_XMLDataType) == 0 )
  355. return g_dataTypeConvtTable[i].m_IDLDataType ;
  356. }
  357. return NULL ;
  358. }
  359. // prints the command line usage
  360. void PrintUsage(PCWSTR exe)
  361. {
  362. fprintf(stderr, "\n\nUsage: %S [<options>] inputfilename [outputfilename] \n",exe);
  363. fprintf(stderr, "\nOptions are:\n");
  364. fprintf(stderr,"-i InterfaceName ..... Input interface name for generating IDL interface\n");
  365. fprintf(stderr,"-d ..... Generate dual interface\n");
  366. fprintf(stderr,"-h HelpString ..... Input Help String\n\n");
  367. exit(0);
  368. }
  369. // input file assumed to have extension !!
  370. // if PATH is specified, again prun it !!
  371. // truncates the extension from the input string and creates a new truncated string
  372. WCHAR* PrunFileExt(PCWSTR fileName )
  373. {
  374. WCHAR *rgTmpName = NULL ;
  375. WCHAR *pFileName = NULL ;
  376. rgTmpName = new WCHAR[wcslen(fileName)+10] ; // +10 -just in case the file doesn't have extension and we are appending some ext !!
  377. if ( rgTmpName == NULL )
  378. callAbort();
  379. pFileName = wcsrchr(fileName,'\\');
  380. if ( pFileName == NULL )
  381. {
  382. wcscpy(rgTmpName,fileName);
  383. pFileName = wcsrchr(rgTmpName,'.');
  384. if ( pFileName )
  385. *pFileName = NULL ;
  386. }
  387. else
  388. {
  389. wcscpy(rgTmpName,pFileName+1);
  390. pFileName = wcsrchr(rgTmpName,'.');
  391. if ( pFileName )
  392. *pFileName = NULL ;
  393. }
  394. return rgTmpName ;
  395. }
  396. void ValidateString(WCHAR *fileName)
  397. {
  398. int nLen ;
  399. int i;
  400. nLen = wcslen(fileName);
  401. for( i=0; i < nLen ; i++ )
  402. {
  403. switch(fileName[i])
  404. {
  405. case '-':
  406. case '!':
  407. case '@':
  408. case '#':
  409. case '$':
  410. case '%':
  411. case '^':
  412. case '&':
  413. case '*':
  414. case '+':
  415. case ' ':
  416. case '(':
  417. case ')':
  418. fileName[i] = '_' ;
  419. break;
  420. default:
  421. ;
  422. }
  423. }
  424. }
  425. /*
  426. * Function: HrGenStateVariableIDLFn()
  427. *
  428. * Description: Generates the propget IDL function for the state variable
  429. *
  430. * Arguments: [in] IXMLDOMNode* - state variable node
  431. *
  432. * Returns: HRESULT
  433. */
  434. HRESULT HrGenStateVariableIDLFn(IXMLDOMNode *pXDNStVar )
  435. {
  436. HRESULT hr = S_OK ;
  437. VARIANT vName, vDataType ;
  438. IXMLDOMNodeList *pXDNLchildNodes = NULL ;
  439. IXMLDOMNode *pXDNStVarTags= NULL ;
  440. IXMLDOMNode *pXDNStVarData = NULL ;
  441. BSTR pszbName = SysAllocString(OLESTR("name"));
  442. BSTR pszbDataType = SysAllocString(OLESTR("dataType"));
  443. BSTR pszbNodeName ;
  444. long lLength ;
  445. DWORD pLen = 0 ;
  446. VariantInit(&vName);
  447. VariantInit(&vDataType);
  448. CHECKHRTRACE(pXDNStVar->get_childNodes(&pXDNLchildNodes),"HrGenStateVariableFn() - Failed");
  449. CHECKHRTRACE(pXDNLchildNodes->get_length(&lLength),"HrGenStateVariableFn() - Failed");
  450. for(int i = 0 ; i < lLength ; i++ )
  451. {
  452. CHECKHRTRACE(pXDNLchildNodes->get_item(i,&pXDNStVarTags),"HrGenStateVariableFn() - Failed") ;
  453. CHECKHRTRACE(pXDNStVarTags->get_firstChild(&pXDNStVarData),"HrGenStateVariableFn() - Failed") ;
  454. //CHECKNULL(pXDNStVarData,"HrGenStateVariableFn() - XML DataValue Missing");
  455. CHECKHRTRACE(pXDNStVarTags->get_nodeName(&pszbNodeName), "HrGenStateVariableFn() - Failed");
  456. if ( wcscmp(pszbNodeName,pszbName) == 0 )
  457. { // TAGS are case sensitive !!
  458. CHECKNULL(pXDNStVarData,"HrGenStateVariableFn() - XML DataValue Missing");
  459. CHECKHRTRACE(pXDNStVarData->get_nodeValue(&vName),"HrGenStateVariableFn() - Failed");
  460. }
  461. else if ( wcscmp(pszbNodeName,pszbDataType) == 0 )
  462. {
  463. CHECKNULL(pXDNStVarData,"HrGenStateVariableFn() - XML DataValue Missing");
  464. CHECKHRTRACE(pXDNStVarData->get_nodeValue(&vDataType),"HrGenStateVariableFn() - Failed");
  465. }
  466. SysFreeString(pszbNodeName);
  467. }
  468. BSTR pszbIDLDataType = getIDLDataType(V_BSTR(&vDataType));
  469. CHECKNULL(pszbIDLDataType,"HrGenStateVariable() : INVALID Data Type");
  470. g_StateVariableInfo.rgStateVariable[g_StateVariableInfo.cStVars] = new STATEVARIABLE ; // check for error
  471. CHECKNULL(g_StateVariableInfo.rgStateVariable[g_StateVariableInfo.cStVars],"HrGenStateVariable() : STATEVARIABLE Allocation Failed");
  472. g_StateVariableInfo.rgStateVariable[g_StateVariableInfo.cStVars]->m_StVarName = SysAllocString(V_BSTR(&vName));
  473. g_StateVariableInfo.rgStateVariable[g_StateVariableInfo.cStVars]->m_StVarType = SysAllocString(pszbIDLDataType);
  474. g_StateVariableInfo.cStVars++ ;
  475. WCHAR *pszwTmp = new WCHAR[wcslen(V_BSTR(&vName))+1] ;
  476. if ( pszwTmp == NULL )
  477. callAbort();
  478. wcscpy(pszwTmp,V_BSTR(&vName));
  479. sprintf(g_pszdumpStr,"\t[propget, id(DISPID_%S), helpstring(\"Property %S\")]\r\n\tHRESULT %S(\r\n\t\t[out, retval] %S *p%S);\r\n\r\n",_wcsupr(pszwTmp),V_BSTR(&vName),V_BSTR(&vName),/*V_BSTR(&vDataType)*/pszbIDLDataType , V_BSTR(&vName));
  480. CHECKNULL(WriteFile(g_hOutFileHandle,g_pszdumpStr,strlen(g_pszdumpStr),&pLen,NULL),"Write to File failed");
  481. delete pszwTmp ;
  482. g_methodID++;
  483. VariantClear(&vName);
  484. VariantClear(&vDataType);
  485. return hr ;
  486. }
  487. /*
  488. * Function: HrProcessStateVariables()
  489. *
  490. * Description: Process all the state variables form the XML document
  491. *
  492. * Arguments: [in] IXMLDOMDocument* - Service Description XML document
  493. *
  494. * Returns: HRESULT
  495. */
  496. HRESULT HrProcessStateVariables(IXMLDOMDocument *pXDMDoc )
  497. {
  498. BSTR pBStVar = SysAllocString(OLESTR("stateVariable"));
  499. IXMLDOMNodeList *pXDNLStVars = NULL;
  500. IXMLDOMNode *pXDNStVar = NULL;
  501. long clistLen = 0 ;
  502. HRESULT hr = S_OK ;
  503. CHECKHRTRACE(pXDMDoc->getElementsByTagName(pBStVar,&pXDNLStVars),"HrProcessStateVariables() : NoStateVariables");
  504. CHECKHRTRACE(pXDNLStVars->get_length(&clistLen),"HrProcessStateVariables() : get_length() Failed");
  505. for( int i = 0 ; i < clistLen ; i++)
  506. {
  507. CHECKHRTRACE(pXDNLStVars->get_item(i,&pXDNStVar),"HrProcessStateVariables() : Failed");
  508. CHECKHRTRACE(HrGenStateVariableIDLFn(pXDNStVar),"HrProcessStateVariables() : Failed");
  509. }
  510. SysFreeString(pBStVar);
  511. return hr ;
  512. }
  513. /*
  514. * Function: HrProcessArguments()
  515. *
  516. * Description: Parses the argument and generates the arguments for the IDL function
  517. *
  518. * Arguments: [in] IXMLDOMNode* - argument node
  519. * [out] BOOL* - indicates if the argument is a return value
  520. *
  521. * Returns: HRESULT
  522. */
  523. HRESULT HrProcessArguments(IXMLDOMNode *pXDNArgument, BOOL *fretVal, BSTR *pszbrelDT, BSTR *pszargName )
  524. {
  525. HRESULT hr = S_OK ;
  526. IXMLDOMNodeList *pXDNLParams = NULL ;
  527. IXMLDOMNode *pXDNParamNode = NULL ;
  528. BSTR pszbParamNodeName ;
  529. VARIANT vargName ;
  530. VARIANT vargDataType ;
  531. VARIANT vargDirection ;
  532. BSTR pszbrelatedDataType = NULL ;
  533. long nNumParams = 0 ;
  534. DWORD pLen = 0 ;
  535. BOOL retVal = false ;
  536. VariantInit(&vargName);
  537. VariantInit(&vargDataType);
  538. VariantInit(&vargDirection);
  539. CHECKHRTRACE(pXDNArgument->get_childNodes(&pXDNLParams),"HrProcessArguments() : failed");
  540. CHECKHRTRACE(pXDNLParams->get_length(&nNumParams),"HrProcessArguments() : failed");
  541. for( int i = 0 ; i < nNumParams ; i++ )
  542. {
  543. CHECKHRTRACE(pXDNLParams->get_item(i,&pXDNParamNode),"HrProcessArguments() : failed");
  544. pszbParamNodeName = NULL ;
  545. CHECKHRTRACE(pXDNParamNode->get_nodeName(&pszbParamNodeName),"HrProcessArguments() : failed");
  546. CHECKNULL(pszbParamNodeName,"HrProcessArguments() : INVALID Arguments");
  547. if ( wcscmp(pszbParamNodeName,OLESTR("name")) == 0)
  548. {
  549. IXMLDOMNode *pXDNargNameNode = NULL ;
  550. CHECKHRTRACE(pXDNParamNode->get_firstChild(&pXDNargNameNode),"HrProcessArguments() : failed");
  551. CHECKNULL( pXDNargNameNode,"HrProcessArguments() : Arguments not specified");
  552. CHECKHRTRACE(pXDNargNameNode->get_nodeValue(&vargName),"HrProcessArguments() : failed");
  553. }
  554. else if ( wcscmp(pszbParamNodeName,OLESTR("relatedStateVariable")) == 0 ) {
  555. IXMLDOMNode *pXDNargRelatedNode = NULL ;
  556. CHECKHRTRACE(pXDNParamNode->get_firstChild(&pXDNargRelatedNode),"HrProcessArguments() : failed");
  557. CHECKNULL(pXDNargRelatedNode,"HrProcessArguments() : Related StateVariable not specified");
  558. CHECKHRTRACE(pXDNargRelatedNode->get_nodeValue(&vargDataType),"HrProcessArguments() : failed");
  559. pszbrelatedDataType = getRelatedDataType(V_BSTR(&vargDataType));
  560. CHECKNULL(pszbrelatedDataType,"HrProcessArguments() : INVALID Related State Variable") ;
  561. }
  562. else if ( wcscmp(pszbParamNodeName,OLESTR("direction")) == 0 )
  563. {
  564. IXMLDOMNode *pXDNargDirectionNode = NULL ;
  565. CHECKHRTRACE(pXDNParamNode->get_firstChild(&pXDNargDirectionNode),"HrProcessArguments() : failed");
  566. CHECKNULL(pXDNargDirectionNode,"HrProcessArguments() : Direction not specified");
  567. CHECKHRTRACE(pXDNargDirectionNode->get_nodeValue(&vargDirection),"HrProcessArguments() : failed");
  568. if ( (_wcsicmp(V_BSTR(&vargDirection),OLESTR("in")) != 0 ) &&
  569. (_wcsicmp(V_BSTR(&vargDirection),OLESTR("out")) != 0 ) ) {
  570. hr = E_FAIL ;
  571. CHECKHRTRACE(hr,"HrProcessArguments() : Direction must be either \"in\" or \"out\"")
  572. }
  573. }
  574. else if ( wcscmp(pszbParamNodeName,OLESTR("retval")) == 0)
  575. {
  576. retVal = true ;
  577. }
  578. else
  579. hr = HrPrintError("INVALID XML Document !!", hr );
  580. SysFreeString(pszbParamNodeName);
  581. }
  582. if ( retVal )
  583. {
  584. if ( _wcsicmp(V_BSTR(&vargDirection),OLESTR("in")) == 0 )
  585. {
  586. hr = HrPrintError("INVALID ARGUMENT DIRECTION", hr);
  587. callAbort();
  588. }
  589. *pszargName = SysAllocString(V_BSTR(&vargName));
  590. *pszbrelDT = SysAllocString(pszbrelatedDataType);
  591. }
  592. else
  593. if ( _wcsicmp(V_BSTR(&vargDirection),OLESTR("out")) == 0 )
  594. {
  595. sprintf(g_pszdumpStr,"\r\n\t\t[in, %S] %S *p%S",V_BSTR(&vargDirection),pszbrelatedDataType,V_BSTR(&vargName));
  596. CHECKNULL(WriteFile(g_hOutFileHandle,g_pszdumpStr,strlen(g_pszdumpStr),&pLen,NULL),"HrProcessArguments() : Write to File failed");
  597. }
  598. else
  599. {
  600. sprintf(g_pszdumpStr,"\r\n\t\t[%S] %S %S",V_BSTR(&vargDirection),pszbrelatedDataType,V_BSTR(&vargName));
  601. CHECKNULL(WriteFile(g_hOutFileHandle,g_pszdumpStr,strlen(g_pszdumpStr),&pLen,NULL),"HrProcessArguments() : Write to File failed");
  602. }
  603. SysFreeString(pszbrelatedDataType);
  604. VariantClear(&vargName);
  605. VariantClear(&vargDirection);
  606. VariantClear(&vargDataType);
  607. *fretVal = retVal ;
  608. return hr ;
  609. }
  610. /*
  611. * Function: HrProcessArgumentList()
  612. *
  613. * Description: Parses all the arguments for a given arguement list
  614. *
  615. * Arguments: [in] IXMLDOMNode* - argument list node
  616. *
  617. * Returns: HRESULT
  618. */
  619. // assumption: the retval must always be specified as the last argument in the XML document
  620. HRESULT HrProcessArgumentList(IXMLDOMNode *pXDNArgsNode )
  621. {
  622. HRESULT hr = S_OK ;
  623. IXMLDOMNodeList *pXDNLArgsList = NULL ;
  624. IXMLDOMNode *pXDNArguments = NULL ;
  625. BSTR pszbrelatedDataType = NULL ;
  626. BSTR pszbArgName = NULL ;
  627. long nNumArgs = 0 ;
  628. BOOL fchkRetVal = false ;
  629. int cretValCount = 0 ;
  630. int nretValIndex = 0 ; // do :-initialize correctly
  631. DWORD pLen = 0 ;
  632. // multiple return Values not allowed
  633. CHECKHRTRACE(pXDNArgsNode->get_childNodes(&pXDNLArgsList),"HrProcessArgumentList() : failed");
  634. CHECKHRTRACE(pXDNLArgsList->get_length(&nNumArgs),"HrProcessArgumentList() : failed");
  635. for(int i = 0 ; i < nNumArgs ; i++ )
  636. {
  637. CHECKHRTRACE(pXDNLArgsList->get_item(i,&pXDNArguments),"HrProcessArgumentList() : failed");
  638. CHECKHRTRACE(HrProcessArguments(pXDNArguments,&fchkRetVal,&pszbrelatedDataType,&pszbArgName),"HrProcessArgumentList() : failed") ;
  639. if ( (i < (nNumArgs-1)) && !fchkRetVal )
  640. {
  641. sprintf(g_pszdumpStr,",");
  642. CHECKNULL(WriteFile(g_hOutFileHandle,g_pszdumpStr,strlen(g_pszdumpStr),&pLen,NULL),"HrProcessArgumentList() : Write to File failed");
  643. }
  644. if ( fchkRetVal )
  645. {
  646. fchkRetVal = false ;
  647. nretValIndex = i ;
  648. cretValCount++ ;
  649. if ( cretValCount > MAXALLOWEDRETVAL )
  650. {
  651. HrPrintError("Maximum of 1 retval allowed",hr) ;
  652. callAbort();
  653. }
  654. }
  655. }
  656. if ( cretValCount )
  657. {
  658. if ( nNumArgs > 1 && nretValIndex < (nNumArgs-1) )
  659. {
  660. sprintf(g_pszdumpStr,",");
  661. CHECKNULL(WriteFile(g_hOutFileHandle,g_pszdumpStr,strlen(g_pszdumpStr),&pLen,NULL),"HrProcessArgumentList() : Write to File failed");
  662. }
  663. sprintf(g_pszdumpStr,"\r\n\t\t[out, retval] %S *p%S",pszbrelatedDataType,pszbArgName);
  664. CHECKNULL(WriteFile(g_hOutFileHandle,g_pszdumpStr,strlen(g_pszdumpStr),&pLen,NULL),"HrProcessArgumentList() : Write to File failed");
  665. }
  666. SysFreeString(pszbrelatedDataType);
  667. SysFreeString(pszbArgName);
  668. return hr ;
  669. }
  670. /*
  671. * Function: HrProcessAction()
  672. *
  673. * Description: Parses each action node and generates the IDL action functions
  674. *
  675. * Arguments: [in] IXMLDOMNode* - action node
  676. *
  677. * Returns: HRESULT
  678. */
  679. HRESULT HrProcessAction(IXMLDOMNode *pXDNAction)
  680. {
  681. HRESULT hr = S_OK ;
  682. VARIANT vActionName ;
  683. IXMLDOMNode *pXDNActionNode = NULL ;
  684. IXMLDOMNode *pXDNArgsNode = NULL ;
  685. IXMLDOMNode *pXDNActionNameNode = NULL ;
  686. DWORD pLen = 0 ;
  687. VariantInit(&vActionName);
  688. CHECKHRTRACE(pXDNAction->selectSingleNode(OLESTR("name"),&pXDNActionNode),"HrProcessAction() : failed");
  689. CHECKNULL(pXDNActionNode,"HrProcessAction() : Not able to retrieve Action Node");
  690. CHECKHRTRACE(pXDNAction->selectSingleNode(OLESTR("argumentList"),&pXDNArgsNode),"HrProcessAction() : failed");
  691. CHECKHRTRACE(pXDNActionNode->get_firstChild(&pXDNActionNameNode),"HrProcessAction() : failed");
  692. CHECKNULL(pXDNActionNameNode,"HrProcessAction() : Not able to retrieve Action Name");
  693. CHECKHRTRACE(pXDNActionNameNode->get_nodeValue(&vActionName),"HrProcessAction() : failed");
  694. WCHAR *pszwTmp = new WCHAR[wcslen(V_BSTR(&vActionName))+1] ;
  695. if ( pszwTmp == NULL )
  696. callAbort();
  697. wcscpy(pszwTmp,V_BSTR(&vActionName));
  698. sprintf(g_pszdumpStr,"\r\n\t[ id(DISPID_%S), helpstring(\"Method %S\")]\r\n",_wcsupr(pszwTmp),V_BSTR(&vActionName));
  699. CHECKNULL(WriteFile(g_hOutFileHandle,g_pszdumpStr,strlen(g_pszdumpStr),&pLen,NULL),"HrProcessAction() : Write to File failed");
  700. delete pszwTmp ;
  701. g_methodID++;
  702. if ( pXDNArgsNode == NULL )
  703. {
  704. sprintf(g_pszdumpStr,"\tHRESULT %S();\r\n",V_BSTR(&vActionName));
  705. CHECKNULL(WriteFile(g_hOutFileHandle,g_pszdumpStr,strlen(g_pszdumpStr),&pLen,NULL),"HrProcessAction() : Write to File failed");
  706. }
  707. else
  708. {
  709. sprintf(g_pszdumpStr,"\tHRESULT %S(",V_BSTR(&vActionName));
  710. CHECKNULL(WriteFile(g_hOutFileHandle,g_pszdumpStr,strlen(g_pszdumpStr),&pLen,NULL),"HrProcessAction() : Write to File failed");
  711. CHECKHRTRACE(HrProcessArgumentList(pXDNArgsNode),"HrProcessAction() : failed");
  712. sprintf(g_pszdumpStr,");\r\n");
  713. CHECKNULL(WriteFile(g_hOutFileHandle,g_pszdumpStr,strlen(g_pszdumpStr),&pLen,NULL),"HrProcessAction() : Write to File failed");
  714. }
  715. VariantClear(&vActionName);
  716. return hr ;
  717. }
  718. /*
  719. * Function: HrProcessActionList()
  720. *
  721. * Description: Parses action list and generates the IDL functions
  722. *
  723. * Arguments: [in] IXMLDOMNode* - action list node
  724. *
  725. * Returns: HRESULT
  726. */
  727. HRESULT HrProcessActionList(IXMLDOMDocument *pXDMDoc )
  728. {
  729. BSTR pBAction = SysAllocString(OLESTR("action"));
  730. IXMLDOMNodeList *pXDNLActionList = NULL;
  731. IXMLDOMNode *pXDNActionItem = NULL;
  732. long clistLen = 0 ;
  733. HRESULT hr = S_OK ;
  734. // can be with out actions
  735. CHECKHRTRACE(pXDMDoc->getElementsByTagName(pBAction,&pXDNLActionList),"HrProcessActionList(): NoActions");
  736. CHECKHRTRACE(pXDNLActionList->get_length(&clistLen),"HrProcessActionList() : failed");
  737. for( int i = 0 ; i < clistLen ; i++)
  738. {
  739. pXDNLActionList->get_item(i,&pXDNActionItem);
  740. CHECKHRTRACE(HrProcessAction(pXDNActionItem),"HrProcessActionList() : failed") ;
  741. }
  742. SysFreeString(pBAction);
  743. return hr ;
  744. }
  745. /*
  746. * Function: HrGenIDLInterface()
  747. *
  748. * Description: Parses the XML document and generates the IDL interface for the Service Description in XML
  749. *
  750. * Arguments: [in] IXMLDOMDocument* - XML Service Description Document
  751. * [in] PCWSTR - HelpString for the interface
  752. * [in] PCWSTR - Interface name for the Service Description
  753. * Returns: HRESULT
  754. */
  755. HRESULT HrGenIDLInterface(IXMLDOMDocument *pXDMDoc, PCWSTR pszHelpString, PCWSTR pszInterfaceName, BOOL fDual )
  756. {
  757. HRESULT hr = S_OK ;
  758. DWORD pLen = 0 ;
  759. CHECKHRTRACE(HrgenGUIDHDR(pszHelpString,fDual),"HrGenIDLInterface() : failed");
  760. sprintf(g_pszdumpStr,"interface IUPnPService_%S%S : %S {\r\n",pszInterfaceName,fDual?OLESTR("Dual"):L"",fDual?OLESTR("IDispatch"):OLESTR("IUnknown"));
  761. CHECKNULL(WriteFile(g_hOutFileHandle,g_pszdumpStr,strlen(g_pszdumpStr),&pLen,NULL),"HrGenIDLInterface() : Write to File failed");
  762. CHECKHRTRACE(HrProcessStateVariables(pXDMDoc),"HrGenIDLInterface() : failed");
  763. CHECKHRTRACE(HrProcessActionList(pXDMDoc),"HrGenIDLInterface() : failed");
  764. sprintf(g_pszdumpStr,"};\r\n");
  765. CHECKNULL(WriteFile(g_hOutFileHandle,g_pszdumpStr,strlen(g_pszdumpStr),&pLen,NULL),"HrGenIDLInterface() : Write to File failed");
  766. return hr ;
  767. }
  768. // Creates a new file for generating IDL interfaces
  769. HANDLE CreateIDLFile()
  770. {
  771. HANDLE hOutFile ;
  772. hOutFile = CreateFile(g_pszOutFileName,GENERIC_WRITE,NULL,NULL,CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
  773. while ( hOutFile == INVALID_HANDLE_VALUE ) {
  774. printf("\n\t The file %S already exists !!\n\t Do you want to OVERWRITE ? [y/n] : ",g_pszOutFileName);
  775. wchar_t wch ;
  776. while( ( (wch = towlower(getwchar()) ) != 'y' ) && (wch != 'n') )
  777. {
  778. fflush(stdout);
  779. printf("\n\t The file %S already exists !!\n\t Do you want to OVERWRITE ? [y/n] : ",g_pszOutFileName);
  780. }
  781. if ( wch == 'y' )
  782. hOutFile = CreateFile(g_pszOutFileName,GENERIC_WRITE,NULL,NULL,CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  783. else
  784. callAbort();
  785. }
  786. return hOutFile ;
  787. }
  788. /*
  789. * Function: wmain()
  790. *
  791. * Description: utl2idl.cpp main function. parses the command line arguments and loads the XML document
  792. * Generates the IDL interface from the XML DOM document which has the service description
  793. * Usage: utl3idl.exe [<options> SpecName] inputfilename [outputfilename]
  794. * The input file is required.
  795. * Options:
  796. * -i - specify the interface name
  797. * -h - specify the helpstring.
  798. *
  799. * Arguments: [i] int - argc
  800. * [i] PCWSTR - argv[]
  801. * Returns: int
  802. */
  803. EXTERN_C
  804. int
  805. __cdecl
  806. wmain ( IN INT argc,
  807. IN PCWSTR argv[])
  808. {
  809. HRESULT hr = S_OK;
  810. IXMLDOMDocument *pXDMDoc = NULL;
  811. IXMLDOMNode *pXDNNode = NULL;
  812. BSTR pBURL = NULL;
  813. PCWSTR pszHelpString = NULL ;
  814. PCWSTR pszInterfaceName = NULL ;
  815. int i;
  816. BOOL fIName = false ;
  817. BOOL fDual = false ;
  818. DWORD pLen = 0 ;
  819. g_StateVariableInfo.cStVars = 0 ;
  820. CHECKHR(CoInitialize(NULL));
  821. // Create an empty XML document
  822. CHECKHR(CoCreateInstance(CLSID_DOMDocument30, NULL, CLSCTX_INPROC_SERVER,
  823. IID_IXMLDOMDocument, (void**)&pXDMDoc));
  824. if (argc == 1)
  825. {
  826. PrintUsage(argv[0]);
  827. }
  828. i = 1 ;
  829. while ( i < argc )
  830. {
  831. PCWSTR arg = argv[i];
  832. if ((arg[0] == '-') || (arg[0] == '/'))
  833. {
  834. switch (arg[1])
  835. {
  836. case 'i':
  837. fIName = true;
  838. i++ ;
  839. pszInterfaceName = argv[i++] ;
  840. break;
  841. case 'h':
  842. i++;
  843. pszHelpString = argv[i++] ;
  844. break;
  845. case 'd':
  846. fDual = true ;
  847. i++;
  848. break ;
  849. case '?':
  850. PrintUsage(argv[0]);
  851. break;
  852. default:
  853. PrintUsage(argv[0]);
  854. }
  855. }
  856. else
  857. {
  858. g_pszInputFileName = arg ;
  859. i++;
  860. if ( i < argc )
  861. g_pszOutFileName = argv[i] ;
  862. i++ ;
  863. break ;
  864. }
  865. }
  866. if ( (g_pszInputFileName != NULL) && (g_pszOutFileName != NULL) )
  867. {
  868. if ( wcscmp(g_pszInputFileName,g_pszOutFileName) == 0 )
  869. {
  870. fprintf(stderr,"\nERROR - Input and Output file must be different\n");
  871. PrintUsage(argv[0]) ;
  872. }
  873. }
  874. // assumes a .xml extension !! change it to generic
  875. if ( g_pszInputFileName == NULL )
  876. PrintUsage(argv[0]) ;
  877. if ( g_pszOutFileName == NULL )
  878. {
  879. g_pszOutFileName = PrunFileExt(g_pszInputFileName) ;
  880. wcscat((WCHAR *)g_pszOutFileName,L".idl");
  881. }
  882. if ( pszHelpString == NULL )
  883. pszHelpString = PrunFileExt(g_pszInputFileName) ;
  884. if ( pszInterfaceName == NULL )
  885. {
  886. pszInterfaceName = PrunFileExt(g_pszInputFileName) ;
  887. ValidateString((WCHAR*)pszInterfaceName);
  888. }
  889. pBURL = SysAllocString(g_pszInputFileName);
  890. hr = HrLoadDocument(pXDMDoc, pBURL);
  891. if(hr == S_OK )
  892. {
  893. HrInit(pXDMDoc);
  894. g_hOutFileHandle = CreateIDLFile();
  895. CHECKHR(HrGenEnumTags(pXDMDoc,pszInterfaceName));
  896. CHECKHR(HrGenIDLInterface(pXDMDoc,pszHelpString, pszInterfaceName,fDual));
  897. printf("\n\tTranslation Done. Check %S file\n",g_pszOutFileName);
  898. SAFERELEASE(pXDMDoc);
  899. }
  900. SAFERELEASE(pXDMDoc);
  901. // free file names !!!!
  902. CloseHandle(g_hOutFileHandle);
  903. CoUninitialize();
  904. }