Solved

PropertySheet DLLs Followup (DanRollins)

Posted on 2002-05-12
24
503 Views
Last Modified: 2012-08-13
I accepted your answer earlier because it seemed like it would work. However I've been having some problems implementing it. I've been using code like this:

*********************************************************
[DLL]
CPage* m_Page; // CPage is derived from CPropertyPage
__declspec(dllexport) void* CreatePage()
{
     m_Page = new CPage();
     return (void*)m_Page;
}

[APPLICATION]
CPropertyPage *aPage;
CPropertySheet Mysheet;
FARPROC CreateFunc;

CreateFunc = GetProcAddress(handletoDLL, "ExportedName");
aPage = (CPropertyPage*)CreateFunc();
Mysheet.AddPage(aPage);
*********************************************************

That code generates this error (copy and pasted):

Application: This program has performed an illegal operation and will be shut down. If the problem persists, contact the program vendor.

APPLICATION caused an invalid page fault in
module THEDLL.DLL at 0167:100056a1.
Registers:
EAX=007b1640 CS=0167 EIP=100056a1 EFLGS=00010246
EBX=00580000 SS=016f ESP=0068fb14 EBP=0068fb7c
ECX=007b1640 DS=016f ESI=0068fb84 FS=60bf
EDX=00000000 ES=016f EDI=0068fb70 GS=0000
Bytes at CS:EIP:
89 82 c8 00 00 00 8b 4d f0 8b 81 c8 00 00 00 8b
Stack dump:
0068fd54 0068fb84 00580000 cccccccc cccccccc cccccccc cccccccc cccccccc cccccccc cccccccc cccccccc cccccccc cccccccc cccccccc cccccccc cccccccc

Do you have any ideas on about what's going wrong here?
0
Comment
Question by:xebra19
  • 14
  • 9
24 Comments
 
LVL 86

Expert Comment

by:jkr
ID: 7004688
Have you checked whether CreateFunc contains a valid address before calling it? E.g.

FARPROC CreateFunc;

CreateFunc = GetProcAddress(handletoDLL, "ExportedName");

if ( NULL != CreateFunc) {

  aPage = (CPropertyPage*)CreateFunc();

} else {

  // error
}

BTW, you should use

extern "C" __declspec(dllexport) void* CreatePage()

to avoid exporting the function with a C++ mangled name...
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 7004746
You need to call
   AFX_MANAGE_STATE(AfxGetStaticModuleState());
in every case where control is passed from the EXE to the DLL.  That big block of comments provided at the top of the AppWizard-generated file goes into excruciating detail in this regard.

-- Dan

0
 
LVL 49

Expert Comment

by:DanRollins
ID: 7004748
Also, when that error occurs, bring up the Call Stack to learn where the code went awry.  You can also diagnose many problems by single-stepping with the debugger.  You can trace right into the DLL.  The trick is putting a breakpoint on the

    aPage = (CPropertyPage*)CreateFunc();

line.

-- Dan
0
 

Author Comment

by:xebra19
ID: 7004848
I did a debug, and it points out this line: m_Page = new CPage(); and says the expression doesn't evaluate.
0
 

Author Comment

by:xebra19
ID: 7004852
note: i added the AFX_MANAGE_STATE line at the top of that function
0
 

Author Comment

by:xebra19
ID: 7005258
jkr: I have checked and it does have the correct name. The function is being called.
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 7005363
>> the expression doesn't evaluate
Are you saying that the DLL cannot be compiled?  If so, then there is some chance that that is related to your problem.
-- Dan
0
 

Author Comment

by:xebra19
ID: 7005383
heh, no the DLL compiles. It compiles just fine. When the error occurs, and i click the debug button, it points to that line. I check the output window and under the line the references "m_Page = new CPage();" It says that the expression doesn't evaluate.
0
 

Author Comment

by:xebra19
ID: 7006249
also, if I set a breakpoint on this line: "aPage = (CPropertyPage*)CreateFunc();". I get this for the value aPage in the Debug output window:
Name: aPage
Value: 0x00000000 {CPropertyPage hWnd=???}

That line has a + sign in front of it. When I click it this drops down underneath:

Name: CDialog
Value: CXX0030: Error: expression cannot be evaluated

There are also a few more dropdowns that list different names but they pretty much all say "expression cannot be evaluated".
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 7007126
the variable aPage will have no value until the line:

   aPage = (CPropertyPage*)CreateFunc();

has been executed.  You need to breakpoint that line, and then single-step.  That could put you right into the DLL code where you can single-step the CreateFunc() function.

-- Dan


0
 

Author Comment

