VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/VBoxGINA/VBoxGINA.cpp@ 37213

Last change on this file since 37213 was 36446, checked in by vboxsync, 14 years ago

VBoxGINA: Implemented support for handling/ignoring remote (desktop) sessions.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 15.8 KB
Line 
1/** @file
2 *
3 * VBoxGINA -- Windows Logon DLL for VirtualBox
4 *
5 * Copyright (C) 2006-2011 Oracle Corporation
6 *
7 * This file is part of VirtualBox Open Source Edition (OSE), as
8 * available from http://www.virtualbox.org. This file is free software;
9 * you can redistribute it and/or modify it under the terms of the GNU
10 * General Public License (GPL) as published by the Free Software
11 * Foundation, in version 2 as it comes in the "COPYING" file of the
12 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
13 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
14 */
15
16#include <stdio.h>
17#include <stdlib.h>
18#include <windows.h>
19#include "winwlx.h"
20#include "VBoxGINA.h"
21#include "Helper.h"
22#include "Dialog.h"
23#include <VBox/VBoxGuestLib.h>
24
25/*
26 * Global variables.
27 */
28
29/** DLL instance handle. */
30HINSTANCE hDllInstance;
31
32/** Version of Winlogon. */
33DWORD wlxVersion;
34
35/** Handle to Winlogon service. */
36HANDLE hGinaWlx;
37/** Winlog function dispatch table. */
38PWLX_DISPATCH_VERSION_1_1 pWlxFuncs;
39
40/**
41 * Function pointers to MSGINA entry points.
42 */
43PGWLXNEGOTIATE GWlxNegotiate;
44PGWLXINITIALIZE GWlxInitialize;
45PGWLXDISPLAYSASNOTICE GWlxDisplaySASNotice;
46PGWLXLOGGEDOUTSAS GWlxLoggedOutSAS;
47PGWLXACTIVATEUSERSHELL GWlxActivateUserShell;
48PGWLXLOGGEDONSAS GWlxLoggedOnSAS;
49PGWLXDISPLAYLOCKEDNOTICE GWlxDisplayLockedNotice;
50PGWLXWKSTALOCKEDSAS GWlxWkstaLockedSAS;
51PGWLXISLOCKOK GWlxIsLockOk;
52PGWLXISLOGOFFOK GWlxIsLogoffOk;
53PGWLXLOGOFF GWlxLogoff;
54PGWLXSHUTDOWN GWlxShutdown;
55/* GINA 1.1. */
56PGWLXSTARTAPPLICATION GWlxStartApplication;
57PGWLXSCREENSAVERNOTIFY GWlxScreenSaverNotify;
58/* GINA 1.3. */
59PGWLXNETWORKPROVIDERLOAD GWlxNetworkProviderLoad;
60PGWLXDISPLAYSTATUSMESSAGE GWlxDisplayStatusMessage;
61PGWLXGETSTATUSMESSAGE GWlxGetStatusMessage;
62PGWLXREMOVESTATUSMESSAGE GWlxRemoveStatusMessage;
63/* GINA 1.4. */
64PGWLXGETCONSOLESWITCHCREDENTIALS GWlxGetConsoleSwitchCredentials;
65PGWLXRECONNECTNOTIFY GWlxReconnectNotify;
66PGWLXDISCONNECTNOTIFY GWlxDisconnectNotify;
67
68
69/**
70 * DLL entry point.
71 */
72BOOL WINAPI DllMain(HINSTANCE hInstance,
73 DWORD dwReason,
74 LPVOID lpReserved)
75{
76 switch (dwReason)
77 {
78 case DLL_PROCESS_ATTACH:
79 {
80 RTR3Init();
81 VbglR3Init();
82 LogRel(("VBoxGINA: DLL loaded.\n"));
83
84 DisableThreadLibraryCalls(hInstance);
85 hDllInstance = hInstance;
86 break;
87 }
88
89 case DLL_PROCESS_DETACH:
90 {
91 LogRel(("VBoxGINA: DLL unloaded.\n"));
92 VbglR3Term();
93 /// @todo RTR3Term();
94 break;
95 }
96
97 default:
98 break;
99 }
100 return TRUE;
101}
102
103
104BOOL WINAPI WlxNegotiate(DWORD dwWinlogonVersion,
105 DWORD *pdwDllVersion)
106{
107 HINSTANCE hDll;
108
109#ifdef DEBUG
110 /* enable full log output */
111 RTLogGroupSettings(RTLogDefaultInstance(), "all=~0");
112#endif
113
114 Log(("VBoxGINA::WlxNegotiate: dwWinlogonVersion: %ld\n", dwWinlogonVersion));
115
116 /* Load global configuration from registry. */
117 DWORD dwRet = loadConfiguration();
118 if (ERROR_SUCCESS != dwRet)
119 Log(("VBoxGINA: Error loading global configuration, error=%ld\n", dwRet));
120
121 /* If we have a remote session (that is, a connection via remote desktop /
122 * terminal services) deny it if not specified explicitly. */
123 if (!handleCurrentSession())
124 Log(("VBoxGINA: Handling of remote desktop sessions is disabled.\n"));
125
126 /* Load the standard Microsoft GINA DLL. */
127 if (!(hDll = LoadLibrary(TEXT("MSGINA.DLL"))))
128 {
129 Log(("VBoxGINA::WlxNegotiate: failed loading MSGINA! Last error=%ld\n", GetLastError()));
130 return FALSE;
131 }
132
133 /*
134 * Now get the entry points of the MSGINA
135 */
136 GWlxNegotiate = (PGWLXNEGOTIATE)GetProcAddress(hDll, "WlxNegotiate");
137 if (!GWlxNegotiate)
138 {
139 Log(("VBoxGINA::WlxNegotiate: failed resolving WlxNegotiate\n"));
140 return FALSE;
141 }
142 GWlxInitialize = (PGWLXINITIALIZE)GetProcAddress(hDll, "WlxInitialize");
143 if (!GWlxInitialize)
144 {
145 Log(("VBoxGINA::WlxNegotiate: failed resolving WlxInitialize\n"));
146 return FALSE;
147 }
148 GWlxDisplaySASNotice =
149 (PGWLXDISPLAYSASNOTICE)GetProcAddress(hDll, "WlxDisplaySASNotice");
150 if (!GWlxDisplaySASNotice)
151 {
152 Log(("VBoxGINA::WlxNegotiate: failed resolving WlxDisplaySASNotice\n"));
153 return FALSE;
154 }
155 GWlxLoggedOutSAS =
156 (PGWLXLOGGEDOUTSAS)GetProcAddress(hDll, "WlxLoggedOutSAS");
157 if (!GWlxLoggedOutSAS)
158 {
159 Log(("VBoxGINA::WlxNegotiate: failed resolving WlxLoggedOutSAS\n"));
160 return FALSE;
161 }
162 GWlxActivateUserShell =
163 (PGWLXACTIVATEUSERSHELL)GetProcAddress(hDll, "WlxActivateUserShell");
164 if (!GWlxActivateUserShell)
165 {
166 Log(("VBoxGINA::WlxNegotiate: failed resolving WlxActivateUserShell\n"));
167 return FALSE;
168 }
169 GWlxLoggedOnSAS =
170 (PGWLXLOGGEDONSAS)GetProcAddress(hDll, "WlxLoggedOnSAS");
171 if (!GWlxLoggedOnSAS)
172 {
173 Log(("VBoxGINA::WlxNegotiate: failed resolving WlxLoggedOnSAS\n"));
174 return FALSE;
175 }
176 GWlxDisplayLockedNotice =
177 (PGWLXDISPLAYLOCKEDNOTICE)GetProcAddress(hDll, "WlxDisplayLockedNotice");
178 if (!GWlxDisplayLockedNotice)
179 {
180 Log(("VBoxGINA::WlxNegotiate: failed resolving WlxDisplayLockedNotice\n"));
181 return FALSE;
182 }
183 GWlxIsLockOk = (PGWLXISLOCKOK)GetProcAddress(hDll, "WlxIsLockOk");
184 if (!GWlxIsLockOk)
185 {
186 Log(("VBoxGINA::WlxNegotiate: failed resolving WlxIsLockOk\n"));
187 return FALSE;
188 }
189 GWlxWkstaLockedSAS =
190 (PGWLXWKSTALOCKEDSAS)GetProcAddress(hDll, "WlxWkstaLockedSAS");
191 if (!GWlxWkstaLockedSAS)
192 {
193 Log(("VBoxGINA::WlxNegotiate: failed resolving WlxWkstaLockedSAS\n"));
194 return FALSE;
195 }
196 GWlxIsLogoffOk = (PGWLXISLOGOFFOK)GetProcAddress(hDll, "WlxIsLogoffOk");
197 if (!GWlxIsLogoffOk)
198 {
199 Log(("VBoxGINA::WlxNegotiate: failed resolving WlxIsLogoffOk\n"));
200 return FALSE;
201 }
202 GWlxLogoff = (PGWLXLOGOFF)GetProcAddress(hDll, "WlxLogoff");
203 if (!GWlxLogoff)
204 {
205 Log(("VBoxGINA::WlxNegotiate: failed resolving WlxLogoff\n"));
206 return FALSE;
207 }
208 GWlxShutdown = (PGWLXSHUTDOWN)GetProcAddress(hDll, "WlxShutdown");
209 if (!GWlxShutdown)
210 {
211 Log(("VBoxGINA::WlxNegotiate: failed resolving WlxShutdown\n"));
212 return FALSE;
213 }
214 /* GINA 1.1, optional */
215 GWlxStartApplication = (PGWLXSTARTAPPLICATION)GetProcAddress(hDll, "WlxStartApplication");
216 GWlxScreenSaverNotify = (PGWLXSCREENSAVERNOTIFY)GetProcAddress(hDll, "WlxScreenSaverNotify");
217 /* GINA 1.3, optional */
218 GWlxNetworkProviderLoad = (PGWLXNETWORKPROVIDERLOAD)GetProcAddress( hDll, "WlxNetworkProviderLoad");
219 GWlxDisplayStatusMessage = (PGWLXDISPLAYSTATUSMESSAGE)GetProcAddress( hDll, "WlxDisplayStatusMessage");
220 GWlxGetStatusMessage = (PGWLXGETSTATUSMESSAGE)GetProcAddress( hDll, "WlxGetStatusMessage");
221 GWlxRemoveStatusMessage = (PGWLXREMOVESTATUSMESSAGE)GetProcAddress( hDll, "WlxRemoveStatusMessage");
222 /* GINA 1.4, optional */
223 GWlxGetConsoleSwitchCredentials =
224 (PGWLXGETCONSOLESWITCHCREDENTIALS)GetProcAddress(hDll, "WlxGetConsoleSwitchCredentials");
225 GWlxReconnectNotify = (PGWLXRECONNECTNOTIFY)GetProcAddress(hDll, "WlxReconnectNotify");
226 GWlxDisconnectNotify = (PGWLXDISCONNECTNOTIFY)GetProcAddress(hDll, "WlxDisconnectNotify");
227 Log(("VBoxGINA::WlxNegotiate: optional function pointers:\n"
228 " WlxStartApplication: %p\n"
229 " WlxScreenSaverNotify: %p\n"
230 " WlxNetworkProviderLoad: %p\n"
231 " WlxDisplayStatusMessage: %p\n"
232 " WlxGetStatusMessage: %p\n"
233 " WlxRemoveStatusMessage: %p\n"
234 " WlxGetConsoleSwitchCredentials: %p\n"
235 " WlxReconnectNotify: %p\n"
236 " WlxDisconnectNotify: %p\n",
237 GWlxStartApplication, GWlxScreenSaverNotify, GWlxNetworkProviderLoad,
238 GWlxDisplayStatusMessage, GWlxGetStatusMessage, GWlxRemoveStatusMessage,
239 GWlxGetConsoleSwitchCredentials, GWlxReconnectNotify, GWlxDisconnectNotify));
240
241 wlxVersion = dwWinlogonVersion;
242
243 /* forward call */
244 return GWlxNegotiate(dwWinlogonVersion, pdwDllVersion);
245}
246
247
248BOOL WINAPI WlxInitialize(LPWSTR lpWinsta, HANDLE hWlx, PVOID pvReserved,
249 PVOID pWinlogonFunctions, PVOID *pWlxContext)
250{
251 Log(("VBoxGINA::WlxInitialize\n"));
252
253 /* store Winlogon function table */
254 pWlxFuncs = (PWLX_DISPATCH_VERSION_1_1)pWinlogonFunctions;
255
256 /* store handle to Winlogon service*/
257 hGinaWlx = hWlx;
258
259 /* hook the dialogs */
260 hookDialogBoxes(pWlxFuncs, wlxVersion);
261
262 /* forward call */
263 return GWlxInitialize(lpWinsta, hWlx, pvReserved, pWinlogonFunctions, pWlxContext);
264}
265
266
267VOID WINAPI WlxDisplaySASNotice(PVOID pWlxContext)
268{
269 Log(("VBoxGINA::WlxDisplaySASNotice\n"));
270
271 /* check if there are credentials for us, if so simulate C-A-D */
272 if (credentialsAvailable())
273 {
274 Log(("VBoxGINA::WlxDisplaySASNotice: simulating C-A-D\n"));
275 /* automatic C-A-D */
276 pWlxFuncs->WlxSasNotify(hGinaWlx, WLX_SAS_TYPE_CTRL_ALT_DEL);
277 }
278 else
279 {
280 Log(("VBoxGINA::WlxDisplaySASNotice: starting credentials poller\n"));
281 /* start the credentials poller thread */
282 credentialsPollerCreate();
283 /* Forward call to MSGINA. */
284 GWlxDisplaySASNotice(pWlxContext);
285 }
286}
287
288
289int WINAPI WlxLoggedOutSAS(PVOID pWlxContext, DWORD dwSasType, PLUID pAuthenticationId,
290 PSID pLogonSid, PDWORD pdwOptions, PHANDLE phToken,
291 PWLX_MPR_NOTIFY_INFO pMprNotifyInfo, PVOID *pProfile)
292{
293 Log(("VBoxGINA::WlxLoggedOutSAS\n"));
294
295 /* when performing a direct logon without C-A-D, our poller might not be running */
296 if (!credentialsAvailable())
297 credentialsPollerCreate();
298
299 int iRet;
300 iRet = GWlxLoggedOutSAS(pWlxContext, dwSasType, pAuthenticationId, pLogonSid,
301 pdwOptions, phToken, pMprNotifyInfo, pProfile);
302
303 if (iRet == WLX_SAS_ACTION_LOGON)
304 {
305 //
306 // copy pMprNotifyInfo and pLogonSid for later use
307 //
308
309 // pMprNotifyInfo->pszUserName
310 // pMprNotifyInfo->pszDomain
311 // pMprNotifyInfo->pszPassword
312 // pMprNotifyInfo->pszOldPassword
313 }
314
315 return iRet;
316}
317
318
319BOOL WINAPI WlxActivateUserShell(PVOID pWlxContext, PWSTR pszDesktopName,
320 PWSTR pszMprLogonScript, PVOID pEnvironment)
321{
322 Log(("VBoxGINA::WlxActivateUserShell\n"));
323
324 /* Forward call to MSGINA. */
325 return GWlxActivateUserShell(pWlxContext, pszDesktopName, pszMprLogonScript, pEnvironment);
326}
327
328
329int WINAPI WlxLoggedOnSAS(PVOID pWlxContext, DWORD dwSasType, PVOID pReserved)
330{
331 Log(("VBoxGINA::WlxLoggedOnSAS: SaSType = %ld\n", dwSasType));
332
333 /*
334 * We don't want to do anything special here since the OS should behave
335 * as VBoxGINA wouldn't have been installed. So pass all calls down
336 * to the original MSGINA.
337 */
338
339 /* Forward call to MSGINA. */
340 Log(("VBoxGINA::WlxLoggedOnSAS: Forwarding call to MSGINA ...\n"));
341 return GWlxLoggedOnSAS(pWlxContext, dwSasType, pReserved);
342}
343
344VOID WINAPI WlxDisplayLockedNotice(PVOID pWlxContext)
345{
346 Log(("VBoxGINA::WlxDisplayLockedNotice\n"));
347
348 /* check if there are credentials for us, if so simulate C-A-D */
349 if (credentialsAvailable())
350 {
351 Log(("VBoxGINA::WlxDisplayLockedNotice: simulating C-A-D\n"));
352 /* automatic C-A-D */
353 pWlxFuncs->WlxSasNotify(hGinaWlx, WLX_SAS_TYPE_CTRL_ALT_DEL);
354 }
355 else
356 {
357 Log(("VBoxGINA::WlxDisplayLockedNotice: starting credentials poller\n"));
358 /* start the credentials poller thread */
359 credentialsPollerCreate();
360 /* Forward call to MSGINA. */
361 GWlxDisplayLockedNotice(pWlxContext);
362 }
363}
364
365
366BOOL WINAPI WlxIsLockOk(PVOID pWlxContext)
367{
368 Log(("VBoxGINA::WlxIsLockOk\n"));
369 /* Forward call to MSGINA. */
370 return GWlxIsLockOk(pWlxContext);
371}
372
373int WINAPI WlxWkstaLockedSAS(PVOID pWlxContext, DWORD dwSasType)
374{
375 Log(("VBoxGINA::WlxWkstaLockedSAS\n"));
376
377 /* when performing a direct logon without C-A-D, our poller might not be running */
378 if (!credentialsAvailable())
379 credentialsPollerCreate();
380
381 /* Forward call to MSGINA. */
382 return GWlxWkstaLockedSAS(pWlxContext, dwSasType);
383}
384
385BOOL WINAPI WlxIsLogoffOk(PVOID pWlxContext)
386{
387 BOOL bSuccess;
388
389 Log(("VBoxGINA::WlxIsLogoffOk\n"));
390
391 bSuccess = GWlxIsLogoffOk(pWlxContext);
392
393 if (bSuccess)
394 {
395 //
396 // if it's ok to logoff, finish with the stored credentials
397 // and scrub the buffers
398 //
399 credentialsReset();
400
401 }
402 return bSuccess;
403}
404
405
406VOID WINAPI WlxLogoff(PVOID pWlxContext)
407{
408 Log(("VBoxGINA::WlxLogoff\n"));
409
410 /* Forward call to MSGINA. */
411 GWlxLogoff(pWlxContext);
412}
413
414
415VOID WINAPI WlxShutdown(PVOID pWlxContext, DWORD ShutdownType)
416{
417 Log(("VBoxGINA::WlxShutdown\n"));
418
419 /* Forward call to MSGINA. */
420 GWlxShutdown(pWlxContext, ShutdownType);
421}
422
423
424/*
425 * GINA 1.1 entry points
426 */
427BOOL WINAPI WlxScreenSaverNotify(PVOID pWlxContext, BOOL *pSecure)
428{
429 Log(("VBoxGINA::WlxScreenSaverNotify\n"));
430
431 /* Forward to MSGINA if present. */
432 if (GWlxScreenSaverNotify)
433 return GWlxScreenSaverNotify(pWlxContext, pSecure);
434 /* return something intelligent */
435 *pSecure = TRUE;
436 return TRUE;
437}
438
439
440BOOL WINAPI WlxStartApplication(PVOID pWlxContext, PWSTR pszDesktopName,
441 PVOID pEnvironment, PWSTR pszCmdLine)
442{
443 Log(("VBoxGINA::WlxStartApplication: pWlxCtx=%p, pszDesktopName=%ls, pEnvironment=%p, pszCmdLine=%ls\n",
444 pWlxContext, pszDesktopName, pEnvironment, pszCmdLine));
445
446 /* Forward to MSGINA if present. */
447 if (GWlxStartApplication)
448 return GWlxStartApplication(pWlxContext, pszDesktopName, pEnvironment, pszCmdLine);
449 return FALSE;
450}
451
452
453/*
454 * GINA 1.3 entry points
455 */
456BOOL WINAPI WlxNetworkProviderLoad(PVOID pWlxContext, PWLX_MPR_NOTIFY_INFO pNprNotifyInfo)
457{
458 Log(("VBoxGINA::WlxNetworkProviderLoad\n"));
459
460 /* Forward to MSGINA if present. */
461 if (GWlxNetworkProviderLoad)
462 return GWlxNetworkProviderLoad(pWlxContext, pNprNotifyInfo);
463 return FALSE;
464}
465
466
467BOOL WINAPI WlxDisplayStatusMessage(PVOID pWlxContext, HDESK hDesktop, DWORD dwOptions,
468 PWSTR pTitle, PWSTR pMessage)
469{
470 Log(("VBoxGINA::WlxDisplayStatusMessage\n"));
471
472 /* Forward to MSGINA if present. */
473 if (GWlxDisplayStatusMessage)
474 return GWlxDisplayStatusMessage(pWlxContext, hDesktop, dwOptions, pTitle, pMessage);
475 return FALSE;
476}
477
478
479BOOL WINAPI WlxGetStatusMessage(PVOID pWlxContext, DWORD *pdwOptions,
480 PWSTR pMessage, DWORD dwBufferSize)
481{
482 Log(("VBoxGINA::WlxGetStatusMessage\n"));
483
484 /* Forward to MSGINA if present. */
485 if (GWlxGetStatusMessage)
486 return GWlxGetStatusMessage(pWlxContext, pdwOptions, pMessage, dwBufferSize);
487 return FALSE;
488}
489
490
491BOOL WINAPI WlxRemoveStatusMessage(PVOID pWlxContext)
492{
493 Log(("VBoxGINA::WlxRemoveStatusMessage\n"));
494
495 /* Forward to MSGINA if present. */
496 if (GWlxRemoveStatusMessage)
497 return GWlxRemoveStatusMessage(pWlxContext);
498 return FALSE;
499}
500
501
502/*
503 * GINA 1.4 entry points
504 */
505BOOL WINAPI WlxGetConsoleSwitchCredentials(PVOID pWlxContext,PVOID pCredInfo)
506{
507 Log(("VBoxGINA::WlxGetConsoleSwitchCredentials\n"));
508
509 /* forward call to MSGINA if present */
510 if (GWlxGetConsoleSwitchCredentials)
511 return GWlxGetConsoleSwitchCredentials(pWlxContext,pCredInfo);
512 return FALSE;
513}
514
515
516VOID WINAPI WlxReconnectNotify(PVOID pWlxContext)
517{
518 Log(("VBoxGINA::WlxReconnectNotify\n"));
519
520 /* Forward to MSGINA if present. */
521 if (GWlxReconnectNotify)
522 GWlxReconnectNotify(pWlxContext);
523}
524
525
526VOID WINAPI WlxDisconnectNotify(PVOID pWlxContext)
527{
528 Log(("VBoxGINA::WlxDisconnectNotify\n"));
529
530 /* Forward to MSGINA if present. */
531 if (GWlxDisconnectNotify)
532 GWlxDisconnectNotify(pWlxContext);
533}
534
Note: See TracBrowser for help on using the repository browser.

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