如何以编程方式清除 WinInet SSL 状态(是否有 Windows API 调用)?

How to clear WinInet SSL state programmatically (is there a Windows API call)?

我需要使用 Delphi 中的 API 函数模拟与 "Internet Options" 对话框("Contents" 选项卡)中的 "Clear SSL State" 按钮相同的行为.

我的目的是将其与 WinInet 一起使用,以建立后续的独立 SSL 连接。没有这个,两个 WinInet 连接共享相同的 SSL 状态,阻止我更正错误的 SSL 证书密码,例如。

没有清除两次连接尝试之间的 SSL 状态,第一次 returns "wrong password",然后我更正密码并重试,但第二次尝试 returns "Secure Channel Support Error".

"Clear SSL State" 按钮仅执行以下未记录的 command-line 命令:

"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 选项对话框,我设法发现了 "Clear SSL State" 按钮的作用。它仅按顺序执行两次 API 调用 SslEmptyCacheIncrementUrlCacheHeaderData

发现这一点后,我能够实现以下代码,在我的请求之前执行:

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,当函数 returns 时接收一个增量数字,在不同进程(不同应用程序)的调用之间保持不变。

有关详细信息,您可以访问 this article,我会在其中解释我所有的故事。文字是葡萄牙语,但该网站有一个很好的翻译工具。

感谢大家的帮助