VirtualBox

Ignore:
Timestamp:
Feb 22, 2012 2:36:09 PM (13 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
76387
Message:

VBoxGINA: Added support for auto-logon facility, added guest log support, misc. refactoring, added basic testcase.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/WINNT/VBoxGINA/Dialog.cpp

    r36258 r40214  
    66/*
    77 *
    8  * Copyright (C) 2006-2011 Oracle Corporation
     8 * Copyright (C) 2006-2012 Oracle Corporation
    99 *
    1010 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    1919#include <windows.h>
    2020#include <stdio.h>      /* Needed for swprintf() */
     21
     22#include <VBox/VboxGuestLib.h>
    2123
    2224#include "Dialog.h"
     
    9294void hookDialogBoxes(PVOID pWinlogonFunctions, DWORD dwWlxVersion)
    9395{
    94     Log(("VBoxGINA::hookDialogBoxes\n"));
     96    if (!pWinlogonFunctions) /* Needed for testcase. */
     97        return;
     98
     99    VBoxGINAVerbose(0, "VBoxGINA::hookDialogBoxes\n");
    95100
    96101    /* this is version dependent */
     
    134139        default:
    135140        {
    136             Log(("VBoxGINA::hookDialogBoxes: unrecognized version '%d', nothing hooked!\n", dwWlxVersion));
     141            VBoxGINAVerbose(0, "VBoxGINA::hookDialogBoxes: unrecognized version '%d', nothing hooked!\n", dwWlxVersion);
    137142            /* not good, don't do anything */
    138143            break;
     
    141146}
    142147
    143 //
    144 // Redirected WlxLoggedOutSASDlgProc().
    145 //
    146 BOOL credentialsToUI(HWND hwndUserId, HWND hwndPassword, HWND hwndDomain)
     148/**
     149 * Enters credentials into the given text fields.
     150 *
     151 * @return  IPRT status code.
     152 * @param   hwndDlg                 Handle of dialog to enter credentials into.
     153 * @param   hwndUserId              Handle of username text field. Optional.
     154 * @param   hwndPassword            Handle of password text field. Optional.
     155 * @param   hwndDomain              Handle of domain text field. Optional.
     156 * @param   pwszUser                Username to enter into username text field.
     157 * @param   pwszPassword            Password to enter into password text field.
     158 * @param   pwszDomain              Domain to enter into domain text field.
     159 */
     160int credentialsToUI(HWND hwndDlg,
     161                    HWND hwndUserId, HWND hwndPassword, HWND hwndDomain,
     162                    PCRTUTF16 pwszUser, PCRTUTF16 pwszPassword, PCRTUTF16 pwszDomain)
    147163{
    148164    BOOL bIsFQDN = FALSE;
     
    151167    {
    152168        /* search the domain combo box for our required domain and select it */
    153         Log(("VBoxGINA::MyWlxLoggedOutSASDlgProc: Trying to find domain entry in combo box ...\n"));
     169        VBoxGINAVerbose(0, "VBoxGINA::MyWlxLoggedOutSASDlgProc: Trying to find domain entry in combo box ...\n");
    154170        DWORD dwIndex = (DWORD) SendMessage(hwndDomain, CB_FINDSTRING,
    155                                             0, (LPARAM)g_Domain);
     171                                            0, (LPARAM)pwszDomain);
    156172        if (dwIndex != CB_ERR)
    157173        {
    158             Log(("VBoxGINA::MyWlxLoggedOutSASDlgProc: Found domain at combo box pos %ld\n", dwIndex));
     174            VBoxGINAVerbose(0, "VBoxGINA::MyWlxLoggedOutSASDlgProc: Found domain at combo box pos %ld\n", dwIndex);
    159175            SendMessage(hwndDomain, CB_SETCURSEL, (WPARAM) dwIndex, 0);
    160176            EnableWindow(hwndDomain, FALSE);
     
    162178        else
    163179        {
    164             Log(("VBoxGINA::MyWlxLoggedOutSASDlgProc: Domain not found in combo box ...\n"));
     180            VBoxGINAVerbose(0, "VBoxGINA::MyWlxLoggedOutSASDlgProc: Domain not found in combo box ...\n");
    165181
    166182            /* If the domain value has a dot (.) in it, it is a FQDN (Fully Qualified Domain Name)
     
    173189             *
    174190             */
    175             size_t l = wcslen(g_Domain);
     191            size_t l = wcslen(pwszDomain);
    176192            if (l > 255)
    177                 Log(("VBoxGINA::MyWlxLoggedOutSASDlgProc: Warning! FQDN is too long (max 255 bytes), will be truncated!\n"));
    178 
    179             if (wcslen(g_Username) > 0) /* We need a user name that we can use in caes of a FQDN */
     193                VBoxGINAVerbose(0, "VBoxGINA::MyWlxLoggedOutSASDlgProc: Warning! FQDN (domain) is too long (max 255 bytes), will be truncated!\n");
     194
     195            if (wcslen(pwszUser) > 0) /* We need a user name that we can use in caes of a FQDN */
    180196            {
    181197                if (l > 16) /* Domain name is longer than 16 chars, cannot be a NetBIOS name anymore */
    182198                {
    183                     Log(("VBoxGINA::MyWlxLoggedOutSASDlgProc: Domain seems to be a FQDN (length)!\n"));
     199                    VBoxGINAVerbose(0, "VBoxGINA::MyWlxLoggedOutSASDlgProc: Domain seems to be a FQDN (length)!\n");
    184200                    bIsFQDN = TRUE;
    185201                }
    186202                else if (   l > 0
    187                          && wcsstr(g_Domain, L".") != NULL) /* if we found a dot (.) in the domain name, this has to be a FQDN */
     203                         && wcsstr(pwszDomain, L".") != NULL) /* if we found a dot (.) in the domain name, this has to be a FQDN */
    188204                {
    189                     Log(("VBoxGINA::MyWlxLoggedOutSASDlgProc: Domain seems to be a FQDN (dot)!\n"));
     205                    VBoxGINAVerbose(0, "VBoxGINA::MyWlxLoggedOutSASDlgProc: Domain seems to be a FQDN (dot)!\n");
    190206                    bIsFQDN = TRUE;
    191207                }
     
    193209                if (bIsFQDN)
    194210                {
    195                     swprintf(szUserFQDN, sizeof(szUserFQDN) / sizeof(wchar_t), L"%s@%s", g_Username, g_Domain);
    196                     Log(("VBoxGINA::MyWlxLoggedOutSASDlgProc: FQDN user name is now: %s!\n", szUserFQDN));
     211                    swprintf(szUserFQDN, sizeof(szUserFQDN) / sizeof(wchar_t), L"%s@%s", pwszUser, pwszDomain);
     212                    VBoxGINAVerbose(0, "VBoxGINA::MyWlxLoggedOutSASDlgProc: FQDN user name is now: %s!\n", szUserFQDN);
    197213                }
    198214            }
     
    202218    {
    203219        if (!bIsFQDN)
    204             SendMessage(hwndUserId, WM_SETTEXT, 0, (LPARAM)g_Username);
     220            SendMessage(hwndUserId, WM_SETTEXT, 0, (LPARAM)pwszUser);
    205221        else
    206222            SendMessage(hwndUserId, WM_SETTEXT, 0, (LPARAM)szUserFQDN);
    207223    }
    208224    if (hwndPassword)
    209         SendMessage(hwndPassword, WM_SETTEXT, 0, (LPARAM)g_Password);
    210 
    211     return TRUE;
     225        SendMessage(hwndPassword, WM_SETTEXT, 0, (LPARAM)pwszPassword);
     226
     227    return VINF_SUCCESS; /** @todo */
     228}
     229
     230/**
     231 * Tries to retrieve credentials and enters them into the specified windows,
     232 * optionally followed by a button press to confirm/abort the dialog.
     233 *
     234 * @return  IPRT status code.
     235 * @param   hwndDlg                 Handle of dialog to enter credentials into.
     236 * @param   hwndUserId              Handle of username text field. Optional.
     237 * @param   hwndPassword            Handle of password text field. Optional.
     238 * @param   hwndDomain              Handle of domain text field. Optional.
     239 * @param   wButtonToPress          Button ID of dialog to press after successful
     240 *                                  retrieval + storage. If set to 0 no button will
     241 *                                  be pressed.
     242 */
     243int credentialsHandle(HWND hwndDlg,
     244                      HWND hwndUserId, HWND hwndPassword, HWND hwndDomain,
     245                      WORD wButtonToPress)
     246{
     247    int rc = VINF_SUCCESS;
     248
     249    if (!VBoxGINAHandleCurrentSession())
     250        rc = VERR_NOT_FOUND;
     251
     252    if (RT_SUCCESS(rc))
     253    {
     254        rc = VbglR3CredentialsQueryAvailability();
     255        if (RT_FAILURE(rc))
     256        {
     257            if (rc != VERR_NOT_FOUND)
     258                VBoxGINAVerbose(0, "VBoxGINA::credentialsHandle: error querying for credentials, rc=%Rrc\n", rc);
     259        }
     260    }
     261
     262    if (RT_SUCCESS(rc))
     263    {
     264        VBoxGINAVerbose(0, "VBoxGINA::credentialsHandle: credentials available\n");
     265
     266        /*
     267         * Set status to "terminating" to let the host know this module now
     268         * tries to receive and use passed credentials so that credentials from
     269         * the host won't be sent twice.
     270         */
     271        VBoxGINAReportStatus(VBoxGuestFacilityStatus_Terminating);
     272
     273        PRTUTF16 pwszUser, pwszPassword, pwszDomain;
     274        rc = VbglR3CredentialsRetrieveUtf16(&pwszUser, &pwszPassword, &pwszDomain);
     275        if (RT_SUCCESS(rc))
     276        {
     277    #ifdef DEBUG
     278            VBoxGINAVerbose(0, "VBoxGINA::credentialsHandle: retrieved credentials: user=%ls, password=%ls, domain=%ls\n",
     279                            pwszUser, pwszPassword, pwszDomain);
     280    #else
     281            VBoxGINAVerbose(0, "VBoxGINA::credentialsHandle: retrieved credentials: user=%ls, password=XXX, domain=%ls\n",
     282                            pwszUser, pwszDomain);
     283    #endif
     284            /* Fill in credentials to appropriate UI elements. */
     285            rc = credentialsToUI(hwndDlg,
     286                                 hwndUserId, hwndPassword, hwndDomain,
     287                                 pwszUser, pwszPassword, pwszDomain);
     288            if (RT_SUCCESS(rc))
     289            {
     290                /* Confirm/cancel the dialog by pressing the appropriate button. */
     291                if (wButtonToPress)
     292                {
     293                    WPARAM wParam = MAKEWPARAM(wButtonToPress, BN_CLICKED);
     294                    PostMessage(hwndDlg, WM_COMMAND, wParam, 0);
     295                }
     296            }
     297
     298            VbglR3CredentialsDestroyUtf16(pwszUser, pwszPassword, pwszDomain,
     299                                          3 /* Passes */);
     300        }
     301    }
     302
     303    VBoxGINAVerbose(3, "VBoxGINA::credentialsHandle: returned with rc=%Rrc\n", rc);
     304    return rc;
    212305}
    213306
     
    220313    static HWND s_hwndUserId, s_hwndPassword, s_hwndDomain = 0;
    221314
    222     /*Log(("VBoxGINA::MyWlxLoggedOutSASDlgProc\n"));*/
     315    /*VBoxGINAVerbose(0, "VBoxGINA::MyWlxLoggedOutSASDlgProc\n");*/
    223316
    224317    //
     
    234327        case WM_INITDIALOG:
    235328        {
    236             Log(("VBoxGINA::MyWlxLoggedOutSASDlgProc: got WM_INITDIALOG\n"));
     329            VBoxGINAVerbose(0, "VBoxGINA::MyWlxLoggedOutSASDlgProc: got WM_INITDIALOG\n");
    237330
    238331            /* get the entry fields */
     
    247340                s_hwndDomain = GetDlgItem(hwndDlg, IDC_WLXLOGGEDOUTSAS_DOMAIN2);
    248341
    249             Log(("VBoxGINA::MyWlxLoggedOutSASDlgProc: hwndUserId: %x, hwndPassword: %d, hwndDomain: %d\n",
    250                  s_hwndUserId, s_hwndPassword, s_hwndDomain));
     342            VBoxGINAVerbose(0, "VBoxGINA::MyWlxLoggedOutSASDlgProc: hwndUserId: %x, hwndPassword: %d, hwndDomain: %d\n",
     343                            s_hwndUserId, s_hwndPassword, s_hwndDomain);
    251344
    252345            /* terminate the credentials poller thread, it's done is job */
    253             credentialsPollerTerminate();
    254 
    255             if (credentialsAvailable())
    256             {
    257                 /* query the credentials from VBox */
    258                 if (credentialsRetrieve())
    259                 {
    260                     /* fill in credentials to appropriate UI elements */
    261                     credentialsToUI(s_hwndUserId, s_hwndPassword, s_hwndDomain);
    262 
    263                     /* we got the credentials, null them out */
    264                     credentialsReset();
    265 
    266                     /* confirm the logon dialog, simulating the user pressing "OK" */
    267                     WPARAM wParam = MAKEWPARAM(IDOK, BN_CLICKED);
    268                     PostMessage(hwndDlg, WM_COMMAND, wParam, 0);
    269                 }
    270             }
    271             else
     346            VBoxGINACredentialsPollerTerminate();
     347
     348            int rc = credentialsHandle(hwndDlg,
     349                                       s_hwndUserId, s_hwndPassword, s_hwndDomain,
     350                                       IDOK /* Button */);
     351            if (RT_FAILURE(rc))
    272352            {
    273353                /*
     
    277357                UINT_PTR uTimer = SetTimer(hwndDlg, IDT_LOGGEDONDLG_POLL, 200, NULL);
    278358                if (!uTimer)
    279                     Log(("VBoxGINA::MyWlxLoggedOutSASDlgProc: failed creating timer! Last error: %ld\n",
    280                          GetLastError()));
     359                    VBoxGINAVerbose(0, "VBoxGINA::MyWlxLoggedOutSASDlgProc: failed creating timer! Last error: %ld\n",
     360                                    GetLastError());
    281361            }
    282362            break;
     
    288368            if (wParam == IDT_LOGGEDONDLG_POLL)
    289369            {
    290                 if (credentialsAvailable())
     370                int rc = credentialsHandle(hwndDlg,
     371                                           s_hwndUserId, s_hwndPassword, s_hwndDomain,
     372                                           IDOK /* Button */);
     373                if (RT_SUCCESS(rc))
    291374                {
    292                     if (credentialsRetrieve())
    293                     {
    294                         /* fill in credentials to appropriate UI elements */
    295                         credentialsToUI(s_hwndUserId, s_hwndPassword, s_hwndDomain);
    296 
    297                         /* we got the credentials, null them out */
    298                         credentialsReset();
    299 
    300                         /* confirm the logon dialog, simulating the user pressing "OK" */
    301                         WPARAM wParam = MAKEWPARAM(IDOK, BN_CLICKED);
    302                         PostMessage(hwndDlg, WM_COMMAND, wParam, 0);
    303 
    304                         /* we don't need the timer any longer */
    305                         KillTimer(hwndDlg, IDT_LOGGEDONDLG_POLL);
    306                     }
     375                    /* we don't need the timer any longer */
     376                    KillTimer(hwndDlg, IDT_LOGGEDONDLG_POLL);
    307377                }
    308378            }
     
    326396    static HWND s_hwndPassword = 0;
    327397
    328     /*Log(("VBoxGINA::MyWlxLockedSASDlgProc\n"));*/
     398    /*VBoxGINAVerbose(0, "VBoxGINA::MyWlxLockedSASDlgProc\n");*/
    329399
    330400    //
     
    340410        case WM_INITDIALOG:
    341411        {
    342             Log(("VBoxGINA::MyWlxLockedSASDlgProc: got WM_INITDIALOG\n"));
     412            VBoxGINAVerbose(0, "VBoxGINA::MyWlxLockedSASDlgProc: WM_INITDIALOG\n");
    343413
    344414            /* get the entry fields */
    345415            s_hwndPassword = GetDlgItem(hwndDlg, IDC_WKSTALOCKED_PASSWORD);
    346             Log(("VBoxGINA::MyWlxLockedSASDlgProc: hwndPassword: %d\n", s_hwndPassword));
     416            VBoxGINAVerbose(0, "VBoxGINA::MyWlxLockedSASDlgProc: hwndPassword: %d\n", s_hwndPassword);
    347417
    348418            /* terminate the credentials poller thread, it's done is job */
    349             credentialsPollerTerminate();
    350 
    351             if (credentialsAvailable())
    352             {
    353                 /* query the credentials from VBox */
    354                 if (credentialsRetrieve())
    355                 {
    356                     /* fill in credentials to appropriate UI elements */
    357                     credentialsToUI(NULL /* User ID */, s_hwndPassword, NULL /* Domain */);
    358 
    359                     /* we got the credentials, null them out */
    360                     credentialsReset();
    361 
    362                     /* confirm the logon dialog, simulating the user pressing "OK" */
    363                     WPARAM wParam = MAKEWPARAM(IDOK, BN_CLICKED);
    364                     PostMessage(hwndDlg, WM_COMMAND, wParam, 0);
    365                 }
    366             }
    367             else
     419            VBoxGINACredentialsPollerTerminate();
     420
     421            int rc = credentialsHandle(hwndDlg,
     422                                       NULL /* Username */, s_hwndPassword, NULL /* Domain */,
     423                                       IDOK /* Button */);
     424            if (RT_FAILURE(rc))
    368425            {
    369426                /*
     
    373430                UINT_PTR uTimer = SetTimer(hwndDlg, IDT_LOCKEDDLG_POLL, 200, NULL);
    374431                if (!uTimer)
    375                     Log(("VBoxGINA::MyWlxLockedSASDlgProc: failed creating timer! Last error: %ld\n",
    376                          GetLastError()));
     432                    VBoxGINAVerbose(0, "VBoxGINA::MyWlxLockedSASDlgProc: failed creating timer! Last error: %ld\n",
     433                         GetLastError());
    377434            }
    378435            break;
     
    384441            if (wParam == IDT_LOCKEDDLG_POLL)
    385442            {
    386                 if (credentialsAvailable())
     443                int rc = credentialsHandle(hwndDlg,
     444                                           NULL /* Username */, s_hwndPassword, NULL /* Domain */,
     445                                           IDOK /* Button */);
     446                if (RT_SUCCESS(rc))
    387447                {
    388                     if (credentialsRetrieve())
    389                     {
    390                         /* fill in credentials to appropriate UI elements */
    391                         credentialsToUI(NULL /* User ID */, s_hwndPassword, NULL /* Domain */);
    392 
    393                         /* we got the credentials, null them out */
    394                         credentialsReset();
    395 
    396                         /* confirm the logon dialog, simulating the user pressing "OK" */
    397                         WPARAM wParam = MAKEWPARAM(IDOK, BN_CLICKED);
    398                         PostMessage(hwndDlg, WM_COMMAND, wParam, 0);
    399 
    400                         /* we don't need the timer any longer */
    401                         KillTimer(hwndDlg, IDT_LOCKEDDLG_POLL);
    402                     }
     448                    /* we don't need the timer any longer */
     449                    KillTimer(hwndDlg, IDT_LOCKEDDLG_POLL);
    403450                }
    404451            }
     
    407454
    408455        case WM_DESTROY:
     456        {
     457            VBoxGINAVerbose(0, "VBoxGINA::MyWlxLockedSASDlgProc: WM_DESTROY\n");
     458
     459            /* Because this is the only point where we know within our module that the locked
     460             * dialog has been closed by a valid unlock password we have to set the appropriate
     461             * facility status here. */
     462            VBoxGINAReportStatus(VBoxGuestFacilityStatus_Terminated);
     463
    409464            KillTimer(hwndDlg, IDT_LOCKEDDLG_POLL);
    410465            break;
     466        }
    411467    }
    412468    return bResult;
     
    421477                               LPARAM  dwInitParam)
    422478{
    423     Log(("VBoxGINA::MyWlxDialogBoxParam: lpszTemplate = %ls\n", lpszTemplate));
     479    VBoxGINAVerbose(0, "VBoxGINA::MyWlxDialogBoxParam: lpszTemplate=%ls\n", lpszTemplate);
     480
     481    VBoxGINAReportStatus(VBoxGuestFacilityStatus_Active);
    424482
    425483    //
     
    433491        switch ((DWORD) lpszTemplate)
    434492        {
     493            case IDD_WLXDIAPLAYSASNOTICE_DIALOG:
     494                VBoxGINAVerbose(0, "VBoxGINA::MyWlxDialogBoxParam: SAS notice dialog displayed; not handled\n");
     495                break;
     496
    435497            case IDD_WLXLOGGEDOUTSAS_DIALOG:     /* Windows NT 4.0. */
    436498            case IDD_WLXLOGGEDOUTSAS_DIALOG2:    /* Windows 2000 and up. */
    437499            {
    438                 Log(("VBoxGINA::MyWlxDialogBoxParam: returning hooked LOGGED OUT dialog\n"));
     500                VBoxGINAVerbose(0, "VBoxGINA::MyWlxDialogBoxParam: returning hooked SAS logged out dialog\n");
    439501                g_pfnWlxLoggedOutSASDlgProc = dlgprc;
    440502                return g_pfnWlxDialogBoxParam(hWlx, hInst, lpszTemplate, hwndOwner,
     
    442504            }
    443505
     506            case IDD_SECURITY_DIALOG:
     507                VBoxGINAVerbose(0, "VBoxGINA::MyWlxDialogBoxParam: Security dialog displayed; not handled\n");
     508                break;
     509
    444510            case IDD_WLXWKSTALOCKEDSAS_DIALOG:   /* Windows NT 4.0. */
    445511            case IDD_WLXWKSTALOCKEDSAS_DIALOG2:  /* Windows 2000 and up. */
    446512            {
    447                 Log(("VBoxGINA::MyWlxDialogBoxParam: returning hooked LOCKED dialog\n"));
     513                VBoxGINAVerbose(0, "VBoxGINA::MyWlxDialogBoxParam: returning hooked SAS locked dialog\n");
    448514                g_pfnWlxLockedSASDlgProc = dlgprc;
    449515                return g_pfnWlxDialogBoxParam(hWlx, hInst, lpszTemplate, hwndOwner,
     
    454520
    455521            default:
    456             {
    457                 char szBuf[1024];
    458                 sprintf(szBuf, "VBoxGINA::MyWlxDialogBoxParam: dialog %ld not handled\n", (DWORD)lpszTemplate);
    459                 Log((szBuf));
     522                VBoxGINAVerbose(0, "VBoxGINA::MyWlxDialogBoxParam: dialog %ld not handled\n", (DWORD)lpszTemplate);
    460523                break;
    461             }
    462         }
    463     }
    464 
    465     //
    466     // The rest will not be redirected.
    467     //
     524        }
     525    }
     526
     527    /* The rest will be redirected. */
    468528    return g_pfnWlxDialogBoxParam(hWlx, hInst, lpszTemplate,
    469529                                  hwndOwner, dlgprc, dwInitParam);
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette