News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

How to implement C++ methods in assembly language (re:PrintDlgEx () )

Started by NoCforMe, February 26, 2019, 04:20:41 PM

Previous topic - Next topic

NoCforMe

Hoping for some help from someone with some experience with this stuff.

I'm trying to add a child dialog to the PrintDlgEx() print dialog, using an in-memory dialog template. (I've done a similar thing with the open-file dialog, which works fine, but PrintDlgEx uses a different method of handling the sub-dialog.)

The problem is that the connection to the code that handles communication with the child dialog is through a set of C++ methods, rather than a pointer to a dialog procedure as the file-open function uses. Specifically, one needs an object of type IPrintDialogCallback. I don't know how to create such an animal in assembly language.

I could use a C++ compiler to generate the assembly code and then use it, but 1) I don't want to use C++ and 2) I don't have a C++ compiler in any case. So does anyone here know how this interface can be translated to assembly language? I can't see how it would be all that complicated.

Here's the MSDN page describing the IPrintDialogCallback interface. I'd need two of the methods described there: IPrintDialogCallback::HandleMessage and IPrintDialogCallback::InitDone. (My child dialog just adds a radio-button selector that I need to get the setting of.)

Thanks in advance to anyone who can help shed some light on this.
Assembly language programming should be fun. That's why I do it.

TimoVJL

Actually COM interface.
This works with poasm:
.686
.model flat, stdcall
; PROTOTYPES and TYPEDEFS
IPrintDialogCB_QueryInterface PROTO :PTR, :PTR, :PTR PTR
IPrintDialogCB_QueryInterfacePtr TYPEDEF PTR
IPrintDialogCB_AddRef PROTO :PTR
IPrintDialogCB_AddRefPtr TYPEDEF PTR
IPrintDialogCB_Release PROTO :PTR
IPrintDialogCB_ReleasePtr TYPEDEF PTR
IPrintDialogCB_InitDone PROTO :PTR
IPrintDialogCB_InitDonePtr TYPEDEF PTR
IPrintDialogCB_SelectionChange PROTO :PTR
IPrintDialogCB_SelectionChangePtr TYPEDEF PTR
IPrintDialogCB_HandleMessage PROTO :PTR, :PTR, :PTR, :PTR, :PTR, :PTR
IPrintDialogCB_HandleMessagePtr TYPEDEF PTR
; VIRTUAL TABLE
IPrintDialogCallbackVtbl STRUCT
QueryInterface IPrintDialogCB_QueryInterfacePtr ?
AddRef IPrintDialogCB_AddRefPtr ?
Release IPrintDialogCB_ReleasePtr ?
InitDone IPrintDialogCB_InitDonePtr ?
SelectionChange IPrintDialogCB_SelectionChangePtr ?
HandleMessage IPrintDialogCB_HandleMessagePtr ?
IPrintDialogCallbackVtbl ENDS
IPrintDialogCallbackVtblPtr TYPEDEF PTR
; INTERFACE
IPrintDialogCallback STRUCT
lpVtbl IPrintDialogCallbackVtblPtr ?
IPrintDialogCallback ENDS

public IPrintDialogCBA

.data
IPrintDialogCBVtbl IPrintDialogCallbackVtbl <IPrintDialogCB_QueryInterface, IPrintDialogCB_AddRef, IPrintDialogCB_Release,
IPrintDialogCB_InitDone, IPrintDialogCB_SelectionChange, IPrintDialogCB_HandleMessage>
IPrintDialogCBA IPrintDialogCallback <IPrintDialogCBVtbl>

.code
IPrintDialogCB_QueryInterface PROC PRIVATE this_:PTR, riid:PTR, ppvObj:PTR PTR
mov edx, riid
mov eax, [edx]
cmp eax, 5852A2C3h ; check IID Data1
jne @F
mov eax, [edx+4]
cmp eax, 11D16530h ; check IID Data2 Data3
jne @F
mov eax, ppvObj
;mov edx, offset IPrintDialogCBA
;mov edx, this
;mov dword ptr [eax], edx
mov dword ptr [eax], offset IPrintDialogCBA
xor eax, eax
jmp @lret
@@: mov eax, ppvObj
mov dword ptr [eax], 0
mov eax, 80004001h
@lret:
ret
IPrintDialogCB_QueryInterface ENDP

IPrintDialogCB_AddRef PROC PRIVATE this_:PTR
mov eax, 1
ret
IPrintDialogCB_AddRef ENDP

IPrintDialogCB_Release PROC PRIVATE this_:PTR
mov eax, 1
ret
IPrintDialogCB_Release ENDP

IPrintDialogCB_InitDone PROC PRIVATE this_:PTR
mov eax, 80004001h
ret
IPrintDialogCB_InitDone ENDP