by:xebra19
ID: 7007338
well what i said earlier was that this line (which is in the CreateFunc function) is causing the problem:
m_Page = new CPage();
It tells me that this expression can not be evaluated (this is the line in the CreateFunc function).
If I mouse over the part that says "CPage()" it displays this tooltip: CPage = {CPage hWnd=???}

Could this be the problem? If not, i must not be understanding what you are saying. I debug my application letting it execute the code line by line until it hits an error, it then stops and points out that line to me. What else am i supposed to do?
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 7007519
right click on that line.  
choose Insert/Remove breakpoint
run the program
when it stops, it will display that line
now choose menu item Debug/Step Into

Now you can execute each program line, one line at a time.  In this case, that will involve stepping into the code that is in the DLL (the exported function, CreateFunc() code ).

-- Dan

0
Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

 

Author Comment

by:xebra19
ID: 7007554
yes i tried that however, after going through about 10,000 lines of code related to AFX_MANAGE_STATE, i just stepped out until I got down to the mPage = net CPage() line. Then it shows this error:
First-chance exception in MainApplication.exe (THEDLL.DLL): 0xC0000005: Access Violation.

I don't see how assaigning a new CPropertyPage derived object to a pointer would cause an Access Violation.
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 7007746
Show your code leading up to the

    mPage= new CPage();

line in the DLL.  How have you defined mPage?

As soon as you are in the DLL, you can put a breakpoint in the constructor for your CPage.  I'd have to guess that something in there is going wrong.



0
 

Author Comment

by:xebra19
ID: 7007885
hmm, doesn't it seem easier to just export the m_Page pointer? And then just load it and call AddPage from the main program instead of messing with this function? It would probably eliminate a lot of possible errors. If this would be a better choice, how would I do what I did with the function to the pointer? (the GetProcAddress Part, in other words, how can i load the pointer into the main program so that I can call AddPage with it as a parameter?)
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 7008949
When you use a .LIB to interface the EXE to the DLL, it is very easy to export class objects and data variable.  As I understand your question, you will be using LoadLibrary, so the only way to access the DLL is via GetProcAddress, which does not return object or data -- only addresses of functions -- so at is not an option.

What's left is to simulate the ActiveX concept of a 'class factory' ... the DLL provides a function that creates and initializes the object and passes back a pointer to that object.

If you want to use 'normal DLL Linking' (using a LIB file and requiring the presence of all potentially needed DLLs at runtime) then that will simplify your task considerably.

-- Dan
0
 

Author Comment

by:xebra19
ID: 7009768
BEGIN[DLL CODE, DLL CODE, DLL CODE, DLL CODE]

Note the CPage I have been referring to has been renamed to CStatPage. Here's all the relavent code:
***********************************************************
// StatPage.cpp : implementation file
//

#include "stdafx.h"
#include "dllapp.h"
#include "StatPage.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CStatPage property page

IMPLEMENT_DYNCREATE(CStatPage, CPropertyPage)

CStatPage::CStatPage() : CPropertyPage(CStatPage::IDD)
{
     //{{AFX_DATA_INIT(CStatPage)
          // NOTE: the ClassWizard will add member initialization here
     //}}AFX_DATA_INIT
}

CStatPage::~CStatPage()
{
}

