The MASM Forum

General => The Workshop => Topic started by: sinsi on December 20, 2019, 02:18:26 AM

Title: Exploring COM
Post by: sinsi on December 20, 2019, 02:18:26 AM
I have been playing with COM (interfaces and such) and everything seems to work OK, but I would like to know
if my assumptions are correct since C++ is a mystery to me.

1. When we ask for an interface, we supply a memory location to be filled with the address of the interface, which is really a structure.
2. The structure address is "this" and is (usually? always?) the first parameter.
3. I have read about ECX having the "this" parameter but is that only for C++ objects? Or COM as well?
4. If a call returns a memory block (allocated by the interface, not my code) it has to be freed by a call to e.g. CoTaskMemFree.
    ExitProcess will not free this memory, but does Release?

Searching gives me lots of HLL stuff (which is to be expected after all), but no low-level stuff, possibly because I don't know the terminology :biggrin:
Title: Re: Exploring COM
Post by: Biterider on December 20, 2019, 03:44:34 AM
Hi Sinsi
1. When we ask for an interface, we supply a memory location to be filled with the address of the interface, which is really a structure.
Right. There is an important fact, that the returned interface pointers are internally tracked with a counter. Each time you request an interface, the counter is incremented and decremented when you release it. When the count is zero, in most cases, the object is destroyed.
2. The structure address is "this" and is (usually? always?) the first parameter.
The first slot in the interface structure is a pointer to a virtual table. This table holds the addresses of the methods that can be called using this interface. The sequence of addresses in the virtual table is given by the declaration of the interface. Be careful, some documentation is sorted alphabetically and not by sequence!
3. I have read about ECX having the "this" parameter but is that only for C++ objects? Or COM as well?
This is true for C++, but you are free to use any register. Don't assume that the this pointer is in rcx/ecx.
4. If a call returns a memory block (allocated by the interface, not my code) it has to be freed by a call to e.g. CoTaskMemFree.  ExitProcess will not free this memory, but does Release?
In most cases yes, but you have to read the documentation in each case.

COM is a lot about standards and documentation.  :biggrin:

Biterider
Title: Re: Exploring COM
Post by: sinsi on December 20, 2019, 03:57:35 AM
QuoteBe careful, some documentation is sorted alphabetically and not by sequence!
I can usually sort out the header files :badgrin:

QuoteCOM is a lot about standards and documentation.  :biggrin:
And knowing the terminology - why is it called an apartment???
Title: Re: Exploring COM
Post by: nidud on December 20, 2019, 03:59:51 AM
deleted
Title: Re: Exploring COM
Post by: Biterider on December 20, 2019, 04:41:08 AM
Hi
QuoteAnd knowing the terminology - why is it called an apartment???
It is a bit of story behind this. COM was born as single threading and in a sigle process. As time goes on, multitreading and interprocess communication was added and things became a bit complicated. Later, net distributed communication was added too. So DCOM was born. It wasn't very successful due to the proxy/server and mashalling difficulties.
MS stepped back and uses today mostly only the interfaces to access the modern APIs.

Biterider
Title: Re: Exploring COM
Post by: jj2007 on December 20, 2019, 06:46:09 AM
Quote from: sinsi on December 20, 2019, 02:18:26 AM
ExitProcess will not free this memory, but does Release?

What makes you think that ExitProcess will not free this memory? The docs are usually vague about this, if you have a good source, I'd be curious to see it...

