Jump to content

Printing with KernelEx 4.5.1


diamant

Recommended Posts

Unfortunately I was not able to print from SumatraPDF-versions higher than 0.8.1 or from Firefox 3 with KernelEx 4.5.1 till now. :(

1.) In SumatraPDF I suppose the following problem:

In older versions one can find the command(?) "PrintDlg" with a hex-editor in its code, which seemed to be replaced by "PrintDlgEx" in newer versions (e.g. SumatraPDF 1.3).

Simply replace the string "PrintDlgEx" by the (older) "PrintDlg" with the hex-editor does not solve the problem.

One can find in the Google-code-search SumatraPDF "code history" that the new command was introduced some time ago, see e.g. here SumatraPDF at code.google.com.

Is ther any known solution for the printing issue?

Maybe it could be useful to "transport" the (old) PrintDlg-function from SumatraPDF 0.8.1 to a newer sumatraPDF-version (and replace PrintDlgEx); but I have no idea how to do this :wacko: .

2.) Has anybody ever found a solution to solve the printing-problem with Firefox 3 with KernelEx? (Maybe transport the printing-function from Firefox 2.0.0.20 to Firefox 3). Sometimes(!) printing worked with Firefox 3, but it was randomly.

Link to comment
Share on other sites


Several weeks ago I was investigating this exact problem. PrintDlgEx uses a new PRINTDLGEX parameter structure that is incompatible with PrintDlg's new PRINTDLG. If we can implement an even semi-functional PrintDlgEx, it would probably go a long way towards solving printing issues in many new apps.

KernelEx currently has a stub for PrintDlgEx that just returns an error. That stub could be rewritten to call PrintDlg, translating between parameter structures.

I think I can patch comdlg32.dll to export PrintDlgEx instead of PrintDlg and inject the needed translation code into the existing function. This patched version would no longer export PrintDlg, so would have to be stored local to the app (not in <system>); or it could be renamed comdlgex.dll and apps would need to have their imports patched to access it.

I have also been considering ways to inject the needed translation code directly into the calling app.

Another possibility is to redirect the call, not to PrintDlg, but to the custom print dialog of another (MS?) app. If we can find one that uses the new PRINTDLGEX structure, that would be ideal. Research in this area would be very helpful :yes:

MSDN: PRINTDLG

typedef struct tagPD {
DWORD lStructSize;
HWND hwndOwner;
HGLOBAL hDevMode;
HGLOBAL hDevNames;
HDC hDC;
DWORD Flags;
WORD nFromPage;
WORD nToPage;
WORD nMinPage;
WORD nMaxPage;
WORD nCopies;
HINSTANCE hInstance;
LPARAM lCustData;
LPPRINTHOOKPROC lpfnPrintHook;
LPSETUPHOOKPROC lpfnSetupHook;
LPCTSTR lpPrintTemplateName;
LPCTSTR lpSetupTemplateName;
HGLOBAL hPrintTemplate;
HGLOBAL hSetupTemplate;
} PRINTDLG, *LPPRINTDLG;

MSDN: PRINTDLGEX

typedef struct tagPDEX {
DWORD lStructSize;
HWND hwndOwner;
HGLOBAL hDevMode;
HGLOBAL hDevNames;
HDC hDC;
DWORD Flags;
DWORD Flags2;
DWORD ExclusionFlags;
DWORD nPageRanges;
DWORD nMaxPageRanges;
LPPRINTPAGERANGE lpPageRanges;
DWORD nMinPage;
DWORD nMaxPage;
DWORD nCopies;
HINSTANCE hInstance;
LPCTSTR lpPrintTemplateName;
LPUNKNOWN lpCallback;
DWORD nPropertyPages;
HPROPSHEETPAGE *lphPropertyPages;
DWORD nStartPage;
DWORD dwResultAction;
} PRINTDLGEX, *LPPRINTDLGEX;

Edited by jumper
Link to comment
Share on other sites

My 2 ¢: Patch the KernelEx stub. Solves all problems, the source is available so it's easy to create a good patch, doesn't involve recompiling the original KernelEx and doesn't touch any system files. This should be the safest possible strategy, IMHO.

Link to comment
Share on other sites

Patching the KernelEx stub does nothing for those who don't use KernelEx.

Having the KernelEx stub source is only useful if I do recompile it. The safest and most efficient strategy would be to recompile rather than patch KernelEx. Since I'm still working on getting KernelEx to compile, I should probably finish that step first.

Link to comment
Share on other sites

Patching the KernelEx stub does nothing for those who don't use KernelEx.