void CStatPage::DoDataExchange(CDataExchange* pDX)
{
     CPropertyPage::DoDataExchange(pDX);
     //{{AFX_DATA_MAP(CStatPage)
          // NOTE: the ClassWizard will add DDX and DDV calls here
     //}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CStatPage, CPropertyPage)
     //{{AFX_MSG_MAP(CStatPage)
          // NOTE: the ClassWizard will add message map macros here
     //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CStatPage message handlers

***********************************************************

// StatPage.h : header file
//

/////////////////////////////////////////////////////////////////////////////
// CStatPage dialog

class CStatPage : public CPropertyPage
{
     DECLARE_DYNCREATE(CStatPage)

// Construction
public:
     CStatPage();
     ~CStatPage();

// Dialog Data
     //{{AFX_DATA(CStatPage)
     enum { IDD = IDD_STATDLG };
          // NOTE - ClassWizard will add data members here.
          //    DO NOT EDIT what you see in these blocks of generated code !
     //}}AFX_DATA


// Overrides
     // ClassWizard generate virtual function overrides
     //{{AFX_VIRTUAL(CStatPage)
     protected:
     virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
     //}}AFX_VIRTUAL

// Implementation
protected:
     // Generated message map functions
     //{{AFX_MSG(CStatPage)
          // NOTE: the ClassWizard will add member functions here
     //}}AFX_MSG
     DECLARE_MESSAGE_MAP()

};

***********************************************************

// MAIN DLL HEADER FILE (IMPORTANT SECTIONS)
CStatPage* m_Page;
__declspec(dllexport) void* CreatePage();

***********************************************************

// MAIN DLL SOURCE FILE (IMPORTANT SECTIONS)
__declspec(dllexport) void* CreatePage()
{
     AFX_MANAGE_STATE(AfxGetStaticModuleState());
     m_Page = new CStatPage;
     return (void*)m_Page;
}

***********************************************************
END[DLL CODE, DLL CODE, DLL CODE, DLL CODE]
0
 

Author Comment

by:xebra19
ID: 7009772
HERE COMES THE MAIN PROGRAM SOURCE CODE
0
 

Author Comment

by:xebra19
ID: 7009790
***********************************************************

// MAIN PROGRAM (EXE) HEADER FILE (IMPORTANT SECTIONS)
CPropertyPage *m_Page;
CMainProgramDlg dlgacc;

***********************************************************

// MAIN PROGRAM (EXE) SOURCE FILE (IMPORTANT SECTIONS)
HMODULE hMod = LoadLibrary( dllPath );
FARPROC CreateFunc;
CreateFunc = GetProcAddress(hMod, "CreatePage");
if(CreateFunc == NULL)
{
     MessageBox("DLL NOT LOADED");
}
else
{
     m_Page = (CPropertyPage*)CreateFunc();
     dlgacc.m_sheet.AddPage(m_Page);
}

***********************************************************

The rest of the important code in the main app is just the code to setup the property sheet but i know that code is correct.
0
 

Author Comment

by:xebra19
ID: 7009794
BTW - m_sheet was Mysheet but i changed it to a more normal variable name. m_sheet is the name of the property sheet
0
 
LVL 49

Accepted Solution

by:
DanRollins earned 100 total points
ID: 7009929
Here is code from my EXE (AppWizard-created, dialog-based app, entirely default but added one button and a handler for it):

CPropertyPage* m_pPage;

void CDllEXETestDlg::OnButton1()
{
     // provide the full path to the DLL
     HMODULE hMod = LoadLibrary( "C:\\MyProj\\test\\test2\\DLLDlgPg\\Debug\\DllDlgPg.dll" );
     FARPROC pfCreateFunc;
     pfCreateFunc= GetProcAddress( hMod, "CreatePage" );
     if( pfCreateFunc == NULL) {
          MessageBox("DLL NOT LOADED");
          return;
     }
     else {
         m_pPage= (CPropertyPage*) pfCreateFunc();
     }
     CPropertySheet pSheet("The Title", this );
     pSheet.AddPage( m_pPage );
     pSheet.DoModal();
}

-=-=-=-=-=-==--=-=-==--=-=
I created a new project MFC AppWizard(dll).   I added this code to the bottom of the only CPP file:

#include "PropPg.h"

CPropPg* gpcPropPg;

__declspec(dllexport) void* CreatePage()
{
    AFX_MANAGE_STATE(AfxGetStaticModuleState());
    gpcPropPg= new CPropPg();
    return (void*)gpcPropPg;
}
-=-=-=-=-=-=-=-=-=-=-==-
I created the CPropPg class by using the dlg editor to create IDD_DIALOG1.  I added some simple controls, then I pressed Ctrl+W.  I was prompted to create a new object and I said yes.  Then I selected CPropertyPage as the base class.

I then opened the .DEF file and added:

   CreatePage @1

to the end.  I built both projects.  Then I ran the EXE and it worked perfectly immediately.

If you follow these steps (not trying to reuse any of your existing code) then you will have a functional system.  That way you can then begin trying out different things.

If it fails then you did not follow the instructions.

-- Dan
0
 

Author Comment

by:xebra19
ID: 7010063
well that worked. It didn't seem any different than what I was doing. I must have made some stupid type errors. Oh well. Thanks! You've been a big help!

If I did this right you should get 500 expert points (if the system hasn't changed)
0
 

Author Comment

by:xebra19
ID: 7010067
hmm, the increase points didn't work. oh well, i'll find a way to give you some more points later.
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 7010515
I'm glad I could help!

To award additional points, just make a new Question in the C++ TA.  Set it's title to
          Points for DanRollins
and place this in the question text:

For your help with: http://www.experts-exchange.com/cplusprog/Q.20299685.html

-- Dan
0

Featured Post

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

What is C++ STL?: STL stands for Standard Template Library and is a part of standard C++ libraries. It contains many useful data structures (containers) and algorithms, which can spare you a lot of the time. Today we will look at the STL Vector. …
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…

760 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now