VirtualBox

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

Last change on this file since 21227 was 21227, checked in by vboxsync, 15 years ago

VBoxGuest.h/VMMDev.h/VBoxGuestLib.h usage cleanup.

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