Those who don't use KernelEx (like myself) actually also won't have any use for PrintDlgEx, AFAI can see, though...

As for you getting KernelEx to compile correctly, that's the first priority, all right, IMO too.

However, the source, when available (and in the Win 9x/ME world it almost never is) does help devise patches better too, but you don't need to agree with me about this, since here YMMV.

Link to comment
Share on other sites

Patching the KernelEx stub does nothing for those who don't use KernelEx.

Having the KernelEx stub source is only useful if I do recompile it. The safest and most efficient strategy would be to recompile rather than patch KernelEx. Since I'm still working on getting KernelEx to compile, I should probably finish that step first.

My DLLHOOK Program can add or replace the function independently of KernelEx, but as dencorso said, it may be of limited value without KernelEx.

Link to comment
Share on other sites

As previously mentioned in the SP3 thread, six files in SP3 contain references to PrintDlgEx:

- tweakui.cpl, hypertrm.dll, mfc70.dll, mfc70u.dll, mfc71.dll, mfc71u.dll

Dependency Walker reports "Warning: At least one module has an unresolved import due to a missing export function in a delay-load dependent module." in all but hypertrm.dll.

I've searched all my local exe and dll files and can't find any meaningful references to PrintDlgEx other than in mfc7*. I'm searching now for references to mfc7--if I don't find much, it might not be much of an issue for apps that don't otherwise need Kex.

mfc7 references found in:

- video2smv.exe / smv.dll

- SUPERsetup.exe

- vdm_free.exe

- avformat-52.dll (ffmpeg)


I'm on my way out the door right now--I'll post translation code for review tonight.

Link to comment
Share on other sites

MSDN - Using Common Dialog Boxes


HRESULT WINAPI PrintDlgExA (PRINTDLGEX *pPdex)
{
PRINTDLG pd;
pd.lStructSize = sizeof(PRINTDLG);
pd.hwndOwner = pPdex->hwndOwner;
pd.hDevMode = pPdex->hDevMode;
pd.hDevNames = pPdex->hDevNames;
pd.hDC = pPdex->hDC;
pd.Flags = PD_USEDEVMODECOPIESANDCOLLATE | PD_RETURNDC; // pPdex->Flags;
pd.nCopies = 1;
pd.nFromPage = 0xFFFF;
pd.nToPage = 0xFFFF;
pd.nMinPage = pPdex->nMinPage;
pd.nMaxPage = pPdex->nMaxPage;
pd.nCopies = pPdex->nCopies;
pd.hInstance = pPdex->hInstance;
pd.lCustData = 0;
pd.lpfnPrintHook = NULL;
pd.lpfnSetupHook = NULL;
pd.lpPrintTemplateName = pPdex->lpPrintTemplateName;
pd.lpSetupTemplateName = NULL;
pd.hPrintTemplate = NULL;
pd.hSetupTemplate = NULL;

if (PrintDlgA (&pd)) {
pPdex->dwResultAction = 1; // Print
//pPdex->lStructSize;
//pPdex->hwndOwner;
pPdex->hDevMode = pd.hDevMode;
pPdex->hDevNames = pd.hDevNames;
pPdex->hDC = pd.hDC;
//pPdex->Flags;
//pPdex->Flags2;
//pPdex->ExclusionFlags;
pPdex->nPageRanges = 0;
pPdex->nMaxPageRanges = 0;
pPdex->lpPageRanges = NULL;
pPdex->nMinPage = pd.nMinPage;
pPdex->nMaxPage = pd.nMaxPage;
pPdex->nCopies = pd.nCopies;
//pPdex->hInstance;
//pPdex->lpPrintTemplateName;
//pPdex->lpCallback;
//pPdex->nPropertyPages;
//pPdex->*lphPropertyPages;
//pPdex->nStartPage;
} else {
pPdex->dwResultAction = 0; // Cancel
}
return 0; // S_OK;
}

I haven't researched and doubled checked every field yet--some are guesses. What am I missing before I try to compile it?

Does anyone know if PRINTDLG is packed? If so, all DWORDs after the five WORDs are misaligned!

Link to comment
Share on other sites

  • 2 weeks later...

I've been working hard on this problem and should have a major announcement by tonight (bigger than just PrintDlgEx). :yes:


<edit>

Today didn't go as planned and I've been away from my computer all day. So here's a sneak preview: fwd.

</edit>

Edited by jumper
Link to comment
Share on other sites

For the brave, here is a COMDLG32.DLL with PrintDlgExA:

<attachment removed>