Raymond Chen on ExitProcess (http://masm32.com/board/index.php?topic=6053.0)
QuoteDon't worry about freeing memory; it will all go away when the process address space is destroyed
Title: Re: Exploring COM
Post by: sinsi on December 20, 2019, 11:48:10 AM
Quote from: jj2007 on December 20, 2019, 06:46:09 AM
What makes you think that ExitProcess will not free this memory? The docs are usually vague about this, if you have a good source, I'd be curious to see it...
Poor wording on my part, ExitProcess will free the memory, as it's part of my process's virtual address space, but does the interface keep any sort of internal pointer?
If so, how will it know that there is no memory there any more?

An example from IShellItem::GetDisplayName
QuoteIt is the responsibility of the caller to free the string pointed to by ppszName when it is
no longer needed. Call CoTaskMemFree on *ppszName to free the memory.

Another example, if I use IPreviewHandler on a .pdf I can see the previewer in task manager, it exits when the preview is closed (IPreviewHandler::Unload).
Except for previewing .docx files with Word, sometimes even after my program releases all interfaces and exits, Word is still running - no window so no way of closing it.
The consequences of this are having several word.exe running and, interestingly, having several blank word documents open when Windows restarts  :rolleyes:


Thanks for the replies and reassurance  :thumbsup:
Title: Re: Exploring COM
Post by: jj2007 on December 20, 2019, 01:00:18 PM
Quote from: sinsi on December 20, 2019, 11:48:10 AMExitProcess will free the memory, as it's part of my process's virtual address space, but does the interface keep any sort of internal pointer?

Good question! Is the interface part of the process's virtual address space? In that case, it will be killed by ExitProcess, too. If not, i.e. if the interface is a separate process, how do our process and the COM process communicate with each other?

I've tried to understand Larry Osterman's Sad Story of CoGetMalloc (https://blogs.msdn.microsoft.com/larryosterman/2007/02/07/the-sad-story-of-cogetmalloc/), but it's a bit late now... maybe you find it inspiring ;-)

There is another post by Osterman: What are these "Threading Models" and why do I care? (https://blogs.msdn.microsoft.com/larryosterman/2004/04/28/what-are-these-threading-models-and-why-do-i-care/)
Quoteinternally, COM uses windows messages to do inter-thread marshalling

See also CLSCTX enumeration (https://docs.microsoft.com/en-gb/windows/win32/api/wtypesbase/ne-wtypesbase-clsctx):
Quote
CLSCTX_INPROC_SERVER   The code that creates and manages objects of this class is a DLL that runs in the same process as the caller of the function specifying the class context.

My badly informed guess is that our programs are normally in-process, which implies that the whole COM stuff is being eliminated by ExitProcess.
Title: Re: Exploring COM
Post by: nidud on December 20, 2019, 01:29:50 PM
deleted
Title: Re: Exploring COM
Post by: sinsi on December 20, 2019, 02:14:01 PM
Hi nidud, I'm not building a preview handler, I am using IPreviewHandler to use other preview handlers.
I don't see prevhost.exe at all.

My code works and previews files (as long as a preview handler is associated with a file extension) but like a lot of my guesswork around C++ concepts
it's nice to confirm things e.g. my code always stopped after the call to IPreviewHandler.DoPreview. Some experimenting showed me that
using COINIT_APARTMENTTHREADED would fix that (or putting the preview code in another thread, which allows my main window to work). Sigh.
Title: Re: Exploring COM
Post by: nidud on December 21, 2019, 10:22:04 AM
deleted
Title: Re: Exploring COM
Post by: sinsi on December 21, 2019, 07:12:45 PM
Here is the code I have, it's messy because I had to convert it to masm32 :biggrin:
A couple of things, masm32 doesn't seem to have uuid.lib, so check the path of includelib, and the preview handler expects a full path to the document.

You can also preview pdf,mp3 etc.
Title: Re: Exploring COM
Post by: jj2007 on December 21, 2019, 09:27:47 PM
No luck on Win7-64 :sad:
AssocQueryString
x:eax           80070483
$Err$()         Operazione completata.__


That is ERROR_NO_ASSOCIATION. But GetLastError says everything is ok, and a double-click on the word doc opens it in Word - mysteries of Windows :biggrin:

It works fine for a pdf doc, though :thumbsup:

... except that I have to kill the process with Ctrl C. Weird :cool:

AssocQueryString        eax             0
CLSIDFromString         eax             0
CoCreateInstance        eax             0
TryUsingStream          eax             0
IPreviewHandler         eax             0
IPreviewHandler         eax             0
IPreviewHandler         eax             0
SafeRelease pst         eax             3
SafeRelease pif         eax             1


No SafeRelease pph :sad:
Title: Re: Exploring COM
Post by: sinsi on December 21, 2019, 10:33:12 PM
Quote from: jj2007 on December 21, 2019, 09:27:47 PM
That is ERROR_NO_ASSOCIATION. But GetLastError says everything is ok, and a double-click on the word doc opens it in Word - mysteries of Windows :biggrin:
Does Explorer preview the doc?

Title: Re: Exploring COM
Post by: Biterider on December 21, 2019, 10:39:20 PM
Hi Sinsi
I compiled your example and it works fine on Win10/64 Home.
I tried a pdf file and it fails on the call "covoke  pph,IPreviewHandler,DoPreview" returning 80004005. After that it crashes.
The registy contains the key {8895B1C6-B41F-4C1C-A562-0D564250836F} for the pdf file extension and it previews fine in the explorer... Any idea?  :icon_idea:

Biterider
Title: Re: Exploring COM
Post by: sinsi on December 21, 2019, 10:49:02 PM
Hi Biterider, can you tell me the pdf viewer you are using (Adobe,Sumatra etc)? And any info on the crash?
Cheers.
Title: Re: Exploring COM
Post by: jj2007 on December 21, 2019, 11:01:05 PM
Quote from: sinsi on December 21, 2019, 10:33:12 PM
Quote from: jj2007 on December 21, 2019, 09:27:47 PM
That is ERROR_NO_ASSOCIATION. But GetLastError says everything is ok, and a double-click on the word doc opens it in Word - mysteries of Windows :biggrin:
Does Explorer preview the doc?

No. Attached Further down a version that takes the file from the commandline and does error checks, plus some testfiles. *.txt and *.html work flawlessly, *.pdf opens but hangs, the rest doesn't work at all :sad:

Title: Re: Exploring COM
Post by: Biterider on December 22, 2019, 12:18:04 AM
Hi Sinsi
The ProgID is found in the registry under PDFPrevHndlr.PDFPreviewHandler (StdKey = Adobe PDF Preview Handler for Vista).
The Subkey CLSID is {DC6EFB56-9CFA-464D-8880-44885D7DC193}, which is the StdKey in HKEY_CLASSES_ROOT\.pdf\ShellEx\

Finally \HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{DC6EFB56-9CFA-464D-8880-44885D7DC193} points to an entry holding an AppID = {534A1E02-D58F-44f0-B58B-36CBED287C7C} and a DisplayName = @C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\pdfprevhndlr.dll,-101.
Computer\HKEY_CLASSES_ROOT\AppID\{534A1E02-D58F-44f0-B58B-36CBED287C7C} has a key called DllSurrogate containig the following path C:\Windows\SysWOW64\prevhost.exe

So, if I'm not wrong, the answer is "Acrobat Reader DC".

About the crash, what I see is the window with a bray background and then it stops running when DoPreview returns with an error code.

Biterider

Title: Re: Exploring COM
Post by: Biterider on December 22, 2019, 12:27:38 AM
Hi Sinsi
A third try with a .txt file works OK like the .docx file.

Biterider



Title: Re: Exploring COM
Post by: sinsi on December 22, 2019, 12:48:07 AM
One thing I have noticed about a pdf is that nothing shows until you click the scroll bar, maybe this would make you think that it has crashed?

jj, is this right?

filename        $$eax           Z:\jj\preview\Test.jpg......T.e.s.t...j.p.g..
extension       $$eax           j\preview\Test.jpg......s.t...j.p.g..
AssocQueryString        $$sExt$         j\preview\Test.jpg......s.t...j.p.g..
AssocQueryString        x:eax           80070483

extension doesn't look right, surely should be .jpg ?
Title: Re: Exploring COM
Post by: jj2007 on December 22, 2019, 01:25:37 AM
Oops, you are right about the extension - my fault :thumbsup:

Quote from: sinsi on December 22, 2019, 12:48:07 AM
One thing I have noticed about a pdf is that nothing shows until you click the scroll bar

No such thing here, the pdf shows immediately (and hangs).
*.txt, *.html, *.rtf work fine here. Same for most text formats like *.inc, *.rc but not *.asm. No luck with *.jpg or *.png :sad:
Title: Re: Exploring COM
Post by: Biterider on December 22, 2019, 01:36:42 AM
Hi sinsi
I finally debugged the code using devenv.exe /DebugExe previewer.exe

The line
covoke  pph,IPreviewHandler,DoPreview
returns an error code (80004005) and

test    eax,eax
jnz       done

finalizes the application jumping to done:
The line
INVOKE  SafeRelease,pph
takes more than 4 seconds to execute. That's why I thought it crashes, but no, it executes fine up to the end.

Biterider
Title: Re: Exploring COM
Post by: sinsi on December 22, 2019, 02:35:36 AM
OK, another attempt. This one previews everything I try (that can be previewed), even music files.
Apparently Microsoft stopped using preview handlers for images after XP?

Still having winword.exe remaining and pdfs not showing until a scroll bar click.
Excel behaves itself though.

The error code 80004005 is a generic failure E_FAIL, so who knows what that is :rolleyes:

Next step after some sleep (it's 2am) is to add some debug feedback and maybe install Adobe (yuck).

Thanks for your efforts fellas  :thumbsup:


EDIT: forgot to add that the program takes a file from the command line and will try to use a shell item if the file/stream interface isn't there.
Title: Re: Exploring COM
Post by: Biterider on December 22, 2019, 02:41:05 AM
Hi
Testing docx, xlsx, pptx, all succeed presenting the preview.
There are very few file extensions that have a ShellEx\{8895B1C6-B41F-4C1C-A562-0D564250836F} key.
On my system, .png or .jpg don't have one. Previewing on the explorer must take another way.

Biterider
Title: Re: Exploring COM
Post by: jimg on December 22, 2019, 06:42:22 AM
Slightly off topic, but what does one have to install to get the include files under folder

C:\Program Files (x86)\Windows Kits\10\

I don't have bin or lib folders here.
Title: Re: Exploring COM
Post by: jj2007 on December 22, 2019, 07:46:38 AM
Quote from: Biterider on December 22, 2019, 01:36:42 AMThe line
covoke  pph,IPreviewHandler,DoPreview
returns an error code (80004005)

Not on my machine. Here, it either exits after AssocQueryString, or it succeeds - see the DoPrev line.

filename                $$eax           C:\Masm32\MasmBasic\Members\Sinsi\previewer.inc
extension               $$eax           .inc
AssocQueryString        x:eax           00000000
CLSIDFromString         x:eax           00000000
CoCreateInstance        x:eax           00000000
TryUsingStream          $$filename$     C:\Masm32\MasmBasic\Members\Sinsi\previewer.inc
TryUsingStream          x:eax           00000000
IPreviewHandler SetWin  x:eax           00000000
IPreviewHandler DoPrev  x:eax           00000000
IPreviewHandler Unload  x:eax           00000000

*** if it hangs, press Ctrl C ***
SafeRelease pst         x:eax           00000000
SafeRelease pif         x:eax           00000001
SafeRelease pph         x:eax           00000000
CoUninitialize          x:eax           00000000
Title: Re: Exploring COM
Post by: Biterider on December 22, 2019, 08:31:43 AM
Hi jimg
QuoteSlightly off topic, but what does one have to install to get the include files under folder
C:\Program Files (x86)\Windows Kits\10\
I don't have bin or lib folders here.
You can install the latest MS SDK for Windows from here https://developer.microsoft.com/de-de/windows/downloads/windows-10-sdk (https://developer.microsoft.com/de-de/windows/downloads/windows-10-sdk)
You will get the most important binaries. Include files for MASM are not there. You can get it from the MASM32 package or other translations here in the forum.
The ObjAsm package also offers a good set of translated include files (check the h2incx project).

@sinsi: were did you get the SDK release 10.0.19018.0?

Biterider
Title: Re: Exploring COM
Post by: sinsi on December 22, 2019, 08:57:28 AM
Quote from: Biterider on December 22, 2019, 08:31:43 AM
@sinsi: were did you get the SDK release 10.0.19018.0?

I think 19018 was a Windows Insider preview version.

Latest news (https://blogs.windows.com/windowsdeveloper/2019/12/17/windows-10-sdk-preview-build-19041-available-now/)
Download link, 740MB (https://software-download.microsoft.com/download/sg/Windows_InsiderPreview_SDK_en-us_19041_1.iso) - not sure if you need to be an Insider

Title: Re: Exploring COM
Post by: Biterider on December 30, 2019, 05:32:35 AM
Hi
QuoteAnd knowing the terminology - why is it called an apartment???
Maybe this post of Raymond Chen can clarify it  :icon_idea:
https://devblogs.microsoft.com/oldnewthing/20191125-00/?p=103135 (https://devblogs.microsoft.com/oldnewthing/20191125-00/?p=103135)

Biterider