IPrintDialogCB_SelectionChange PROC PRIVATE this_:PTR
mov eax, 80004001h
ret
IPrintDialogCB_SelectionChange ENDP

IPrintDialogCB_HandleMessage PROC PRIVATE this_:PTR, hDlg:PTR, uMsg:PTR, wParam:PTR, lParam:PTR, pResult:PTR
mov eax, 1 ; S_FALSE
ret
IPrintDialogCB_HandleMessage ENDP

END

Here is a static C-version:#define WINVER 0x0500
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <objbase.h>
#include <commdlg.h>
// https://docs.microsoft.com/en-us/windows/desktop/dlgbox/using-common-dialog-boxes#using-the-print-property-sheet
HRESULT STDMETHODCALLTYPE IPrintDialogCB_QueryInterface(IPrintDialogCallback *This, REFIID riid, LPVOID FAR *ppvObj);
ULONG STDMETHODCALLTYPE IPrintDialogCB_AddRef(IPrintDialogCallback *This);
ULONG STDMETHODCALLTYPE IPrintDialogCB_Release(IPrintDialogCallback *This);
HRESULT STDMETHODCALLTYPE IPrintDialogCB_InitDone(IPrintDialogCallback *This);
HRESULT STDMETHODCALLTYPE IPrintDialogCB_SelectionChange(IPrintDialogCallback *This);
HRESULT STDMETHODCALLTYPE IPrintDialogCB_HandleMessage(IPrintDialogCallback *This, HWND, UINT, WPARAM, LPARAM, LRESULT*);

IPrintDialogCallbackVtbl IPrintDialogCBTable = {
IPrintDialogCB_QueryInterface,
IPrintDialogCB_AddRef,
IPrintDialogCB_Release,
IPrintDialogCB_InitDone,
IPrintDialogCB_SelectionChange,
IPrintDialogCB_HandleMessage
};
IPrintDialogCallback IPrintDialogCB = { &IPrintDialogCBTable };

HRESULT STDMETHODCALLTYPE IPrintDialogCB_QueryInterface(IPrintDialogCallback *This, REFIID riid, LPVOID FAR *ppvObj)
{
OutputDebugString("IPrintDialogCB_QueryInterface");
if (!memcmp(riid, &IID_IPrintDialogCallback, sizeof(IID)))
{
*ppvObj = (void **)&IPrintDialogCB;
return 0;
}
*ppvObj = NULL;
return E_NOTIMPL;
}

ULONG STDMETHODCALLTYPE IPrintDialogCB_AddRef(IPrintDialogCallback *This)
{
OutputDebugString("IPrintDialogCB_AddRef");
return 1;
}

ULONG STDMETHODCALLTYPE IPrintDialogCB_Release(IPrintDialogCallback *This)
{
OutputDebugString("IPrintDialogCB_Release");
return 1;
}

HRESULT STDMETHODCALLTYPE IPrintDialogCB_InitDone(IPrintDialogCallback *This)
{
OutputDebugString("IPrintDialogCB_InitDone");
return E_NOTIMPL;
}

HRESULT STDMETHODCALLTYPE IPrintDialogCB_SelectionChange(IPrintDialogCallback *This)
{
OutputDebugString("IPrintDialogCB_SelectionChange");
return E_NOTIMPL;
}

HRESULT STDMETHODCALLTYPE IPrintDialogCB_HandleMessage(IPrintDialogCallback *This, HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *pResult)
{
OutputDebugString("IPrintDialogCB_HandleMessage");
return S_FALSE;
}

const GUID IID_IPrintDialogCallback={0x5852a2c3,0x6530,0x11d1,0xb6,0xa3,0x0,0x0,0xf8,0x75,0x7b,0xf9};

void __cdecl WinMainCRTStartup(void)
{
PRINTDLGEX pdx = {0};
LPPRINTPAGERANGE pPageRanges = NULL;
HRESULT hResult;

pdx.lStructSize = sizeof(PRINTDLGEX);
pdx.hwndOwner = GetDesktopWindow();
pdx.Flags = PD_RETURNDC  | PD_NOPAGENUMS;
pdx.lpCallback = (LPUNKNOWN)&IPrintDialogCB;
pdx.nStartPage = START_PAGE_GENERAL;
hResult = PrintDlgEx(&pdx);
char szBuf[100];
wsprintf(szBuf, TEXT("result:\n%p"), hResult);
MessageBox(0, szBuf, 0, 0);
ExitProcess(hResult);
}
May the source be with you

NoCforMe

Wow, thanks! Haven't had a chance yet to even look at this, let alone digest it, but I will, I promise.
Assembly language programming should be fun. That's why I do it.