Search code examples
c++winapitype-conversion64-bit

How to convert from long long to DRAWITEMSTRUCT*


I have this function:

GwBoolean win95_draw_button(DRAWITEMSTRUCT *pDrawParam, GwCore *pCore)
{
    ...
    assert(pDrawParam);
    HDC hDC = pDrawParam->hDC;
    ...
}

And I get this Exception:

Exception thrown: read access violation. pDrawParam was 0x2B4FE760. The exception is pointing at HDC hDC = pDrawParam->hDC;

HDC is defined like this:

HANDLE HDC 
value: void* 

and this hDC on the right site like this:

HDC hDC in struct tagDRAWITEMSTRUCT The function win95_draw_button is called here:

GwBoolean GwPushButton::EventHandler(GwEvent *ev)
{
     long long lParam;
     GwWord wParam;
     GwWindowParams(&wParam, &lParam);
     ...

     // Painting in Win95 Style
    win95_draw_button ((DRAWITEMSTRUCT*)(long long)(lParam),this);
}

GwWindowParams is defined like this (if it helps):

PREEXPORT void              POSTEXPORT GwWindowParams(GwWord* nwParam, long long* nlParam); 

And the declaration looks like this:

 void GwWindowParams(GwWord *nwParam, long long *nlParam)
{
    GwFUNCTION_TRACE(GwWindowParams(GwWord *,long long*), 0)

    *nwParam = paramw;
    *nlParam = paraml;
}

paraml is defined like this: static long paraml = 0L;

I strongly assume that the problem here is lParam. lParam is of type long. I already tried and changed it to long long but I still got the exception. I guess this is also not the correct way (DRAWITEMSTRUCT*)(long long)(lParam) to convert to DRAWITEMSTRUCT*.


Solution

  • I suspect that your problem is the definition of paraml.

    You are trying to store a 64-bit pointer in a 32-bit long which truncates the pointer, invalidating it.

    Change static long paraml = 0L; to static long long paraml = 0LL or better static std::uintptr_t paraml = 0;.

    std::uintptr_t is designed to be an integer type large enough to contain an address.

    Casting paraml to long long is not sufficient as the information is already lost at that point.