Solved

Messageprocessing in DLL's

Posted on 1997-11-05
4
409 Views
Last Modified: 2013-11-20
I have created DLL used for DLC communication
(a low level network protocol). I want to be able
to load the DLL, start a service thread and post
it messages.

The VC+5.0 environment has a wizard that can create a
DLL template. The produced code gives me a CWinApp derived
object that should be able to receive messages.

However, if I try to start it's CWinThread::Run() method
it terminates since there is no Windows handle assigned
to the DLL (i think).

How do I post a message to a service routine running in a DLL?

Cincerly
Rune.Bundesen @ i-data.com
0
Comment
Question by:puff
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
4 Comments
 
LVL 8

Expert Comment

by:MikeP090797
ID: 1309395
You use LoadLibrary from an EXE, and the ::Run is called automaticly. the ::Run is instead of DllMain function of a DLL.
0
 

Author Comment

by:puff
ID: 1309396
Thanks for the reply.
Unfortunately it's a little more complex then that I think.
Perhabs im missing something, but here is what I think is
the problem.

I want to load a dll from an exe file (using loadlibrary).
The exe file is a CWinApp itself and lives in the main
thread.

After the library is loaded, I want to call a function
from the dll (still inside the main thread), lets call it
Init().

Inits function is to start a new thread holding a message pump.
I have tried this.. (CDlcDriverThread is a derrivation of
CWinThread).

DWORD CALLBACK InitDlcDriver(HWND hWndReceiver)
{
 AFX_MANAGE_STATE(AfxGetStaticModuleState());
 BOOL bRes;

 pDlcDriverThread=new CDlcDriverThread(hWndReceiver);
 bRes=pDlcDriverThread->CreateThread();

 if (!bRes) AfxMessageBox("Cannot create DlcDriverThread");
 return pDlcDriverThread->m_nThreadID;
}

The 'new' operation seems to create a valid object,
but the thread being created shuts down almost immediately.
I have tried to remove the CWinApp object in the dll, since
i thought it could be associated with having two CWinApp's,
but this just causes CreateThread to give an assertion error
[AfxGetApp() returns Null].

I just cant figure out how on earth I can create a
userinterface thread from a function inside a dll!.
Probably a trivial problem once you know the answer,
and I need it to be a userinterface thread since I want
to post the new thread messages (do this, do that, etc.)

thanks for the go Mike ;-), I hope you can clarify things
further.
0
 
LVL 1

Accepted Solution

by:
IgorGrebnev earned 300 total points
ID: 1309397
Dear Puff,
You can create new user interface thread in DLL, just like you can do that inside of code of your main exe.
The problem that you mixed the CWinApp object created inside of the DLL with application wizard with creation of new thread. THe application object inside of DLL used for managing of DLL module ( handle of DLL, name of INI file ) but its Run() funciton is never called.

What you need is to create new CWinThread object and call its Run() function. It should be different class from the CWinApp object created in the DLL.
Creating of user interface threads in DLL is not different from creation of threads inside of exe.
For creation of user-interface thread your need to derive class from CWinThread object.
class CMyThread : public CWinThread

{ BOOL InitInstance() { return TRUE; }
}
YOu should override InitInstance(), because the base implementation return FALSE, thus the thread closed immidiately.
Then you write
CMyThread *pMyThread = new CMyThread;
pMyThread->CreateThread(...);
and the new thread runs and enter message loop. You can send messages to the thread with PostThreadMessage API. You should close the thread by posting WM_QUIT message to the thread, thus the MFC message loop is broken and thread exit. You do not need to call delete on thread object, because the default implementation of MFC do it after calling of ExitInstance() of the thread object.
I worked a lot with user-interface threads and created userful base class "CBaseThread" that used for posting of messages to the thread ( the thread do not have window) closing it and syncronisation. I just copy the source of the the BaseTHread.h and BaseTHread.cpp into the my answer and I can send it to you by mail if you provide the address. Here the source:


// BaseThread.h : header file. Base for all IP threads.
//
/////////////////////////////////////////////////////////////////////////////
// CBaseThread thread

class CBaseThread : public CWinThread
{
      DECLARE_DYNAMIC(CBaseThread)
  CEvent *m_pInitEvent;
  void WaitUntilInit();
//------------------------------
  BOOL m_IsInitSucceded;
//------------------- Should not be iverridden by derived classes
  virtual BOOL  InitInstance();
protected:
      CBaseThread(); // protected constructor used by derived classes
//--------------- Derived threads should use this function for initialization
  virtual BOOL InitThread() { return TRUE; }  
public:
//----------- Waits until InitInstance is finished
      BOOL CreateIPThread(UINT nStackSize = 0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL );
  BOOL PostIPMessage( WPARAM, LPARAM );
//---------------- Should NOT be called from the contents of this thread.
  void CloseThread();
  // Overrides
//------------------ Notification function from WM_IPTHREAD_NOTIFY
protected:
//----The value of lParam depends on wParam. In base class do nothing, like pure virtual
  virtual void OnIPThreadMsg( WPARAM, LPARAM ) {}  

