[Bug 8033] TOPO 4.2.7: Unhandled Page Fault Using

Wine Bugs wine-bugs at winehq.org
Fri Apr 13 09:32:31 CDT 2007


http://bugs.winehq.org/show_bug.cgi?id=8033





------- Additional Comments From focht at gmx.net  2007-13-04 09:32 -------
Created an attachment (id=5758)
 --> (http://bugs.winehq.org/attachment.cgi?id=5758&action=view)
in-depth crash analysis of TOPO 4.x binary

Hello,



seems there is no demo/trial from website available, so i downloaded the
"upgrade" from http://maps.nationalgeographic.com/TOPO/ 

Though the upgrade requires 4.x full version installed, i "convinced" the
installer to work.


Analysis would be too large to post here, so i refer to problematic code
snippets here.

To see in-depth analysis scratch pad, consult the attachment.



Basically it's a combination of wine bug in common dialog (printing) module and
the way the application is coded (error handling).

The application makes heavy use of MFC 7.x (native dlls).



--- snip pseudo app code ---

CPageSetupDialog dlg( PSD_RETURNDEFAULT | PSD_NOWARNING, NULL);

if(dlg.DoModal() != IDOK)

    return;

--- snip pseudo app code ---



Returns on both platforms (windows and wine) "IDOK".

Printer subsystems dlls are loaded on demand (in DoModal() call)



The next snippet is the culprit:



--- snip pseudo app code ---

 if( pThis->m_hDevMode != NULL)

	{

	     ::GlobalFree( pThis->m_hDevMode);

	}

     

	if( pThis->m_hDevNames != NULL)

	{

	     ::GlobalFree( pThis->m_hDevMode);

	}



	pThis->m_hDevMode = m_psd.hDevMode;

	pThis->m_hDevNames = m_psd.hDevNames;

	pThis->m_Name = dlg.GetDeviceName();



	// fill in pThis->PrinterCapsData1...4

	get_device_caps_from_printer_dc( dlg);



	PDEVMODEA* pDevMode = ::GlobalLock( pThis->m_hDevMode);

	// crash here deref NULL ptr

	pDevMode->dmOrientation = (pThis->IsPortraitOrientation != 0) ?

				DMORIENT_PORTRAIT : DMORIENT_LANDSCAPE;  

--- snip pseudo app code ---



The application expects PAGESETUPDLG data structure (subclassed data member) to
be correctly filled in when doing CPageSetupDialog::DoModal() + dlgResult ==
IDOK.

But neither m_psd.hDevMode nor m_psd.hDevNames have meaningful values in wine
(NULL ptr).

Even the "query default printer" does not return any printers/data to client at
all.


Windows returns valid struct handles (e.g. filled DEVMODEA and DEVNAMES).

The application dies on first dereference of one of these data pointers after
locking the handles (pDevMode->dmOrientation).

Of course one can argue its bad error handling to rely on data being valid all
the time (even "fallback/default" case).


Armed with this knowledge, i put additional trace code into wine and found the
cause.

--- snip dlls/comdlg32/printdlg.c ---
BOOL WINAPI PageSetupDlgA(LPPAGESETUPDLGA setupdlg) 
{
.....

 /* Initialize default printer struct. If no printer device info is specified
       retrieve the default printer data. */
    memset(&pdlg,0,sizeof(pdlg));
    pdlg.lStructSize	= sizeof(pdlg);
    if (setupdlg->hDevMode && setupdlg->hDevNames) {
	pdlg.hDevMode = setupdlg->hDevMode;
	pdlg.hDevNames = setupdlg->hDevNames;
    } else {
	pdlg.Flags = PD_RETURNDEFAULT;
	bRet = PrintDlgA(&pdlg);
	if (!bRet){
	    if (!(setupdlg->Flags & PSD_NOWARNING)) {
		char errstr[256];
		LoadStringA(COMDLG32_hInstance, PD32_NO_DEFAULT_PRINTER,
errstr, 255);
		MessageBoxA(setupdlg->hwndOwner, errstr, 0, MB_OK |
MB_ICONERROR);
	    }
	    return FALSE;
	}
    }
....
}
--- snip dlls/comdlg32/printdlg.c ---

The culprit is: if an application (win32 code, MFC ...) calls PageSetupDlgA()
with hDevMode and hDevNames both NULL ("give me default one") it *expects*
something usefull if PrintDlgA() dlgResult == ok.

To fix this, copy devmode/devname structure handles for client use.

--- snip dlls/comdlg32/printdlg.c ---
BOOL WINAPI PageSetupDlgA(LPPAGESETUPDLGA setupdlg) 
{
.....

 /* Initialize default printer struct. If no printer device info is specified
       retrieve the default printer data. */
    memset(&pdlg,0,sizeof(pdlg));
    pdlg.lStructSize	= sizeof(pdlg);
    if (setupdlg->hDevMode && setupdlg->hDevNames) {
	pdlg.hDevMode = setupdlg->hDevMode;
	pdlg.hDevNames = setupdlg->hDevNames;
    } else {
	pdlg.Flags = PD_RETURNDEFAULT;
	bRet = PrintDlgA(&pdlg);
	if (!bRet){
	    if (!(setupdlg->Flags & PSD_NOWARNING)) {
		char errstr[256];
		LoadStringA(COMDLG32_hInstance, PD32_NO_DEFAULT_PRINTER,
errstr, 255);
		MessageBoxA(setupdlg->hwndOwner, errstr, 0, MB_OK |
MB_ICONERROR);
	    }
	    return FALSE;
	}

	// FIX: there was no input hDevMode and hDevNames: give it to client!  

	setupdlg->hDevMode = pdlg.hDevMode;
	setupdlg->hDevNames = pdlg.hDevNames;
    }
....
}
-- snip dlls/comdlg32/printdlg.c ---

With this fix, the app doesnt crash anymore - though it exits later (due to my
upgrade-hack -> no full version avail -> incomlete install)

It could be possible that this one might "heal" related printing setup bug
reports/crashes too.

Regards


-- 
Configure bugmail: http://bugs.winehq.org/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug, or are watching the assignee.



More information about the wine-bugs mailing list