VirtualBox

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

Last change on this file since 19015 was 13837, checked in by vboxsync, 16 years ago

s/%Vr\([acfs]\)/%Rr\1/g - since I'm upsetting everyone anyway, better make the most of it...

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