Subversion Repositories Aucun

Rev

Rev 205 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
139 ixe013 1
/*
2
 Copyright (c) 2008, Guillaume Seguin ([email protected])
3
 All rights reserved.
4
 
5
 Redistribution and use in source and binary forms, with or without
6
 modification, are permitted provided that the following conditions
7
 are met:
8
 
9
 1. Redistributions of source code must retain the above copyright
10
    notice, this list of conditions and the following disclaimer.
11
 
12
 2. Redistributions in binary form must reproduce the above copyright
13
    notice, this list of conditions and the following disclaimer in the
14
    documentation and/or other materials provided with the distribution.
15
 
16
 THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
17
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
 ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
20
 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25
 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26
 SUCH DAMAGE.
27
*/
28
 
2 ixe013 29
#include <windows.h>
30
#include <winwlx.h>
31
#include <assert.h>
32
#include <lm.h>
40 ixe013 33
#include <string.h>
34
#include <security.h>
35
#include <windowsx.h>
2 ixe013 36
 
37
#include "Ginahook.h"
23 ixe013 38
#include "Settings.h"
39
#include "UnlockPolicy.h"
2 ixe013 40
 
40 ixe013 41
#include "global.h"
42
#include "debug.h"
139 ixe013 43
#include "trace.h"
44
#include "SecurityHelper.h"
2 ixe013 45
 
40 ixe013 46
 
23 ixe013 47
typedef struct
48
{
40 ixe013 49
    int IDD_SAS;
50
    int IDC_LOCKWKSTA;
51
    int IDC_LOGOFF;
52
    int IDD_UNLOCKPASSWORD;
23 ixe013 53
    int IDC_USERNAME;
54
    int IDC_PASSWORD;
55
    int IDC_DOMAIN;
40 ixe013 56
    int IDS_CAPTION;
57
    int IDS_DOMAIN_USERNAME;
58
    int IDS_USERNAME;
59
    int IDS_GENERIC_UNLOCK;
23 ixe013 60
}
61
DialogAndControlsID;
2 ixe013 62
 
23 ixe013 63
static const DialogAndControlsID gDialogsAndControls[] =
64
{
139 ixe013 65
    //Windows Server 2003
66
    //XP SP3 (and probably previeus versions also, never tested)
67
    {
68
        1800,    // IDD_SAS
69
            1800,    // IDC_LOCKWKSTA
70
            1801,    // IDC_LOGOFF
71
            1950,    // IDD_UNLOCKPASSWORD
72
            1953,    // IDC_USERNAME
73
            1954,    // IDC_PASSWORD
74
            1956,    // IDC_DOMAIN
75
            1501,    // IDS_CAPTION
76
            1528,    // IDS_DOMAIN_USERNAME
77
            1561,    // IDS_USERNAME
78
            1528     // IDS_GENERIC_UNLOCK //1607
79
    },
23 ixe013 80
};
81
 
82
static const int nbDialogsAndControlsID = sizeof gDialogsAndControls / sizeof *gDialogsAndControls;
40 ixe013 83
static int gCurrentDlgIndex = -1;
23 ixe013 84
 
2 ixe013 85
//
86
// Pointers to redirected functions.
87
//
88
 
89
static PWLX_DIALOG_BOX_PARAM pfWlxDialogBoxParam = NULL;
40 ixe013 90
typedef struct
91
{
92
    HANDLE CurrentUser;
93
    HANDLE Winlogon;
94
    LPARAM HookedLPARAM;
95
} DialogLParamHook;
2 ixe013 96
 
40 ixe013 97
const wchar_t gAucunWinlogonContext[] = L"Paralint.com_Aucun_WinlogonContext";
98
 
99
 
2 ixe013 100
//
101
// Pointers to redirected dialog box.
102
//
103
 
104
static DLGPROC pfWlxWkstaLockedSASDlgProc = NULL;
105
 
106
//
107
// Local functions.
108
//
109
 