      // ClassWizard generated virtual function overrides
      //{{AFX_VIRTUAL(CBaseThread)
protected:
      virtual int   ExitInstance();
      virtual BOOL  PreTranslateMessage(MSG* pMsg);
      //}}AFX_VIRTUAL

// Implementation
protected:
      virtual ~CBaseThread();

      // Generated message map functions
      //{{AFX_MSG(CBaseThread)
            // NOTE - the ClassWizard will add and remove member functions here.
      //}}AFX_MSG

      DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////


// BaseThread.cpp : implementation file
//

#include "stdafx.h"

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

/////////////////////////////////////////////////////////////////////////////
// CBaseThread

IMPLEMENT_DYNAMIC(CBaseThread, CWinThread)

CBaseThread::CBaseThread()

{ m_pInitEvent = new CEvent( FALSE, TRUE );
  m_pInitEvent->ResetEvent();
  m_IsInitSucceded = TRUE;
}

CBaseThread::~CBaseThread()
{
}

BOOL CBaseThread::InitInstance()          
{//----------Creates message Que for the threadv and unlock init event
  MSG msg;
  PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE );              
  m_IsInitSucceded = InitThread();
  m_pInitEvent->SetEvent();
  return TRUE;
}

int CBaseThread::ExitInstance()
{
      if ( m_pInitEvent != NULL )
  { delete m_pInitEvent;
  }
      return CWinThread::ExitInstance();
}

//----------- Waits until InitInstance is finished
void CBaseThread::WaitUntilInit()

{ if ( m_pInitEvent != NULL )
  { m_pInitEvent->Lock();
    if ( m_IsInitSucceded )
    { delete m_pInitEvent;
      m_pInitEvent = NULL;
    }
  }
  else
  { ASSERT( FALSE );
  }
}

BEGIN_MESSAGE_MAP(CBaseThread, CWinThread)
      //{{AFX_MSG_MAP(CBaseThread)
            // NOTE - the ClassWizard will add and remove mapping macros here.
      //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CBaseThread message handlers

BOOL CBaseThread::PreTranslateMessage(MSG* pMsg)
{
      if ( pMsg->hwnd      == NULL &&  pMsg->message == WM_IPTHREAD_NOTIFY )
  { OnIPThreadMsg( pMsg->wParam, pMsg->lParam );
    return TRUE; // No further processing
  }      
      return CWinThread::PreTranslateMessage(pMsg);
}

BOOL CBaseThread::CreateIPThread( UINT nStackSize, LPSECURITY_ATTRIBUTES lpSecurityAttrs )

{//--------------- Do NOT create suspended thread!!!
  BOOL retVal = CWinThread::CreateThread( 0, nStackSize, lpSecurityAttrs );
  if ( retVal )
  { WaitUntilInit();
    return m_IsInitSucceded;
  }
  return retVal;
}

void CBaseThread::CloseThread()

{ if ( m_hThread != NULL )
  { HANDLE hThread = m_hThread;
    BOOL result = ::PostThreadMessage( m_nThreadID, WM_QUIT, 0, 0 );
    ASSERT( result );
    WaitForSingleObject( hThread, INFINITE );
  }
}

BOOL CBaseThread::PostIPMessage( WPARAM wParam, LPARAM lParam  )

{ BOOL retVal = ::PostThreadMessage( m_nThreadID, WM_IPTHREAD_NOTIFY, wParam, lParam );
  ASSERT( retVal );
  return retVal;
}



 
0
 

Author Comment

by:puff
ID: 1309398
Thanks for the reply Igor, you hit it right on the spot!
Your solution works fine, so Ill incorporate your class
into my code right away.

Sorry I missed my address, here it is.
Email work: Rune.Bundesen@i-data.com

Cincerly
-Rune Bundesen
0

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction: Dialogs (2) modeless dialog and a worker thread.  Handling data shared between threads.  Recursive functions. Continuing from the tenth article about sudoku.   Last article we worked with a modal dialog to help maintain informat…
Have you tried to learn about Unicode, UTF-8, and multibyte text encoding and all the articles are just too "academic" or too technical? This article aims to make the whole topic easy for just about anyone to understand.
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
In this brief tutorial Pawel from AdRem Software explains how you can quickly find out which services are running on your network, or what are the IP addresses of servers responsible for each service. Software used is freeware NetCrunch Tools (https…

627 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