[PATCH 2/2] wininet: Add a simple certificate dialog to InternetErrorDlg.

David Hedberg dhedberg at codeweavers.com
Sun Dec 19 14:34:28 CST 2010


---
 dlls/wininet/dialogs.c         |  125 ++++++++++++++++++++++++++++++++-
 dlls/wininet/resource.h        |    6 ++
 dlls/wininet/tests/Makefile.in |    2 +-
 dlls/wininet/tests/internet.c  |  148 ++++++++++++++++++++++++++++++++++++++++
 dlls/wininet/wininet_En.rc     |   16 ++++
 dlls/wininet/wininet_Sv.rc     |   16 ++++
 6 files changed, 308 insertions(+), 5 deletions(-)

diff --git a/dlls/wininet/dialogs.c b/dlls/wininet/dialogs.c
index b3713a5..4fd3d3f 100644
--- a/dlls/wininet/dialogs.c
+++ b/dlls/wininet/dialogs.c
@@ -44,6 +44,8 @@
 
 #include "resource.h"
 
+#define MAX_STRING_LEN 1024
+
 WINE_DEFAULT_DEBUG_CHANNEL(wininet);
 
 struct WININET_ErrorDlgParams
@@ -461,6 +463,109 @@ static INT_PTR WINAPI WININET_PasswordDialog(
 }
 
 /***********************************************************************
+ *         WININET_InvalidCertificateDialog
+ */
+static INT_PTR WINAPI WININET_InvalidCertificateDialog(
+    HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
+{
+    struct WININET_ErrorDlgParams *params;
+    HWND hitem;
+    WCHAR buf[1024];
+
+    if( uMsg == WM_INITDIALOG )
+    {
+        TRACE("WM_INITDIALOG (%08lx)\n", lParam);
+
+        /* save the parameter list */
+        params = (struct WININET_ErrorDlgParams*) lParam;
+        SetWindowLongPtrW( hdlg, GWLP_USERDATA, lParam );
+
+        switch( params->dwError )
+        {
+        case ERROR_INTERNET_INVALID_CA:
+            LoadStringW( WININET_hModule, IDS_CERT_CA_INVALID, buf, 1024 );
+            break;
+        case ERROR_INTERNET_SEC_CERT_DATE_INVALID:
+            LoadStringW( WININET_hModule, IDS_CERT_DATE_INVALID, buf, 1024 );
+            break;
+        case ERROR_INTERNET_SEC_CERT_CN_INVALID:
+            LoadStringW( WININET_hModule, IDS_CERT_CN_INVALID, buf, 1024 );
+            break;
+        case ERROR_INTERNET_SEC_CERT_ERRORS:
+            /* FIXME: We should fetch information about the
+             * certificate here and show all the relevant errors.
+             */
+            LoadStringW( WININET_hModule, IDS_CERT_ERRORS, buf, 1024 );
+            break;
+        default:
+            FIXME( "No message for error %d\n", params->dwError );
+            buf[0] = '\0';
+        }
+
+        hitem = GetDlgItem( hdlg, IDC_CERT_ERROR );
+        SetWindowTextW( hitem, buf );
+
+        return TRUE;
+    }
+
+    params = (struct WININET_ErrorDlgParams*)
+                 GetWindowLongPtrW( hdlg, GWLP_USERDATA );
+
+    switch( uMsg )
+    {
+    case WM_COMMAND:
+        if( wParam == IDOK )
+        {
+            BOOL res = TRUE;
+
+            if( params->dwFlags & FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS )
+            {
+                DWORD flags, size = sizeof(flags);
+
+                InternetQueryOptionW( params->hRequest, INTERNET_OPTION_SECURITY_FLAGS, &flags, &size );
+                switch( params->dwError )
+                {
+                case ERROR_INTERNET_INVALID_CA:
+                    flags |= SECURITY_FLAG_IGNORE_UNKNOWN_CA;
+                    break;
+                case ERROR_INTERNET_SEC_CERT_DATE_INVALID:
+                    flags |= SECURITY_FLAG_IGNORE_CERT_DATE_INVALID;
+                    break;
+                case ERROR_INTERNET_SEC_CERT_CN_INVALID:
+                    flags |= SECURITY_FLAG_IGNORE_CERT_CN_INVALID;
+                    break;
+                case ERROR_INTERNET_SEC_CERT_ERRORS:
+                    FIXME("Should only add ignore flags as needed.\n");
+                    flags |= SECURITY_FLAG_IGNORE_CERT_CN_INVALID |
+                        SECURITY_FLAG_IGNORE_CERT_DATE_INVALID |
+                        SECURITY_FLAG_IGNORE_UNKNOWN_CA;
+                    /* FIXME: ERROR_INTERNET_SEC_CERT_ERRORS also
+                     * seems to set the corresponding DLG_* flags.
+                     */
+                    break;
+                }
+                res = InternetSetOptionW( params->hRequest, INTERNET_OPTION_SECURITY_FLAGS, &flags, size );
+                if(!res)
+                    WARN("InternetSetOption(INTERNET_OPTION_SECURITY_FLAGS) failed.\n");
+            }
+
+            EndDialog( hdlg, res ? ERROR_SUCCESS : ERROR_NOT_SUPPORTED );
+            return TRUE;
+        }
+        if( wParam == IDCANCEL )
+        {
+            TRACE("Pressed cancel.\n");
+
+            EndDialog( hdlg, ERROR_CANCELLED );
+            return TRUE;
+        }
+        break;
+    }
+
+    return FALSE;
+}
+
+/***********************************************************************
  *         WININET_GetConnectionStatus
  */
 static INT WININET_GetConnectionStatus( HINTERNET hRequest )
@@ -494,6 +599,9 @@ DWORD WINAPI InternetErrorDlg(HWND hWnd, HINTERNET hRequest,
 
     TRACE("%p %p %d %08x %p\n", hWnd, hRequest, dwError, dwFlags, lppvData);
 
+    if( !hWnd && !(dwFlags & FLAGS_ERROR_UI_FLAGS_NO_UI) )
+        return ERROR_INVALID_HANDLE;
+
     params.hWnd = hWnd;
     params.hRequest = hRequest;
     params.dwError = dwError;
@@ -520,14 +628,23 @@ DWORD WINAPI InternetErrorDlg(HWND hWnd, HINTERNET hRequest,
             WARN("unhandled status %u\n", dwStatus);
             return 0;
         }
+    case ERROR_INTERNET_SEC_CERT_ERRORS:
+    case ERROR_INTERNET_SEC_CERT_CN_INVALID:
+    case ERROR_INTERNET_SEC_CERT_DATE_INVALID:
+    case ERROR_INTERNET_INVALID_CA:
+        if( dwFlags & FLAGS_ERROR_UI_FLAGS_NO_UI )
+            return ERROR_CANCELLED;
 
+        if( dwFlags & ~FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS )
+            FIXME("%08x contains unsupported flags.\n", dwFlags);
+
+        return DialogBoxParamW( WININET_hModule, MAKEINTRESOURCEW( IDD_INVCERTDLG ),
+                                hWnd, WININET_InvalidCertificateDialog, (LPARAM) &params );
     case ERROR_INTERNET_HTTP_TO_HTTPS_ON_REDIR:
-    case ERROR_INTERNET_INVALID_CA:
     case ERROR_INTERNET_POST_IS_NON_SECURE:
-    case ERROR_INTERNET_SEC_CERT_CN_INVALID:
-    case ERROR_INTERNET_SEC_CERT_DATE_INVALID:
         FIXME("Need to display dialog for error %d\n", dwError);
         return ERROR_SUCCESS;
     }
-    return ERROR_INVALID_PARAMETER;
+
+    return ERROR_NOT_SUPPORTED;
 }