23 ixe013 110
int WINAPI MyWlxDialogBoxParam(HANDLE, HANDLE, LPWSTR, HWND, DLGPROC, LPARAM);
2 ixe013 111
 
40 ixe013 112
BOOLEAN ShouldHookUnlockPasswordDialog();
2 ixe013 113
 
40 ixe013 114
 
2 ixe013 115
//
116
// Hook WlxDialogBoxParam() dispatch function.
117
//
23 ixe013 118
void HookWlxDialogBoxParam(PVOID pWinlogonFunctions, DWORD dwWlxVersion)
2 ixe013 119
{
23 ixe013 120
    //WlxDialogBoxParam
121
    pfWlxDialogBoxParam = ((PWLX_DISPATCH_VERSION_1_0) pWinlogonFunctions)->WlxDialogBoxParam;
122
    ((PWLX_DISPATCH_VERSION_1_0) pWinlogonFunctions)->WlxDialogBoxParam = MyWlxDialogBoxParam;
2 ixe013 123
}
124
 
23 ixe013 125
BOOLEAN GetDomainUsernamePassword(HWND hwndDlg, wchar_t *domain, int nbdomain, wchar_t *username, int nbusername, wchar_t *password, int nbpassword)
2 ixe013 126
{
23 ixe013 127
    BOOLEAN result = FALSE;
2 ixe013 128
 
139 ixe013 129
    if ((gCurrentDlgIndex >= 0) && (gCurrentDlgIndex < nbDialogsAndControlsID)) //sanity
23 ixe013 130
    {
139 ixe013 131
        if ((GetDlgItemText(hwndDlg, gDialogsAndControls[gCurrentDlgIndex].IDC_PASSWORD, password, nbpassword) > 0)
23 ixe013 132
            && (GetDlgItemText(hwndDlg, gDialogsAndControls[gCurrentDlgIndex].IDC_USERNAME, username, nbusername) > 0))
133
        {
205 ixe013 134
            HWND domainCombo;
135
            int cursel;
136
 
23 ixe013 137
            result = TRUE; //That's enough to keep going. Let's try the domain nonetheless
2 ixe013 138
 
205 ixe013 139
            domainCombo = GetDlgItem(hwndDlg, gDialogsAndControls[gCurrentDlgIndex].IDC_DOMAIN);
140
 
23 ixe013 141
            GetDlgItemText(hwndDlg, gDialogsAndControls[gCurrentDlgIndex].IDC_DOMAIN, domain, nbdomain);
205 ixe013 142
 
143
            cursel = ComboBox_GetCurSel(domainCombo);
144
 
145
            if(cursel >= 0)
146
            {
147
                if(ComboBox_GetLBTextLen(domainCombo, cursel) < nbdomain)
148
                {
149
                    ComboBox_GetLBText(domainCombo, cursel, domain);
150
                }
151
            }
152
            else
153
            {
154
                *domain = 0;
155
            }
23 ixe013 156
        }
157
    }
2 ixe013 158
 
23 ixe013 159
    return result;
2 ixe013 160
}
161
 
139 ixe013 162
BOOL IsWindowsServer()
163
{
164
    OSVERSIONINFOEX osvi;
165
    DWORDLONG dwlConditionMask = 0;
166
 
167
    // Initialize the OSVERSIONINFOEX structure.
168
    ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
169
    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
170
    osvi.dwMajorVersion = 5;
171
    osvi.wProductType = VER_NT_SERVER;
172
 
173
    // Initialize the condition mask.
174
    VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
175
    VER_SET_CONDITION(dwlConditionMask, VER_PRODUCT_TYPE, VER_EQUAL);
176
 
177
    // Perform the test.
178
    return VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_PRODUCT_TYPE, dwlConditionMask);
179
}
180
 
181
 
