We have a delphi XE application that uses SOAP (THTTPRIO etc) communications which (in delphi) works over WinInet.dll, by default. We fixed the authentication code so that it works, using https authentication, and when the user name and password for https are correct, everything is fine.
The problem is that when authentication details are incorrect, you get a message box from Windows, that is probably being popped up by WinInet.dll itself. I want to make that dialog box go away. I can't figure out how to change my Delphi SOAP so the password won't come up.
The situation is different than this question in the following ways:
I am doing all the things that he is doing, including calling InternetSetOption(...) to set the user name and password.
I am not using a server with a self-signed certificate, so the soIgnoreInvalidCerts flag is not applicable to my case.
Somehow, I think I need to get some API calls into WinInet to tell it not to pop up the InternetErrorDlg
that it has (some versions of windows say Windows Security Options) that pops up to ask the user.
In my case the user name and password we have in our configuration file is being used, it is wrong (out of date) and so we want the WinInet code to simply return an error instead of popping up the dialog box.
Perhaps the other question the guy really did figure out how to do this, but the detail on that question is insufficient to see how he did it. The accepted answer does not work for me.
Some dead ends I've followed:
WinInet MSDN docs for PLUGIN_AUTH_FLAGS_CAN_HANDLE_UI
- that doesn't appear to be applicable to a WinInet user, rather to a plugin.
WinInet MSDN docs discuss InternetSetOption, and some newsgroups have lead me to the following on-before-post event handler code:
procedure TMyDevice.HTTPWebNodeOnBeforePost(
const HTTPReqResp: SOAPHTTPTrans.THTTPReqResp; Data: Pointer);
var
SecurityFlagsLen:DWORD;
SecurityFlags:DWORD;
begin
{ authentication, NTLM+HTTPS, WinInet authentication set via WinInet SET INTERNET OPTION API.
This approach recommended on newsgroups for https basic authentication. }
if fUserName<>'' then
if not InternetSetOption(Data,
INTERNET_OPTION_USERNAME,
PChar(fUserName),
Length(fUserName)) then
raise EWebServiceAuthException.Create(SysErrorMessage(Windows.GetLastError));
if fPassword<>'' then
if not InternetSetOption(Data,
INTERNET_OPTION_PASSWORD,
PChar(fPassword),
Length (fPassword)) then
raise EWebServiceAuthException.Create(SysErrorMessage(Windows.GetLastError));
{ possible type of hackage: WinInet Security option flags to stop password box? }
SecurityFlagsLen := SizeOf(SecurityFlags);
InternetQueryOption({Request}data, INTERNET_OPTION_SECURITY_FLAGS,
Pointer(@SecurityFlags), SecurityFlagsLen);
SecurityFlags := SecurityFlags or SECURITY_FLAG_something;
InternetSetOption({Request}data, INTERNET_OPTION_SECURITY_FLAGS,
Pointer(@SecurityFlags), SecurityFlagsLen);
end;
This code makes the password work, but when the user's entered password is wrong, how do I get the SOAP call to fail, or raise an exception, instead of popping up a message box?
Replace WinINet by WinHTTP component. Both have very close APIs, and the 2nd does not create any UI interaction, but will return error codes, just like any other API. The UI part of WinINet may be a good idea for some software, but it sounds like if does not fit your needs.
See http://msdn.microsoft.com/en-us/library/windows/desktop/aa384068(v=vs.85).aspx
Of course, HTTPS and authentication will be handled in a similar manner. But you'll have to prompt for the user name and password, and update the HTTP headers as requested. See this link.
From our tests, WinHTTP is much faster than WinINet (certainly because it does not implement any UI part, and is not linked to Internet Explorer libraries).
You can take a look at our Open Source classes to guess how small is the difference in the API between WinINet and WinHTTP (most code is shared in the linked unit).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With