VirtualBox

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

Last change on this file since 5999 was 5999, checked in by vboxsync, 17 years ago

The Giant CDDL Dual-License Header Change.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.1 KB
Line 
1/** @file
2 *
3 * VBoxGINA -- Windows Logon DLL for VirtualBox Helper Functions
4 *
5 * Copyright (C) 2006-2007 innotek GmbH
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 <windows.h>
17#include "winwlx.h"
18#include "Helper.h"
19#include "VBoxGINA.h"
20
21#include <VBox/VBoxGuest.h>
22#include <iprt/string.h>
23
24/* the credentials */
25wchar_t g_Username[VMMDEV_CREDENTIALS_STRLEN];
26wchar_t g_Password[VMMDEV_CREDENTIALS_STRLEN];
27wchar_t g_Domain[VMMDEV_CREDENTIALS_STRLEN];
28
29
30HANDLE getVBoxDriver(void)
31{
32 static HANDLE sVBoxDriver = INVALID_HANDLE_VALUE;
33 if (sVBoxDriver == INVALID_HANDLE_VALUE)
34 {
35 sVBoxDriver = CreateFile(L"\\\\.\\VBoxGuest", /** @todo use define */
36 GENERIC_READ | GENERIC_WRITE,
37 FILE_SHARE_READ | FILE_SHARE_WRITE,
38 NULL,
39 OPEN_EXISTING,
40 FILE_ATTRIBUTE_NORMAL,
41 NULL);
42 if (sVBoxDriver == INVALID_HANDLE_VALUE)
43 Log(("VBoxGINA::sVBoxDriver: failed to open VBoxGuest driver, last error = %d\n", GetLastError()));
44 }
45 return sVBoxDriver;
46}
47
48void credentialsReset(void)
49{
50 memset(g_Username, '\0', sizeof(g_Username));
51 memset(g_Password, '\0', sizeof(g_Password));
52 memset(g_Domain, '\0', sizeof(g_Domain));
53}
54
55bool credentialsAvailable(void)
56{
57 HANDLE vboxDriver = getVBoxDriver();
58 if (vboxDriver == INVALID_HANDLE_VALUE)
59 return false;
60
61 /* query the VMMDev whether there are credentials */
62 VMMDevCredentials vmmreqCredentials = {0};
63 vmmdevInitRequest((VMMDevRequestHeader*)&vmmreqCredentials, VMMDevReq_QueryCredentials);
64 vmmreqCredentials.u32Flags |= VMMDEV_CREDENTIALS_QUERYPRESENCE;
65 DWORD cbReturned;
66 if (!DeviceIoControl(vboxDriver, IOCTL_VBOXGUEST_VMMREQUEST, &vmmreqCredentials, sizeof(vmmreqCredentials),
67 &vmmreqCredentials, sizeof(vmmreqCredentials), &cbReturned, NULL))
68 {
69 Log(("VBoxGINA::credentialsAvailable: error doing IOCTL, last error: %d\n", GetLastError()));
70 return false;
71 }
72 bool fAvailable = ((vmmreqCredentials.u32Flags & VMMDEV_CREDENTIALS_PRESENT) != 0);
73 Log(("VBoxGINA::credentialsAvailable: fAvailable: %d\n", fAvailable));
74 return fAvailable;
75}
76
77bool credentialsRetrieve(void)
78{
79 Log(("VBoxGINA::credentialsRetrieve\n"));
80
81 HANDLE vboxDriver = getVBoxDriver();
82 if (vboxDriver == INVALID_HANDLE_VALUE)
83 return false;
84
85 /* to be safe, reset the credentials */
86 credentialsReset();
87
88 /* query the credentials */
89 VMMDevCredentials vmmreqCredentials = {0};
90 vmmdevInitRequest((VMMDevRequestHeader*)&vmmreqCredentials, VMMDevReq_QueryCredentials);
91 vmmreqCredentials.u32Flags |= VMMDEV_CREDENTIALS_READ;
92 vmmreqCredentials.u32Flags |= VMMDEV_CREDENTIALS_CLEAR;
93 DWORD cbReturned;
94 if (!DeviceIoControl(vboxDriver, IOCTL_VBOXGUEST_VMMREQUEST, &vmmreqCredentials, sizeof(vmmreqCredentials),
95 &vmmreqCredentials, sizeof(vmmreqCredentials), &cbReturned, NULL))
96 {
97 Log(("VBoxGINA::credentialsRetrieve: error doing IOCTL, last error: %d\n", GetLastError()));
98 return false;
99 }
100 /* convert from UTF-8 to UCS2 and store in global variables */
101 PRTUCS2 ptr = NULL;
102 if (VBOX_SUCCESS(RTStrUtf8ToUcs2(&ptr, vmmreqCredentials.szUserName)) && ptr)
103 {
104 wcscpy(g_Username, ptr);
105 RTStrUcs2Free(ptr);
106 }
107 ptr = NULL;
108 if (VBOX_SUCCESS(RTStrUtf8ToUcs2(&ptr, vmmreqCredentials.szPassword)) && ptr)
109 {
110 wcscpy(g_Password, ptr);
111 RTStrUcs2Free(ptr);
112 }
113 ptr = NULL;
114 if (VBOX_SUCCESS(RTStrUtf8ToUcs2(&ptr, vmmreqCredentials.szDomain)) && ptr)
115 {
116 wcscpy(g_Domain, ptr);
117 RTStrUcs2Free(ptr);
118 }
119 Log(("VBoxGINA::credentialsRetrieve: returning user '%s', password '%s', domain '%s'\n",
120 vmmreqCredentials.szUserName, vmmreqCredentials.szPassword, vmmreqCredentials.szDomain));
121 return true;
122}
123
124/* handle of the poller thread */
125RTTHREAD gThreadPoller = NIL_RTTHREAD;
126
127
128/**
129 * Poller thread. Checks periodically whether there are credentials.
130 */
131static DECLCALLBACK(int) credentialsPoller(RTTHREAD ThreadSelf, void *pvUser)
132{
133 Log(("VBoxGINA::credentialsPoller\n"));
134
135 do
136 {
137 if (credentialsAvailable())
138 {
139 Log(("VBoxGINA::credentialsPoller: got credentials, simulating C-A-D\n"));
140 /* tell WinLogon to start the attestation process */
141 pWlxFuncs->WlxSasNotify(hGinaWlx, WLX_SAS_TYPE_CTRL_ALT_DEL);
142 /* time to say goodbye */
143 return 0;
144 }
145 /* wait a bit */
146 if (RTThreadUserWait(ThreadSelf, 500) == VINF_SUCCESS)
147 {
148 Log(("VBoxGINA::credentialsPoller: we were asked to terminate\n"));
149 /* we were asked to terminate, do that instantly! */
150 return 0;
151 }
152 }
153 while (1);
154
155 return 0;
156}
157
158bool credentialsPollerCreate(void)
159{
160 Log(("VBoxGINA::credentialsPollerCreate\n"));
161
162 /* don't create more than one of them */
163 if (gThreadPoller != NIL_RTTHREAD)
164 {
165 Log(("VBoxGINA::credentialsPollerCreate: thread already running, returning!\n"));
166 return false;
167 }
168
169 /* create the poller thread */
170 int rc = RTThreadCreate(&gThreadPoller, credentialsPoller, NULL, 0, RTTHREADTYPE_INFREQUENT_POLLER,
171 RTTHREADFLAGS_WAITABLE, "creds");
172 if (VBOX_FAILURE(rc))
173 {
174 Log(("VBoxGINA::credentialsPollerCreate: failed to create thread, rc = %Vrc\n", rc));
175 return false;
176 }
177 return true;
178}
179
180bool credentialsPollerTerminate(void)
181{
182 Log(("VBoxGINA::credentialsPollerTerminate\n"));
183
184 if (gThreadPoller == NIL_RTTHREAD)
185 {
186 Log(("VBoxGINA::credentialsPollerTerminate: either thread or exit sem is NULL!\n"));
187 return false;
188 }
189 /* post termination event semaphore */
190 int rc = RTThreadUserSignal(gThreadPoller);
191 if (VBOX_SUCCESS(rc))
192 {
193 Log(("VBoxGINA::credentialsPollerTerminate: waiting for thread to terminate\n"));
194 /* wait until the thread has terminated */
195 rc = RTThreadWait(gThreadPoller, RT_INDEFINITE_WAIT, NULL);
196 Log(("VBoxGINA::credentialsPollerTermiante: thread has (probably) terminated (rc = %Vrc)\n", rc));
197 }
198 else
199 {
200 /* failed to signal the thread - very unlikely - so no point in waiting long. */
201 Log(("VBoxGINA::credentialsPollerTermiante: failed to signal semaphore, rc = %Vrc\n", rc));
202 rc = RTThreadWait(gThreadPoller, 100, NULL);
203 Log(("VBoxGINA::credentialsPollerTermiante: thread has terminated? wait rc = %Vrc\n", rc));
204 }
205 /* now cleanup */
206 gThreadPoller = NIL_RTTHREAD;
207 return true;
208}
Note: See TracBrowser for help on using the repository browser.

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