40 ixe013 182
DWORD DisplayUnlockNotice(HWND hDlg, HANDLE hWlx)
183
{
184
    DWORD result = IDNO; //proceed with lock
185
 
186
    wchar_t unlock[MAX_GROUPNAME] = L"";
187
 
139 ixe013 188
    if (GetGroupName(gUnlockGroupName, unlock, sizeof unlock / sizeof *unlock) == S_OK)
40 ixe013 189
    {
190
        wchar_t caption[512];
191
        wchar_t text[2048];
192
 
139 ixe013 193
        if ((GetNoticeText(L"Caption", caption, sizeof caption / sizeof *caption) == S_OK)
194
            && (GetNoticeText(L"Text", text, sizeof text / sizeof *text) == S_OK))
40 ixe013 195
        {
196
            wchar_t message[MAX_USERNAME + sizeof text / sizeof *text];
197
            wchar_t *read = text;
198
            wchar_t *write = text;
199
 
139 ixe013 200
            TRACE(L"Unlock notice will be displayed.\n");
201
 
40 ixe013 202
            //Insert real \n caracters from the \n found in the string.
139 ixe013 203
            while (*read)
40 ixe013 204
            {
139 ixe013 205
                if ((*read == '\\') && (*(read+1) == 'n'))
40 ixe013 206
                {
207
                    *write++ = '\n';
208
                    read += 2;
209
                }
210
                else
211
                {
212
                    *write++ = *read++;
213
                }
214
            }
215
 
216
            *write = 0;
217
 
218
            wsprintf(message, text, unlock); //Will insert group name if there is a %s in the message
219
            result = ((PWLX_DISPATCH_VERSION_1_0) g_pWinlogon)->WlxMessageBox(hWlx, hDlg, message, caption, MB_YESNOCANCEL|MB_ICONEXCLAMATION);
220
        }
221
    }
222
 
223
    return result;
224
 
225
}
226
 
139 ixe013 227
DWORD DisplayForceLogoffNotice(HWND hDlg, HANDLE hWlx, HANDLE current_user)
40 ixe013 228
{
229
    DWORD result = IDCANCEL;
230
 
139 ixe013 231
    TRACE(L"About to display a notice for dialog index %d\n", gCurrentDlgIndex);
232
 
233
    if ((gCurrentDlgIndex >= 0) && (gCurrentDlgIndex < nbDialogsAndControlsID)) //sanity
40 ixe013 234
    {
139 ixe013 235
        wchar_t buf[2048];
40 ixe013 236
        wchar_t caption[512];
237
 
139 ixe013 238
        //Start with the caption
178 ixe013 239
        LoadString(hResourceDll, gDialogsAndControls[gCurrentDlgIndex].IDS_CAPTION, caption, sizeof caption / sizeof *caption);
40 ixe013 240
 
139 ixe013 241
        //Windows XP has a plain vanilla message, no insert. Let's start with that
178 ixe013 242
        LoadString(hResourceDll, gDialogsAndControls[gCurrentDlgIndex].IDS_GENERIC_UNLOCK, buf, sizeof buf / sizeof *buf);
40 ixe013 243
 
139 ixe013 244
        //The format of the message is different on Windows Server. This test is somewhat short sighted,
245
        //but we know that in the future versions there is no Gina at all ! That's why we shortcut
246
        //the test to either Windows XP or Windows Server.
247
        if (IsWindowsServer())
40 ixe013 248
        {
139 ixe013 249
            wchar_t format[1024];
250
            wchar_t username[1024];
251
            wchar_t domain[1024];
252
            int howmany;
40 ixe013 253
 
139 ixe013 254
            howmany = GetUsernameAndDomainFromToken(current_user, domain, sizeof domain / sizeof *domain, username, sizeof username /  sizeof *username);
40 ixe013 255
 
139 ixe013 256
            switch(howmany)
40 ixe013 257
            {
139 ixe013 258
            case 2:
259
                {
178 ixe013 260
                    LoadString(hResourceDll, gDialogsAndControls[gCurrentDlgIndex].IDS_DOMAIN_USERNAME, format, sizeof format / sizeof *format);
139 ixe013 261
                    wsprintf(buf, format, domain, username, L"some time");
262
                }
263
                break;
264
            case 1:
265
                {
178 ixe013 266
                    LoadString(hResourceDll, gDialogsAndControls[gCurrentDlgIndex].IDS_USERNAME, format, sizeof format / sizeof *format);
139 ixe013 267
                    wsprintf(buf, format, username, L"some time");
268
                }
269
                break;
40 ixe013 270
            }
271
        }
272
 
139 ixe013 273
        TRACE(buf);
274
        TRACEMORE(L"\n");
40 ixe013 275
 
276
        result = ((PWLX_DISPATCH_VERSION_1_0) g_pWinlogon)->WlxMessageBox(hWlx, hDlg, buf, caption, MB_OKCANCEL|MB_ICONEXCLAMATION);
277
    }
278
 
279
    return result;
280
}
281
 
