win32 dll that should: glGetString(GL_VENDOR)

I have a problem creating a dll that should return GL_VENDOR and GL_RENDERER as a const char. I suspect that I do not release ressources correctly but I’m unable to spot the error - could you help ?

mainTest:

#include <windows.h>
#include <stdio.h>

void getInfo();
typedef const char* (* InfoFunc)();

int main(int argc, char **argv)
{
getInfo();
getInfo();

return 0;
}

void getInfo()
{
HINSTANCE dll;
InfoFunc infoFunc;

dll=LoadLibrary(“Info.dll”);
if(dll != NULL)
{
printf("success LoadLibrary
");
infoFunc = (InfoFunc)GetProcAddress(dll, “getInfo”);
if(infoFunc != NULL)
{
printf(“success GetProcAddress
“);
printf(” OUTPUT:
%s”, infoFunc());
if(FreeLibrary(dll))
{
printf("success FreeLibrary
");
}
else
{
printf("error FreeLibrary
");
}
}
else
{
printf("error GetProcAddress
");
}
}
else
{
printf("error LoadLibrary
");
}
}

dllInfo:

#include <windows.h>
#include <GL/GL.h>
#include <string.h>
#include <stdio.h>

extern “C” const char* getInfo();

int WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
return false;
}

__declspec ( dllexport) const char* getInfo()
{
GLuint PixelFormat;
HWND hWnd = NULL;
HDC hDC = NULL;
HGLRC hRC = NULL;
char info[1024] = “”;

if(hDC=GetDC(hWnd)){
static PIXELFORMATDESCRIPTOR pfd= { sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, PFD_TYPE_RGBA, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, PFD_MAIN_PLANE, 0, 0, 0, 0};
if(PixelFormat=ChoosePixelFormat(hDC, &pfd)){
if(SetPixelFormat(hDC, PixelFormat, &pfd)){
if(hRC=wglCreateContext(hDC)){
if(wglMakeCurrent(hDC, hRC)){
strcpy(info, "
VENDOR[");
strcat(info, (char *)glGetString(GL_VENDOR));
strcat(info, “]
RENDERER[”);
strcat(info, (char *)glGetString(GL_RENDERER));
strcat(info, "]
");
if(hRC){
if(wglMakeCurrent(NULL, NULL)){
if(wglDeleteContext(hRC)){
hRC=NULL;
if(hDC && !ReleaseDC(hWnd, hDC)){
printf("error ReleaseDC
");
hDC=NULL;
}
} else { printf("error wglDeleteContext
");}
} else { printf("error wglMakeCurrent(NULL, NULL)
");}
} else { printf("error hRC
");}
} else { printf("error wglMakeCurrent
");}
} else { printf("error wglCreateContext
");}
} else { printf("error SetPixelFormat
");}
} else { printf("error ChoosePixelFormat
");}
} else { printf("error GetDC
");}

return info;
}

output is:
success LoadLibrary
success GetProcAddress
OUTPUT:

VENDOR[NVIDIA Corporation]
RENDERER[GeForce2 MX/PCI/3DNOW!]
success FreeLibrary
success LoadLibrary
success GetProcAddress
error SetPixelFormat
OUTPUT:
success FreeLibrary

mvh
Søren Olesen

You can’t call SetPixel for the screen DC (GetDC(NULL)).

“return info;”

You return a pointer to a local variable. Your compiler should give you a warning for this.

Thank you for your reply.

>>You can’t call SetPixel for the screen DC GetDC(NULL)).

But what should I do then ?

>>You return a pointer to a local variable. Your compiler should give you a warning for this.

info is returned as a const char which the compiler doesn’t warn about.

What about creating an invisible window to get the infos ?

And Humus is right, you’re returning an invalid pointer. If you really want to do that, make your info string static.

Y.

It doesn’t matter if your compiler complains or not. info, like all local variables in C/C++, is created on the stack. When you return it, you are returning a pointer, not the string itself. When the function returns, the data pointed to by info can be overwritten. Declaring info as static should fix this problem.

>>What about creating an invisible window to get the infos ?

well, I just thought that if I could get the info once it would be possible to get it twice (using my method) :slight_smile:

perhaps the problem is that pdf is static - i’ll try playing with it when i get home.

what I don’t understand is that it gets the info the 1. time is’t run - but the 2. try fails. Why is that ?

Will the solution be to create a window (not showing it), get info, and destroy the window?

Yes, as Aaron said, info should be a static. If it’s not made static, then the code is flat out wrong, as the stack (which your current info is allocated on) will be blown to hell after the return… once in a while you may get lucky and it might work.

The compiler doesn’t complain because of the const char* declaration. Take out the const and it will complain. const != static.

the easiest way to get a valid, current dc is to call GetDesktopWindow(), then GetDC() on that - but remember to release the dc… i’m not at my home pc so i might’ve got the function name wrong or misspelt, search the msdn for it if i did

[This message has been edited by mattc (edited 09-26-2002).]

ok, the SetPixelFormat(…) returns
1410 - Class already exists.

is there a way to delete this class ?

Read the docs on SetPixelFormat, it clearly says that it can only be called once for any given window. You must create a new window in order to call SetPixelFormat again.

… and don’t use the desktop window or any other window you don’t own.

ok,
the battleplans is as follows:
1> register uniqe class (question: would this be legal, WNDPROC.lpfnWndProc = NULL ?)
2> createwindow using uniqe class
3> setup pixel format, wgl*
4> get info
5> destroy window
6> unregister uniqe class
goto 1

would this work ?

[This message has been edited by soreno (edited 09-26-2002).]

oops, i didn’t realise that soreno was calling SetPixelFormat() on the dc, humus, my bad i thought he just wanted to query current pfd etc, which is a valid use for GetDesktopWindow().

soreno, window proc can’t be null (though win32 might actually not be that stupid to try and call that), but you can set it to DefWindowProc (a good trick, this) which would work for this purpose…

i wonder though, why do this twice? pfd info, like video mode stuff, sits cached in the registry and only changes when driver’s video mode changes, so obtaining info twice won’t show any changes. similarly, opengl server info (vendor etc) can only change if you’re running 2+ video cards on separate monitors… or am i missing something? why stick it in a dll in the first place? seems like a lot of work for three glGetString() calls

[This message has been edited by mattc (edited 09-27-2002).]

Yes, it might seem stupid to put such effort in getting it run twice. However getting the vendor/card is only 1/20 of the stuff the dll does. The dll functions needs to get called (including vendor/card) about every 30 minutes. Plus it’s challenge getting it working… :slight_smile: