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

1321 lines
40 KiB

  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Copyright (c) 1998-2000 Microsoft Corporation
  3. Module Name:
  4. netmon.cxx
  5. Abstract:
  6. Generate C code for the stub DLL's used for Netmon debugging
  7. Notes:
  8. Two files are generated by this file:
  9. xxx_netmon_stub.c
  10. xxx_netmob_stub_obj.c
  11. History:
  12. - Created 7/28/98 by Max Attar Feingold
  13. ----------------------------------------------------------------------------*/
  14. #include "becls.hxx"
  15. // Stub version
  16. #define NETMON_STUB_VERSION "(float) 1.0"
  17. #pragma hdrstop
  18. CG_STATUS
  19. CG_NETMONSTUB_FILE::GenCode(
  20. CCB * pCCB)
  21. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  22. Routine Description:
  23. Generate the Netmon stub file for classic and object interfaces
  24. Arguments:
  25. pCCB - The code gen controller block.
  26. Return Value:
  27. CG_OK if all is well.
  28. Notes:
  29. ----------------------------------------------------------------------------*/
  30. {
  31. ISTREAM Stream( GetFileName(), 4 );
  32. ISTREAM * pStream = pCCB->SetStream( &Stream, this );
  33. m_pCCB = pCCB;
  34. m_pStream = pStream;
  35. // Scan for interfaces of the appropriate type
  36. ScanInterfaces();
  37. if (!m_bDoObject && !m_bClassic ||
  38. m_bDoObject && !m_bObject) {
  39. m_pStream->Close();
  40. return CG_OK;
  41. }
  42. // If m_bDoObject is TRUE, then we're producing a stub file for object interfaces;
  43. // otherwise, we're doing classic interfaces
  44. if (m_bDoObject) {
  45. EmitFileHeadingBlock (pCCB, "code for an object interface Netmon stub DLL",
  46. "This file should be compiled as source for a DLL, linked with rpcrt4.lib");
  47. } else {
  48. EmitFileHeadingBlock (pCCB, "code for a classic interface Netmon stub DLL",
  49. "This file should be compiled as source for a DLL, linked with rpcrt4.lib");
  50. }
  51. // Write standard include files
  52. EmitStandardIncludes();
  53. // Write local include files
  54. EmitLocalIncludes();
  55. // Write definitions (#defines and variables needed by the code)
  56. EmitDefinitions();
  57. if (m_bDoObject) {
  58. // We seem to need this to solve a link error
  59. OpenComment();
  60. EmitComment ("This implementation is needed to solve a link error");
  61. CloseComment();
  62. pStream->NewLine();
  63. pStream->Write ("ULONG STDMETHODCALLTYPE CStdStubBuffer_Release "\
  64. "(IRpcStubBuffer *This) { ULONG u = 0; return u; }");
  65. // Write the special data for object interfaces
  66. EmitObjectInterfaceData();
  67. }
  68. // Write the server and client debug procedures for each interface
  69. EmitDebugProcedures();
  70. // Write the data tables
  71. EmitDataTables();
  72. // Close the header block
  73. EmitFileClosingBlock( pCCB );
  74. // Close the stream
  75. pStream->Close();
  76. return CG_OK;
  77. }
  78. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  79. Routine Descriptions:
  80. Determine which types of interfaces (object or classic) we have and how many,
  81. adding the names to the interface table
  82. Arguments:
  83. Return Value:
  84. TRUE if yes
  85. FALSE if no
  86. Notes:
  87. ----------------------------------------------------------------------------*/
  88. CG_STATUS CG_NETMONSTUB_FILE::ScanInterfaces() {
  89. CG_ITERATOR I;
  90. CG_NDR * pCG;
  91. GetMembers( I );
  92. while( ITERATOR_GETNEXT( I, pCG ) )
  93. {
  94. // We check GetChild()'s non-nullness here and elsewhere in the code because
  95. // there are object interfaces without children that cause problems, such as IUnknown
  96. if (pCG->GetChild()) {
  97. switch(pCG->GetCGID())
  98. {
  99. case ID_CG_INTERFACE:
  100. m_bClassic = TRUE;
  101. m_lNumClassicInterfaces ++;
  102. m_itInterfaceTable.AddInterface (((CG_INTERFACE*)pCG)->GetInterfaceName());
  103. break;
  104. case ID_CG_OBJECT_INTERFACE:
  105. m_bObject = TRUE;
  106. m_lNumObjectInterfaces ++;
  107. m_itInterfaceTable.AddInterface (((CG_INTERFACE*)pCG)->GetInterfaceName());
  108. break;
  109. default:
  110. break;
  111. }
  112. }
  113. }
  114. return CG_OK;
  115. }
  116. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  117. Routine Descriptions:
  118. Respectively,
  119. -Open a comment block
  120. -Write comments
  121. -Close a comment block
  122. Arguments:
  123. pszString is the comment that should be emitted
  124. Return Value:
  125. CG_OK if all is well.
  126. Notes:
  127. ----------------------------------------------------------------------------*/
  128. CG_STATUS CG_NETMONSTUB_FILE::OpenComment() {
  129. m_pStream->NewLine();
  130. m_pStream->NewLine();
  131. m_pStream->Write ("/*");
  132. return CG_OK;
  133. }
  134. CG_STATUS CG_NETMONSTUB_FILE::EmitComment (char* pszString) {
  135. m_pStream->NewLine();
  136. m_pStream->Write (" * ");
  137. m_pStream->Write (pszString);
  138. return CG_OK;
  139. }
  140. CG_STATUS CG_NETMONSTUB_FILE::CloseComment() {
  141. m_pStream->NewLine();
  142. m_pStream->Write (" */");
  143. return CG_OK;
  144. }
  145. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  146. Routine Description:
  147. Generate the standard includes for the netmon stub dll
  148. Arguments:
  149. Return Value:
  150. CG_OK if all is well.
  151. Notes:
  152. ----------------------------------------------------------------------------*/
  153. CG_STATUS CG_NETMONSTUB_FILE::EmitStandardIncludes() {
  154. m_pStream->NewLine();
  155. m_pStream->Write ("#include <stdio.h>");
  156. return CG_OK;
  157. }
  158. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  159. Routine Description:
  160. Generate the local includes for the netmon stub dll.
  161. Arguments:
  162. Return Value:
  163. CG_OK if all is well.
  164. Notes:
  165. Local includes are the proxy and iid files for object interfaces
  166. and the stub file for classic interfaces.
  167. ----------------------------------------------------------------------------*/
  168. CG_STATUS CG_NETMONSTUB_FILE::EmitLocalIncludes() {
  169. m_pStream->NewLine(2);
  170. // This is defined to avoid target errors
  171. m_pStream->Write ("#define _WIN32_DCOM");
  172. // Write includes
  173. m_pStream->NewLine();
  174. if (m_bDoObject) {
  175. m_pStream->Write ("#include \"");
  176. m_pStream->Write (pCommand->GetProxyFName());
  177. m_pStream->Write ("\"");
  178. m_pStream->NewLine();
  179. m_pStream->Write ("#include \"");
  180. m_pStream->Write (pCommand->GetIIDFName());
  181. m_pStream->Write ("\"");
  182. m_pStream->NewLine();
  183. } else {
  184. m_pStream->Write ("#include \"");
  185. m_pStream->Write (pCommand->GetSstubFName());
  186. m_pStream->Write ("\"");
  187. m_pStream->NewLine();
  188. }
  189. return CG_OK;
  190. }
  191. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  192. Routine Description:
  193. Generate any definitions needed by the netmon stub dll.
  194. Arguments:
  195. Return Value:
  196. CG_OK if all is well.
  197. Notes:
  198. ----------------------------------------------------------------------------*/
  199. const char* ppszIncludeBlock[] = {
  200. "#define DLL_EXPORT_PROC(x) __declspec(dllexport) GLOBAL_INTERFACE_DATA* GetGlobalInterfaceData__##x () { return &GlobalInterfaceData__##x ; }",
  201. "#define NetmonStubAllocate(x) malloc(x)",
  202. "#define Debug() *pNull = 0",
  203. "static DWORD* pNull = NULL;",
  204. NULL
  205. };
  206. const char* ppszGlobalInterfaceDataStructure[] = {
  207. "float Version;",
  208. "char* InterfaceName;",
  209. "DWORD ProcFormatStringSize;",
  210. "DWORD NumProcedures;",
  211. "char** ProcedureNames;",
  212. "SERVER_ROUTINE* ServerRoutineTable;",
  213. "SERVER_ROUTINE* ClientRoutineTable;",
  214. "RPC_SERVER_INTERFACE* RpcServerInterface;",
  215. "void* DebugArgumentBuffer;",
  216. NULL
  217. };
  218. CG_STATUS CG_NETMONSTUB_FILE::EmitDefinitions() {
  219. if (!m_bDoObject) {
  220. m_pStream->NewLine();
  221. m_pStream->Write ("#pragma warning (disable : 4700) /* No warnings from the "\
  222. "use of uninitialized variables */");
  223. m_pStream->NewLine();
  224. }
  225. m_pStream->WriteBlock (ppszIncludeBlock);
  226. OpenComment();
  227. EmitComment ("Structure used to encapsulate all relevant interface information");
  228. CloseComment();
  229. m_pStream->NewLine(2);
  230. m_pStream->Write ("typedef struct _GLOBAL_INTERFACE_DATA {");
  231. Out_IndentInc( m_pCCB );
  232. m_pStream->WriteBlock (ppszGlobalInterfaceDataStructure);
  233. Out_IndentDec( m_pCCB );
  234. m_pStream->NewLine();
  235. m_pStream->Write ("} GLOBAL_INTERFACE_DATA;");
  236. OpenComment();
  237. EmitComment ("Function used to view unmarshalled argument buffers");
  238. CloseComment();
  239. m_pStream->NewLine();
  240. m_pStream->Write ("static void DebugArgumentBuffer (BYTE* ArgumentBuffer, DWORD BufferSize) "\
  241. "{ Debug(); }");
  242. return CG_OK;
  243. }
  244. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  245. Routine Description:
  246. Generate the data used specifically by object interfaces.
  247. Arguments:
  248. Return Value:
  249. CG_OK if all is well.
  250. Notes:
  251. ----------------------------------------------------------------------------*/
  252. CG_STATUS CG_NETMONSTUB_FILE::EmitObjectInterfaceData() {
  253. CG_ITERATOR I;
  254. CG_NDR * pCG;
  255. OpenComment();
  256. EmitComment ("Data used specifically by object interfaces");
  257. CloseComment();
  258. // Loop through all interfaces
  259. GetMembers( I );
  260. while( ITERATOR_GETNEXT( I, pCG ) ) {
  261. if (pCG->GetChild()) {
  262. switch(pCG->GetCGID()) {
  263. case ID_CG_OBJECT_INTERFACE:
  264. // Emit the object interface RPC_SERVER_INTERFACE structures
  265. OpenComment();
  266. EmitComment ("RPC_SERVER_INTERFACE structure for object interface ");
  267. m_pStream->Write (pCG->GetSymName());
  268. CloseComment();
  269. EmitRPCServerInterface ((CG_INTERFACE*) pCG);
  270. break;
  271. default:
  272. break;
  273. }
  274. }
  275. }
  276. return CG_OK;
  277. }
  278. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  279. Routine Description:
  280. Generate an RPC_SERVER_INTERFACE structure for the given interface
  281. Arguments:
  282. Return Value:
  283. CG_OK if all is well.
  284. Notes:
  285. Most of the code was taken from misccls.cxx -> CG_INTERFACE::GenServerStub
  286. ----------------------------------------------------------------------------*/
  287. CG_STATUS CG_NETMONSTUB_FILE::EmitRPCServerInterface (CG_INTERFACE* pCG) {
  288. GUID_STRS TransferSyntaxGuid( TRANSFER_SYNTAX_GUID_STR_1,
  289. TRANSFER_SYNTAX_GUID_STR_2,
  290. TRANSFER_SYNTAX_GUID_STR_3,
  291. TRANSFER_SYNTAX_GUID_STR_4,
  292. TRANSFER_SYNTAX_GUID_STR_5);
  293. GUID_STRS GuidStrs;
  294. unsigned short M, m;
  295. char Buffer[ _MAX_DRIVE + _MAX_DIR + _MAX_FNAME + _MAX_EXT + 1 ];
  296. long ProtSeqEPCount = 0;
  297. ITERATOR * pProtSeqIterator;
  298. GuidStrs = pCG->GetGuidStrs();
  299. m_pCCB->SetInterfaceCG (pCG);
  300. m_pCCB->SetInterfaceName (pCG->GetInterfaceName());
  301. m_pCCB->GetVersion( &M,&m );
  302. sprintf( Buffer,
  303. "&%s_%s_DispatchTable",
  304. pCG->GetInterfaceName(),
  305. m_pCCB->GenMangledName()
  306. );
  307. if ( ( pProtSeqIterator = pCG->GetProtSeqEps() ) != 0 )
  308. {
  309. ProtSeqEPCount = ITERATOR_GETCOUNT( *pProtSeqIterator );
  310. Out_EP_Info( m_pCCB, pProtSeqIterator );
  311. }
  312. Out_IFInfo( m_pCCB, // controller block.
  313. RPC_S_INT_INFO_TYPE_NAME, // interface info type name.
  314. RPC_S_INT_INFO_STRUCT_NAME, // variable name.
  315. SIZEOF_RPC_SERVER_INTERFACE, // string speicifying size.
  316. GuidStrs, // Guid specified in idl
  317. M, // user specified major version
  318. m, // user specified minor version
  319. // TransferSyntaxGuid, // ndr identifying guid.
  320. // NDR_UUID_MAJOR_VERSION, // ndr's version
  321. // NDR_UUID_MINOR_VERSION,
  322. NULL, //Buffer,
  323. ProtSeqEPCount, // if this is 0, then the next
  324. // 2 fields are ignored by the call.
  325. PROTSEQ_EP_TYPE_NAME, // RPC_PROTSEQ_ENDPOINT
  326. PROTSEQ_EP_VAR_NAME, // ___RpcProtSeqEndpoint
  327. m_pCCB->IsNoDefaultEpv(),
  328. 1,
  329. pCG->HasPipes()
  330. );
  331. return CG_OK;
  332. }
  333. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  334. Routine Description:
  335. Generate the debug procedures for all interfaces
  336. Arguments:
  337. Return Value:
  338. CG_OK if all is well.
  339. Notes:
  340. ----------------------------------------------------------------------------*/
  341. CG_STATUS CG_NETMONSTUB_FILE::EmitDebugProcedures() {
  342. CG_ITERATOR I;
  343. CG_NDR * pCG;
  344. CG_PROC * pProc;
  345. CG_INTERFACE * pInt;
  346. ID_CG idCg;
  347. ITERATOR IProc;
  348. char* pszInterfaceName, * pszLastInterfaceName, * pszOurInterfaceName;
  349. // Write midl malloc and free if we're writing a classic interface stub
  350. if (!m_bDoObject) {
  351. OpenComment();
  352. EmitComment ("Procedures used by the runtime to allocate and free memory");
  353. CloseComment();
  354. m_pStream->NewLine(2);
  355. m_pStream->Write (
  356. "static void * __RPC_API midl_user_allocate(size_t len) { return NetmonStubAllocate(len); }");
  357. m_pStream->NewLine();
  358. m_pStream->Write (
  359. "static void __RPC_API midl_user_free(void * ptr) { free(ptr); }");
  360. }
  361. OpenComment();
  362. EmitComment ("Implementation of debug server and client functions for all ");
  363. if (m_bDoObject) {
  364. m_pStream->Write ("object");
  365. } else {
  366. m_pStream->Write ("classic");
  367. }
  368. m_pStream->Write (" interfaces");
  369. CloseComment();
  370. // Loop through all interfaces
  371. GetMembers( I );
  372. while( ITERATOR_GETNEXT( I, pCG ) )
  373. {
  374. if (pCG->GetChild()) {
  375. pInt = (CG_INTERFACE*) pCG;
  376. idCg = pCG->GetCGID();
  377. switch(idCg) {
  378. case ID_CG_INTERFACE:
  379. if (!m_bDoObject) {
  380. // Loop through all member functions
  381. pInt->GetAllMemberFunctions( IProc );
  382. while( ITERATOR_GETNEXT( IProc, pProc ) ) {
  383. EmitServerClientDebugProcedure (pProc, FALSE);
  384. // Emit the procedure as is (to avoid link errors)
  385. m_pStream->NewLine(2);
  386. m_pStream->Write ("static");
  387. Out_ClientProcedureProlog( m_pCCB, pProc->GetType() );
  388. Out_IndentInc( m_pCCB );
  389. // Return a variable of the appropriate return value
  390. if (((node_proc*) pProc->GetType())->HasReturn()) {
  391. m_pStream->Spaces( STANDARD_STUB_TAB );
  392. m_pStream->Write( pProc->GetReturnType()->GetSymName() );
  393. m_pStream->Write(" RetVal;");
  394. m_pStream->NewLine();
  395. m_pStream->Write( "return RetVal;" );
  396. }
  397. // Close the procedure
  398. Out_IndentDec( m_pCCB );
  399. Out_ProcClosingBrace( m_pCCB );
  400. }
  401. }
  402. break;
  403. case ID_CG_OBJECT_INTERFACE:
  404. if (m_bDoObject) {
  405. pszOurInterfaceName = pInt->GetInterfaceName();
  406. pszLastInterfaceName = NULL;
  407. // Loop through all member functions
  408. pInt->GetAllMemberFunctions ( IProc);
  409. while( ITERATOR_GETNEXT( IProc, pProc ) ) {
  410. // Get the procedure's real interface name
  411. pszInterfaceName = pProc->GetInterfaceNode()->GetInterfaceName();
  412. // Write the function if:
  413. // a) We're its real interface.
  414. // b) The interface hasn't been used yet and it's not IUnknown
  415. // c) The interface name is the same as the last one we used
  416. // (so it's OK to use it again)
  417. if (strcmp (pszInterfaceName, pszOurInterfaceName) == 0 ||
  418. (!m_itOutputInterfaceTable.FindInterface (pszInterfaceName) &&
  419. strcmp (pszInterfaceName, "IUnknown") != 0) ||
  420. (pszLastInterfaceName != NULL &&
  421. strcmp (pszInterfaceName, pszLastInterfaceName) == 0)
  422. ) {
  423. // Write the server and client debug procedures
  424. EmitServerClientDebugProcedure (pProc, TRUE);
  425. // Add the interface name to the table of used interfaces
  426. m_itOutputInterfaceTable.AddInterface (pszInterfaceName);
  427. // Record the last interface name used
  428. pszLastInterfaceName = pszInterfaceName;
  429. }
  430. }
  431. }
  432. break;
  433. default:
  434. break;
  435. }
  436. }
  437. }
  438. return CG_OK;
  439. }
  440. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  441. Routine Description:
  442. Generate server, client and link stub procedures for a given procedure
  443. Arguments:
  444. pProc -> The procedure to be processed
  445. bIsObject -> TRUE if the procedure belongs to an object interface
  446. FALSE otherwise
  447. Return Value:
  448. CG_OK if all is well.
  449. Notes:
  450. This function is long and ugly
  451. ----------------------------------------------------------------------------*/
  452. CG_STATUS CG_NETMONSTUB_FILE::EmitServerClientDebugProcedure (CG_PROC* pProc, BOOL bIsObject) {
  453. PNAME pszProcName, pszNewProcName;
  454. node_proc * pNodeProc = ((node_proc*) pProc->GetType());
  455. node_param * pRetValParam, * pThisParam, * pParam;
  456. node_skl * pOldRetType;
  457. node_base_type * pVoidBaseType;
  458. type_node_list ITypeNodeList;
  459. short i, siNumArgs;
  460. PNAME* ppszOldArgName;
  461. PNAME* ppszNewArgName;
  462. node_base_attr * pNodeAttribIn, * pNodeAttribOut;
  463. BOOL bHasReturn = pNodeProc->HasReturn();
  464. // Get the procedure name
  465. pszProcName = pProc->GetSymName();
  466. // Rename the procedure to Server__InterfaceName__ProcName
  467. pszNewProcName = new char [strlen (pProc->GetInterfaceName()) +
  468. strlen (pszProcName) + 11];
  469. sprintf ( pszNewProcName, "Server__%s__%s", pProc->GetInterfaceName(), pszProcName );
  470. pNodeProc->SetSymName ( pszNewProcName );
  471. // Set void type
  472. pVoidBaseType = new node_base_type( NODE_VOID, ATTR_BASE );
  473. pVoidBaseType->SetSymName( "void" );
  474. pOldRetType = pNodeProc->GetChild();
  475. pNodeProc->SetChild( pVoidBaseType );
  476. // Rename the arguments to IN__Name, OUT__Name or IN_OUT__name
  477. i = 0;
  478. siNumArgs = pNodeProc->GetNumberOfArguments();
  479. ppszOldArgName = new PNAME [siNumArgs];
  480. ppszNewArgName = new PNAME [siNumArgs];
  481. pNodeProc->GetParameterList (&ITypeNodeList);
  482. while( ITERATOR_GETNEXT( ITypeNodeList, pParam ) ) {
  483. MIDL_ASSERT (i < siNumArgs);
  484. ppszOldArgName[i] = pParam->GetSymName();
  485. ppszNewArgName[i] = new char [strlen (ppszOldArgName[i]) + 10];
  486. if ((pNodeAttribIn = pParam->GetAttribute (ATTR_IN)) &&
  487. (pNodeAttribOut = pParam->GetAttribute (ATTR_OUT))) {
  488. sprintf (ppszNewArgName[i], "IN_OUT__%s", ppszOldArgName[i]);
  489. } else {
  490. if (pNodeAttribIn) {
  491. sprintf (ppszNewArgName[i], "IN__%s", ppszOldArgName[i]);
  492. } else {
  493. sprintf (ppszNewArgName[i], "OUT__%s", ppszOldArgName[i]);
  494. }
  495. }
  496. pParam->SetSymName (ppszNewArgName[i]);
  497. i ++;
  498. delete []ppszOldArgName;
  499. delete []ppszNewArgName;
  500. }
  501. // If proc belongs to an object interface, add the 'this' pointer
  502. if (bIsObject) {
  503. pThisParam = new node_param();
  504. pThisParam->SetAttribute (ATTR_IN);
  505. pThisParam->SetSymName ("this");
  506. pThisParam->SetBasicType( (node_skl *) new node_def( "void*" ));
  507. pThisParam->SetEdgeType( EDGE_USE );
  508. pNodeProc->AddFirstMember (pThisParam);
  509. }
  510. // Emit the server procedure
  511. m_pStream->NewLine(2);
  512. m_pStream->Write ("static");
  513. Out_ClientProcedureProlog( m_pCCB, pNodeProc );
  514. Out_IndentInc( m_pCCB );
  515. m_pStream->Spaces( STANDARD_STUB_TAB );
  516. m_pStream->Write( "Debug();" );
  517. Out_IndentDec( m_pCCB );
  518. Out_ProcClosingBrace( m_pCCB );
  519. // Rename the procedure to Client__InterfaceName__ProcName
  520. sprintf( pszNewProcName, "Client__%s__%s", pProc->GetInterfaceName(), pszProcName );
  521. // Add a RetVal parameter to the param list if the function isn't void
  522. if (bHasReturn) {
  523. pRetValParam = new node_param();
  524. pRetValParam->SetAttribute (ATTR_IN);
  525. pRetValParam->SetSymName ("RetVal");
  526. pRetValParam->SetBasicType( (node_skl *) new node_def( pProc->GetReturnType()->GetSymName() ));
  527. pRetValParam->SetEdgeType( EDGE_USE );
  528. pNodeProc->AddLastMember (pRetValParam);
  529. }
  530. // Emit the client procedure
  531. m_pStream->NewLine(2);
  532. m_pStream->Write ("static");
  533. Out_ClientProcedureProlog( m_pCCB, pNodeProc );
  534. Out_IndentInc( m_pCCB );
  535. m_pStream->Spaces( STANDARD_STUB_TAB );
  536. m_pStream->Write( "Debug();" );
  537. Out_IndentDec( m_pCCB );
  538. Out_ProcClosingBrace( m_pCCB );
  539. // Delete the this parameter we created
  540. if (bIsObject) {
  541. pNodeProc->RemoveFirstMember();
  542. delete pThisParam;
  543. }
  544. // Delete the RetVal from the param List
  545. if (bHasReturn) {
  546. pNodeProc->RemoveLastMember();
  547. delete pRetValParam;
  548. }
  549. // Restore the procedure's name
  550. pNodeProc->SetSymName( pszProcName );
  551. // Restore the procedure's parameter names
  552. if (siNumArgs > 0) {
  553. i = 0;
  554. pNodeProc->GetParameterList (&ITypeNodeList);
  555. while( ITERATOR_GETNEXT( ITypeNodeList, pParam ) ) {
  556. pParam->SetSymName (ppszOldArgName[i]);
  557. delete [] ppszNewArgName[i];
  558. i ++;
  559. }
  560. delete [] ppszNewArgName;
  561. delete [] ppszOldArgName;
  562. }
  563. // Restore the node's return type
  564. pNodeProc->SetChild( pOldRetType );
  565. // Delete the fake void type node we created
  566. delete pVoidBaseType;
  567. // Delete the new name we created
  568. delete [] pszNewProcName;
  569. return CG_OK;
  570. }
  571. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  572. Routine Description:
  573. Generate data tables for each interface
  574. Arguments:
  575. Return Value:
  576. CG_OK if all is well.
  577. Notes:
  578. ----------------------------------------------------------------------------*/
  579. CG_STATUS CG_NETMONSTUB_FILE::EmitDataTables() {
  580. // Write procedure name tables for each interface
  581. EmitProcNameTables();
  582. // Write the server and client lookup tables for each interface
  583. EmitServerClientTables();
  584. // Write the global_interface_data structures and exports for each interface
  585. EmitGlobalInterfaceData();
  586. return CG_OK;
  587. }
  588. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  589. Routine Description:
  590. Generate tables with each interface's procedure names and the number of
  591. procedures in each interface.
  592. Arguments:
  593. Return Value:
  594. CG_OK if all is well.
  595. Notes:
  596. ----------------------------------------------------------------------------*/
  597. CG_STATUS CG_NETMONSTUB_FILE::EmitProcNameTables() {
  598. CG_ITERATOR I;
  599. CG_NDR * pCG;
  600. CG_INTERFACE* pInt;
  601. ITERATOR IProc;
  602. CG_PROC * pProc;
  603. long lNumProcs;
  604. BOOL bBeenHereBefore;
  605. char* pszInterfaceName;
  606. char pszTemp [1024];
  607. GetMembers( I );
  608. while( ITERATOR_GETNEXT( I, pCG ) ) {
  609. if (pCG->GetChild()) {
  610. pInt = (CG_INTERFACE*) pCG;
  611. if (m_bDoObject && pCG->GetCGID() == ID_CG_OBJECT_INTERFACE ||
  612. !m_bDoObject && pCG->GetCGID() == ID_CG_INTERFACE) {
  613. lNumProcs = 0;
  614. bBeenHereBefore = FALSE;
  615. pszInterfaceName = pInt->GetInterfaceName();
  616. OpenComment();
  617. EmitComment ("Procedure tables for interface ");
  618. m_pStream->Write (pszInterfaceName);
  619. CloseComment();
  620. m_pStream->NewLine();
  621. sprintf (pszTemp, "static char* %s__ProcedureNames[] = {", pszInterfaceName);
  622. m_pStream->Write (pszTemp);
  623. Out_IndentInc( m_pCCB );
  624. pInt->GetAllMemberFunctions ( IProc);
  625. while( ITERATOR_GETNEXT( IProc, pProc ) ) {
  626. pszInterfaceName = pProc->GetInterfaceNode()->GetInterfaceName();
  627. if (strcmp (pszInterfaceName, "IUnknown") != 0) {
  628. // Write a comma if we're not the first function in the list
  629. if (bBeenHereBefore) {
  630. m_pStream->Write (",");
  631. } else {
  632. bBeenHereBefore = TRUE;
  633. }
  634. // Write procedure name enclosed in quotes
  635. m_pStream->NewLine();
  636. m_pStream->Write ("\"");
  637. m_pStream->Write (pProc->GetSymName());
  638. m_pStream->Write ("\"");
  639. // Increment procedure count
  640. lNumProcs ++;
  641. }
  642. }
  643. Out_IndentDec( m_pCCB );
  644. m_pStream->NewLine();
  645. m_pStream->Write ("};");
  646. // Set number of procedures in interface table
  647. m_itInterfaceTable.SetNumProcedures (pszInterfaceName, lNumProcs);
  648. }
  649. } // if
  650. } // while
  651. return CG_OK;
  652. }
  653. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  654. Routine Description:
  655. Generate the server and client lookup tables for each interface
  656. Arguments:
  657. Return Value:
  658. CG_OK if all is well.
  659. Notes:
  660. ----------------------------------------------------------------------------*/
  661. CG_STATUS CG_NETMONSTUB_FILE::EmitServerClientTables() {
  662. CG_ITERATOR I;
  663. CG_NDR * pCG;
  664. CG_INTERFACE* pInt;
  665. ITERATOR IProc;
  666. CG_PROC * pProc;
  667. char* pszInterfaceName;
  668. GetMembers( I );
  669. while( ITERATOR_GETNEXT( I, pCG ) ) {
  670. if (pCG->GetChild()) {
  671. if (m_bDoObject && pCG->GetCGID() == ID_CG_OBJECT_INTERFACE ||
  672. !m_bDoObject && pCG->GetCGID() == ID_CG_INTERFACE) {
  673. pInt = (CG_INTERFACE*) pCG;
  674. pszInterfaceName = pInt->GetInterfaceName();
  675. // Write the server table
  676. OpenComment();
  677. EmitComment ("Debug server procedures for interface ");
  678. m_pStream->Write (pszInterfaceName);
  679. CloseComment();
  680. m_pStream->NewLine();
  681. m_pStream->Write ("static SERVER_ROUTINE ");
  682. m_pStream->Write (pszInterfaceName);
  683. m_pStream->Write ("__ServerRoutineTable[] = {");
  684. Out_IndentInc( m_pCCB );
  685. // If we're processing an object interface,
  686. // we have to make room for the 3 IUnknown procedures
  687. if (m_bDoObject) {
  688. m_pStream->NewLine();
  689. m_pStream->Write ("NULL,");
  690. m_pStream->NewLine();
  691. m_pStream->Write ("NULL,");
  692. m_pStream->NewLine();
  693. m_pStream->Write ("NULL,");
  694. }
  695. pInt->GetAllMemberFunctions ( IProc);
  696. while( ITERATOR_GETNEXT( IProc, pProc ) ) {
  697. pszInterfaceName = pProc->GetInterfaceNode()->GetInterfaceName();
  698. if (strcmp (pszInterfaceName, "IUnknown") != 0) {
  699. m_pStream->NewLine();
  700. m_pStream->Write ("(SERVER_ROUTINE)Server__");
  701. m_pStream->Write (pProc->GetInterfaceNode()->GetSymName());
  702. m_pStream->Write ("__");
  703. m_pStream->Write (pProc->GetSymName());
  704. m_pStream->Write (",");
  705. }
  706. }
  707. Out_IndentDec( m_pCCB );
  708. m_pStream->NewLine();
  709. m_pStream->Write ("};");
  710. // Write client table
  711. OpenComment();
  712. EmitComment ("Debug client procedures for interface ");
  713. m_pStream->Write (pszInterfaceName);
  714. CloseComment();
  715. m_pStream->NewLine();
  716. m_pStream->Write ("static SERVER_ROUTINE ");
  717. m_pStream->Write (pszInterfaceName);
  718. m_pStream->Write ("__ClientRoutineTable[] = {");
  719. Out_IndentInc( m_pCCB );
  720. // If we're processing an object interface,
  721. // we have to make room for the 3 IUnknown procedures
  722. if (m_bDoObject) {
  723. m_pStream->NewLine();
  724. m_pStream->Write ("NULL,");
  725. m_pStream->NewLine();
  726. m_pStream->Write ("NULL,");
  727. m_pStream->NewLine();
  728. m_pStream->Write ("NULL,");
  729. }
  730. pInt->GetAllMemberFunctions ( IProc);
  731. while( ITERATOR_GETNEXT( IProc, pProc ) ) {
  732. pszInterfaceName = pProc->GetInterfaceNode()->GetInterfaceName();
  733. if (strcmp (pszInterfaceName, "IUnknown") != 0) {
  734. m_pStream->NewLine();
  735. m_pStream->Write ("(SERVER_ROUTINE)Client__");
  736. m_pStream->Write (pProc->GetInterfaceNode()->GetSymName());
  737. m_pStream->Write ("__");
  738. m_pStream->Write (pProc->GetSymName());
  739. m_pStream->Write (",");
  740. }
  741. }
  742. Out_IndentDec( m_pCCB );
  743. m_pStream->NewLine();
  744. m_pStream->Write ("};");
  745. }
  746. }
  747. }
  748. return CG_OK;
  749. }
  750. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  751. Routine Description:
  752. Generate the global interface data structures for each interface, as well
  753. as the export functions that return them
  754. Arguments:
  755. Return Value:
  756. CG_OK if all is well.
  757. Notes:
  758. ----------------------------------------------------------------------------*/
  759. CG_STATUS CG_NETMONSTUB_FILE::EmitGlobalInterfaceData() {
  760. CG_ITERATOR I;
  761. CG_NDR * pCG;
  762. ID_CG idCG;
  763. char pszTemp [100], * pszInterfaceName, * pszFixedUuid;
  764. char * p1, * p2, * p3, * p4, * p5;
  765. long lNumProcs;
  766. size_t lLength;
  767. GetMembers( I );
  768. while( ITERATOR_GETNEXT( I, pCG ) ) {
  769. idCG = pCG->GetCGID();
  770. if (((idCG == ID_CG_OBJECT_INTERFACE && m_bDoObject) ||
  771. (idCG == ID_CG_INTERFACE && !m_bDoObject)) &&
  772. pCG->GetChild()) {
  773. // Get the underscored uuid
  774. ((CG_INTERFACE*) pCG)->GetGuidStrs().GetStrs (p1, p2, p3, p4, p5);
  775. lLength = (long) strlen (p1) + strlen (p2) + strlen (p3) + strlen (p4) + strlen (p5);
  776. pszFixedUuid = new char [lLength + 5];
  777. sprintf (pszFixedUuid, "%s_%s_%s_%s_%s", p1, p2, p3, p4, p5);
  778. pszFixedUuid = _strlwr (pszFixedUuid);
  779. // Get the interface name
  780. pszInterfaceName = pCG->GetSymName();
  781. // Write a comment
  782. OpenComment();
  783. EmitComment ("GLOBAL_INTERFACE_DATA structure for interface ");
  784. m_pStream->Write (pszInterfaceName);
  785. CloseComment();
  786. // Header
  787. m_pStream->NewLine();
  788. m_pStream->Write ("static GLOBAL_INTERFACE_DATA GlobalInterfaceData__");
  789. m_pStream->Write (pszFixedUuid);
  790. m_pStream->Write (" = {");
  791. Out_IndentInc( m_pCCB );
  792. // Version
  793. m_pStream->NewLine();
  794. m_pStream->Write (NETMON_STUB_VERSION);
  795. m_pStream->Write (",");
  796. // Name
  797. m_pStream->NewLine();
  798. m_pStream->Write ("\"");
  799. m_pStream->Write (pszInterfaceName);
  800. m_pStream->Write ("\",");
  801. // Proc format string size
  802. m_pStream->NewLine();
  803. m_pStream->Write ("PROC_FORMAT_STRING_SIZE,");
  804. // NumProcs
  805. m_pStream->NewLine();
  806. if (m_itInterfaceTable.GetNumProcedures (pszInterfaceName, &lNumProcs)) {
  807. m_pStream->Write (_itoa (lNumProcs, pszTemp, 10));
  808. } else {
  809. MIDL_ASSERT (FALSE);
  810. }
  811. m_pStream->Write (",");
  812. // Proc name table
  813. m_pStream->NewLine();
  814. m_pStream->Write (pszInterfaceName);
  815. m_pStream->Write ("__ProcedureNames,");
  816. // Server routine table
  817. m_pStream->NewLine();
  818. m_pStream->Write (pszInterfaceName);
  819. m_pStream->Write ("__ServerRoutineTable,");
  820. // Client routine table
  821. m_pStream->NewLine();
  822. m_pStream->Write (pszInterfaceName);
  823. m_pStream->Write ("__ClientRoutineTable,");
  824. // Rpc server interface pointer
  825. m_pStream->NewLine();
  826. m_pStream->Write ("(RPC_SERVER_INTERFACE*) &");
  827. m_pStream->Write (pszInterfaceName);
  828. m_pStream->Write ("___RpcServerInterface,");
  829. // DebugArgumentBuffer
  830. m_pStream->NewLine();
  831. m_pStream->Write ("(void*) DebugArgumentBuffer");
  832. Out_IndentDec( m_pCCB );
  833. m_pStream->NewLine();
  834. m_pStream->Write ("};");
  835. // Export function
  836. OpenComment();
  837. EmitComment ("Export function for interface ");
  838. m_pStream->Write (pszInterfaceName);
  839. CloseComment();
  840. m_pStream->NewLine();
  841. m_pStream->Write ("DLL_EXPORT_PROC (");
  842. m_pStream->Write (pszFixedUuid);
  843. m_pStream->Write (")");
  844. delete [] pszFixedUuid;
  845. }
  846. }
  847. return CG_OK;
  848. }
  849. /****************************************************
  850. * InterfaceTable implementations
  851. ****************************************************/
  852. #define NUM_BUCKETS 100
  853. NetmonStubFileInterfaceTable::NetmonStubFileInterfaceTable() {
  854. m_pTable = new NetmonStubFileInterfaceList [NUM_BUCKETS];
  855. }
  856. NetmonStubFileInterfaceTable::~NetmonStubFileInterfaceTable() {
  857. delete [] m_pTable;
  858. }
  859. void NetmonStubFileInterfaceTable::AddInterface (char* pszInterface) {
  860. m_pTable[GetHashValue (pszInterface)].AddInterface (pszInterface);
  861. }
  862. // Return true if the interface name was found
  863. BOOL NetmonStubFileInterfaceTable::FindInterface (char* pszInterface) {
  864. return m_pTable[GetHashValue (pszInterface)].FindInterface (pszInterface);
  865. }
  866. // Set the number of procedures in the interface
  867. BOOL NetmonStubFileInterfaceTable::SetNumProcedures (char* pszInterface, long lNumProcs) {
  868. return m_pTable[GetHashValue (pszInterface)].SetNumProcedures (pszInterface, lNumProcs);
  869. }
  870. // Get the number of procedures in the interface
  871. BOOL NetmonStubFileInterfaceTable::GetNumProcedures (char* pszInterface, long* plNumProcs) {
  872. return m_pTable[GetHashValue (pszInterface)].GetNumProcedures (pszInterface, plNumProcs);
  873. }
  874. // The hash value is just the sum of the characters in the interface name
  875. // mod the number of buckets in the table
  876. long NetmonStubFileInterfaceTable::GetHashValue (char* pszInterface) {
  877. long i, lSum = 0, lLen = (long) strlen (pszInterface);
  878. for (i = 0; i < lLen; i ++) {
  879. lSum += (long) pszInterface[i];
  880. }
  881. return lSum % NUM_BUCKETS;
  882. }
  883. /* InterfaceNode */
  884. NetmonStubFileInterfaceNode::NetmonStubFileInterfaceNode (char* pszInterface) {
  885. m_pszInterface = new char [strlen (pszInterface) + 1];
  886. strcpy (m_pszInterface, pszInterface);
  887. m_pNext = NULL;
  888. m_lNumProcs = 0;
  889. }
  890. NetmonStubFileInterfaceNode::~NetmonStubFileInterfaceNode() {
  891. delete [] m_pszInterface;
  892. }
  893. void NetmonStubFileInterfaceNode::SetNext (NetmonStubFileInterfaceNode* pNext) {
  894. m_pNext = pNext;
  895. }
  896. NetmonStubFileInterfaceNode* NetmonStubFileInterfaceNode::GetNext() {
  897. return m_pNext;
  898. }
  899. char* NetmonStubFileInterfaceNode::GetInterface() {
  900. return m_pszInterface;
  901. }
  902. void NetmonStubFileInterfaceNode::SetNumProcedures (long lNumProcs) {
  903. m_lNumProcs = lNumProcs;
  904. }
  905. long NetmonStubFileInterfaceNode::GetNumProcedures() {
  906. return m_lNumProcs;
  907. }
  908. /* InterfaceList */
  909. NetmonStubFileInterfaceList::NetmonStubFileInterfaceList() {
  910. m_pHead = NULL;
  911. m_pTail = NULL;
  912. }
  913. NetmonStubFileInterfaceList::~NetmonStubFileInterfaceList() {
  914. NetmonStubFileInterfaceNode* pNode = m_pHead, *pDeleteNode;
  915. while (pNode != NULL) {
  916. pDeleteNode = pNode;
  917. pNode = pNode->GetNext();
  918. delete pDeleteNode;
  919. }
  920. }
  921. void NetmonStubFileInterfaceList::AddInterface (char* pszInterface) {
  922. NetmonStubFileInterfaceNode* pNode = new NetmonStubFileInterfaceNode (pszInterface);
  923. if (m_pHead == NULL) {
  924. m_pHead = m_pTail = pNode;
  925. } else {
  926. m_pTail->SetNext (pNode);
  927. m_pTail = pNode;
  928. }
  929. }
  930. BOOL NetmonStubFileInterfaceList::FindInterface (char* pszInterface) {
  931. NetmonStubFileInterfaceNode* pNode = m_pHead;
  932. while (pNode != NULL) {
  933. if (strcmp (pszInterface, pNode->GetInterface()) == 0) {
  934. return TRUE;
  935. }
  936. pNode = pNode->GetNext();
  937. }
  938. return FALSE;
  939. }
  940. BOOL NetmonStubFileInterfaceList::SetNumProcedures (char* pszInterface, long lNumProcs) {
  941. NetmonStubFileInterfaceNode* pNode = m_pHead;
  942. while (pNode != NULL) {
  943. if (strcmp (pszInterface, pNode->GetInterface()) == 0) {
  944. pNode->SetNumProcedures (lNumProcs);
  945. return TRUE;
  946. }
  947. pNode = pNode->GetNext();
  948. }
  949. return FALSE;
  950. }
  951. BOOL NetmonStubFileInterfaceList::GetNumProcedures (char* pszInterface, long* plNumProcs) {
  952. NetmonStubFileInterfaceNode* pNode = m_pHead;
  953. while (pNode != NULL) {
  954. if (strcmp (pszInterface, pNode->GetInterface()) == 0) {
  955. *plNumProcs = pNode->GetNumProcedures();
  956. return TRUE;
  957. }
  958. pNode = pNode->GetNext();
  959. }
  960. return FALSE;
  961. }