139 ixe013 282
// DelPropProc is an application-defined callback function
283
// that deletes a window property.
284
BOOL CALLBACK DelPropProc(HWND hwndSubclass, LPTSTR lpszString, HANDLE hData, ULONG_PTR x)       // data handle
285
{
286
    RemoveProp(hwndSubclass, lpszString);
287
    return TRUE;
288
}
40 ixe013 289
 
290
INT_PTR CALLBACK MyWlxWkstaLoggedOnSASDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
291
{
292
    INT_PTR bResult = FALSE;
293
 
294
    // We hook a click on OK
139 ixe013 295
    if (uMsg == WM_INITDIALOG)
40 ixe013 296
    {
297
        DialogLParamHook *myinitparam = (DialogLParamHook*)lParam;
298
 
299
        lParam = myinitparam->HookedLPARAM;
300
 
301
        SetProp(hwndDlg, gAucunWinlogonContext, myinitparam->Winlogon);
139 ixe013 302
 
303
        TRACE(L"Hooked dialog shown.\n");
40 ixe013 304
    }
139 ixe013 305
    else if (uMsg == WM_DESTROY)
40 ixe013 306
    {
139 ixe013 307
        EnumPropsEx(hwndDlg, DelPropProc, 0);
40 ixe013 308
    }
309
    else if ((uMsg == WM_COMMAND) && (wParam == gDialogsAndControls[gCurrentDlgIndex].IDC_LOCKWKSTA))
310
    {
139 ixe013 311
        TRACE(L"User locking workstation.\n");
40 ixe013 312
        /*
313
        There is a race condition here (time of check, time of use).
139 ixe013 314
        We check for a certain condition and display a warning. Then we let go
40 ixe013 315
        and make the same test again to hook the dialog or not. An administrator
139 ixe013 316
        with a good sense of timing could manage set the registry just after the
317
        test of ShouldHookUnlockPasswordDialog is made but before the actual
318
        dialog would be hooked.
40 ixe013 319
 
139 ixe013 320
        In other words: with good timing, an administrator with access to the
40 ixe013 321
        registry can prevent the unlock notice from showing.
322
 
323
        Spotting the flaw is 80% of the fun... I will probably never fix it.
324
        */
139 ixe013 325
        if (ShouldHookUnlockPasswordDialog(pgAucunContext->mCurrentUser))
40 ixe013 326
        {
139 ixe013 327
            TRACE(L"Will hook dialog if allowed to.\n");
328
            switch (DisplayUnlockNotice(hwndDlg, GetProp(hwndDlg, gAucunWinlogonContext)))
40 ixe013 329
            {
139 ixe013 330
                //We said that a custom Gina was installed, and asked "do you want
331
                //to lof off instead" ?
332
            case IDYES:
333
                //Why 113 ? I didn't find this value anywhere in the header files,
334
                //but it is the value returned by the original MSGINA DialogProc
335
                //When you click YES on the "Are you sure you want to log off" dialog box.
336
                TRACE(L"User wants to logoff instead.\n");
337
                EndDialog(hwndDlg, 113);
338
                bResult = TRUE;
339
                break;
40 ixe013 340
 
139 ixe013 341
                //Forget about it, I am not locking at all
342
            case IDCANCEL:
343
                TRACE(L"Lock request cancelled.\n");
344
                bResult = TRUE;
345
                break;
346
 
347
                //I don't care. Lock my workstation
348
            case IDNO:
349
            default:
350
                break;
40 ixe013 351
            }
352
        }
353
    }
178 ixe013 354
    else if (uMsg == WM_COMMAND)
355
    {
356
        TRACE(L"User clicked on %d\n", wParam);
357
    }
40 ixe013 358
 
359
    if (!bResult)
360
        bResult = pfWlxWkstaLockedSASDlgProc(hwndDlg, uMsg, wParam, lParam);
361
 
362
    return bResult;
363
}
364
 
