C Board  

Go Back   C Board > Platform Specific Boards > Windows Programming

Reply
 
LinkBack Thread Tools Display Modes
Old 06-30-2009, 06:55 PM   #1
Registered User
 
Join Date: Jun 2009
Posts: 5
Question CreateWindowEx() failing with 64-bit

Hi guys,

I'm new to this forum and fairly new to Windows programming as well. Anyway, I inherited some code from a previous engineer that works fine in 32-bit, but fails in 64-bit. In 64-bit, CreateWindowEx() fails, and GetLastError() returns code 1413, which is "invalid index". I haven't been able to find anything online mentioning any problem with CreateWindowEx() in 64-bit environments.

Any help is appreciated:

Code:
//call this function to creat the actual window.
bool CPrintWindow::Create(char*     szWindowName, 
                          DWORD     dwStyle, 
                          const     RECT& rect,   
                          HWND      hParentWnd, 
                          HINSTANCE hInst,
                          char*     szClassName, 
                          bool      registerClass)
{
  //TraceFunc("CPrintWindow::Create()");  

  if(registerClass) //local register requested
  {
    if(!szClassName) szClassName = "DefaultCPrintWindowName"; //if no name specified
    m_wndClass.lpszClassName     = szClassName;
    m_wndClass.hInstance         = hInst;
    
    if(!GetClassInfo(hInst, szClassName, &m_wndClass))
    {
      //not yet registered, must register
      m_classAtom = RegisterClass(&m_wndClass);
    }
  }
  else if(!szClassName) 
    return false; //error, must have a WNDCLASS

  m_hInstance = hInst;

  //set the static variable to point to this instance so that
  //the message loop can find it when it starts up
  m_lastCPrintWindow = this;

  m_hWndMain = CreateWindowEx(m_exStyle,
                              szClassName,	
                              szWindowName,	
                              dwStyle,
                              rect.left,
                              rect.top,
                              rect.right  - rect.left,
                              rect.bottom - rect.top,
                              hParentWnd,
                              NULL,
                              m_hInstance,
                              NULL);
  
  if(m_hWndMain) 
    return true; //success

  //Failed! - Give a detailed error message to show what went wrong
  char szMessage[256];
  DWORD result = GetLastError();
  FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, result, 0, szMessage, 256, 0);
  MessageBox(NULL, szMessage, "Error", MB_OK);

  return false;
}
I'm not sure if it matters, but there is a thread created off the main thread, which then calls the Create() function above. I can post the code for that if you think it might be a problem.

Thanks,
Kenneth
domokato is offline   Reply With Quote
Old 06-30-2009, 08:06 PM   #2
Hat seller extraordinaire
 
Join Date: Apr 2008
Posts: 159
Do you have any calls to GetWindowLongPtr/GetClassLongPtr or their Set equivalents in the relevant WndProc for WM_NCCREATE or WM_CREATE? That'd be my bet. You should also check that RegisterClass is succeeding, though that would probably give a different error.

The use of FormatMessage seems a bit dubious too, FORMAT_MESSAGE_IGNORE_INSERTS should also be passed so that it doesn't try and do parameter substitution in messages that require it. FormatMessage will fail if you pass NULL/0 for the last parameter and the string contains inserts, causing your MessageBox to potentally display garbage.
adeyblue is offline   Reply With Quote
Old 07-01-2009, 11:24 AM   #3
Registered User
 
Join Date: Jun 2009
Posts: 5
Here's the wndproc:

Code:
		static __declspec(dllexport) 
		LRESULT CALLBACK WndProcedure(HWND   hWnd,   UINT wMessage, 
									  WPARAM wParam, LPARAM lParam)
		{
			//retrieve the pointer to the class stored in the HWND
#ifdef _WIN64
			CPrintWindow* pWnd = (CPrintWindow*)GetWindowLongPtr(hWnd, 0);
#else
			CPrintWindow* pWnd = (CPrintWindow*)GetWindowLong(hWnd, 0);
#endif	    
		    if (pWnd == NULL)  //this must be the first time here 
			{
				//store the class instance
#ifdef _WIN64
				SetWindowLongPtr(hWnd, 0, (ULONG_PTR)m_lastCPrintWindow);
				//Set pWnd to point to the class instance
				pWnd = (CPrintWindow*)GetWindowLongPtr(hWnd, 0);   
#else
				SetWindowLong(hWnd, 0, (LONG)m_lastCPrintWindow); 
				//Set pWnd to point to the class instance
				pWnd = (CPrintWindow*)GetWindowLong(hWnd, 0);   
#endif

			}
			return pWnd->OnMainMessage(hWnd, wMessage, wParam, lParam);
		}
Here's OnMainMessage():

