1414
1515using System ;
1616using System . Collections . Generic ;
17+ using System . Linq ;
1718
1819namespace NtApiDotNet . Ndr
1920{
@@ -51,23 +52,39 @@ public interface INdrFormatter
5152 string FormatRpcServerInterface ( NdrRpcServerInterface rpc_server ) ;
5253 }
5354
55+ internal interface INdrFormatterInternal : INdrFormatter
56+ {
57+ string SimpleTypeToName ( NdrFormatCharacter format ) ;
58+ string FormatComment ( string comment ) ;
59+ string FormatComment ( string comment , params object [ ] args ) ;
60+ string FormatPointer ( string base_type ) ;
61+ string IidToName ( Guid iid ) ;
62+ string DemangleComName ( string name ) ;
63+ bool ShowProcedureParameterAttributes { get ; }
64+ }
65+
5466 /// <summary>
5567 /// An base class which describes a text formatter for NDR data.
5668 /// </summary>
57- internal class NdrFormatter : INdrFormatter
69+ internal class NdrFormatter : INdrFormatterInternal
5870 {
5971 private readonly IDictionary < Guid , string > _iids_to_name ;
6072 private readonly Func < string , string > _demangle_com_name ;
6173 private DefaultNdrFormatterFlags _flags ;
6274
75+ bool INdrFormatterInternal . ShowProcedureParameterAttributes { get { return true ; } }
76+
6377 internal NdrFormatter ( IDictionary < Guid , string > iids_to_names , Func < string , string > demangle_com_name , DefaultNdrFormatterFlags flags )
6478 {
6579 _iids_to_name = iids_to_names ;
66- _demangle_com_name = demangle_com_name ;
80+ _demangle_com_name = demangle_com_name ?? ( s => s ) ;
6781 _flags = flags ;
6882 }
69-
70- internal string IidToName ( Guid iid )
83+ string INdrFormatterInternal . IidToName ( Guid iid )
84+ {
85+ return IidToName ( iid ) ;
86+ }
87+ protected string IidToName ( Guid iid )
7188 {
7289 if ( _iids_to_name . ContainsKey ( iid ) )
7390 {
@@ -76,12 +93,12 @@ internal string IidToName(Guid iid)
7693 return null ;
7794 }
7895
79- internal string DemangleComName ( string name )
96+ string INdrFormatterInternal . DemangleComName ( string name )
8097 {
8198 return _demangle_com_name ( name ) ;
8299 }
83100
84- internal string SimpleTypeToName ( NdrFormatCharacter format )
101+ string INdrFormatterInternal . SimpleTypeToName ( NdrFormatCharacter format )
85102 {
86103 switch ( format )
87104 {
@@ -136,12 +153,21 @@ internal string SimpleTypeToName(NdrFormatCharacter format)
136153 return string . Format ( "{0}" , format ) ;
137154 }
138155
139- internal string FormatPointer ( string base_type )
156+ string INdrFormatterInternal . FormatPointer ( string base_type )
140157 {
141158 return $ "{ base_type } *";
142159 }
143160
144- internal string FormatComment ( string comment )
161+ string INdrFormatterInternal . FormatComment ( string comment )
162+ {
163+ return FormatComment ( comment ) ;
164+ }
165+ string INdrFormatterInternal . FormatComment ( string comment , params object [ ] args )
166+ {
167+ return FormatComment ( string . Format ( comment , args ) ) ;
168+ }
169+
170+ private string FormatComment ( string comment )
145171 {
146172 if ( ( _flags & DefaultNdrFormatterFlags . RemoveComments ) == DefaultNdrFormatterFlags . RemoveComments )
147173 {
@@ -150,11 +176,6 @@ internal string FormatComment(string comment)
150176 return $ "/* { comment } */";
151177 }
152178
153- internal string FormatComment ( string comment , params object [ ] args )
154- {
155- return FormatComment ( string . Format ( comment , args ) ) ;
156- }
157-
158179 string INdrFormatter . FormatComplexType ( NdrComplexTypeReference complex_type )
159180 {
160181 return complex_type . FormatComplexType ( this ) ;
@@ -176,6 +197,139 @@ string INdrFormatter.FormatRpcServerInterface(NdrRpcServerInterface rpc_server)
176197 }
177198 }
178199
200+
201+ /**
202+ * This formatter generates data that the CPP compiler can (hopefully) understand,
203+ * at least it will serve as a good skeleton to support spinning up new projects easily.
204+ * */
205+ internal class CppNdrFormatterInternal : NdrFormatter , INdrFormatterInternal
206+ {
207+ internal CppNdrFormatterInternal ( IDictionary < Guid , string > iids_to_names , Func < string , string > demangle_com_name , DefaultNdrFormatterFlags flags )
208+ : base ( iids_to_names , demangle_com_name , flags )
209+ {
210+
211+ }
212+
213+ bool INdrFormatterInternal . ShowProcedureParameterAttributes { get { return false ; } }
214+
215+ string INdrFormatterInternal . SimpleTypeToName ( NdrFormatCharacter format )
216+ {
217+ switch ( format )
218+ {
219+ case NdrFormatCharacter . FC_BYTE :
220+ case NdrFormatCharacter . FC_USMALL :
221+ return "uint8_t" ;
222+ case NdrFormatCharacter . FC_SMALL :
223+ case NdrFormatCharacter . FC_CHAR :
224+ return "int8_t" ;
225+ case NdrFormatCharacter . FC_WCHAR :
226+ return "wchar_t" ;
227+ case NdrFormatCharacter . FC_SHORT :
228+ return "int16_t" ;
229+ case NdrFormatCharacter . FC_USHORT :
230+ return "uint16_t" ;
231+ case NdrFormatCharacter . FC_LONG :
232+ return "int64_t" ;
233+ case NdrFormatCharacter . FC_ULONG :
234+ return "uint64_t" ;
235+ case NdrFormatCharacter . FC_FLOAT :
236+ return "float" ;
237+ case NdrFormatCharacter . FC_HYPER :
238+ return "int64_t" ;
239+ case NdrFormatCharacter . FC_DOUBLE :
240+ return "double" ;
241+ case NdrFormatCharacter . FC_INT3264 :
242+ return "intptr_t" ;
243+ case NdrFormatCharacter . FC_UINT3264 :
244+ return "uintptr_t" ;
245+ case NdrFormatCharacter . FC_C_WSTRING :
246+ case NdrFormatCharacter . FC_WSTRING :
247+ return "wchar_t" ;
248+ case NdrFormatCharacter . FC_C_CSTRING :
249+ case NdrFormatCharacter . FC_CSTRING :
250+ return "char" ;
251+ case NdrFormatCharacter . FC_ENUM16 :
252+ return "/* ENUM16 */ uint16_t" ;
253+ case NdrFormatCharacter . FC_ENUM32 :
254+ return "/* ENUM32 */ uint32_t" ;
255+ case NdrFormatCharacter . FC_SYSTEM_HANDLE :
256+ return "HANDLE" ;
257+ case NdrFormatCharacter . FC_AUTO_HANDLE :
258+ case NdrFormatCharacter . FC_CALLBACK_HANDLE :
259+ case NdrFormatCharacter . FC_BIND_CONTEXT :
260+ case NdrFormatCharacter . FC_BIND_PRIMITIVE :
261+ case NdrFormatCharacter . FC_BIND_GENERIC :
262+ return "handle_t" ;
263+ case NdrFormatCharacter . FC_ERROR_STATUS_T :
264+ return "uint" ;
265+ }
266+
267+ return string . Format ( "{0}" , format ) ;
268+ }
269+
270+ string INdrFormatter . FormatProcedure ( NdrProcedureDefinition procedure )
271+ {
272+ return FormatProcedure ( procedure ) ;
273+ }
274+ private string FormatProcedure ( NdrProcedureDefinition procedure )
275+ {
276+ string return_value ;
277+
278+ if ( procedure . ReturnValue == null )
279+ {
280+ return_value = "void" ;
281+ }
282+ else if ( procedure . ReturnValue . Type . Format == NdrFormatCharacter . FC_LONG )
283+ {
284+ return_value = "HRESULT" ;
285+ }
286+ else
287+ {
288+ return_value = procedure . ReturnValue . Type . FormatType ( this ) ;
289+ }
290+
291+ string procedureParameters = string . Join ( ", " , procedure . Params . Select (
292+ ( p , i ) => string . Format (
293+ "{0} {1} {2}" ,
294+ ( this as INdrFormatterInternal ) . FormatComment ( "Stack Offset: {0}" , p . Offset ) ,
295+ p . Format ( this ) ,
296+ p . FormatName ( i )
297+ )
298+ ) ) ;
299+ return string . Format ( "virtual {0} __stdcall {1}({2});" , return_value ,
300+ procedure . Name , procedureParameters ) ;
301+ }
302+
303+ string INdrFormatter . FormatComProxy ( NdrComProxyDefinition com_proxy )
304+ {
305+ NdrStringBuilder builder = new NdrStringBuilder ( ) ;
306+
307+ string base_name = this . IidToName ( com_proxy . BaseIid ) ;
308+ if ( base_name == null )
309+ {
310+ string unknown_iid = $ "Unknown IID { com_proxy . BaseIid } ";
311+ string comment = ( this as INdrFormatterInternal ) . FormatComment ( unknown_iid ) ;
312+ base_name = $ "{ comment } IUnknown";
313+ }
314+
315+ builder . AppendLine (
316+ "class __declspec(uuid(\" {0}\" )) {1} : public {2} {{\n public:" ,
317+ com_proxy . Iid ,
318+ ( this as INdrFormatterInternal ) . DemangleComName ( com_proxy . Name ) ,
319+ base_name
320+ ) ;
321+
322+ builder . PushIndent ( ' ' , 4 ) ;
323+ foreach ( NdrProcedureDefinition proc in com_proxy . Procedures )
324+ {
325+ builder . AppendLine ( this . FormatProcedure ( proc ) ) ;
326+ }
327+ builder . PopIndent ( ) ;
328+ builder . AppendLine ( "}" ) . AppendLine ( ) ;
329+ return builder . ToString ( ) ;
330+ }
331+ }
332+
179333 /// <summary>
180334 /// Flags for the NDR formatter.
181335 /// </summary>
@@ -228,7 +382,7 @@ public static INdrFormatter Create(IDictionary<Guid, string> iids_to_names, Func
228382 /// <returns>The default formatter.</returns>
229383 public static INdrFormatter Create ( IDictionary < Guid , string > iids_to_names , DefaultNdrFormatterFlags flags )
230384 {
231- return Create ( iids_to_names , s => s , flags ) ;
385+ return Create ( iids_to_names , null , flags ) ;
232386 }
233387
234388 /// <summary>
@@ -238,7 +392,7 @@ public static INdrFormatter Create(IDictionary<Guid, string> iids_to_names, Defa
238392 /// <returns>The default formatter.</returns>
239393 public static INdrFormatter Create ( IDictionary < Guid , string > iids_to_names )
240394 {
241- return Create ( iids_to_names , s => s ) ;
395+ return Create ( iids_to_names , null ) ;
242396 }
243397
244398 /// <summary>
@@ -260,4 +414,74 @@ public static INdrFormatter Create()
260414 return Create ( new Dictionary < Guid , string > ( ) ) ;
261415 }
262416 }
417+
418+
419+ /// <summary>
420+ /// NDR formatter constructor for CPP style output.
421+ /// </summary>
422+ public static class CppNdrFormatter
423+ {
424+ /// <summary>
425+ /// Create the CPP formatter.
426+ /// </summary>
427+ /// <param name="iids_to_names">Specify a dictionary of IIDs to names.</param>
428+ /// <param name="demangle_com_name">Function to demangle COM interface names during formatting.</param>
429+ /// <param name="flags">Formatter flags.</param>
430+ /// <returns>The CPP formatter.</returns>
431+ public static INdrFormatter Create ( IDictionary < Guid , string > iids_to_names , Func < string , string > demangle_com_name , DefaultNdrFormatterFlags flags )
432+ {
433+ return new CppNdrFormatterInternal ( iids_to_names , demangle_com_name , flags ) ;
434+ }
435+
436+ /// <summary>
437+ /// Create the CPP formatter.
438+ /// </summary>
439+ /// <param name="iids_to_names">Specify a dictionary of IIDs to names.</param>
440+ /// <param name="demangle_com_name">Function to demangle COM interface names during formatting.</param>
441+ /// <returns>The CPPformatter.</returns>
442+ public static INdrFormatter Create ( IDictionary < Guid , string > iids_to_names , Func < string , string > demangle_com_name )
443+ {
444+ return Create ( iids_to_names , demangle_com_name , DefaultNdrFormatterFlags . None ) ;
445+ }
446+
447+ /// <summary>
448+ /// Create the CPP formatter.
449+ /// </summary>
450+ /// <param name="iids_to_names">Specify a dictionary of IIDs to names.</param>
451+ /// <param name="flags">Formatter flags.</param>
452+ /// <returns>The CPP formatter.</returns>
453+ public static INdrFormatter Create ( IDictionary < Guid , string > iids_to_names , DefaultNdrFormatterFlags flags )
454+ {
455+ return Create ( iids_to_names , null , flags ) ;
456+ }
457+
458+ /// <summary>
459+ /// Create the CPP formatter.
460+ /// </summary>
461+ /// <param name="iids_to_names">Specify a dictionary of IIDs to names.</param>
462+ /// <returns>The CPP formatter.</returns>
463+ public static INdrFormatter Create ( IDictionary < Guid , string > iids_to_names )
464+ {
465+ return Create ( iids_to_names , null ) ;
466+ }
467+
468+ /// <summary>
469+ /// Create the default formatter.
470+ /// </summary>
471+ /// <param name="flags">Formatter flags.</param>
472+ /// <returns>The CPP formatter.</returns>
473+ public static INdrFormatter Create ( DefaultNdrFormatterFlags flags )
474+ {
475+ return Create ( new Dictionary < Guid , string > ( ) , flags ) ;
476+ }
477+
478+ /// <summary>
479+ /// Create the default formatter.
480+ /// </summary>
481+ /// <returns>The CPP formatter.</returns>
482+ public static INdrFormatter Create ( )
483+ {
484+ return Create ( new Dictionary < Guid , string > ( ) ) ;
485+ }
486+ }
263487}
0 commit comments