You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

VNCServerService.cxx 5.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
  2. *
  3. * This is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation; either version 2 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This software is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this software; if not, write to the Free Software
  15. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  16. * USA.
  17. */
  18. // -=- WinVNC Version 4.0 Service-Mode implementation
  19. #include <winvnc/VNCServerService.h>
  20. #include <rfb_win32/OSVersion.h>
  21. #include <rfb_win32/TsSessions.h>
  22. #include <rfb_win32/ModuleFileName.h>
  23. #include <wtsapi32.h>
  24. #include <tlhelp32.h>
  25. using namespace winvnc;
  26. using namespace rfb;
  27. using namespace win32;
  28. const TCHAR* winvnc::VNCServerService::Name = _T("WinVNC4");
  29. VNCServerService::VNCServerService()
  30. : Service(Name)
  31. , SendSas(_T("sas.dll"), "SendSAS")
  32. , stopServiceEvent(CreateEvent(0, FALSE, FALSE, 0))
  33. , sessionEvent(CreateEvent(0, FALSE, FALSE, "Global\\SessionEventTigerVNC"))
  34. , sessionEventCad(CreateEvent(0, FALSE, FALSE, "Global\\SessionEventTigerVNCCad")) {
  35. // - Set the service-mode logging defaults
  36. // These will be overridden by the Log option in the
  37. // registry, if present.
  38. if (osVersion.isPlatformNT)
  39. logParams.setParam("*:EventLog:0,Connections:EventLog:100");
  40. else
  41. logParams.setParam("*:file:0,Connections:file:100");
  42. }
  43. //////////////////////////////////////////////////////////////////////////////
  44. DWORD GetLogonPid(DWORD dwSessionId)
  45. {
  46. DWORD dwLogonPid = 0;
  47. HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  48. if (hSnap != INVALID_HANDLE_VALUE)
  49. {
  50. PROCESSENTRY32 procEntry;
  51. procEntry.dwSize = sizeof procEntry;
  52. if (Process32First(hSnap, &procEntry)) do
  53. {
  54. DWORD dwLogonSessionId = 0;
  55. if (_stricmp(procEntry.szExeFile, "winlogon.exe") == 0 &&
  56. ProcessIdToSessionId(procEntry.th32ProcessID, &dwLogonSessionId) &&
  57. dwLogonSessionId == dwSessionId)
  58. {
  59. dwLogonPid = procEntry.th32ProcessID;
  60. break;
  61. }
  62. } while (Process32Next(hSnap, &procEntry));
  63. CloseHandle(hSnap);
  64. }
  65. return dwLogonPid;
  66. }
  67. //////////////////////////////////////////////////////////////////////////////
  68. BOOL GetSessionUserTokenWin(OUT LPHANDLE lphUserToken)
  69. {
  70. BOOL bResult = FALSE;
  71. ConsoleSessionId ID_session;
  72. DWORD Id = GetLogonPid(ID_session.id);
  73. if (HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, Id))
  74. {
  75. bResult = OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, lphUserToken);
  76. CloseHandle(hProcess);
  77. }
  78. return bResult;
  79. }
  80. //////////////////////////////////////////////////////////////////////////////
  81. // START the app as system
  82. HANDLE LaunchProcessWin(DWORD dwSessionId)
  83. {
  84. HANDLE hProcess = NULL;
  85. HANDLE hToken = NULL;
  86. if (GetSessionUserTokenWin(&hToken))
  87. {
  88. ModuleFileName filename;
  89. static const char cmdLineFmt[] = "\"%s\" -noconsole -service_run";
  90. TCharArray cmdLine(_tcslen(filename.buf) + sizeof(cmdLineFmt)/sizeof(cmdLineFmt[0]));
  91. _stprintf(cmdLine.buf, cmdLineFmt, filename.buf);
  92. STARTUPINFO si;
  93. ZeroMemory(&si, sizeof si);
  94. si.cb = sizeof si;
  95. si.dwFlags = STARTF_USESHOWWINDOW;
  96. PROCESS_INFORMATION pi;
  97. if (CreateProcessAsUser(hToken, NULL, cmdLine.buf, NULL, NULL, FALSE, DETACHED_PROCESS, NULL, NULL, &si, &pi))
  98. {
  99. CloseHandle(pi.hThread);
  100. hProcess = pi.hProcess;
  101. }
  102. CloseHandle(hToken);
  103. }
  104. return hProcess;
  105. }
  106. DWORD VNCServerService::serviceMain(int argc, TCHAR* argv[])
  107. {
  108. ConsoleSessionId OlddwSessionId;
  109. HANDLE hProcess = NULL;
  110. //We use this event to notify the program that the session has changed
  111. //The program need to end so the service can restart the program in the correct session
  112. //wait_for_existing_process();
  113. HANDLE testevent[2] = { stopServiceEvent, sessionEventCad };
  114. setStatus(SERVICE_RUNNING);
  115. while (status.dwCurrentState == SERVICE_RUNNING)
  116. {
  117. DWORD dwEvent = WaitForMultipleObjects(2, testevent, FALSE, 1000);
  118. switch (dwEvent)
  119. {
  120. //stopServiceEvent, exit while loop
  121. case WAIT_OBJECT_0 + 0:
  122. setStatus(SERVICE_STOP_PENDING);
  123. break;
  124. //cad request
  125. case WAIT_OBJECT_0 + 1:
  126. if (SendSas.isValid())
  127. (*SendSas)(FALSE);
  128. break;
  129. case WAIT_TIMEOUT:
  130. {
  131. ConsoleSessionId dwSessionId;
  132. if (OlddwSessionId.id != dwSessionId.id)
  133. {
  134. OlddwSessionId.id = dwSessionId.id;
  135. SetEvent(sessionEvent);
  136. }
  137. DWORD dwExitCode = 0;
  138. if (hProcess == NULL ||
  139. (GetExitCodeProcess(hProcess, &dwExitCode) &&
  140. dwExitCode != STILL_ACTIVE &&
  141. CloseHandle(hProcess)))
  142. {
  143. hProcess = LaunchProcessWin(dwSessionId.id);
  144. }
  145. }
  146. break;
  147. }
  148. }
  149. SetEvent(sessionEvent);
  150. if (hProcess)
  151. {
  152. WaitForSingleObject(hProcess, 15000);
  153. CloseHandle(hProcess);
  154. }
  155. return 0;
  156. }
  157. void VNCServerService::stop() {
  158. SetEvent(stopServiceEvent);
  159. SetEvent(sessionEvent);
  160. }