Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What do you do when MIDL can't create a tlb?

Tags:

c#

idl

tlbimp

midl

I am attempting to create a C# inproc server for sbtsv.idl (it is included with the Windows 8 SDK). Almost every instructions I find tell you to use MIDL to create a .tlb file then tlbimport to create the proxy dll.

However, if the IDL does not include a library section no .tlb file will be generated, and sbtsv.idl does not include a library section.

I tried creating my own IDL file that declared the interface I wanted to create inside a library

#include "C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Include\sbtsv.idl"

[uuid(43250D0C-BBC6-4109-BCD2-6F61F0D3B611)]
library sbtsvClientLib
{
    interface ITsSbResourceNotification;
};

However when I try to run it through MIDL i get the following error

Microsoft (R) 32b/64b MIDL Compiler Version 8.00.0603  
Copyright (c) Microsoft Corporation. All rights reserved.  
Processing .\sbtsvClientLib.idl  
sbtsvClientLib.idl  
Processing C:\Program Files (x86)\Windows Kits\8.1\include\um\oaidl.idl  
oaidl.idl  
Processing C:\Program Files (x86)\Windows Kits\8.1\include\um\objidl.idl  
objidl.idl  
Processing C:\Program Files (x86)\Windows Kits\8.1\include\um\unknwn.idl  
unknwn.idl  
Processing C:\Program Files (x86)\Windows Kits\8.1\include\shared\wtypes.idl  
wtypes.idl  
Processing C:\Program Files (x86)\Windows Kits\8.1\include\shared\wtypesbase.idl  
wtypesbase.idl  
Processing C:\Program Files (x86)\Windows Kits\8.1\include\shared\basetsd.h  
basetsd.h  
Processing C:\Program Files (x86)\Windows Kits\8.1\include\shared\guiddef.h  
guiddef.h  
Processing C:\Program Files (x86)\Windows Kits\8.1\include\um\SessdirPublicTypes.idl  
SessdirPublicTypes.idl  
Processing C:\Program Files (x86)\Windows Kits\8.1\include\um\oaidl.acf  
oaidl.acf  
midl\oleaut32.dll : error MIDL2020 : error generating type library : SetFuncAndParamNames failed : put_State (0x8002802C)

I am thinking I am going to be forced to write the classes and interfaces by hand, but I wanted to check to see if I was doing anything wrong that would allow this to work.

like image 324
Scott Chamberlain Avatar asked Oct 31 '13 21:10

Scott Chamberlain


1 Answers

There are two kinds of COM. The original kind, dating from the early nineties, targeted to make interop work in C or C++ and originated by the Office group at Microsoft. And the later kind, a subset of COM originally named OLE Automation. Developed by the Visual Basic team in the DevDiv group when they looked for an alternative for VBX, a 16-bit extension model for early versions of Visual Basic. Later renamed to ActiveX as a marketing term. Gaining lots of notoriety for being insecure, renamed back to plain COM.

Automation has been incredibly successful beyond the VB usage, any language runtime in Windows supports it. Significantly helped by it implementing a strict subset of COM that was easy to implement. And for supporting type libraries, a language-independent way to make a compiler aware of declarations.

That did not supplant the "old" COM, still very heavily used in Windows. Lots of apis are "old" style. The standard bat-signal for the non-Automation kind is seeing "cppquote" in the IDL file. Or interfaces that derive from IUnknown instead of IDispatch. Or methods using raw arrays instead of SAFEARRAY. Or structure types that comes from a Windows SDK header, the kind that only a C or C++ compiler can read.

Everything you see back in sbtsv.idl.

MIDL doesn't have any actual knowledge of the Automation restrictions, it just compiles the IDL and pig-headedly calls the ICreateTypeInfo interface methods in oleauto32. Which can easily object when the type library format doesn't support it. The error message sucks, it doesn't tell you exactly what declaration was at fault. Not unusual for MIDL, or Windows SDK tools in general, diagnostics are not its strength. DevDiv creates the friendly tools.

It doesn't otherwise takes a lot of guessing what declaration is at fault in sbtsv.idl. About all of them. You really do have to do this the hard way, writing the [ComImport] declarations yourself. Painful and error prone, do consider a C++/CLI wrapper instead.

like image 51
Hans Passant Avatar answered Sep 26 '22 15:09

Hans Passant