COM Input Format

The `COM` input format allows users to write their own input formats as COM objects, which can then be used with Log Parser through both the command-line application or through the scriptable COM components.

There are two ways to write a COM plugin for Log Parser:

### Implementing the ILogParserInputContext interface:

Your COM object must implement the ILogParserInputContext interface, whose declaration can be found in the `COM\ILogParserInputContext.h` file.
A sample COM object implementing the interface can be found in the `Samples\COM\ProcessesInputContext` folder.
This method usually requires writing C++ code or VB code.

### Implementing the IDispatch interface exposing the methods of the ILogParserInputContext interface:

Your COM object must implement the IDispatch interface, and support the same methods exposed by the ILogParserInputContext interface.
A sample COM object implementing the IDispatch interface can be found in the `Samples\COM\QFE` folder.
This method usually requires writing scriptlets (.wsc) files in JScript or VBScript.
COM input format plugins that implement the IDispatch interface can also support custom properties.

After you have created your COM object, you will have to register it (usually using regsvr32.exe), and then it will be ready for use by Log Parser.
As an example, if your COM object's ProgID is "`MyLogParser.ComObject`", you can use it by typing the following command:

    LogParser "SELECT * FROM MyFromEntity" -i:COM -iprogid:MyLogParser.ComObject

If your COM object also supports properties (put_ only is enough), then you can set those properties through the command line as follows:

    LogParser "SELECT * FROM MyFromEntity" -i:COM -iprogid:MyLogParser.ComObject -icomparams:TargetMachine=localhost,ExtendedFields=on

The order in which the ILogParserInputContext interface methods are called is as follows:

1. OpenInput( szFromEntity )
   - szFromEntity contains the value specified in the `FROM` statement.
   - The implementation of this method could open the specified entity and eventually gather information about what fields to export to Log Parser.
2. DWORD GetFieldCount( )
   - The implementation of this method must return the total number of fields that the input format exports to Log Parser.
3. BSTR GetFieldName( index )
   - The implementation of this method must return the name of the field identified by the 0-based index argument.
   - This method is called as many times as the number of fields declared by the GetFieldCount( ) method.
4. DWORD GetFieldType( index )
   - The implementation of this method must return the type of the field identified by the 0-based index argument.
   - This method is called as many times as the number of fields declared by the GetFieldCount( ) method.
   - Fields can have one of four different types, whose values are defined in the FieldType enumeration:

         enum FieldType
         {
         	Integer         =0,
         	Real            =1,
         	String          =2,
         	Timestamp       =3
         };

   - It is possible for any field, regardless of the declared type, to return a NULL value.
5. BOOL ReadRecord( )
   - The implementation of this method should read a new "record" from its from-entity, thus advancing its internal state machine.
   - This method is called repeatedly until the object determines that there are no more "records" to export, in which case it must return FALSE causing Log Parser to call the CloseInput method.
6. VARIANT GetValue( index )
   - The implementation of this method must return the last record's value of the field identified by the 0-based index argument.
   - This method is called only for those fields that the user has specified in the SQL query; if the query is a "`SELECT COUNT(*)`" query, this method will never be called.
   - Values can be encoded in many different ways, as long as the `VARIANT` type can be casted onto the following `VARTYPE`'s according to the type declared for the field:
     - INTEGER: `VT_I8`
     - REAL: `VT_R8`
     - STRING: `VT_BSTR`
     - TIMESTAMP: either a `VT_DATE`, or a `VT_I8` specifying the number of 100-nanosecond intervals since January 1, 1601 (UTC).
   - NULL values can be encoded through either the `VT_NULL` or the `VT_EMPTY` `VARTYPE`'s.
7. CloseInput( bAbort )
   - The implementation of this method should release all the resources associated with the current execution.
   - bAbort is `TRUE` when the execution has been terminated due to abnormal situations (e.g. the user pressed `CTRL+C`, or an error occurred).

For example, if a COM object exports 3 `STRING` fields to Log Parser, the order of method calls would look as follows:

1. OpenInput( szFromEntity )
2. GetFieldCount( ) //Returns 3

3. GetFieldName( 0 ) //Returns "field1"
4. GetFieldType( 0 ) //Returns 2
5. GetFieldName( 1 ) //Returns "field1"
6. GetFieldType( 1 ) //Returns 2
7. GetFieldName( 2 ) //Returns "field1"
8. GetFieldType( 2 ) //Returns 2

9. ReadRecord( ) //Returns TRUE
10. GetValue( 0 ) //Returns a `VT_BSTR VARIANT`
11. GetValue( 1 ) //Returns a `VT_BSTR VARIANT`
12. GetValue( 2 ) //Returns a `VT_BSTR VARIANT`

13. ReadRecord( ) //Returns TRUE
14. GetValue( 0 ) //Returns a `VT_BSTR VARIANT`
15. GetValue( 1 ) //Returns a `VT_BSTR VARIANT`
16. GetValue( 2 ) //Returns a `VT_BSTR VARIANT`

17. ReadRecord( ) //Returns TRUE
18. GetValue( 0 ) //Returns a `VT_BSTR VARIANT`
19. GetValue( 1 ) //Returns a `VT_BSTR VARIANT`
20. GetValue( 2 ) //Returns a `VT_BSTR VARIANT`

21. ReadRecord( ) //Returns TRUE
22. GetValue( 0 ) //Returns a `VT_BSTR VARIANT`
23. GetValue( 1 ) //Returns a `VT_BSTR VARIANT`
24. GetValue( 2 ) //Returns a `VT_BSTR VARIANT`

25. ReadRecord( ) //Returns FALSE
26. CloseInput( false )