vncService.cpp
资源名称:vnc3326s.zip [点击查看]
上传用户:sbftbdw
上传日期:2007-01-03
资源大小:379k
文件大小:25k
源码类别:
远程控制编程
开发平台:
Visual C++
- // Copyright (C) 1997, 1998 Olivetti & Oracle Research Laboratory
- //
- // 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.orl.co.uk/vnc or contact
- // the authors on vnc@orl.co.uk 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 "vncTimedMsgBox.h"
- // Error message logging
- void LogErrorMsg(char *message);
- // 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;
- 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;
- }
- // CurrentUser - fills a buffer with the name of the current user!
- BOOL
- vncService::CurrentUser(char *buffer, UINT size)
- {
- // 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
- // 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);
- // Check the required buffer size isn't zero
- if (usersize == 0)
- {
- // No user is logged in, so return "" as the name...
- if (strlen("") >= size)
- return FALSE;
- strcpy(buffer, "");
- return TRUE;
- }
- // *** HACK - Use the registry to get the user name...
- {
- // Look into the winlogon registry section
- HKEY key;
- if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
- "SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon",
- 0,
- KEY_QUERY_VALUE,
- &key) != ERROR_SUCCESS)
- {
- return FALSE;
- }
- // Now retrieve the user's name...
- DWORD valuetype;
- DWORD buffersize = size;
- if (RegQueryValueEx(key, "DefaultUserName",
- NULL, &valuetype,
- (unsigned char *)buffer, &buffersize) != ERROR_SUCCESS)
- {
- RegCloseKey(key);
- return FALSE;
- }
- RegCloseKey(key);
- }
- /* *** This code gets the Logon SID, not the User SID.... :(
- _RPT1(_CRT_WARN, VNCLOG("username=%sn"), buffer);
- // Now allocate an SID and retrieve it
- PSID puser = (PSID) new BYTE[usersize];
- if (puser == NULL)
- return FALSE;
- if (!GetUserObjectInformation(station,
- UOI_USER_SID, puser, usersize, &usersize))
- {
- delete [] puser;
- return FALSE;
- }
- char sidbuffer[1024];
- ULONG bufflen=1024;
- if (GetTextualSid(puser, sidbuffer, &bufflen))
- {
- _RPT1(_CRT_WARN, VNCLOG("sid=%sn"), sidbuffer);
- }
- // We now have the SID
- SID_NAME_USE nameuse = (SID_NAME_USE) 0;
- char domainname[4096];
- DWORD userlen = size;
- DWORD domainlen = 4096;
- if (!LookupAccountSid(NULL,
- puser,
- buffer, &userlen,
- domainname, &domainlen,
- &nameuse))
- {
- _RPT2(_CRT_WARN, VNCLOG("vncService : LookupAccountSid returned %d, %dn"),
- GetLastError(), (int)nameuse);
- _RPT2(_CRT_WARN, VNCLOG("vncService : user name size = %d/%dn"),
- size, userlen);
- // Failed to get the user's name!
- delete [] puser;
- return FALSE;
- }
- _RPT1(_CRT_WARN, VNCLOG("username=%sn"), buffer);
- // We should by now have the user's name!
- delete [] puser;
- */
- return TRUE;
- }
- else
- switch (g_platform_id)
- {
- // Windows 95/98, either service or application mode.
- // WinNT, application mode.
- 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...
- log.Print(LL_INTERR, VNCLOG("getusername error %dn"), GetLastError());
- return FALSE;
- }
- }
- }
- return TRUE;
- };
- // OS was not recognised!
- return FALSE;
- }
- // 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);
- }
- // Internal routine to find the WinVNC menu class window and
- // post a message to it!
- BOOL
- PostToWinVNC(UINT message)
- {
- // 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, 0, 0);
- return TRUE;
- }
- // Static routine only used on Windows NT to ensure we're in the right desktop
- // This routine is generally available to any thread at any time.
- // 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.
- BOOL
- vncService::SelectDesktop(char *name)
- {
- // Are we running on NT?
- if (IsWinNT())
- {
- HDESK desktop;
- if (name != NULL)
- {
- // 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
- {
- // 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);
- }
- // Did we succeed?
- if (desktop == NULL)
- return FALSE;
- if (!SetThreadDesktop(desktop))
- return FALSE;
- // We successfully switched desktops!
- return TRUE;
- }
- return (name == NULL);
- }
- // NT only function to establish whether we're on the current input desktop
- BOOL
- vncService::InputDesktopSelected()
- {
- // Are we running on NT?
- if (IsWinNT())
- {
- // Retrieve a device context for the
- 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)
- return FALSE;
- DWORD dummy;
- char threadname[256];
- char inputname[256];
- if (!GetUserObjectInformation(threaddesktop, UOI_NAME, &threadname, 256, &dummy))
- return FALSE;
- _ASSERT(dummy <= 256);
- if (!GetUserObjectInformation(inputdesktop, UOI_NAME, &inputname, 256, &dummy))
- return FALSE;
- _ASSERT(dummy <= 256);
- CloseDesktop(inputdesktop);
- if (strcmp(threadname, inputname) != 0)
- return FALSE;
- }
- return TRUE;
- }
- // Static routine used to fool Winlogon into thinking CtrlAltDel was pressed
- void *
- SimulateCtrlAltDelThreadFn(void *context)
- {
- // Switch into the Winlogon desktop
- if (!vncService::SelectDesktop("Winlogon"))
- {
- log.Print(LL_INTERR, VNCLOG("failed to select logon desktopn"));
- return FALSE;
- }
- log.Print(LL_ALL, VNCLOG("generating ctrl-alt-deln"));
- // 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));
- return NULL;
- }
- // Static routine to simulate Ctrl-Alt-Del locally
- BOOL
- vncService::SimulateCtrlAltDel()
- {
- log.Print(LL_ALL, VNCLOG("preparing to generate ctrl-alt-deln"));
- // Are we running on NT?
- if (IsWinNT())
- {
- log.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 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))
- {
- MessageBox(NULL, "No existing instance of WinVNC could be contacted", 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))
- {
- MessageBox(NULL, "No existing instance of WinVNC could be contacted", szAppName, MB_ICONEXCLAMATION | MB_OK);
- 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 dependency 2 ")
- // *** 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;
- }
- // SERVICE MAIN ROUTINE
- int
- vncService::WinVNCServiceMain()
- {
- // Mark that we are a service
- g_servicemode = TRUE;
- // How to run as a service depends upon the OS being used
- switch (g_platform_id)
- {
- // Windows 95/98
- case VER_PLATFORM_WIN32_WINDOWS:
- {
- // Obtain a handle to the kernel library
- HINSTANCE kerneldll = LoadLibrary("KERNEL32.DLL");
- if (kerneldll == NULL)
- break;
- // And find the RegisterServiceProcess function
- DWORD (*RegisterService)(DWORD, DWORD);
- RegisterService = (DWORD (*)(DWORD, DWORD))
- GetProcAddress(kerneldll, "RegisterServiceProcess");
- if (RegisterService == NULL)
- break;
- // Register this process with the OS as a service!
- RegisterService(NULL, 1);
- // Run the service itself
- WinVNCAppMain();
- // Then remove the service from the system service table
- RegisterService(NULL, 0);
- // Free the kernel library
- FreeLibrary(kerneldll);
- // *** If we don't kill the process directly here, then
- // for some reason, WinVNC crashes...
- ExitProcess(0);
- }
- break;
- // Windows NT
- case VER_PLATFORM_WIN32_NT:
- {
- // Create a service entry table
- SERVICE_TABLE_ENTRY dispatchTable[] =
- {
- {VNCSERVICENAME, (LPSERVICE_MAIN_FUNCTION)ServiceMain},
- {NULL, NULL}
- };
- // Call the service control dispatcher with our entry table
- if (!StartServiceCtrlDispatcher(dispatchTable))
- LogErrorMsg("StartServiceCtrlDispatcher failed.");
- }
- break;
- };
- return 0;
- }
- // SERVICE MAIN ROUTINE
- void WINAPI ServiceMain(DWORD argc, char**argv)
- {
- // Register the service control handler
- g_hstatus = RegisterServiceCtrlHandler(VNCSERVICENAME, ServiceCtrl);
- if (g_hstatus == 0)
- return;
- // Set up some standard service state values
- g_srvstatus.dwServiceType = SERVICE_WIN32 | SERVICE_INTERACTIVE_PROCESS;
- g_srvstatus.dwServiceSpecificExitCode = 0;
- // Give this status to the SCM
- if (!ReportStatus(
- SERVICE_START_PENDING, // Service state
- NO_ERROR, // Exit code type
- 15000)) // Hint as to how long WinVNC should have hung before you assume error
- {
- ReportStatus(
- SERVICE_STOPPED,
- g_error,
- 0);
- return;
- }
- // Now start the service for real
- omni_thread *workthread = omni_thread::create(ServiceWorkThread);
- return;
- }
- // SERVICE START ROUTINE - thread that calls WinVNCAppMain
- void ServiceWorkThread(void *arg)
- {
- // Save the current thread identifier
- g_servicethread = GetCurrentThreadId();
- // report the status to the service control manager.
- //
- if (!ReportStatus(
- SERVICE_RUNNING, // service state
- NO_ERROR, // exit code
- 0)) // wait hint
- return;
- // RUN!
- WinVNCAppMain();
- // Mark that we're no longer running
- g_servicethread = NULL;
- // Tell the service manager that we've stopped.
- ReportStatus(
- SERVICE_STOPPED,
- g_error,
- 0);
- }
- // SERVICE STOP ROUTINE - post a quit message to the relevant thread
- void ServiceStop()
- {
- // Post a quit message to the main service thread
- if (g_servicethread != NULL)
- {
- PostThreadMessage(g_servicethread, WM_QUIT, 0, 0);
- }
- }
- // SERVICE INSTALL ROUTINE
- int
- vncService::InstallService()
- {
- const int pathlength = 2048;
- char path[pathlength];
- char servicecmd[pathlength];
- // Get the filename of this executable
- if (GetModuleFileName(NULL, path, pathlength-(strlen(winvncRunService)+2)) == 0)
- {
- MessageBox(NULL, "Unable to install WinVNC service", szAppName, MB_ICONEXCLAMATION | MB_OK);
- return 0;
- }
- // Append the service-start flag to the end of the path:
- if (strlen(path) + 4 + strlen(winvncRunService) < pathlength)
- sprintf(servicecmd, ""%s" %s", path, winvncRunService);
- else
- return 0;
- // How to add the WinVNC service depends upon the OS
- switch (g_platform_id)
- {
- // Windows 95/98
- case VER_PLATFORM_WIN32_WINDOWS:
- {
- // Locate the RunService registry entry
- HKEY runservices;
- if (RegCreateKey(HKEY_LOCAL_MACHINE,
- "Software\Microsoft\Windows\CurrentVersion\RunServices",
- &runservices) != ERROR_SUCCESS)
- {
- MessageBox(NULL, "The SCM could not be contacted - the WinVNC service was not installed", szAppName, MB_ICONEXCLAMATION | MB_OK);
- break;
- }
- // Attempt to add a WinVNC key
- if (RegSetValueEx(runservices, szAppName, 0, REG_SZ, (unsigned char *)servicecmd, strlen(servicecmd)+1) != ERROR_SUCCESS)
- {
- RegCloseKey(runservices);
- MessageBox(NULL, "The WinVNC service could not be installed", szAppName, MB_ICONEXCLAMATION | MB_OK);
- break;
- }
- RegCloseKey(runservices);
- // We have successfully installed the service!
- vncTimedMsgBox::Do(
- "The WinVNC service was successfully installedn"
- "The service will start now and will automaticallyn"
- "be run the next time this machine is reset",
- szAppName,
- MB_ICONINFORMATION | MB_OK);
- // Run the service...
- STARTUPINFO si;
- si.cb = sizeof(si);
- si.cbReserved2 = 0;
- si.lpReserved = NULL;
- si.lpReserved2 = NULL;
- si.dwFlags = 0;
- si.lpTitle = NULL;
- PROCESS_INFORMATION pi;
- if (!CreateProcess(
- NULL, servicecmd, // Program name & path
- NULL, NULL, // Security attributes
- FALSE, // Inherit handles?
- NORMAL_PRIORITY_CLASS, // Extra startup flags
- NULL, // Environment table
- NULL, // Current directory
- &si,
- &pi
- ))
- {
- MessageBox(NULL, "The WinVNC service failed to start", szAppName, MB_ICONSTOP | MB_OK);
- break;
- }
- }
- break;
- // Windows NT
- case VER_PLATFORM_WIN32_NT:
- {
- SC_HANDLE hservice;
- SC_HANDLE hsrvmanager;
- // Open the default, local Service Control Manager database
- hsrvmanager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
- if (hsrvmanager != NULL)
- {
- // Create an entry for the WinVNC service
- hservice = CreateService(
- hsrvmanager, // SCManager database
- VNCSERVICENAME, // name of service
- VNCSERVICEDISPLAYNAME, // name to display
- SERVICE_ALL_ACCESS, // desired access
- SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
- // service type
- SERVICE_AUTO_START, // start type
- SERVICE_ERROR_NORMAL, // error control type
- servicecmd, // service's binary
- NULL, // no load ordering group
- NULL, // no tag identifier
- VNCDEPENDENCIES, // dependencies
- NULL, // LocalSystem account
- NULL); // no password
- if (hservice != NULL)
- {
- vncTimedMsgBox::Do(
- "The WinVNC service was successfully installedn"
- "The service may be started from the Control Panel, and willn"
- "automatically be run the next time this machine is reset",
- szAppName,
- MB_ICONINFORMATION | MB_OK);
- CloseServiceHandle(hservice);
- }
- else
- {
- MessageBox(NULL,
- "The WinVNC service could not be installed",
- szAppName,
- MB_ICONEXCLAMATION | MB_OK);
- }
- CloseServiceHandle(hsrvmanager);
- }
- else
- MessageBox(NULL,
- "The SCM could not be contacted - the WinVNC service was not installed",
- szAppName,
- MB_ICONEXCLAMATION | MB_OK);
- }
- break;
- };
- return 0;
- }
- // SERVICE REMOVE ROUTINE
- int
- vncService::RemoveService()
- {
- // How to remove the WinVNC service depends upon the OS
- switch (g_platform_id)
- {
- // Windows 95/98
- case VER_PLATFORM_WIN32_WINDOWS:
- {
- // Locate the RunService registry entry
- HKEY runservices;
- if (RegOpenKey(HKEY_LOCAL_MACHINE,
- "Software\Microsoft\Windows\CurrentVersion\RunServices",
- &runservices) != ERROR_SUCCESS)
- {
- MessageBox(NULL, "The SCM could not be contacted - the WinVNC service was not removed", szAppName, MB_ICONEXCLAMATION | MB_OK);
- }
- else
- {
- // Attempt to delete the WinVNC key
- if (RegDeleteValue(runservices, szAppName) != ERROR_SUCCESS)
- {
- RegCloseKey(runservices);
- MessageBox(NULL, "The WinVNC service could not be removed", szAppName, MB_ICONEXCLAMATION | MB_OK);
- }
- RegCloseKey(runservices);
- }
- // Try to kill any running copy of WinVNC
- if (!KillRunningCopy())
- {
- MessageBox(NULL,
- "The WinVNC service could not be contacted",
- szAppName,
- MB_ICONEXCLAMATION | MB_OK);
- break;
- }
- // We have successfully removed the service!
- vncTimedMsgBox::Do("The WinVNC service has been removed", szAppName, MB_ICONINFORMATION | MB_OK);
- }
- break;
- // Windows NT
- case VER_PLATFORM_WIN32_NT:
- {
- SC_HANDLE hservice;
- SC_HANDLE hsrvmanager;
- // Open the SCM
- hsrvmanager = OpenSCManager(
- NULL, // machine (NULL == local)
- NULL, // database (NULL == default)
- SC_MANAGER_ALL_ACCESS // access required
- );
- if (hsrvmanager)
- {
- hservice = OpenService(hsrvmanager, VNCSERVICENAME, SERVICE_ALL_ACCESS);
- if (hservice != NULL)
- {
- SERVICE_STATUS status;
- // Try to stop the WinVNC service
- if (ControlService(hservice, SERVICE_CONTROL_STOP, &status))
- {
- while(QueryServiceStatus(hservice, &status))
- {
- if (status.dwCurrentState == SERVICE_STOP_PENDING)
- Sleep(1000);
- else
- break;
- }
- if (status.dwCurrentState != SERVICE_STOPPED)
- MessageBox(NULL, "The WinVNC service could not be stopped", szAppName, MB_ICONEXCLAMATION | MB_OK);
- }
- // Now remove the service from the SCM
- if(DeleteService(hservice))
- vncTimedMsgBox::Do("The WinVNC service has been removed", szAppName, MB_ICONINFORMATION | MB_OK);
- else
- MessageBox(NULL, "The WinVNC service could not be removed", szAppName, MB_ICONEXCLAMATION | MB_OK);
- CloseServiceHandle(hservice);
- }
- else
- MessageBox(NULL, "The WinVNC service could not be found", szAppName, MB_ICONEXCLAMATION | MB_OK);
- CloseServiceHandle(hsrvmanager);
- }
- else
- MessageBox(NULL, "The SCM could not be contacted - the WinVNC service was not removed", szAppName, MB_ICONEXCLAMATION | MB_OK);
- }
- break;
- };
- return 0;
- }
- // USEFUL SERVICE SUPPORT ROUTINES
- // Service control routine
- void WINAPI ServiceCtrl(DWORD ctrlcode)
- {
- // What control code have we been sent?
- switch(ctrlcode)
- {
- case SERVICE_CONTROL_STOP:
- // STOP : The service must stop
- g_srvstatus.dwCurrentState = SERVICE_STOP_PENDING;
- ServiceStop();
- break;
- case SERVICE_CONTROL_INTERROGATE:
- // QUERY : Service control manager just wants to know our state
- break;
- default:
- // Control code not recognised
- break;
- }
- // Tell the control manager what we're up to.
- ReportStatus(g_srvstatus.dwCurrentState, NO_ERROR, 0);
- }
- // Service manager status reporting
- BOOL ReportStatus(DWORD state,
- DWORD exitcode,
- DWORD waithint)
- {
- static DWORD checkpoint = 1;
- BOOL result = TRUE;
- // If we're in the start state then we don't want the control manager
- // sending us control messages because they'll confuse us.
- if (state == SERVICE_START_PENDING)
- g_srvstatus.dwControlsAccepted = 0;
- else
- g_srvstatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
- // Save the new status we've been given
- g_srvstatus.dwCurrentState = state;
- g_srvstatus.dwWin32ExitCode = exitcode;
- g_srvstatus.dwWaitHint = waithint;
- // Update the checkpoint variable to let the SCM know that we
- // haven't died if requests take a long time
- if ((state == SERVICE_RUNNING) || (state == SERVICE_STOPPED))
- g_srvstatus.dwCheckPoint = 0;
- else
- g_srvstatus.dwCheckPoint = checkpoint++;
- // Tell the SCM our new status
- if (!(result = SetServiceStatus(g_hstatus, &g_srvstatus)))
- LogErrorMsg("SetServiceStatus failed");
- return result;
- }
- // 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);
- sprintf(msgbuff, "%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);
- }
- }