Changeset 71139 in vbox for trunk/src/VBox
- Timestamp:
- Feb 27, 2018 5:48:13 PM (7 years ago)
- svn:sync-xref-src-repo-rev:
- 121027
- Location:
- trunk/src/VBox/Main
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/Makefile.kmk
r70880 r71139 297 297 src-all/VirtualBoxBase.cpp \ 298 298 src-all/VirtualBoxErrorInfoImpl.cpp \ 299 src-all/VirtualBoxClientListImpl.cpp \ 299 300 src-global/VirtualBoxSDSImpl.cpp 300 301 VBoxSDS_SOURCES.win = \ … … 1201 1202 VBoxProxyStub_SDKS = VBOX_NTDLL 1202 1203 VBoxProxyStub_DEFPATH = $(VBoxCOM_0_OUTDIR)/# Hack to workaround drive letter in $(VBoxCOM_0_OUTDIR)/ for CFLAGS hack below. 1203 VBoxProxyStub_INCS = $(VBoxCOM_0_OUTDIR)/ 1204 VBoxProxyStub_INCS = $(VBoxCOM_0_OUTDIR)/ \ 1205 $(VBOX_PATH_MAIN_SRC)/include/ 1204 1206 VBoxProxyStub_SOURCES := \ 1205 1207 VirtualBox_p.c \ … … 1207 1209 $(PATH_SUB_CURRENT)/src-all/win/VBoxProxyStub.def \ 1208 1210 $(PATH_SUB_CURRENT)/src-all/win/VBoxProxyStub.rc \ 1209 $(PATH_SUB_CURRENT)/src-all/win/VBoxProxyStub.c 1211 $(PATH_SUB_CURRENT)/src-all/win/RpcChannelHook.cpp \ 1212 $(PATH_SUB_CURRENT)/src-all/win/VBoxProxyStub.c 1210 1213 src-all/win/VBoxProxyStub.rc_DEPS = $(VBoxCOM_0_OUTDIR)/VirtualBox.tlb 1211 1214 VBoxProxyStub_VirtualBox_p.c_CFLAGS.x86 = /Gz # Workaround for incorrect ObjectStublessClient* prototypes in SDK v7.1. … … 1215 1218 VBoxProxyStubLegacy_EXTENDS = VBoxProxyStub 1216 1219 VBoxProxyStubLegacy_DEFS = $(VBoxProxyStub_DEFS) VBOX_IN_PROXY_STUB_LEGACY 1217 VBoxProxyStubLegacy_INCS = $(VBoxCOM_0_OUTDIR)/legacy/ 1220 VBoxProxyStubLegacy_INCS = $(VBoxCOM_0_OUTDIR)/legacy/ \ 1221 $(VBOX_PATH_MAIN_SRC)/include/ 1218 1222 VBoxProxyStubLegacy_SOURCES = \ 1219 1223 $(VBoxCOM_0_OUTDIR)/legacy/VirtualBox_p.c \ … … 1221 1225 src-all/win/VBoxProxyStub.def \ 1222 1226 src-all/win/VBoxProxyStubLegacy.rc \ 1223 src-all/win/VBoxProxyStub.c 1227 src-all/win/RpcChannelHook.cpp \ 1228 src-all/win/VBoxProxyStub.c 1224 1229 src-all/win/VBoxProxyStubLegacy.rc_DEPS = $(VBoxCOM_0_OUTDIR)/legacy/VirtualBox.tlb 1225 1230 … … 1229 1234 VBoxProxyStub-x86_SDKS = VBOX_NTDLL 1230 1235 VBoxProxyStub-x86_DEFS = $(VBoxProxyStub_DEFS) VBOX_PROXY_STUB_32_ON_64 WIN32 1231 VBoxProxyStub-x86_INCS = $(VBoxCOM-x86_0_OUTDIR)/ 1236 VBoxProxyStub-x86_INCS = $(VBoxCOM-x86_0_OUTDIR)/ \ 1237 $(VBOX_PATH_MAIN_SRC)/include/ 1232 1238 VBoxProxyStub-x86_SOURCES = \ 1233 1239 $(VBoxCOM-x86_0_OUTDIR)/VirtualBox_p.c \ … … 1235 1241 src-all/win/VBoxProxyStub.c \ 1236 1242 src-all/win/VBoxProxyStub-x86.rc \ 1243 src-all/win/RpcChannelHook.cpp \ 1237 1244 src-all/win/VBoxProxyStub.def 1238 1245 src-all/win/VBoxProxyStub-x86.rc_DEPS = $(VBoxCOM-x86_0_OUTDIR)/VirtualBox-x86.tlb -
trunk/src/VBox/Main/idl/VirtualBox.xidl
r71108 r71139 24481 24481 </method> 24482 24482 24483 <method name="notifyClientsFinished"> 24484 <desc>Notify service that their clients finished.</desc> 24485 </method> 24486 24483 24487 </interface> 24484 24488 … … 24530 24534 </method> 24531 24535 24536 <method name="notifyClientsFinished"> 24537 <desc>Notify SDS that clients finished.</desc> 24538 </method> 24539 24532 24540 </interface> 24541 24542 <!-- 24543 // IVirtualBoxClientList 24544 ////////////////////////////////////////////////////////////////////////// 24545 --> 24546 24547 <interface 24548 name="IVirtualBoxClientList" extends="$unknown" 24549 uuid="6e7f09c9-da13-4126-9cc8-9aab81fed413" 24550 wsmap="managed" 24551 reservedMethods="2" reservedAttributes="2" 24552 > 24553 <desc> 24554 The IVirtualBoxClientList interface represents a list of VirtualBox API clients. 24555 </desc> 24556 24557 <method name="registerClient"> 24558 <desc>Register VirtualBox API Client.</desc> 24559 <param name="pid" type="long" dir="in"> 24560 <desc>Process ID of VirtualBox API client.</desc> 24561 </param> 24562 </method> 24563 24564 <attribute name="clients" readonly="yes" type="long" dir="out" safearray="yes"> 24565 <desc>List of registered VirtualBox API clients.</desc> 24566 </attribute> 24567 24568 </interface> 24533 24569 24534 24570 </if> <!-- bird: shouldn't this if-element at leat include the VBoxSDS module, if not the whole system service application? --> … … 24544 24580 --> 24545 24581 <module name="VBoxSDS" context="LocalService"> 24546 <class name="VirtualBoxSDS" uuid="74ab5ffe-8726-4435-aa7e-876d705bcba5" 24547 namespace="virtualbox.org"> 24548 <interface name="IVirtualBoxSDS" default="yes"/> 24549 </class> 24582 <class name="VirtualBoxSDS" uuid="74ab5ffe-8726-4435-aa7e-876d705bcba5" 24583 namespace="virtualbox.org"> 24584 <interface name="IVirtualBoxSDS" default="yes"/> 24585 </class> 24586 <class name="VirtualBoxClientList" uuid="b2313c29-07eb-4613-ab27-f86bda7a0cae" namespace="virtualbox.org" > 24587 <interface name="IVirtualBoxClientList" default="yes" /> 24588 </class> 24550 24589 </module> 24551 24590 -
trunk/src/VBox/Main/include/VirtualBoxSDSImpl.h
r70129 r71139 74 74 STDMETHODIMP_(HRESULT) RegisterVBoxSVC(IVBoxSVCRegistration *aVBoxSVC, LONG aPid, IUnknown **aExistingVirtualBox); 75 75 STDMETHODIMP_(HRESULT) DeregisterVBoxSVC(IVBoxSVCRegistration *aVBoxSVC, LONG aPid); 76 STDMETHODIMP_(HRESULT) NotifyClientsFinished(); 76 77 77 78 -
trunk/src/VBox/Main/src-all/win/VBoxProxyStub.c
r70240 r71139 41 41 #include <iprt/uuid.h> 42 42 #include <iprt/utf16.h> 43 #include "RpcChannelHook.h" 43 44 44 45 … … 147 148 }; 148 149 150 BOOL IsVBoxServiceProcess(void) 151 { 152 if (GetEnvironmentVariable(L"VBOX_SERVICE_PROCESS", NULL, 0) == 0) 153 { 154 int res = GetLastError(); 155 if (res != ERROR_ENVVAR_NOT_FOUND) 156 LogRel(("Error: cannot get service environment variable: %Rrwa\n", res)); 157 return false; 158 } 159 return true; 160 } 161 149 162 150 163 /** … … 171 184 RTR3InitDll(RTR3INIT_FLAGS_UNOBTRUSIVE); 172 185 Log12(("VBoxProxyStub[%u]/DllMain: DLL_PROCESS_ATTACH\n", GetCurrentProcessId())); 186 187 /* Install RPC channel hook to intercept a moment just after VirtualBox object activation. 188 It's reports to VBoxSDS that a new VirtualBox API client started. */ 189 if(!IsVBoxServiceProcess()) 190 SetupClientRpcChannelHook(); 173 191 174 192 #ifdef VBOX_STRICT … … 1346 1364 VbpsRegisterClassId(pState, &CLSID_VirtualBoxSDS, "VirtualBoxSDS Class", pszSdsAppId, "VirtualBox.VirtualBoxSDS", ".1", 1347 1365 &LIBID_VirtualBox, "LocalServer32", pwszVBoxDir, pszSdsExe, NULL /*N/A*/); 1366 1367 VbpsRegisterClassName(pState, "VirtualBox.VirtualBoxClientList.1", "VirtualBoxClientList Class", &CLSID_VirtualBoxClientList, NULL); 1368 VbpsRegisterClassName(pState, "VirtualBox.VirtualBoxClientList", "VirtualBoxClientList Class", &CLSID_VirtualBoxClientList, ".1"); 1369 VbpsRegisterClassId(pState, &CLSID_VirtualBoxClientList, "VirtualBoxClientList Class", pszSdsAppId, "VirtualBox.VirtualBoxClientList", ".1", 1370 &LIBID_VirtualBox, "LocalServer32", pwszVBoxDir, pszSdsExe, NULL /*N/A*/); 1348 1371 #endif 1349 1372 } -
trunk/src/VBox/Main/src-global/VirtualBoxSDSImpl.cpp
r70507 r71139 53 53 * This is NULL if not set. */ 54 54 ComPtr<IVBoxSVCRegistration> m_ptrTheChosenOne; 55 ComPtr<IVirtualBoxClientList> m_ptrClientList; 55 56 private: 56 57 /** Reference count to make destruction safe wrt hung callers. … … 178 179 LogRel(("VirtualBoxSDS::registerVBoxSVC: Seems VBoxSVC instance died. Dropping it and letting caller take over.\n")); 179 180 pUserData->m_ptrTheChosenOne.setNull(); 181 /* Release the client list and stop client list watcher thread*/ 182 pUserData->m_ptrClientList.setNull(); 180 183 } 181 184 } … … 190 193 { 191 194 pUserData->m_ptrTheChosenOne = aVBoxSVC; 195 /* 196 * Create instance of ClientList 197 */ 198 HRESULT hrc = CoCreateInstance(CLSID_VirtualBoxClientList, NULL, CLSCTX_LOCAL_SERVER, 199 IID_IVirtualBoxClientList, 200 (void **)pUserData->m_ptrClientList.asOutParam()); 201 if (SUCCEEDED(hrc)) 202 { 203 LogFunc(("Created API client list instance in VBoxSDS : hr=%Rhrf\n", hrc)); 204 } 205 else 206 { 207 LogFunc(("Error in creating API client list instance: hr=%Rhrf\n", hrc)); 208 } 209 192 210 hrc = S_OK; 193 211 } … … 235 253 pUserData->m_ptrTheChosenOne.setNull(); 236 254 /** @todo consider evicting the user from the table... */ 255 /* Release the client list and stop client list watcher thread*/ 256 pUserData->m_ptrClientList.setNull(); 237 257 } 238 258 else … … 260 280 } 261 281 282 283 STDMETHODIMP_(HRESULT) VirtualBoxSDS::NotifyClientsFinished() 284 { 285 LogRelFlowThisFuncEnter(); 286 287 int vrc = RTCritSectRwEnterShared(&m_MapCritSect); 288 if (RT_SUCCESS(vrc)) 289 { 290 for (UserDataMap_T::iterator it = m_UserDataMap.begin(); it != m_UserDataMap.end(); ++it) 291 { 292 VBoxSDSPerUserData *pUserData = it->second; 293 if (pUserData && pUserData->m_ptrTheChosenOne) 294 { 295 LogRelFunc(("Notify VBoxSVC that all clients finished\n")); 296 /* Notify VBoxSVC about finishing all API clients it should free references to VBoxSDS 297 and clean up itself */ 298 if (pUserData->m_ptrClientList) 299 pUserData->m_ptrClientList.setNull(); 300 pUserData->m_ptrTheChosenOne->NotifyClientsFinished(); 301 } 302 } 303 RTCritSectRwLeaveShared(&m_MapCritSect); 304 } 305 306 LogRelFlowThisFuncLeave(); 307 return S_OK; 308 } 262 309 263 310 // private methods -
trunk/src/VBox/Main/src-global/win/VBoxSDS.cpp
r70684 r71139 87 87 88 88 #include "VirtualBoxSDSImpl.h" 89 #include "VirtualBoxClientListImpl.h" 89 90 #include "Logging.h" 90 91 … … 694 695 695 696 697 int SetServiceEnvFlag() 698 { 699 int rc = VINF_SUCCESS; 700 if (!SetEnvironmentVariable(L"VBOX_SERVICE_PROCESS", L"")) 701 { 702 rc = RTErrConvertFromWin32(GetLastError()); 703 LogRel(("Error: cannot set service environment flag: %Rrs\n", rc)); 704 } 705 return rc; 706 } 707 708 696 709 /** 697 710 * Main function for the VBoxSDS process. … … 715 728 */ 716 729 RTR3InitExe(argc, &argv, 0); 730 731 SetServiceEnvFlag(); 717 732 718 733 static const RTGETOPTDEF s_aOptions[] = … … 922 937 BEGIN_OBJECT_MAP(s_aObjectMap) 923 938 OBJECT_ENTRY(CLSID_VirtualBoxSDS, VirtualBoxSDS) 939 OBJECT_ENTRY(CLSID_VirtualBoxClientList, VirtualBoxClientList) 924 940 END_OBJECT_MAP() 925 941 hrcExit = pServiceModule->init(s_aObjectMap, hInstance, &LIBID_VirtualBox, -
trunk/src/VBox/Main/src-server/win/svcmain.cpp
r70030 r71139 28 28 #include "VBox/com/com.h" 29 29 #include "VBox/com/VirtualBox.h" 30 #include "VBox/com/array.h" 30 31 31 32 #include "VirtualBoxImpl.h" … … 44 45 #include <iprt/asm.h> 45 46 47 #include <TlHelp32.h> 46 48 47 49 /********************************************************************************************************************************* … … 94 96 volatile uint32_t dwTimeOut = dwNormalTimeout; /* time for EXE to be idle before shutting down. Can be decreased at system shutdown phase. */ 95 97 98 99 BOOL CALLBACK CloseWindowProc(_In_ HWND hWnd, _In_ LPARAM /* lParam */) 100 { 101 _ASSERTE(hWnd); 102 DWORD_PTR dwResult; 103 // Close topmost windows in the thread 104 LRESULT lResult = SendMessageTimeout(hWnd, WM_CLOSE, NULL, NULL, 105 SMTO_ABORTIFHUNG | SMTO_BLOCK, 0, &dwResult); 106 if (lResult != 0) 107 { 108 LogRel(("EnumThreadWndProc: Close message sent to window %x successfully \n", hWnd)); 109 } 110 else 111 { 112 LogRel(("EnumThreadWndProc: Cannot send event to window %x. result: %d, last error: %x\n", 113 hWnd, dwResult, GetLastError())); 114 } 115 return TRUE; 116 } 117 118 void SendCloseToAllThreads(DWORD dwTargetPid) 119 { 120 HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); 121 if (hSnapshot == NULL) 122 { 123 LogRel(("SendCloseToAllThreads: cannot get threads snapshot. error: 0x%x \n", 124 GetLastError())); 125 return; 126 } 127 128 THREADENTRY32 threadEntry; 129 ZeroMemory(&threadEntry, sizeof(threadEntry)); 130 threadEntry.dwSize = sizeof(threadEntry); 131 132 if (Thread32First(hSnapshot, &threadEntry)) 133 { 134 do 135 { 136 LogRel(("SendCloseToAllThreads: process: %d thread: %x \n", 137 threadEntry.th32OwnerProcessID, threadEntry.th32ThreadID)); 138 if (threadEntry.th32OwnerProcessID == dwTargetPid) 139 { 140 BOOL bRes = EnumThreadWindows(threadEntry.th32ThreadID, CloseWindowProc, NULL); 141 if (!bRes) 142 { 143 LogRel(("SendCloseToAllThreads: EnumThreadWindows() failed to enumerate threads. error: %x \n", 144 GetLastError())); 145 } 146 else 147 { 148 LogRel(("SendCloseToAllThreads: about to close window in thread %x of process d\n", 149 threadEntry.th32ThreadID, dwTargetPid)); 150 } 151 } 152 } while (Thread32Next(hSnapshot, &threadEntry)); 153 } 154 CloseHandle(hSnapshot); 155 } 156 157 static int CloseActiveClients() 158 { 159 ComPtr<IVirtualBoxClientList> ptrClientList; 160 /* 161 * Connect to VBoxSDS. 162 */ 163 // TODO: here we close all API client processes: our own and customers 164 LogRelFunc(("Forcibly close API clients during system shutdown on Windows 7:\n")); 165 HRESULT hrc = CoCreateInstance(CLSID_VirtualBoxClientList, NULL, CLSCTX_LOCAL_SERVER, IID_IVirtualBoxClientList, 166 (void **)ptrClientList.asOutParam()); 167 if (SUCCEEDED(hrc)) 168 { 169 com::SafeArray<LONG> aCllients; 170 hrc = ptrClientList->get_Clients(aCllients.__asOutParam()); 171 RTCList<LONG> clientsList = aCllients.toList(); 172 LogRel(("==========Client list begin ========\n")); 173 for (int i = 0; i < clientsList.size(); i++) 174 { 175 LogRel(("About to close client pid: %d\n", clientsList[i])); 176 SendCloseToAllThreads(clientsList[i]); 177 } 178 LogRel(("==========Client list end ========\n")); 179 } 180 else 181 { 182 LogFunc(("Error to connect to VBoxSDS: hr=%Rhrf\n", hrc)); 183 } 184 return 0; 185 } 186 187 // These are copies of functions defined in VersionHelpers.h 188 bool IsWindowsVersionOrGreaterWrap(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor) 189 { 190 OSVERSIONINFOEXW osvi = { sizeof(osvi), 0, 0, 0, 0,{ 0 }, 0, 0 }; 191 DWORDLONG const dwlConditionMask = VerSetConditionMask( 192 VerSetConditionMask( 193 VerSetConditionMask( 194 0, VER_MAJORVERSION, VER_GREATER_EQUAL), 195 VER_MINORVERSION, VER_GREATER_EQUAL), 196 VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL); 197 198 osvi.dwMajorVersion = wMajorVersion; 199 osvi.dwMinorVersion = wMinorVersion; 200 osvi.wServicePackMajor = wServicePackMajor; 201 202 return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask) != FALSE; 203 } 204 205 206 #if !defined _WIN32_WINNT_WIN8 207 208 #define _WIN32_WINNT_WIN8 0x0602 209 210 #endif // #if !defined _WIN32_WINNT_WIN8 211 212 bool IsWindows8OrGreaterWrap() 213 { 214 return IsWindowsVersionOrGreaterWrap(HIBYTE(_WIN32_WINNT_WIN8), LOBYTE(_WIN32_WINNT_WIN8), 0); 215 } 96 216 97 217 … … 241 361 HRESULT VirtualBoxClassFactory::i_registerWithSds(IUnknown **ppOtherVirtualBox); 242 362 void VirtualBoxClassFactory::i_deregisterWithSds(void); 363 void VirtualBoxClassFactory::i_finishVBoxSvc(); 243 364 244 365 friend VBoxSVCRegistration; … … 311 432 return m_pFactory->i_getVirtualBox(ppResult); 312 433 return E_FAIL; 434 } 435 436 // IVBoxSVCRegistration: called from 437 STDMETHOD(NotifyClientsFinished)() 438 { 439 LogRelFunc(("All clients gone - shutdown sequence initiated\n")); 440 441 m_pFactory->i_finishVBoxSvc(); 442 443 // This is not enough to finish VBoxSvc such as reference to crashed client still is in action 444 // So I forcebly shutdown VBoxSvc 445 while (g_pModule->Unlock() > 0) 446 {}; 447 448 return S_OK; 313 449 } 314 450 }; … … 354 490 NOREF(hrc); 355 491 } 356 m_ptrVirtualBoxSDS.setNull(); 357 g_fRegisteredWithVBoxSDS = false; 358 } 359 if (m_pVBoxSVC) 360 { 361 m_pVBoxSVC->m_pFactory = NULL; 362 m_pVBoxSVC->Release(); 363 m_pVBoxSVC = NULL; 364 } 492 } 493 i_finishVBoxSvc(); 365 494 } 366 495 … … 381 510 Log(("VirtualBoxClassFactory::GetVirtualBox: E_FAIL\n")); 382 511 return E_FAIL; 512 } 513 514 515 void VirtualBoxClassFactory::i_finishVBoxSvc() 516 { 517 LogRelFunc(("Finish work of VBoxSVc and VBoxSDS\n")); 518 if (m_ptrVirtualBoxSDS.isNotNull()) 519 { 520 m_ptrVirtualBoxSDS.setNull(); 521 g_fRegisteredWithVBoxSDS = false; 522 } 523 if (m_pVBoxSVC) 524 { 525 m_pVBoxSVC->m_pFactory = NULL; 526 m_pVBoxSVC->Release(); 527 m_pVBoxSVC = NULL; 528 } 383 529 } 384 530 … … 536 682 Log(("VBoxSVCWinMain: WM_QUERYENDSESSION: VBoxSvc has active connections. bActivity = %d. Loc count = %d\n", 537 683 g_pModule->bActivity, g_pModule->GetLockCount())); 684 685 // On Windows 7 our clients doesn't receive right sequence of Session End events 686 // So we send them all WM_QUIT to forcible close them. 687 // Windows 10 sends end session events correctly 688 // Note: the IsWindows8Point1() and IsWindows10OrGreater() doesnt work in 689 // application without manifest so I use old compatible functions for detection of Win 7 690 if(!IsWindows8OrGreaterWrap()) 691 CloseActiveClients(); 538 692 } 539 693 rc = !fActiveConnection; … … 629 783 } 630 784 } 785 } 786 787 788 int SetServiceEnvFlag() 789 { 790 int rc = VINF_SUCCESS; 791 if (!SetEnvironmentVariable(L"VBOX_SERVICE_PROCESS", L"")) 792 { 793 rc = RTErrConvertFromWin32(GetLastError()); 794 LogRel(("Error: cannot set service environment flag: %Rrs\n", rc)); 795 } 796 return rc; 631 797 } 632 798 … … 667 833 */ 668 834 RTR3InitExe(argc, &argv, 0); 835 836 SetServiceEnvFlag(); 669 837 670 838 static const RTGETOPTDEF s_aOptions[] = … … 873 1041 if (RT_FAILURE(vrc)) 874 1042 { 875 Log(("SVCMAIN: Failed to process Helper request (%Rrc). ", vrc));1043 Log(("SVCMAIN: Failed to process Helper request (%Rrc).\n", vrc)); 876 1044 nRet = 1; 877 1045 }
Note:
See TracChangeset
for help on using the changeset viewer.