1

I have a vb6 service which uses Synchronous WinHttp calls to a remote server. These calls lockup the service during times when there appears to be connection issues (network/Internet etc).

My task is to implement WinHttp Asynchronous calls.

First step, I'm trying to figure out the conversions from C++ to vb6. Bearing in mind I've never written a line of C++ before.

http://msdn.microsoft.com/en-us/library/windows/desktop/aa383917(v=vs.85).aspx

typedef void ( CALLBACK *WINHTTP_STATUS_CALLBACK)(
_In_  HINTERNET hInternet,
_In_  DWORD_PTR dwContext,
_In_  DWORD dwInternetStatus,
_In_  LPVOID lpvStatusInformation,
_In_  DWORD dwStatusInformationLength
);

This is my attempt:

Public Declare Function WINHTTP_STATUS_CALLBACK Lib "winhttp.dll"
(ByVal hSession As Long, dwContext As Long, dwInternetStatus As Integer,
lpvStatusInformation As Long, dwStatusInformationLength As Integer)

I have no idea if that's correct and unfortunately I can't test it until I get a bit further.

The next one is WinHttpSetStatusCallback

http://msdn.microsoft.com/en-us/library/windows/desktop/aa384115(v=vs.85).aspx

WINHTTP_STATUS_CALLBACK WINAPI WinHttpSetStatusCallback(
_In_        HINTERNET hInternet,
_In_        WINHTTP_STATUS_CALLBACK lpfnInternetCallback,
_In_        DWORD dwNotificationFlags,
_Reserved_  DWORD_PTR dwReserved
);

This is my attempt:

Public Declare Function WinHttpSetStatusCallback Lib "winhttp.dll"
(ByVal hInternet As Long, ByVal lpfnInternetCallback As Long,
ByVal dwNotificationFlags As Long, ByVal dwReserved As Long) As Long

I don't really know if my conversions are correct. Can anyone verify this?

Next, I don't know how to implement WinHttpSetStatusCallback - for example I don't know if I have the pointer to the Callback function correct.

_In_        WINHTTP_STATUS_CALLBACK lpfnInternetCallback,

converted to:

ByVal lpfnInternetCallback As Long

I'm not sure if I have that correct either.

I don't have a clear idea on how to define the Async Callback function itself. Here is my initial attempt:

Public Function AsyncCallback(
                        ByVal hInternet As Long,
                        dwContext As Long,
                        dwInternetStatus As Long,
                        lpvStatusInformation As Long,
                        dwStatusInformationLength As Long)
    //code in here
End Function

Then finally, wiring it all up is going to be interesting. But first I have to make sure I have the foundations right, otherwise I can't expect it to magically "work".

The MSDN C++ example is as follows: http://msdn.microsoft.com/en-us/library/windows/desktop/aa384115(v=vs.85).aspx

// Install the status callback function.
WINHTTP_STATUS_CALLBACK isCallback = WinHttpSetStatusCallback( hSession,
                                           (WINHTTP_STATUS_CALLBACK)AsyncCallback,
                                           WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS, 
                                           NULL);

How do I define a pointer to the AsyncCallback function in vb6?

Ben
  • 1,000
  • 2
  • 15
  • 36
  • The `WinHttp.WinHttpRequest` class is a fairly thin wrapper around lower-level WinHttp calls and provides events instead of callbacks. Is there a reason why you don't just use it instead? – Bob77 Aug 12 '13 at 06:04
  • Are these GET requests? If so why not just perform asynchronous HTTP GET the easy way? See [my answer here](http://stackoverflow.com/questions/1976152/download-file-vb6/1979417#1979417) – MarkJ Aug 12 '13 at 12:11
  • @MarkJ thanks for the suggestion, looks interesting. Are you aware of how I can implement a UserControl without a Form? i.e. unattended service? – Ben Aug 12 '13 at 22:39
  • @Bob77 I did look at the possibility of WinHttp.WinHttpRequest, however it doesn't provide as much flexibility as WinHttp directly. The service is already 'built' with a lot of WinHttp functionality, porting it to WinHttp.WinHttpRequest would require a lot of retrofitting and possibly reduction in some options. Also, my task is only to implement Asynchronous, not completely re-write what's already developed. – Ben Aug 12 '13 at 22:42
  • Even if you set the callback successfully (use the AddressOf operator) you're doomed. The callback thread doesn't have COM initialized, it won't be running in your UI thread's apartment, and your function must be threadsafe. There are only a very few simple VB6 statements you will be able to execute successfully inside it. – Bob77 Aug 13 '13 at 09:59
  • Hey @Bob77 the service doesn't have a UI. The only code I need inside the callback function is a select statement checking against the notification, set a global boolean and a check to see if the service has received a stop notification. If a stop notification has been received, the service has to respond - which is the problem faced currently when operations are locked using synchronous processing. – Ben Aug 13 '13 at 22:06
  • All of the code you can write in VB6 runs on the UI thread, whether you think you have a UI or not. It isn't about having a Form, all VB6 programs have a hidden top-level window and message loop. Just about all you can do in this sort of callback are a few conditional statements that set variables in a static module, then exit. The rest of your code runs on the UI thread and it will have to poll for results (changes in static data). – Bob77 Aug 14 '13 at 04:22
  • Ok, understand. I wanted to ensure you knew I wasn't trying to set a status bar or something like that. Nonetheless, I only want to run a few conditional statements and set a global boolean - that's it really. So, it sounds like Async will do what I want. So, question now is, can you answer the question? – Ben Aug 15 '13 at 04:10
  • Are you able to answer the question @Bob77 – Ben Aug 17 '13 at 00:25
  • I already did. Use the AddressOf operator http://msdn.microsoft.com/en-us/library/aa242738(v=VS.60).aspx – Bob77 Aug 17 '13 at 08:58
  • Global vars in VB6 are actually thread-local, so you can't set a flag from callback thread and poll on it from UI thread. Use API events or similar objects. – wqw Aug 19 '13 at 14:46

0 Answers0