我需要使用Delphi中的API函数模仿与“Internet选项”对话框(“内容”选项卡)中的“清除SSL状态”按钮相同的行为。
我的目的是与WinInet一起使用它来建立后续的独立SSL连接。如果没有这个,两个WinInet连接共享相同的SSL状态,例如,阻止我纠正错误的SSL证书密码。
如果没有在两次连接尝试之间清除SSL状态,第一次返回“密码错误”,然后我更正密码并再次尝试,但第二次尝试返回“安全通道支持错误”。
“清除SSL状态”按钮只执行以下未记录的命令行命令:
"C:\Windows\system32\rundll32.exe" "C:\Windows\system32\WININET.dll",DispatchAPICall 3
使用CreateProcess()
在Delphi代码中执行相同的命令。
你是对的:如果rundll可以做到,你可以通过编程方式完成:
//somewhere in an interface section:
procedure DispatchAPICall(h: HWND; hinst: HINST; lpszCmdLine: PAnsiChar; nCmdShow: integer); stdcall;
//somewhere in the implementation section:
function DispatchAPICall; external 'wininet.dll';
//somewhere in your code:
DispatchAPICall(GetDesktopWindow(), GetModuleHandle('wininet.dll'), '3', SW_NORMAL);
最后!我成就了!
我使用了优秀的API Monitor来监控整个“Internet选项”对话框,并设法发现“清除SSL状态”按钮的作用。它按此顺序仅执行两个API调用SslEmptyCache和IncrementUrlCacheHeaderData。
发现这个后,我能够实现以下代码,在我的请求之前执行:
type
TSslEmptyCache = function (pszTargetName: LPSTR; dwFlags: DWORD): BOOL; WINAPI;
TIncrementUrlCacheHeaderData = function (nIdx: DWORD; lpdwData: LPDWORD): BOOL; WINAPI;
var
SchannelDLLHandle, WinInetHandle: HMODULE;
SslEmptyCache: TSslEmptyCache;
IncrementUrlCacheHeaderData: TIncrementUrlCacheHeaderData;
SchannelDLLHandle := LoadLibrary('schannel.dll');
WinInetHandle := LoadLibrary('wininet.dll');
if (SchannelDLLHandle > 0) and (WinInetHandle > 0) then
try
SslEmptyCache := GetProcAddress(SchannelDLLHandle,'SslEmptyCacheW');
IncrementUrlCacheHeaderData := GetProcAddress(WinInetHandle,'IncrementUrlCacheHeaderData');
if Assigned(SslEmptyCache) and Assigned(IncrementUrlCacheHeaderData) then
begin
SslEmptyCache(nil,0);
IncrementUrlCacheHeaderData(14,@buffer);
end;
finally
FreeLibrary(SchannelDLLHandle);
FreeLibrary(WinInetHandle);
end;
当然,这是一个伪代码,但它是完整的;)
SslEmptyCache函数在MSDN上有文档,但是IncrementUrlCacheHeaderData函数没有,所以我不得不再研究一下,发现第二个参数必须是PDWORD,当函数返回时,它接收一个增量数,它在调用之间是持久的在不同的过程(不同的应用程序)。
有关更多信息,您可以访问this article,在那里我解释我的所有传奇故事。该文本是葡萄牙语,但该网站有一个很好的translatin工具。
我要感谢大家的帮助