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:
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
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???
deleted
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
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
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:
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.
deleted
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.
deleted
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.
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:
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?
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
Hi Biterider, can you tell me the pdf viewer you are using (Adobe,Sumatra etc)? And any info on the crash?
Cheers.
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:
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
Hi Sinsi
A third try with a .txt file works OK like the .docx file.
Biterider
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 ?
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:
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
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.
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
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.
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
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
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
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