Extract COMDLG32.DLL and ComDlgEx.dll into <system>, or put them in a test app's local folder and remove COMDLG32.DLL from KnownDLLs.

COMDLG32.DLL was extended with fwd.02 (now working, not posted yet).

The PrintDlgExA sources (.c + .def) for ComDlgEx.dll are included.

I have high confidence in the validity of the export forwarding in this COMDLG32.DLL (Dependency Walker and PEinfo both like it). The structure translation in PrintDlgExA should be good enough to yield positive results.

There were seven downloads before I decided to remove the attachment--if anyone has any results at all, please give us all a report! :hello:

Edited by jumper
Link to comment
Share on other sites

I downloaded SumatraPDF 0.9 to test with, but couldn't get past the "missing export COMDLG32.DLL:PrintDlgExA" message.

My system also became unstable each time I tried the extended COMDLG32, so I've removed the attachment from the previous message pending a complete design review.

If it turns out that export-forwarding is an NT-only DLL feature that isn't implemented in the 9x loader...then we'll just have to extend the 9x loader! :lol:

Since this method was actually something like plan C, I can still go back to plan B (direct function injection). B)

Link to comment
Share on other sites

Plan D: ComDlgEx.7z

  • ComDlgEx.dll
  • ComDlgEx.reg

SumatraPDF 0.9 now loads without Kex, but run with Kex to get past ComCtl32 issues.

ComDlgEx.reg

REGEDIT4

;Installation:
; 1) Place ComDlgEx.dll in <winsys> folder
; 2) Copy COMDLG32.DLL to COMDLG99.DLL
; 3) Merge this file into the registry

;Uninstallation:
; 1) Edit comments below and remerge
; 2) Delete COMDLG99.DLL and ComDlgEx.dll

[HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\SessionManager\KnownDLLs]
"COMDLG32"="ComDlgEx.DLL"
;"COMDLG32"="COMDLG32.DLL"
;"COMDLG32"=-

ComDlgEx.def


;LIBRARY ComDlg32

EXPORTS
xyz=COMDLG99.@100 @100 NONAME
ChooseColorA=COMDLG99.ChooseColorA @101
ChooseColorW=COMDLG99.ChooseColorW @102
ChooseFontA=COMDLG99.ChooseFontA @103
ChooseFontW=COMDLG99.ChooseFontW @104
CommDlgExtendedError=COMDLG99.CommDlgExtendedError @105
FindTextA=COMDLG99.FindTextA @106
FindTextW=COMDLG99.FindTextW @107
GetFileTitleA=COMDLG99.GetFileTitleA @108
GetFileTitleW=COMDLG99.GetFileTitleW @109
GetOpenFileNameA=COMDLG99.GetOpenFileNameA @110
GetOpenFileNameW=COMDLG99.GetOpenFileNameW @111
GetSaveFileNameA=COMDLG99.GetSaveFileNameA @112
GetSaveFileNameW=COMDLG99.GetSaveFileNameW @113
LoadAlterBitmap=COMDLG99.LoadAlterBitmap @114
PageSetupDlgA=COMDLG99.PageSetupDlgA @115
PageSetupDlgW=COMDLG99.PageSetupDlgW @116
PrintDlgA=COMDLG99.PrintDlgA @117
PrintDlgW=COMDLG99.PrintDlgW @118
ReplaceTextA=COMDLG99.ReplaceTextA @119
ReplaceTextW=COMDLG99.ReplaceTextW @120
WantArrows=COMDLG99.WantArrows @121
dwLBSubclass=COMDLG99.dwLBSubclass @122
dwOKSubclass=COMDLG99.dwOKSubclass @123
PrintDlgExA @124

PrintDlgExA.c


// PrintDlgExA.c - jumper, Feb 16, 2012
// http://www.msfn.org/board/topic/

//***** Standard #define and #include statements *****//

//#define WIN32_LEAN_AND_MEAN
#define STRICT
#include <windows.h>
#include "commdlg.h"


//***** DLL entry point *****//

BOOL APIENTRY _DllMainCRTStartup (HANDLE hInst, DWORD ul_reason_being_called, LPVOID lpReserved)
{ return 1;
}


//***** Export functions *****//

typedef struct tagPDEX {
DWORD lStructSize;
HWND hwndOwner;
HGLOBAL hDevMode;
HGLOBAL hDevNames;
HDC hDC;
DWORD Flags;
DWORD Flags2;
DWORD ExclusionFlags;
DWORD nPageRanges;
DWORD nMaxPageRanges;
//LPPRINTPAGERANGE lpPageRanges;
LPVOID lpPageRanges;
DWORD nMinPage;
DWORD nMaxPage;
DWORD nCopies;
HINSTANCE hInstance;
LPCTSTR lpPrintTemplateName;
LPUNKNOWN lpCallback;
DWORD nPropertyPages;
HPROPSHEETPAGE *lphPropertyPages;
DWORD nStartPage;
DWORD dwResultAction;
} PRINTDLGEX;