diff --git a/dlls/wininet/resource.h b/dlls/wininet/resource.h
index 279c112..256a374 100644
--- a/dlls/wininet/resource.h
+++ b/dlls/wininet/resource.h
@@ -21,6 +21,7 @@
 #include <windef.h>
 #include <winuser.h>
 
+#define IDD_INVCERTDLG   0x398
 #define IDD_AUTHDLG      0x399
 #define IDD_PROXYDLG     0x400
 
@@ -30,5 +31,10 @@
 #define IDC_PASSWORD     0x404
 #define IDC_SAVEPASSWORD 0x405
 #define IDC_SERVER       0x406
+#define IDC_CERT_ERROR   0x407
 
 #define IDS_LANCONNECTION 0x500
+#define IDS_CERT_CA_INVALID   0x501
+#define IDS_CERT_DATE_INVALID 0x502
+#define IDS_CERT_CN_INVALID   0x503
+#define IDS_CERT_ERRORS       0x504
diff --git a/dlls/wininet/tests/Makefile.in b/dlls/wininet/tests/Makefile.in
index 942267a..2f58593 100644
--- a/dlls/wininet/tests/Makefile.in
+++ b/dlls/wininet/tests/Makefile.in
@@ -1,5 +1,5 @@
 TESTDLL   = wininet.dll
