vncservice.cpp
21.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
// Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
// Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
//
// This file is part of the VNC system.
//
// The VNC system is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
//
// If the source code for the VNC system is not available from the place
// whence you received this file, check http://www.uk.research.att.com/vnc or contact
// the authors on vnc@uk.research.att.com for information on obtaining it.
// vncService
// Implementation of service-oriented functionality of WinVNC
#include "stdhdrs.h"
// Header
#include "vncService.h"
#include <lmcons.h>
#include "omnithread.h"
#include "WinVNC.h"
#include "vncMenu.h"
#include "localization.h" // Act : add localization on messages
// Error message logging
void LogErrorMsg(char *message);
BOOL serviceshutdown;
// OS-SPECIFIC ROUTINES
// Create an instance of the vncService class to cause the static fields to be
// initialised properly
vncService init;
DWORD g_platform_id;
BOOL g_impersonating_user = 0;
DWORD g_version_major;
DWORD g_version_minor;
DWORD g_Session_Status;
BOOL g_Fus;
vncService::vncService()
{
OSVERSIONINFO osversioninfo;
osversioninfo.dwOSVersionInfoSize = sizeof(osversioninfo);
// Get the current OS version
if (!GetVersionEx(&osversioninfo))
g_platform_id = 0;
g_platform_id = osversioninfo.dwPlatformId;
g_version_major = osversioninfo.dwMajorVersion;
g_version_minor = osversioninfo.dwMinorVersion;
serviceshutdown=false;
g_Session_Status=0;
g_Fus=0;
}
// CurrentUser - fills a buffer with the name of the current user!
BOOL
GetCurrentUser(char *buffer, UINT size) // RealVNC 336 change
{ // How to obtain the name of the current user depends upon the OS being used
if ((g_platform_id == VER_PLATFORM_WIN32_NT) && vncService::RunningAsService())
{
// Windows NT, service-mode
// -=- FIRSTLY - verify that a user is logged on
// Get the current Window station
HWINSTA station = GetProcessWindowStation();
if (station == NULL)
return FALSE;
// Get the current user SID size
DWORD usersize;
GetUserObjectInformation(station,
UOI_USER_SID, NULL, 0, &usersize);
DWORD dwErrorCode = GetLastError();
SetLastError(0);
// Check the required buffer size isn't zero
if (usersize == 0)
{
// No user is logged in - ensure we're not impersonating anyone
RevertToSelf();
g_impersonating_user = FALSE;
// Return "" as the name...
if (strlen("") >= size)
return FALSE;
strcpy(buffer, "");
return TRUE;
}
// -=- SECONDLY - a user is logged on but if we're not impersonating
// them then we can't continue!
if (!g_impersonating_user) {
// Return "" as the name...
if (strlen("") >= size)
return FALSE;
strcpy(buffer, "");
return TRUE;
}
}
// -=- When we reach here, we're either running under Win9x, or we're running
// under NT as an application or as a service impersonating a user
// Either way, we should find a suitable user name.
switch (g_platform_id)
{
case VER_PLATFORM_WIN32_WINDOWS:
case VER_PLATFORM_WIN32_NT:
{
// Just call GetCurrentUser
DWORD length = size;
if (GetUserName(buffer, &length) == 0)
{
UINT error = GetLastError();
if (error == ERROR_NOT_LOGGED_ON)
{
// No user logged on
if (strlen("") >= size)
return FALSE;
strcpy(buffer, "");
return TRUE;
}
else
{
// Genuine error...
vnclog.Print(LL_INTERR, VNCLOG("getusername error %d\n"), GetLastError());
return FALSE;
}
}
}
return TRUE;
};
// OS was not recognised!
return FALSE;
}
// RealVNC 336 change
BOOL
vncService::CurrentUser(char *buffer, UINT size)
{
BOOL result = GetCurrentUser(buffer, size);
if (result && (strcmp(buffer, "") == 0) && !vncService::RunningAsService()) {
strncpy(buffer, "Default", size);
}
return result;
}
// IsWin95 - returns a BOOL indicating whether the current OS is Win95
BOOL
vncService::IsWin95()
{
return (g_platform_id == VER_PLATFORM_WIN32_WINDOWS);
}
// IsWinNT - returns a bool indicating whether the current OS is WinNT
BOOL
vncService::IsWinNT()
{
return (g_platform_id == VER_PLATFORM_WIN32_NT);
}
// Version info
DWORD
vncService::VersionMajor()
{
return g_version_major;
}
DWORD
vncService::VersionMinor()
{
return g_version_minor;
}
// Internal routine to find the WinVNC menu class window and
// post a message to it!
BOOL
PostToWinVNC(UINT message, WPARAM wParam, LPARAM lParam)
{
// Locate the hidden WinVNC menu window
HWND hservwnd = FindWindow(MENU_CLASS_NAME, NULL);
if (hservwnd == NULL)
return FALSE;
// Post the message to WinVNC
PostMessage(hservwnd, message, wParam, lParam);
return TRUE;
}
// Static routines only used on Windows NT to ensure we're in the right desktop
// These routines are generally available to any thread at any time.
// - SelectDesktop(HDESK)
// Switches the current thread into a different desktop by deskto handle
// This call takes care of all the evil memory management involved
BOOL
vncService::SelectHDESK(HDESK new_desktop)
{
// Are we running on NT?
if (IsWinNT())
{
HDESK old_desktop = GetThreadDesktop(GetCurrentThreadId());
DWORD dummy;
char new_name[256];
if (!GetUserObjectInformation(new_desktop, UOI_NAME, &new_name, 256, &dummy)) {
return FALSE;
}
vnclog.Print(LL_INTERR, VNCLOG("SelectHDESK to %s (%x) from %x\n"), new_name, new_desktop, old_desktop);
// Switch the desktop
if(!SetThreadDesktop(new_desktop)) {
return FALSE;
}
// Switched successfully - destroy the old desktop
if (!CloseDesktop(old_desktop))
vnclog.Print(LL_INTERR, VNCLOG("SelectHDESK failed to close old desktop %x (Err=%d)\n"), old_desktop, GetLastError());
return TRUE;
}
return TRUE;
}
// - SelectDesktop(char *)
// Switches the current thread into a different desktop, by name
// Calling with a valid desktop name will place the thread in that desktop.
// Calling with a NULL name will place the thread in the current input desktop.
void
vncService::Start_new_instance()
{
vnclog.Print(LL_INTERR, VNCLOG("New Instance \n"));
// mytest();
}
BOOL
vncService::SelectDesktop(char *name)
{
// Are we running on NT?
if (IsWinNT())
{
HDESK desktop;
vnclog.Print(LL_INTERR, VNCLOG("SelectDesktop \n"));
if (name != NULL)
{
vnclog.Print(LL_INTERR, VNCLOG("OpenInputdesktop2 named\n"));
// Attempt to open the named desktop
desktop = OpenDesktop(name, 0, FALSE,
DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW |
DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL |
DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS |
DESKTOP_SWITCHDESKTOP | GENERIC_WRITE);
}
else
{
vnclog.Print(LL_INTERR, VNCLOG("OpenInputdesktop2 NULL\n"));
// No, so open the input desktop
desktop = OpenInputDesktop(0, FALSE,
DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW |
DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL |
DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS |
DESKTOP_SWITCHDESKTOP | GENERIC_WRITE);
}
if (g_Session_Status==1) {
vnclog.Print(LL_INTERR, VNCLOG("g_Session_Status 1 \n"));
// mytest();
return TRUE;
}
// Did we succeed?
if (desktop == NULL && g_Session_Status!=1) {
vnclog.Print(LL_INTERR, VNCLOG("OpenInputdesktop2 \n"));
return FALSE;
}
else vnclog.Print(LL_INTERR, VNCLOG("OpenInputdesktop2 OK\n"));
// Switch to the new desktop
if (!SelectHDESK(desktop)) {
// Failed to enter the new desktop, so free it!
if (!CloseDesktop(desktop))
vnclog.Print(LL_INTERR, VNCLOG("SelectDesktop failed to close desktop\n"));
return FALSE;
}
// We successfully switched desktops!
return TRUE;
}
return (name == NULL);
}
// Find the visible window station and switch to it
// This would allow the service to be started non-interactive
// Needs more supporting code & a redesign of the server core to
// work, with better partitioning between server & UI components.
static HWINSTA home_window_station = GetProcessWindowStation();
BOOL CALLBACK WinStationEnumProc(LPTSTR name, LPARAM param) {
HWINSTA station = OpenWindowStation(name, FALSE, GENERIC_ALL);
HWINSTA oldstation = GetProcessWindowStation();
USEROBJECTFLAGS flags;
if (!GetUserObjectInformation(station, UOI_FLAGS, &flags, sizeof(flags), NULL)) {
return TRUE;
}
BOOL visible = flags.dwFlags & WSF_VISIBLE;
if (visible) {
if (SetProcessWindowStation(station)) {
if (oldstation != home_window_station) {
CloseWindowStation(oldstation);
}
} else {
CloseWindowStation(station);
}
return FALSE;
}
return TRUE;
}
BOOL
vncService::SelectInputWinStation()
{
home_window_station = GetProcessWindowStation();
return EnumWindowStations(&WinStationEnumProc, NULL);
}
void
vncService::SelectHomeWinStation()
{
HWINSTA station=GetProcessWindowStation();
SetProcessWindowStation(home_window_station);
CloseWindowStation(station);
}
// NT only function to establish whether we're on the current input desktop
BOOL
vncService::InputDesktopSelected()
{
// Are we running on NT?
// if (serviceshutdown==true) return TRUE;
if (IsWinNT())
{
// Get the input and thread desktops
HDESK threaddesktop = GetThreadDesktop(GetCurrentThreadId());
HDESK inputdesktop = OpenInputDesktop(0, FALSE,
DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW |
DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL |
DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS |
DESKTOP_SWITCHDESKTOP | GENERIC_WRITE);
// Get the desktop names:
// *** I think this is horribly inefficient but I'm not sure.
if (inputdesktop == NULL)
{
DWORD lasterror;
lasterror=GetLastError();
vnclog.Print(LL_INTERR, VNCLOG("OpenInputDesktop I\n"));
if (lasterror==170) return TRUE;
vnclog.Print(LL_INTERR, VNCLOG("OpenInputDesktop II\n"));
return FALSE;
}
DWORD dummy;
char threadname[256];
char inputname[256];
if (!GetUserObjectInformation(threaddesktop, UOI_NAME, &threadname, 256, &dummy)) {
if (!CloseDesktop(inputdesktop))
vnclog.Print(LL_INTWARN, VNCLOG("failed to close input desktop\n"));
return FALSE;
}
_ASSERT(dummy <= 256);
if (!GetUserObjectInformation(inputdesktop, UOI_NAME, &inputname, 256, &dummy)) {
if (!CloseDesktop(inputdesktop))
vnclog.Print(LL_INTWARN, VNCLOG("failed to close input desktop\n"));
return FALSE;
}
_ASSERT(dummy <= 256);
if (!CloseDesktop(inputdesktop))
vnclog.Print(LL_INTWARN, VNCLOG("failed to close input desktop\n"));
if (strcmp(threadname, inputname) != 0)
return FALSE;
}
return TRUE;
}
// Static routine used to fool Winlogon into thinking CtrlAltDel was pressed
void *
SimulateCtrlAltDelThreadFn(void *context)
{
HDESK old_desktop = GetThreadDesktop(GetCurrentThreadId());
// Switch into the Winlogon desktop
if (!vncService::SelectDesktop("Winlogon"))
{
vnclog.Print(LL_INTERR, VNCLOG("failed to select logon desktop\n"));
return FALSE;
}
vnclog.Print(LL_ALL, VNCLOG("generating ctrl-alt-del\n"));
// Fake a hotkey event to any windows we find there.... :(
// Winlogon uses hotkeys to trap Ctrl-Alt-Del...
PostMessage(HWND_BROADCAST, WM_HOTKEY, 0, MAKELONG(MOD_ALT | MOD_CONTROL, VK_DELETE));
// Switch back to our original desktop
if (old_desktop != NULL)
vncService::SelectHDESK(old_desktop);
return NULL;
}
// Static routine to simulate Ctrl-Alt-Del locally
BOOL
vncService::SimulateCtrlAltDel()
{
vnclog.Print(LL_ALL, VNCLOG("preparing to generate ctrl-alt-del\n"));
// Are we running on NT?
if (IsWinNT())
{
vnclog.Print(LL_ALL, VNCLOG("spawn ctrl-alt-del thread...\n"));
// *** This is an unpleasant hack. Oh dear.
// I simulate CtrAltDel by posting a WM_HOTKEY message to all
// the windows on the Winlogon desktop.
// This requires that the current thread is part of the Winlogon desktop.
// But the current thread has hooks set & a window open, so it can't
// switch desktops, so I instead spawn a new thread & let that do the work...
omni_thread *thread = omni_thread::create(SimulateCtrlAltDelThreadFn);
if (thread == NULL)
return FALSE;
thread->join(NULL);
return TRUE;
}
return TRUE;
}
// Static routine to lock a 2K or above workstation
BOOL
vncService::LockWorkstation()
{
if (!IsWinNT()) {
vnclog.Print(LL_INTERR, VNCLOG("unable to lock workstation - not NT\n"));
return FALSE;
}
vnclog.Print(LL_ALL, VNCLOG("locking workstation\n"));
// Load the user32 library
HMODULE user32 = LoadLibrary("user32.dll");
if (!user32) {
vnclog.Print(LL_INTERR, VNCLOG("unable to load User32 DLL (%u)\n"), GetLastError());
return FALSE;
}
// Get the LockWorkstation function
typedef BOOL (*LWProc) ();
LWProc lockworkstation = (LWProc)GetProcAddress(user32, "LockWorkStation");
if (!lockworkstation) {
vnclog.Print(LL_INTERR, VNCLOG("unable to locate LockWorkStation - requires Windows 2000 or above (%u)\n"), GetLastError());
FreeLibrary(user32);
return FALSE;
}
// Attempt to lock the workstation
BOOL result = (lockworkstation)();
if (!result) {
vnclog.Print(LL_INTERR, VNCLOG("call to LockWorkstation failed\n"));
FreeLibrary(user32);
return FALSE;
}
FreeLibrary(user32);
return result;
}
// Static routine to show the Properties dialog for a currently-running
// copy of WinVNC, (usually a servicified version.)
BOOL
vncService::ShowProperties()
{
// Post to the WinVNC menu window
if (!PostToWinVNC(MENU_PROPERTIES_SHOW, 0, 0))
{
#ifndef SINGLECLICKULTRA
MessageBox(NULL, sz_ID_NO_EXIST_INST, szAppName, MB_ICONEXCLAMATION | MB_OK);
#else
//MessageBox(NULL, sz_ID_NO_EXIST_INST, szAppName, MB_ICONEXCLAMATION | MB_OK);
#endif
return FALSE;
}
return TRUE;
}
// Static routine to show the Default Properties dialog for a currently-running
// copy of WinVNC, (usually a servicified version.)
BOOL
vncService::ShowDefaultProperties()
{
// Post to the WinVNC menu window
if (!PostToWinVNC(MENU_DEFAULT_PROPERTIES_SHOW, 0, 0))
{
MessageBox(NULL, sz_ID_NO_EXIST_INST, szAppName, MB_ICONEXCLAMATION | MB_OK);
return FALSE;
}
return TRUE;
}
// Static routine to show the About dialog for a currently-running
// copy of WinVNC, (usually a servicified version.)
BOOL
vncService::ShowAboutBox()
{
// Post to the WinVNC menu window
if (!PostToWinVNC(MENU_ABOUTBOX_SHOW, 0, 0))
{
MessageBox(NULL, sz_ID_NO_EXIST_INST, szAppName, MB_ICONEXCLAMATION | MB_OK);
return FALSE;
}
return TRUE;
}
// Static routine to tell a locally-running instance of the server
// to connect out to a new client
BOOL
vncService::PostAddNewClient(unsigned long ipaddress, unsigned short port)
{
// Post to the WinVNC menu window
if (!PostToWinVNC(MENU_ADD_CLIENT_MSG, (WPARAM)port, (LPARAM)ipaddress))
{
#ifndef SINGLECLICKULTRA
MessageBox(NULL, sz_ID_NO_EXIST_INST, szAppName, MB_ICONEXCLAMATION | MB_OK);
#else
//MessageBox(NULL, sz_ID_NO_EXIST_INST, szAppName, MB_ICONEXCLAMATION | MB_OK);
#endif
return FALSE;
}
return TRUE;
}
// SERVICE-MODE ROUTINES
// Service-mode defines:
// Executable name
#define VNCAPPNAME "winvnc"
// Internal service name
#define VNCSERVICENAME "winvnc"
// Displayed service name
#define VNCSERVICEDISPLAYNAME "VNC Server"
// List of other required services ("dependency 1\0dependency 2\0\0")
// *** These need filling in properly
#define VNCDEPENDENCIES ""
// Internal service state
SERVICE_STATUS g_srvstatus; // current status of the service
SERVICE_STATUS_HANDLE g_hstatus;
DWORD g_error = 0;
DWORD g_servicethread = NULL;
char* g_errortext[256];
// Forward defines of internal service functions
//void WINAPI ServiceMain(DWORD argc, char **argv);
//void ServiceWorkThread(void *arg);
void ServiceStop();
void WINAPI ServiceCtrl(DWORD ctrlcode);
bool WINAPI CtrlHandler (DWORD ctrltype);
BOOL ReportStatus(DWORD state, DWORD exitcode, DWORD waithint);
// ROUTINE TO QUERY WHETHER THIS PROCESS IS RUNNING AS A SERVICE OR NOT
BOOL g_servicemode = FALSE;
BOOL
vncService::RunningAsService()
{
return g_servicemode;
}
BOOL
vncService::KillRunningCopy()
{
// Locate the hidden WinVNC menu window
HWND hservwnd;
while ((hservwnd = FindWindow(MENU_CLASS_NAME, NULL)) != NULL)
{
// Post the message to WinVNC
PostMessage(hservwnd, WM_CLOSE, 0, 0);
omni_thread::sleep(1);
}
return TRUE;
}
// ROUTINE TO POST THE HANDLE OF THE CURRENT USER TO THE RUNNING WINVNC, IN ORDER
// THAT IT CAN LOAD THE APPROPRIATE SETTINGS. THIS IS USED ONLY BY THE SVCHELPER
// OPTION, WHEN RUNNING UNDER NT
BOOL
vncService::PostUserHelperMessage()
{
// - Check the platform type
if (!IsWinNT())
return TRUE;
// - Get the current process ID
DWORD processId = GetCurrentProcessId();
// - Post it to the existing WinVNC
// RealVNC 336 change
// if (!PostToWinVNC(MENU_SERVICEHELPER_MSG, 0, (LPARAM)processId))
// return FALSE;
int retries = 6;
while (!PostToWinVNC(MENU_SERVICEHELPER_MSG, 0, (LPARAM)processId) && retries--)
omni_thread::sleep(10);
// - Wait until it's been used
omni_thread::sleep(5);
return retries;
}
// ROUTINE TO PROCESS AN INCOMING INSTANCE OF THE ABOVE MESSAGE
BOOL
vncService::ProcessUserHelperMessage(WPARAM wParam, LPARAM lParam) {
// - Check the platform type
if (!IsWinNT() || !vncService::RunningAsService())
return TRUE;
// - Close the HKEY_CURRENT_USER key, to force NT to reload it for the new user
// NB: Note that this is _really_ dodgy if ANY other thread is accessing the key!
if (RegCloseKey(HKEY_CURRENT_USER) != ERROR_SUCCESS) {
vnclog.Print(LL_INTERR, VNCLOG("failed to close current registry hive\n"));
return FALSE;
}
// - Revert to our own identity
RevertToSelf();
g_impersonating_user = FALSE;
// Modif Jeremy C.
if (lParam!=0) // Normal case
{ // if lParam is zero then we are just re-setting the impersonation
*((PHANDLE)wParam)=NULL;
// - Open the specified process
HANDLE processHandle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, (DWORD)lParam);
if (processHandle == NULL) {
vnclog.Print(LL_INTERR, VNCLOG("failed to open specified process(%d)\n"), GetLastError());
return FALSE;
}
// - Get the token for the given process
if (!OpenProcessToken(processHandle, TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE, (PHANDLE)wParam)) {
vnclog.Print(LL_INTERR, VNCLOG("failed to get user token(%d)\n"), GetLastError());
CloseHandle(processHandle);
return FALSE;
}
CloseHandle(processHandle);
}
// Modif Jeremy C. - Duplicate and store the security token to use later
HANDLE userToken = NULL;
if (!DuplicateToken(*((PHANDLE)wParam), SecurityImpersonation, &userToken))
{
vnclog.Print(LL_INTERR, VNCLOG("failed to duplicate user token(%d)\n"), GetLastError());
return FALSE;
}
// - Set this thread to impersonate them
if (!ImpersonateLoggedOnUser(userToken)) {
vnclog.Print(LL_INTERR, VNCLOG("failed to impersonate user(%d)\n"), GetLastError());
CloseHandle(userToken);
return FALSE;
}
CloseHandle(userToken);
g_impersonating_user = TRUE;
vnclog.Print(LL_INTINFO, VNCLOG("impersonating logged on user\n"));
return TRUE;
}
// Error reporting
void LogErrorMsg(char *message)
{
char msgbuff[256];
HANDLE heventsrc;
char * strings[2];
// Save the error code
g_error = GetLastError();
// Use event logging to log the error
heventsrc = RegisterEventSource(NULL, VNCSERVICENAME);
_snprintf(msgbuff, 256, "%s error: %d", VNCSERVICENAME, g_error);
strings[0] = msgbuff;
strings[1] = message;
if (heventsrc != NULL)
{
MessageBeep(MB_OK);
ReportEvent(
heventsrc, // handle of event source
EVENTLOG_ERROR_TYPE, // event type
0, // event category
0, // event ID
NULL, // current user's SID
2, // strings in 'strings'
0, // no bytes of raw data
(const char **)strings, // array of error strings
NULL); // no raw data
DeregisterEventSource(heventsrc);
}
}
BOOL
vncService::Get_Fus()
{
return g_Fus;
}
// FAST USER SWITCH TEST
void
vncService::Set_SessionStatus(DWORD status)
{
g_Session_Status=status;
}
DWORD
vncService::Get_SessionStatus()
{
return g_Session_Status;
}
void
vncService::Set_Fus(BOOL status)
{
g_Fus=status;
}