Thread: ESP not saved accross function call?

  1. #1
    Banned nickname_changed's Avatar
    Join Date
    Feb 2003
    Location
    Australia
    Posts
    986

    Unhappy ESP not saved accross function call?

    Hi,

    I doubt anyone here will be able to solve this, but I'm open to any suggestions. I have a function that looks like so:

    Code:
    int main()
    {
    	// Create an Extension Control Block
    	EXTENSION_CONTROL_BLOCK ECB;
    	ECB.cbSize = sizeof(ECB);
    	ECB.ConnID = (HCONN) 10;
    	ECB.dwHttpStatusCode = 200;
    	ECB.lpbData = (unsigned char *)&ECB.cbAvailable;
    	ECB.lpszMethod = "GET";
    	ECB.lpszPathInfo = "/index.php";
    	ECB.lpszPathTranslated = "C:\\SWS\\Webroot\\test.php";
    	ECB.lpszQueryString = "user=john";
    	ECB.lpszContentType = "text/html";
    
    	HSE_VERSION_INFO hse;
    
    	// Load the DLL
    	gMyDLL = LoadLibrary("C:\\PHP\\sapi\\php4isapi.dll");
    	if (gMyDLL == NULL)
    	{
    		cout << "ERROR LOADING DLL\n\n";
    		return 0;
    	}
    
    	pHttpExtensionProc  = (HTTPEXTENSIONPROC) GetProcAddress(gMyDLL, "HttpExtensionProc");
    
    	ECB.ReadClient = &pReadClient;
    	ECB.WriteClient = &pWriteClient;
    	ECB.ServerSupportFunction = &pServerSupportFunction;
    	ECB.GetServerVariable = &pGetServerVariable;
    
    	pHttpExtensionProc(&ECB);
    	
    	return 0;	
    }
    HttpExtensionProc is a function in a DLL that is loaded in (no problems there). Now, pReadClient, pWriteClient etc etc are all functions I've made myself that I've put into the ECB structure.

    Then I call the HttpExtensionProc function. It runs fine, and gives me all the output I expected. But then I get this error:

    (Note: Its in a message box titled Microsoft Visual C++ Debug Library)
    Code:
    The Value of ESP was not properly saved accross a function call. This is usually the result of a function declared with one calling convention with a function pointer declared with another convention
    Now, to me this suggests perhaps I didn't send enough arguments to HttpExtensionProc. So, I head over to MSDN and it has this:
    DWORD WINAPI HttpExtensionProc(
    LPEXTENSION_CONTROL_BLOCK lpECB
    );
    So obviously I'm sending enough arguments. So then I say to myself... what if the pReadClient, pWriteClients have the wrong number of arguments? Nope. That can't be because I got them straigh from the header file from microsoft, and I know they're right.

    So I wonder, maybe I declared HttpExtensionProc wrongly when I created the function pointer. This is what I have:
    typedef DWORD (*HTTPEXTENSIONPROC)( EXTENSION_CONTROL_BLOCK *pECB );
    Which, minus the WINAPI return thing, is exactly what it wants. So I don't think thats the problem either (it was to do with a function argument, not a return type).

    So basically I'm stumped. Does anyone have any idea what the cause of the problem could be? Its not in the DLL I'm sure, because its the PHP ISAPI Dll, and it runs on apache/IIS just fine, so I know its me whos done something wrong. Any ideas?

    PS: If your interested, I'm trying to write a web server that uses ISAPI with PHP. Thats what this code is, its almost impossible to find anything about writing the server side of things, so I've had to make most of it up. So far though everythings going great, I call the DLL, hand it a file to interpret, any query strings etc etc and it gives me the correct output. It just stuffs up at that point.

  2. #2
    &TH of undefined behavior Fordy's Avatar
    Join Date
    Aug 2001
    Posts
    5,793
    This is windows code...so why isnt it on the windows board?

    Anyway....your typedef is wrong....it should be

    typedef DWORD (WINAPI *HTTPEXTENSIONPROC)( EXTENSION_CONTROL_BLOCK *pECB )

    Without the WINAPI qualifier, most compiler will defaulkt to the C calling convention.....but add it to the declararion and the compiler will treat a call with the STDCALL convention......

    Using the wrong convection screws your stack...and there lies your error

  3. #3
    Banned nickname_changed's Avatar
    Join Date
    Feb 2003
    Location
    Australia
    Posts
    986
    OMG Fordy thankyou so much! I had tried
    typedef DWORD WINAPI (*HTTPEXTENSIONPROC)( EXTENSION_CONTROL_BLOCK *pECB );

    But that gave me a compiler error, I never knew to call it the way you did. I can't thank you enough for this! It seems I'm lacking in a lot of understanding of concepts that seems pretty normal to most people. The C++ book I read was old, and never used namespaces or anything like that. I think I'll get a newer more advanced one to cover what I don't seem to fully understand, such as function pointers, and pointers in general (Never gotten the hang of those). Once again, thankyou very much!

  4. #4
    ¡Amo fútbol!
    Join Date
    Dec 2001
    Posts
    2,138
    Fordy, how are the calling conventions different?

  5. #5
    pronounced 'fib' FillYourBrain's Avatar
    Join Date
    Aug 2002
    Posts
    2,297
    _stdcall/PASCAL/WINAPI are all the same. They mean right to left calling convention. So that's the order they are pushed on the call stack. without it, your variables are in the wrong place.
    "You are stupid! You are stupid! Oh, and don't forget, you are STUPID!" - Dexter

  6. #6
    &TH of undefined behavior Fordy's Avatar
    Join Date
    Aug 2001
    Posts
    5,793
    STDCALL and PASCAL werent always the same( if indeed they are now) the difference is how they pass (params passed to the function right to left/left to right...cant remember which is which).......I think PASCAL was used in Win3.11....so the name is scattered around various headers even now.....it may be that PASCAL typedefs to STDCALL/WINAPI in recend SDKs

    If you create a function in a C/C++ compiler without any explicit calling convention, then the C calling convention applies......the difference between this convention and the others is that the calling function is responsible for clearing the stack...with the others, it the called function's responsibility...

    SO for instance if I call a STDCALL function, but the compiler thinks it's a normal C type function, then the called function will clear the stack before return, then the calling function will try to clear the stack again....this will probably corrupt the stack.......and debug versions of VC++ check for this and assert when it happens

  7. #7
    pronounced 'fib' FillYourBrain's Avatar
    Join Date
    Aug 2002
    Posts
    2,297
    here's a small section of the windef.h file that should shed some light

    #ifdef _MAC
    #define CALLBACK PASCAL
    #define WINAPI CDECL
    #define WINAPIV CDECL
    #define APIENTRY WINAPI
    #define APIPRIVATE CDECL
    #ifdef _68K_
    #define PASCAL __pascal
    #else
    #define PASCAL
    #endif
    #elif (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED)
    #define CALLBACK __stdcall
    #define WINAPI __stdcall
    #define WINAPIV __cdecl
    #define APIENTRY WINAPI
    #define APIPRIVATE __stdcall
    #define PASCAL __stdcall

    #else
    #define CALLBACK
    #define WINAPI
    #define WINAPIV
    #define APIENTRY WINAPI
    #define APIPRIVATE
    #define PASCAL pascal
    #endif

    from what I can tell, the red section is what is used in VC++ 6.0 windows projects
    "You are stupid! You are stupid! Oh, and don't forget, you are STUPID!" - Dexter

  8. #8
    Just because ygfperson's Avatar
    Join Date
    Jan 2002
    Posts
    2,490
    Does the WINAPI calling convention mangle the names like the C++ calling convention does? (regarding type information about parameters)

    Why do the calling conventions differ? Is there a speed boost using one of them?

  9. #9
    pronounced 'fib' FillYourBrain's Avatar
    Join Date
    Aug 2002
    Posts
    2,297
    the __stdcall mangling is different than C/C++ mangling. __stdcall mangling (I think) is just an underscore added to the name. The only way that I'm aware of that you can get rid of the "_" character is to use a .def file.

    Speed difference? no. Its just that when the Windows API was created, the pascal language was considered a more reasonable tool for Windows development than it is now. Or at least that you would catch a wider range of platforms by doing it (C could switch its calling convention). Anyway, I don't know the true reasoning behind it. Either one of those works for me
    "You are stupid! You are stupid! Oh, and don't forget, you are STUPID!" - Dexter

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Undefined Reference Compiling Error
    By AlakaAlaki in forum C++ Programming
    Replies: 1
    Last Post: 06-27-2008, 11:45 AM
  2. Troubleshooting Input Function
    By SiliconHobo in forum C Programming
    Replies: 14
    Last Post: 12-05-2007, 07:18 AM
  3. temperature sensors
    By danko in forum C Programming
    Replies: 22
    Last Post: 07-10-2007, 07:26 PM
  4. Including lib in a lib
    By bibiteinfo in forum C++ Programming
    Replies: 0
    Last Post: 02-07-2006, 02:28 PM
  5. Unknown C ESP function call error message
    By wbeasl in forum C Programming
    Replies: 1
    Last Post: 10-08-2003, 01:33 PM