//extern BOOL APIENTRY PrintDlgA(LPPRINTDLGA);

HRESULT WINAPI PrintDlgExA (PRINTDLGEX *pPdex)
{
PRINTDLG pd;
pd.lStructSize = sizeof(PRINTDLG);
pd.hwndOwner = pPdex->hwndOwner;
pd.hDevMode = pPdex->hDevMode;
pd.hDevNames = pPdex->hDevNames;
pd.hDC = pPdex->hDC;
pd.Flags = PD_USEDEVMODECOPIESANDCOLLATE | PD_RETURNDC; // pPdex->Flags;
pd.nCopies = 1;
pd.nFromPage = 0xFFFF;
pd.nToPage = 0xFFFF;
pd.nMinPage = (WORD)pPdex->nMinPage;
pd.nMaxPage = (WORD)pPdex->nMaxPage;
pd.nCopies = (WORD)pPdex->nCopies;
pd.hInstance = pPdex->hInstance;
pd.lCustData = 0;
pd.lpfnPrintHook = NULL;
pd.lpfnSetupHook = NULL;
pd.lpPrintTemplateName = pPdex->lpPrintTemplateName;
pd.lpSetupTemplateName = NULL;
pd.hPrintTemplate = NULL;
pd.hSetupTemplate = NULL;

if (PrintDlgA (&pd)) {
pPdex->dwResultAction = 1; // Print
//pPdex->lStructSize;
//pPdex->hwndOwner;
pPdex->hDevMode = pd.hDevMode;
pPdex->hDevNames = pd.hDevNames;
pPdex->hDC = pd.hDC;
//pPdex->Flags;
//pPdex->Flags2;
//pPdex->ExclusionFlags;
pPdex->nPageRanges = 0;
pPdex->nMaxPageRanges = 0;
pPdex->lpPageRanges = NULL;
pPdex->nMinPage = pd.nMinPage;
pPdex->nMaxPage = pd.nMaxPage;
pPdex->nCopies = pd.nCopies;
//pPdex->hInstance;
//pPdex->lpPrintTemplateName;
//pPdex->lpCallback;
//pPdex->nPropertyPages;
//pPdex->*lphPropertyPages;
//pPdex->nStartPage;
} else {
pPdex->dwResultAction = 0; // Cancel
}
return 0; // S_OK;
}


This version was stable (six days). It redirected PrintDlgExA to PrintDlgA and operated as expected if the dialog was cancelled, but did not print.

Edited by jumper
Link to comment
Share on other sites

Working solution: ComDlg32.7z

  1. Place ComDlg32.dll in app folder.
  2. In <winsysdir>, copy original COMDLG32.DLL to COMDLG00.DLL.
  3. Remove any COMDLG32 redirections in KnownDLLs.

Should print to printer.

Print to file not implemented yet in SumatraPDF 0.9.

PrintDlgExA.c source:

// PrintDlgExA.c - jumper, Mar 12, 2012

//***** Standard #define and #include statements *****//

#define STRICT
#include <windows.h>
#include "commdlg.h"


//***** DLL entry point *****//

BOOL APIENTRY
_DllMainCRTStartup (HANDLE hInst, DWORD ul, LPVOID lp)
{ return 1;
}


//***** Export functions *****//

typedef struct tagPRINTPAGERANGE {
DWORD nFromPage;
DWORD nToPage;
} PRINTPAGERANGE, *LPPRINTPAGERANGE;

typedef struct tagPDEX {
DWORD lStructSize;
HWND hwndOwner;
HGLOBAL hDevMode;
HGLOBAL hDevNames;
HDC hDC;
DWORD Flags;
DWORD Flags2;
DWORD ExclusionFlags;
DWORD nPageRanges;
DWORD nMaxPageRanges;
LPPRINTPAGERANGE lpPageRanges;
DWORD nMinPage;
DWORD nMaxPage;
DWORD nCopies;
HINSTANCE hInstance;
LPCTSTR lpPrintTemplateName;
LPUNKNOWN lpCallback;
DWORD nPropertyPages;
HPROPSHEETPAGE *lphPropertyPages;
DWORD nStartPage;
DWORD dwResultAction;
} PRINTDLGEX;


HRESULT WINAPI PrintDlgExA (PRINTDLGEX *pPdex)
{
PRINTDLG pd;
pd.lStructSize = sizeof(PRINTDLG);
pd.hwndOwner = pPdex->hwndOwner;
pd.hDevMode = pPdex->hDevMode;
pd.hDevNames = pPdex->hDevNames;
pd.hDC = pPdex->hDC;
pd.Flags = (pPdex->Flags & PD_RETURNDC)?
pPdex->Flags | PD_USEDEVMODECOPIESANDCOLLATE:
pPdex->Flags;
pd.nFromPage = 0xFFFF;
pd.nToPage = 0xFFFF;
if (pPdex->nMaxPageRanges) {
pd.nFromPage = (WORD)pPdex->lpPageRanges[0].nFromPage;
pd.nToPage = (WORD)pPdex->lpPageRanges[0].nToPage;
}
pd.nMinPage = (WORD)pPdex->nMinPage;
pd.nMaxPage = (WORD)pPdex->nMaxPage;
pd.nCopies = (WORD)pPdex->nCopies;
pd.hInstance = NULL; //for templates
pd.lCustData = 0;
pd.lpfnPrintHook = NULL;
pd.lpfnSetupHook = NULL;
pd.lpPrintTemplateName = NULL;
pd.lpSetupTemplateName = NULL;
pd.hPrintTemplate = NULL;
pd.hSetupTemplate = NULL;

if (PrintDlgA (&pd)) {
pPdex->dwResultAction = 1; // Print
pPdex->hDevMode = pd.hDevMode;
pPdex->hDevNames = pd.hDevNames;
pPdex->hDC = pd.hDC;
pPdex->Flags = pd.Flags;
if (pPdex->nMaxPageRanges) {
pPdex->nPageRanges = 1;
pPdex->lpPageRanges[0].nFromPage = pd.nFromPage;
pPdex->lpPageRanges[0].nToPage = pd.nToPage;
}
pPdex->nCopies = pd.nCopies;
} else {
pPdex->dwResultAction = 0; // Cancel
}
return 0; // S_OK;
}

Edited by jumper
Link to comment
Share on other sites

Installation clarification using SeaMonkey as an example:

Q) Where in the SeaMonkey folder should I place the dll? I find dll's in almost every folder there.

A) Place a copy of my ComDlg32.dll in the folder containing SeaMonkey.exe. Also, search for text "PrintDlgEx" in SeaMonkey's top folder using Find. Place a copy in the folder of each file that contains a reference to "PrintDlgEx".

Q) Should I rename comdlg32.dll to comdlg00.dll and NOT replace the original windows one with your dll? So, Windows does not have this file at all?

A) Copy (do not Rename) the original ComDlg32.dll:

  1. Right-click on the original ComDlg32.dll, drag until [+] appears and release, then select "Copy Here".
  2. Rename the new copy "ComDlg00.dll".

The original ComDlg32.dll remains for all other programs to continue using.

Link to comment
Share on other sites

Three ways to install the ComDlg32.dll update:

  1. In <system> folder (affects all applications including OS):
    • rename to ComDlgEx.dll and place in <system> folder
    • do one of the following:
      1. DOS method
        • exit to DOS and cd to <system> folder
        • rename COMDLG32.DLL to COMDLG00.DLL
        • rename COMDLGEX.DLL to COMDLG32.DLL

      2. KnownDLLs method:
        • copy <system>\ComDlg32.dll to <system>\ComDlg00.dll
        • merge into registry:
          REGEDIT4
          
          [HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\SessionManager\KnownDLLs]
          "COMDLG32"="ComDlgEx.DLL" 

  2. In <windows>\KernelEx folder (affects only KernelEx-enabled applications):
    • place in <windows>\KernelEx folder
    • copy <system>\ComDlg32.dll to <system>\ComDlg00.dll
    • merge into registry:
      REGEDIT4
      
      [HKEY_LOCAL_MACHINE\Software\KernelEx\KnownDLLs]
      "COMDLG32"="ComDlg32.dll"

  3. In specific application/DLL folders (affects only those EXEs/DLLs):
    • place in folder of EXE or DLL that references PrintDlgExA
    • copy <system>\ComDlg32.dll to <system>\ComDlg00.dll
    • remove any global redirection from registry:
      REGEDIT4
      
      [HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\SessionManager\KnownDLLs]
      "COMDLG32"=-


Note: To modify registry, save boxed text as new.reg, right-click and select 'Merge'; or use RegEdit.


Edited by jumper
restore original formatting
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...