-IMPORTS   = wininet ws2_32 advapi32
+IMPORTS   = wininet ws2_32 user32 advapi32
 
 C_SRCS = \
 	ftp.c \
diff --git a/dlls/wininet/tests/internet.c b/dlls/wininet/tests/internet.c
index a38e196..df0a882 100644
--- a/dlls/wininet/tests/internet.c
+++ b/dlls/wininet/tests/internet.c
@@ -22,6 +22,7 @@
 #include <string.h>
 #include "windef.h"
 #include "winbase.h"
+#include "winuser.h"
 #include "wininet.h"
 #include "winerror.h"
 #include "winreg.h"
@@ -1123,6 +1124,152 @@ static void test_Option_PerConnectionOptionA(void)
     HeapFree(GetProcessHeap(), 0, list.pOptions);
 }
 
+#define FLAG_TODO     0x1
+#define FLAG_NEEDREQ  0x2
+#define FLAG_UNIMPL   0x4
+
+void test_InternetErrorDlg(void)
+{
+    HINTERNET ses, con, req;
+    DWORD res, flags;
+    HWND hwnd;
+    ULONG i;
+    static const struct {
+        DWORD error;
+        DWORD res;
+        DWORD test_flags;
+    } no_ui_res[] = {
+        { ERROR_INTERNET_INCORRECT_PASSWORD     , ERROR_SUCCESS, FLAG_NEEDREQ },
+        { ERROR_INTERNET_SEC_CERT_DATE_INVALID  , ERROR_CANCELLED, 0 },
+        { ERROR_INTERNET_SEC_CERT_CN_INVALID    , ERROR_CANCELLED, 0 },
+        { ERROR_INTERNET_HTTP_TO_HTTPS_ON_REDIR , ERROR_SUCCESS, 0 },
+        { ERROR_INTERNET_HTTPS_TO_HTTP_ON_REDIR , ERROR_SUCCESS, FLAG_TODO },
+        { ERROR_INTERNET_MIXED_SECURITY         , ERROR_CANCELLED, FLAG_TODO },
+        { ERROR_INTERNET_CHG_POST_IS_NON_SECURE , ERROR_CANCELLED, FLAG_TODO },
+        { ERROR_INTERNET_POST_IS_NON_SECURE     , ERROR_SUCCESS, 0 },
+        { ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED, ERROR_CANCELLED, FLAG_NEEDREQ|FLAG_TODO },
+        { ERROR_INTERNET_INVALID_CA             , ERROR_CANCELLED, 0 },
+        { ERROR_INTERNET_HTTPS_HTTP_SUBMIT_REDIR, ERROR_CANCELLED, FLAG_TODO },
+        { ERROR_INTERNET_INSERT_CDROM           , ERROR_CANCELLED, FLAG_TODO|FLAG_NEEDREQ|FLAG_UNIMPL },
+        { ERROR_INTERNET_SEC_CERT_ERRORS        , ERROR_CANCELLED, 0 },
+        { ERROR_INTERNET_SEC_CERT_REV_FAILED    , ERROR_CANCELLED, FLAG_TODO },
+        { ERROR_HTTP_COOKIE_NEEDS_CONFIRMATION  , ERROR_HTTP_COOKIE_DECLINED, FLAG_TODO },
+        { ERROR_INTERNET_BAD_AUTO_PROXY_SCRIPT  , ERROR_CANCELLED, FLAG_TODO },
+        { ERROR_INTERNET_UNABLE_TO_DOWNLOAD_SCRIPT, ERROR_CANCELLED, FLAG_TODO },
+        { ERROR_HTTP_REDIRECT_NEEDS_CONFIRMATION, ERROR_CANCELLED, FLAG_TODO },
+        { ERROR_INTERNET_SEC_CERT_REVOKED       , ERROR_CANCELLED, 0 },
+        { 0, ERROR_NOT_SUPPORTED }
+    };
+
+    flags = 0;
+
+    res = InternetErrorDlg(NULL, NULL, 12055, flags, NULL);
+    ok(res == ERROR_INVALID_HANDLE, "Got %d\n", res);
+
+    ses = InternetOpen(NULL, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
+    ok(ses != 0, "InternetOpen failed: 0x%08x\n", GetLastError());
+    con = InternetConnect(ses, "www.winehq.org", 80, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
+    ok(con != 0, "InternetConnect failed: 0x%08x\n", GetLastError());
+    req = HttpOpenRequest(con, "GET", "/", NULL, NULL, NULL, 0, 0);
+    ok(req != 0, "HttpOpenRequest failed: 0x%08x\n", GetLastError());
+
+    /* NULL hwnd and FLAGS_ERROR_UI_FLAGS_NO_UI not set */
+    for(i = INTERNET_ERROR_BASE; i < INTERNET_ERROR_LAST; i++)
+    {
+        res = InternetErrorDlg(NULL, req, i, flags, NULL);
+        ok(res == ERROR_INVALID_HANDLE, "Got %d (%d)\n", res, i);
+    }
+
+    hwnd = GetDesktopWindow();
+    ok(hwnd != NULL, "GetDesktopWindow failed (%d)\n", GetLastError());
+
+    flags = FLAGS_ERROR_UI_FLAGS_NO_UI;
+    for(i = INTERNET_ERROR_BASE; i < INTERNET_ERROR_LAST; i++)
+    {
+        DWORD expected, test_flags, j;
+
+        for(j = 0; no_ui_res[j].error != 0; ++j)
+            if(no_ui_res[j].error == i)
+                break;
+
+        test_flags = no_ui_res[j].test_flags;
+        expected = no_ui_res[j].res;
+
+        /* Try an invalid request handle */
+        res = InternetErrorDlg(hwnd, (HANDLE)0xdeadbeef, i, flags, NULL);
+        if(res == ERROR_CALL_NOT_IMPLEMENTED)
+        {
+            todo_wine ok(test_flags & FLAG_UNIMPL, "%i is unexpectedly unimplemented.\n", i);
+            continue;
+        }
+        else
+            todo_wine ok(res == ERROR_INVALID_HANDLE, "Got %d (%d)\n", res, i);
+
+        /* With a valid req */
+        if(i == ERROR_INTERNET_NEED_UI)
+            continue; /* Crashes on windows XP */
+
+        if(i == ERROR_INTERNET_SEC_CERT_REVOKED)
+            continue; /* Interactive (XP, Win7) */
+
+        res = InternetErrorDlg(hwnd, req, i, flags, NULL);
+
+        /* Handle some special cases */
+        switch(i)
+        {
+        case ERROR_INTERNET_HTTP_TO_HTTPS_ON_REDIR:
+        case ERROR_INTERNET_HTTPS_TO_HTTP_ON_REDIR:
+            if(res == ERROR_CANCELLED)
+            {
+                /* Some windows XP, w2k3 x64, W2K8 */
+                win_skip("Skipping some tests for %d\n", i);
+                continue;
+            }
+            break;
+        case 12054: /* ERROR_INTERNET_FORTEZZA_LOGIN_NEEDED */
+            if(res != expected)
+            {
+                /* Windows XP, W2K3 */
+                ok(res == NTE_PROV_TYPE_NOT_DEF, "Got %d\n", res);
+                win_skip("Skipping some tests for %d\n", i);
+                continue;
+            }
+            break;
+        default: break;
+        }
+
+        if(test_flags & FLAG_TODO)
+            todo_wine ok(res == expected, "Got %d, expected %d (%d)\n", res, expected, i);
+        else
+            ok(res == expected, "Got %d, expected %d (%d)\n", res, expected, i);
+
+        /* Same thing with NULL hwnd */
+        res = InternetErrorDlg(NULL, req, i, flags, NULL);
+        if(test_flags & FLAG_TODO)
+            todo_wine ok(res == expected, "Got %d, expected %d (%d)\n", res, expected, i);
+        else
+            ok(res == expected, "Got %d, expected %d (%d)\n", res, expected, i);
+
+
+        /* With a null req */
+        if(test_flags & FLAG_NEEDREQ)
+            expected = ERROR_INVALID_PARAMETER;
+
+        res = InternetErrorDlg(hwnd, NULL, i, flags, NULL);
+        if( test_flags & FLAG_TODO || i == ERROR_INTERNET_INCORRECT_PASSWORD)
+            todo_wine ok(res == expected, "Got %d, expected %d (%d)\n", res, expected, i);
+        else
+            ok(res == expected, "Got %d, expected %d (%d)\n", res, expected, i);
+    }
+
+    res = InternetCloseHandle(req);
+    ok(res == TRUE, "InternetCloseHandle failed: 0x%08x\n", GetLastError());
+    res = InternetCloseHandle(con);
+    ok(res == TRUE, "InternetCloseHandle failed: 0x%08x\n", GetLastError());
+    res = InternetCloseHandle(ses);
+    ok(res == TRUE, "InternetCloseHandle failed: 0x%08x\n", GetLastError());
+}
+
 /* ############################### */
 
 START_TEST(internet)
@@ -1153,6 +1300,7 @@ START_TEST(internet)
     test_null();
     test_Option_PerConnectionOption();
     test_Option_PerConnectionOptionA();
+    test_InternetErrorDlg();
 
     if (!pInternetTimeFromSystemTimeA)
         win_skip("skipping the InternetTime tests\n");
diff --git a/dlls/wininet/wininet_En.rc b/dlls/wininet/wininet_En.rc
index d4ad275..5566859 100644
--- a/dlls/wininet/wininet_En.rc
+++ b/dlls/wininet/wininet_En.rc
@@ -60,7 +60,23 @@ FONT 8, "MS Shell Dlg"
  PUSHBUTTON "Cancel", IDCANCEL, 158, 126, 56, 14, WS_GROUP | WS_TABSTOP
 }
 
+IDD_INVCERTDLG DIALOG 3, 24, 250, 86
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Security Warning"
+FONT 8, "MS Shell Dlg"
+{
+ LTEXT "There is a problem with the certificate for this site.", -1, 40, 6, 200, 20
+ LTEXT "", IDC_CERT_ERROR, 40, 26, 200, 20
+ LTEXT "Do you want to continue anyway?", -1, 40, 46, 200, 20
+ PUSHBUTTON "Yes", IDOK, 40, 66, 56, 14, WS_GROUP | WS_TABSTOP | BS_DEFPUSHBUTTON
+ PUSHBUTTON "No", IDCANCEL, 100, 66, 56, 14, WS_GROUP | WS_TABSTOP
+}
+
 STRINGTABLE
 {
   IDS_LANCONNECTION "LAN Connection"
+  IDS_CERT_CA_INVALID   "The certificate is issued by an unknown or untrusted publisher."
+  IDS_CERT_DATE_INVALID "The date on the certificate is invalid."
+  IDS_CERT_CN_INVALID   "The name on the certificate does not match the site."
+  IDS_CERT_ERRORS       "There is at least one unspecified security problem with this certificate."
 }
diff --git a/dlls/wininet/wininet_Sv.rc b/dlls/wininet/wininet_Sv.rc
index 520cdcb..cc97d6e 100644
--- a/dlls/wininet/wininet_Sv.rc
+++ b/dlls/wininet/wininet_Sv.rc
@@ -60,7 +60,23 @@ FONT 8, "MS Shell Dlg"
  PUSHBUTTON "Avbryt", IDCANCEL, 158, 126, 56, 14, WS_GROUP | WS_TABSTOP
 }
 