Code:
//this is the main message loop.
//handles most used messages here
LRESULT CPrintWindow::OnMainMessage(HWND hWnd, UINT wMessage, 
                                    WPARAM wParam, LPARAM lParam)
{
  //TraceFunc("CPrintWindow::OnMainMessage()");  

  LRESULT result = 0;
  m_hWndMain     = hWnd;
  
  if (wMessage == WM_DESTROY)
  {
    result = 0;
    SendMessage(m_hWndMain, WM_QUIT, 0, 0);
  }
  
  //first see if this message is handled by any other handler
  if (OnMessage(hWnd, wMessage, wParam, lParam, &result)) 
    return result;
  
  //see if the message is one of the basic handled ones, 
  //and call the correct handler if it is
  switch (wMessage)
  {
  case WM_PAINT:
    {
      PAINTSTRUCT psPaint;
      HDC hDC = BeginPaint(hWnd, &psPaint);
      OnPaint(hDC, &psPaint);
      EndPaint(hWnd, &psPaint);
    }
    break;

  case WM_ERASEBKGND:
    {
      HDC hDC = (HDC) wParam;
      if (OnEraseBkGnd(hDC)) 
        return true; //handled, so return
      else 
        return DefWindowProc(hWnd, wMessage, wParam, lParam);
    }
    //break;

  case WM_COMMAND:
    if(!OnCommand(wParam, lParam))
      return DefWindowProc(hWnd, wMessage, wParam, lParam); //return if handled
    break;
  
  default:
    //seems like this message was not processed by any handler, so
    //let's send it to the default handler
    return DefWindowProc(hWnd, wMessage, wParam, lParam);
    //break;
  }
  return 0;
}
I wasn't able to find "WM_NCCREATE" or "WM_CREATE" anywhere in the code...
domokato is offline   Reply With Quote
Old 07-01-2009, 12:23 PM   #4
Registered User
 
Join Date: Jun 2009
Posts: 5
Okay, I just traced through WndProcedure() and found that this line,

Code:
CPrintWindow* pWnd = (CPrintWindow*)GetWindowLongPtr(hWnd, 0);
and this line,

Code:
pWnd = (CPrintWindow*)GetWindowLongPtr(hWnd, 0);
return null. hWnd seems to be correct, though:

Intellisense:
Code:
hWnd = 0x00000000012e0114 {unused=??? }
domokato is offline   Reply With Quote
Old 07-01-2009, 05:19 PM   #5
Hat seller extraordinaire
 
Join Date: Apr 2008
Posts: 159
What is m_wndClass.cbWndExtra set to? It should be sizeof(CPrintWindow*) or at least greater than or equal to 4 or 8 if it's in an #ifdef _WIN64 block.
adeyblue is offline   Reply With Quote
Old 07-02-2009, 01:29 PM   #6
Registered User
 
Join Date: Jun 2009
Posts: 5
Yes, thank you. It used to be 4, actually, but I changed it to sizeof(CPrintWindow *) and now the window displays.

However, the contents of the window doesn't show up. It is painted using bitblt(). You can see the handling for WM_PAINT in OnMainMessage() above. BeginPaint() results in:

Intellisense:
Code:
hDC = 0xfffffffff9010287 {unused=??? }
Intellisense:
Code:
psPaint = {hdc=0xfffffffff9010287 fErase=0 rcPaint={...} ...}
Both point to the same address and look wrong...This causes OnPaint(), which is overridden in my code, to fail:

Code:
void CPrintWindow::OnPaint(HDC hDC, PAINTSTRUCT* pPS)
{
  //TraceFunc("CPrintWindow::OnPaint()");  

  RECT rectBmUpdate;
  IntersectRect(&rectBmUpdate, &m_rectBitmap, &pPS->rcPaint);

  if(!IsRectEmpty(&rectBmUpdate))
  {
    BitBlt(hDC, 
           rectBmUpdate.left, 
           rectBmUpdate.top, 
           rectBmUpdate.right  - rectBmUpdate.left,
           rectBmUpdate.bottom - rectBmUpdate.top, 
           m_hMemDC, 
           rectBmUpdate.left - PAGE_BORDER, 
           rectBmUpdate.top  - PAGE_BORDER, 
           SRCCOPY);
  }
}
IsRectEmpty(&rectBmUpdate) is true, so the bitblt is skipped.

Thanks,
Kenneth
domokato is offline   Reply With Quote
Old 07-02-2009, 04:14 PM   #7
Registered User
 
Join Date: Jun 2009
Posts: 5
Hi, I found this thread:

how splwow64 works - Windows Device Drivers

which says that a printer driver plugin running in the context of splwow64 (which mine is) should not call CreateDC() because it will fail. My code calls CreateCompatibleDC(), and this does indeed return null. This is probably related to the problem described in my previous post.

Perhaps I have to use an alternative to HDCs? Is there an alternative?

Thanks,
Kenneth
domokato is offline   Reply With Quote
Old 07-02-2009, 07:30 PM   #8
Hat seller extraordinaire
 
Join Date: Apr 2008
Posts: 159
There isn't any alternative as far as GDI is concerned, though what you can do about it I've no idea. I tend to stay away from all things printer related. Posting what GetLastError() returns after CreateCompatibleDC fails might help any other potential helpers provide a course of action.
adeyblue is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
A few questions about 64 bit and Windows... yaya Tech Board 9 08-28-2008 08:49 AM
[Tutorial] Implementing the Advanced Encryption Standard KONI C Programming 16 11-23-2007 01:48 PM
File IO Jack1982 C++ Programming 9 10-15-2007 01:14 AM
bit patterns of negtive numbers? chunlee C Programming 4 11-08-2004 08:20 AM
Array of boolean DMaxJ C++ Programming 11 10-25-2001 11:45 PM


All times are GMT -6. The time now is 03:31 PM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.0 RC2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22