365
 
2 ixe013 366
//
367
// Redirected WlxWkstaLockedSASDlgProc().
368
//
23 ixe013 369
INT_PTR CALLBACK MyWlxWkstaLockedSASDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
2 ixe013 370
{
23 ixe013 371
    INT_PTR bResult = FALSE;
2 ixe013 372
 
23 ixe013 373
    // We hook a click on OK
139 ixe013 374
    if (uMsg == WM_INITDIALOG)
23 ixe013 375
    {
40 ixe013 376
        DialogLParamHook *myinitparam = (DialogLParamHook*)lParam;
377
 
378
        lParam = myinitparam->HookedLPARAM;
379
 
380
        SetProp(hwndDlg, gAucunWinlogonContext, myinitparam->Winlogon);
139 ixe013 381
        TRACE(L"Hooked dialog shown.\n");
40 ixe013 382
    }
139 ixe013 383
    else if (uMsg == WM_DESTROY)
40 ixe013 384
    {
139 ixe013 385
        EnumPropsEx(hwndDlg, DelPropProc, 0);
40 ixe013 386
    }
387
    else if ((uMsg == WM_COMMAND) && (wParam == IDOK))
388
    {
23 ixe013 389
        wchar_t rawdomain[MAX_DOMAIN];
390
        wchar_t rawusername[MAX_USERNAME];
391
        wchar_t password[MAX_PASSWORD];
2 ixe013 392
 
139 ixe013 393
        TRACE(L"Unlock or logoff attemp\n");
394
 
23 ixe013 395
        //Get the username and password for this particular Dialog template
139 ixe013 396
        if (GetDomainUsernamePassword(hwndDlg, rawdomain, sizeof rawdomain / sizeof *rawdomain,
397
            rawusername, sizeof rawusername / sizeof *rawusername,
398
            password, sizeof password / sizeof *password))
23 ixe013 399
        {
400
            wchar_t *username = 0;
401
            wchar_t *domain = 0;
2 ixe013 402
 
40 ixe013 403
            //Replace this hack with CredUIParseUserName
23 ixe013 404
            username = wcsstr(rawusername, L"\\");
2 ixe013 405
 
206 ixe013 406
            //If there is a backslash, parse the domain from the username
139 ixe013 407
            if (username)
23 ixe013 408
            {
409
                domain = rawusername;
410
                *username++ = 0; //Null terminate the domain name and skip the separator
411
            }
412
            else
413
            {
414
                username = rawusername; //No domain entered, so point directly to the supplied buffer
139 ixe013 415
                if (*rawdomain)
206 ixe013 416
                {
417
                    //So let's get the local computer name
418
                    wchar_t chrComputerName[MAX_COMPUTERNAME_LENGTH + 1];  
419
                    DWORD dwBufferSize = MAX_COMPUTERNAME_LENGTH + 1;  
420
 
421
                    //This will work unless the local computer was chosen
422
                    domain = rawdomain;
423
 
424
                    if(GetComputerName(chrComputerName,&dwBufferSize))
425
                    {  
426
                        //see if the computer name is in the domain string
427
                        wchar_t *pComputerName = wcsstr(rawdomain, chrComputerName);
428
 
429
                        if(pComputerName)
430
                        {
431
                            //There is a chance that the user selected the current computer
432
                            //But it could be just that the computer name is a subset of a
433
                            //longer domain name
434
                            //But we know that the name will be qualified with the string
435
                            //"(this computer)" localized. It could be in front or at the end.
436
                            //Example : domain ABC123
437
                            //        computer  BC1 (this computer)       
438
                            //       (cet ordi) BC1
439
 
440
                            //This will handle cases when the computer name is
441
                            //after the localized text. It doesn't do anything on
442
                            //an English or French local.
443
                            domain = pComputerName;
444
                            //If it ends with a space, trim it
445
                            if(domain[dwBufferSize] == ' ')
446
                            {
447
                                domain[dwBufferSize] = 0;
448
                            }
449
                        }
450
                    }  
451
                }
23 ixe013 452
            }
2 ixe013 453
 
23 ixe013 454
            if (*username && *password)
455
            {
139 ixe013 456
                // Can you spot the buffer overflow vulnerability in this next line ?
205 ixe013 457
                TRACE(L"User %s\\%s has entered his password.\n", *domain?domain:L"", username);
139 ixe013 458
                // Don't worry, GetDomainUsernamePassword validated input length. We are safe.
459
 
460
                switch (ShouldUnlockForUser(pgAucunContext->mLSA, pgAucunContext->mCurrentUser, domain, username, password))
23 ixe013 461
                {
40 ixe013 462
                case eForceLogoff:
463
                    //Might help with house keeping, instead of directly calling EndDialog
139 ixe013 464
                    if (DisplayForceLogoffNotice(hwndDlg, GetProp(hwndDlg, gAucunWinlogonContext), pgAucunContext->mCurrentUser) == IDOK)
40 ixe013 465
                    {
139 ixe013 466
                        TRACE(L"User was allowed (and agreed) to forcing a logoff.\n");
40 ixe013 467
                        PostMessage(hwndDlg, WLX_WM_SAS, WLX_SAS_TYPE_USER_LOGOFF, 0);
468
                    }
469
                    else
470
                    {
471
                        //mimic MSGINA behavior
472
                        SetDlgItemText(hwndDlg, gDialogsAndControls[gCurrentDlgIndex].IDC_PASSWORD, L"");
473
                    }
474
                    bResult = TRUE;
475
                    break;
476
                case eUnlock:
139 ixe013 477
                    TRACE(L"User was allowed to unlock.\n");
23 ixe013 478
                    EndDialog(hwndDlg, IDOK);
479
                    bResult = TRUE;
40 ixe013 480
                    break;
139 ixe013 481
 
482
                case eLetMSGINAHandleIt:
483
                default:
484
                    TRACE(L"Will be handled by MSGINA.\n");
40 ixe013 485
                    //Most of the time, we end up here with nothing to do
486
                    break;
23 ixe013 487
                }
40 ixe013 488
 
489
                SecureZeroMemory(password, sizeof password);
23 ixe013 490
            }
491
        }
492
    }
2 ixe013 493
 
23 ixe013 494
    if (!bResult)
495
        bResult = pfWlxWkstaLockedSASDlgProc(hwndDlg, uMsg, wParam, lParam);
2 ixe013 496
 
23 ixe013 497
    return bResult;
2 ixe013 498
}
499
 