+IDD_INVCERTDLG DIALOG 3, 24, 250, 86
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Säkerhetsvarning"
+FONT 8, "MS Shell Dlg"
+{
+ LTEXT "Ett problem upptäcktes med certifikatet för denna site.", -1, 40, 6, 200, 20
+ LTEXT "", IDC_CERT_ERROR, 40, 26, 200, 20
+ LTEXT "Vill du fortsätta ändå?", -1, 40, 46, 200, 20
+ PUSHBUTTON "Ja", IDOK, 40, 66, 56, 14, WS_GROUP | WS_TABSTOP | BS_DEFPUSHBUTTON
+ PUSHBUTTON "Nej", IDCANCEL, 100, 66, 56, 14, WS_GROUP | WS_TABSTOP
+}
+
 STRINGTABLE
 {
   IDS_LANCONNECTION "LAN-anslutning"
+  IDS_CERT_CA_INVALID   "Certifikatet är utfärdat av en okänd eller ej betrodd utgivare."
+  IDS_CERT_DATE_INVALID "Certifikatets datum är ogiltigt."
+  IDS_CERT_CN_INVALID   "Namnet på certifikatet matchar inte sitens namn."
+  IDS_CERT_ERRORS       "Certifikatet har minst ett ospecificerat säkerhetsproblem."
 }
-- 
1.7.3.3




More information about the wine-patches mailing list