0

I am trying to implement some COM interfaces that can be used while exporting Word documents as PDF. Some of these interfaces don't inherit from IUnknown, for instance:

#undef  INTERFACE
#define INTERFACE  IMsoServerFileManagerSite
DECLARE_INTERFACE(IMsoServerFileManagerSite)
{
  STDMETHOD_(BOOL, FGetHandle) (const WCHAR *pwzFileName, HANDLE *phFile, BOOL fRead, BOOL fWrite) PURE;
  STDMETHOD_(BOOL, FCloseHandle) (HANDLE hFile) PURE;
};

I found that I can translate these interfaces to IDL if I use the local attribute (declaring that they aren't remote). For instance

[
    local,
    uuid(f8e47685-e402-4119-aa07-4ea4ff1f1123)
]
interface IMsoServerFileManagerSite
{
    BOOL FGetHandle(const WCHAR *pwzFileName, HANDLE *phFile, BOOL fRead, BOOL fWrite);
    BOOL FCloseHandle(HANDLE hFile);
}

Another such interface, IMsoDocExporter, does inherit from IUnknown, but has some functions that return void rather than HRESULT. When I pass an object implementing this interface to the Word API I can attach a debugger and see that my dll is being called by functions like combase.dll!CRemoteUnknown::RemQueryInterface.

So my questions are:

  1. Does combase.dll!CRemoteUnknown::RemQueryInterface mean that my object is being queried remotely? (i.e. I'll need a proxy/stub, and can't use the [local] attr?)

  2. if an interface uses non-automation types, such as HANDLE, and doesn't return an HRESULT can it still be marshalled?

  3. is there a way/what is the best way to translate these interfaces to IDL so that MIDL will provide the proxy/stub implementation? (e.g. MIDL reference suggested that call_as could be used to map these functions to remote callable functions -- still unclear what I could do with HANDLE though)

Eugene Astafiev
  • 47,483
  • 3
  • 24
  • 45
VersBersch
  • 193
  • 1
  • 8
  • 2
    A COM object must implement the `IUnknown` interface. – molbdnilo Apr 19 '23 at 10:52
  • generally yes, but these interfaces don't (they are from Microsoft, so presumably it's not a mistake). To quote from the [link](https://learn.microsoft.com/en-us/sharepoint/dev/general-development/extend-the-fixed-format-export-feature-in-word-automation-services) in my post: "_This interface does not inherit from IUnknown. Accordingly, the fixed-format export DLL is allowed to keep a reference to it for its lifetime._" – VersBersch Apr 19 '23 at 11:02
  • do you have to treat them as COM? I also notice that `the service runs in a highly restricted environment without access to most places in the file system` so are you sure it can even contact a server process? – user253751 Apr 19 '23 at 11:05
  • I don't think the service has to contact anything because it just provides `IMsoDocExporter*` and then the Word application is querying that interface (from another thread/process perhaps). – VersBersch Apr 19 '23 at 11:26
  • 3
    If it doesn't inherit from IUnknown it's not a COM interface. – Jonathan Potter Apr 19 '23 at 11:48
  • Where are these interface (like IMsoServerFileManagerSite) declared? what SDK? file? – Simon Mourier Apr 19 '23 at 13:19
  • Good question, I've been searching for an official resource. [This article](https://learn.microsoft.com/en-us/previous-versions/office/developer/office-2007/aa338206(v=office.12)?redirectedfrom=MSDN) says that the interfaces are defined in fixedformatext.h, but so far I only managed to find [this forum post](https://www.vbforums.com/showthread.php?846465-How-to-use-IMsoDocExporter-interface-of-ExportAsFixedFormat) where someone has uploaded that header. It seems to be accurate though. – VersBersch Apr 19 '23 at 13:33

1 Answers1

1

After some more playing around I finally managed to make it work. @molbdnilo and @Jonathan Potter were correct. Only the IMsoDocExporter interface is a COM object, and it inherits from IUnknown. The other interfaces are just plain vtables I suppose and it seems that they can't be marshalled (at least not without writing lots of custom proxy/stub code).

  1. Does combase.dll!CRemoteUnknown::RemQueryInterface mean that my object is being queried remotely?

Yes, but this only applied to IMsoDocExporter (the actual COM object)

  1. if an interface uses non-automation types, such as HANDLE, and doesn't return an HRESULT can it still be marshalled?

It turns out yes. As mentioned in my original post you can mark these methods [local] and then define a similar method with the [call_as] attribute that returns HRESULT and has RPC-able parameters. Then you just need to define the functions that translates one call to the other. Ultimately, to marshal a HANDLE you need to specify the type information.

VersBersch
  • 193
  • 1
  • 8