500
//
501
// Redirected WlxDialogBoxParam() function.
502
//
23 ixe013 503
int WINAPI MyWlxDialogBoxParam(HANDLE hWlx, HANDLE hInst, LPWSTR lpszTemplate, HWND hwndOwner, DLGPROC dlgprc, LPARAM dwInitParam)
2 ixe013 504
{
23 ixe013 505
    DLGPROC proc2use = dlgprc;
40 ixe013 506
    LPARAM lparam2use = dwInitParam;
507
    DialogLParamHook myInitParam = {0};
139 ixe013 508
    DWORD dlgid = 0;
148 ixe013 509
    int result = 0;
510
   DLGPROC saved_pfWlxWkstaLockedSASDlgProc;
2 ixe013 511
 
40 ixe013 512
    //We might doint this for nothing (if dialog is not hooked)
513
    myInitParam.HookedLPARAM = dwInitParam;
514
    myInitParam.Winlogon = hWlx;
2 ixe013 515
 
148 ixe013 516
    //First user-reported bug !!!
517
    //This function was not re-entrant with regards to pfWlxWkstaLockedSASDlgProc
518
   saved_pfWlxWkstaLockedSASDlgProc = pfWlxWkstaLockedSASDlgProc;
519
 
40 ixe013 520
    pfWlxWkstaLockedSASDlgProc = dlgprc;
521
 
139 ixe013 522
    TRACE(L"About to create the dialog");
23 ixe013 523
    //
524
    // We only know MSGINA dialogs by identifiers.
525
    //
526
    if (!HIWORD(lpszTemplate))
527
    {
528
        // Hook appropriate dialog boxes as necessary.
529
        int i;
139 ixe013 530
        dlgid = LOWORD(lpszTemplate);    //Cast to remove warning C4311
2 ixe013 531
 
23 ixe013 532
        //Try to find the dialog
139 ixe013 533
        for (i=0; i<nbDialogsAndControlsID; ++i)
23 ixe013 534
        {
535
            //Is it one of the ID we know ?
139 ixe013 536
            if (gDialogsAndControls[i].IDD_SAS == dlgid)
23 ixe013 537
            {
139 ixe013 538
                //The dialog that asks if you would like to change password, lock, taskmgr, etc.
539
                TRACEMORE(L" to change password, lock wkst, taskmgr, etc.\n");
23 ixe013 540
                gCurrentDlgIndex = i;
40 ixe013 541
 
542
                proc2use = MyWlxWkstaLoggedOnSASDlgProc;
543
                lparam2use = (LPARAM)&myInitParam;
544
 
23 ixe013 545
                break;
546
            }
139 ixe013 547
            else if (gDialogsAndControls[i].IDD_UNLOCKPASSWORD == dlgid)
40 ixe013 548
            {
139 ixe013 549
                //The dialog where you enter your password
550
                TRACEMORE(L" where you try to unlock a locked session\n");
551
 
40 ixe013 552
                gCurrentDlgIndex = i;
553
 
139 ixe013 554
                if (ShouldHookUnlockPasswordDialog(pgAucunContext->mCurrentUser))
40 ixe013 555
                {
139 ixe013 556
                    TRACE(L"Hooking the unlock dialog\n");
40 ixe013 557
                    proc2use = MyWlxWkstaLockedSASDlgProc; //Use our proc instead
558
                    lparam2use = (LPARAM)&myInitParam;
139 ixe013 559
                }
40 ixe013 560
 
561
                //No need to go on, even if nothing was hooked
562
                break;
563
            }
23 ixe013 564
        }
565
    }
2 ixe013 566
 
139 ixe013 567
    if (proc2use == dlgprc)
568
    {
569
        TRACE(L"(%d). it was not hooked.\n", dlgid);
570
    }
571
 
148 ixe013 572
    result = pfWlxDialogBoxParam(hWlx, hInst, lpszTemplate, hwndOwner, proc2use, lparam2use);
178 ixe013 573
    pfWlxWkstaLockedSASDlgProc = saved_pfWlxWkstaLockedSASDlgProc;
574
 
575
    if (proc2use != dlgprc)
576
    {
577
        TRACE(L"Hooked dialog returned %d\n", result);
578
    }
579
    else
580
    {
581
        TRACE(L"Regular dialog returned %d\n", result);
582
    }
583
 
148 ixe013 584
    return result;
8 ixe013 585
}