]>
Commit | Line | Data |
---|---|---|
67c8f8a1 A |
1 | /* -*- Mode: C; tab-width: 4 -*- |
2 | * | |
4aea607d A |
3 | * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. |
4 | * | |
67c8f8a1 A |
5 | * Licensed under the Apache License, Version 2.0 (the "License"); |
6 | * you may not use this file except in compliance with the License. | |
7 | * You may obtain a copy of the License at | |
4aea607d | 8 | * |
67c8f8a1 | 9 | * http://www.apache.org/licenses/LICENSE-2.0 |
4aea607d | 10 | * |
67c8f8a1 A |
11 | * Unless required by applicable law or agreed to in writing, software |
12 | * distributed under the License is distributed on an "AS IS" BASIS, | |
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 | * See the License for the specific language governing permissions and | |
4aea607d | 15 | * limitations under the License. |
4aea607d A |
16 | |
17 | Change History (most recent first): | |
18 | ||
19 | $Log: VPCDetect.cpp,v $ | |
67c8f8a1 A |
20 | Revision 1.3 2006/08/14 23:25:20 cheshire |
21 | Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 | |
22 | ||
23 | Revision 1.2 2006/02/26 19:31:05 herscher | |
24 | <rdar://problem/4455038> Bonjour For Windows takes 90 seconds to start. This was caused by a bad interaction between the VirtualPC check, and the removal of the WMI dependency. The problem was fixed by: 1) checking to see if WMI is running before trying to talk to it. 2) Retrying the VirtualPC check every 10 seconds upon failure, stopping after 10 unsuccessful tries. | |
25 | ||
4aea607d A |
26 | Revision 1.1 2005/11/27 20:21:16 herscher |
27 | <rdar://problem/4210580> Workaround Virtual PC bug that incorrectly modifies incoming mDNS packets | |
28 | ||
29 | */ | |
30 | ||
31 | #define _WIN32_DCOM | |
32 | #include "VPCDetect.h" | |
33 | #include "DebugServices.h" | |
34 | #include <comdef.h> | |
35 | #include <Wbemidl.h> | |
36 | ||
37 | # pragma comment(lib, "wbemuuid.lib") | |
38 | ||
39 | static BOOL g_doneCheck = FALSE; | |
40 | static BOOL g_isVPC = FALSE; | |
41 | ||
42 | ||
67c8f8a1 A |
43 | mStatus |
44 | IsVPCRunning( BOOL * inVirtualPC ) | |
4aea607d A |
45 | { |
46 | IWbemLocator * pLoc = 0; | |
47 | IWbemServices * pSvc = 0; | |
48 | IEnumWbemClassObject * pEnumerator = NULL; | |
49 | bool coInit = false; | |
50 | HRESULT hres; | |
67c8f8a1 A |
51 | SC_HANDLE scm = NULL; |
52 | SC_HANDLE service = NULL; | |
53 | SERVICE_STATUS status; | |
54 | mStatus err; | |
55 | BOOL ok = TRUE; | |
56 | ||
57 | // Initialize flag | |
58 | ||
59 | *inVirtualPC = FALSE; | |
60 | ||
61 | // Find out if WMI is running | |
62 | ||
63 | scm = OpenSCManager( 0, 0, SC_MANAGER_CONNECT ); | |
64 | err = translate_errno( scm, (OSStatus) GetLastError(), kOpenErr ); | |
65 | require_noerr( err, exit ); | |
66 | ||
67 | service = OpenService( scm, TEXT( "winmgmt" ), SERVICE_QUERY_STATUS ); | |
68 | err = translate_errno( service, (OSStatus) GetLastError(), kNotFoundErr ); | |
69 | require_noerr( err, exit ); | |
70 | ||
71 | ok = QueryServiceStatus( service, &status ); | |
72 | err = translate_errno( ok, (OSStatus) GetLastError(), kAuthenticationErr ); | |
73 | require_noerr( err, exit ); | |
74 | require_action( status.dwCurrentState == SERVICE_RUNNING, exit, err = kUnknownErr ); | |
75 | ||
4aea607d A |
76 | // Initialize COM. |
77 | ||
78 | hres = CoInitializeEx(0, COINIT_MULTITHREADED); | |
67c8f8a1 | 79 | require_action( SUCCEEDED( hres ), exit, err = kUnknownErr ); |
4aea607d A |
80 | coInit = true; |
81 | ||
82 | // Initialize Security | |
83 | ||
84 | hres = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL ); | |
67c8f8a1 | 85 | require_action( SUCCEEDED( hres ), exit, err = kUnknownErr ); |
4aea607d A |
86 | |
87 | ||
88 | // Obtain the initial locator to Windows Management on a particular host computer. | |
89 | ||
90 | hres = CoCreateInstance( CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &pLoc ); | |
67c8f8a1 | 91 | require_action( SUCCEEDED( hres ), exit, err = kUnknownErr ); |
4aea607d A |
92 | |
93 | // Connect to the root\cimv2 namespace with the | |
94 | // current user and obtain pointer pSvc | |
95 | // to make IWbemServices calls. | |
96 | ||
67c8f8a1 A |
97 | hres = pLoc->ConnectServer( _bstr_t(L"ROOT\\CIMV2"), NULL, NULL, 0, WBEM_FLAG_CONNECT_USE_MAX_WAIT, 0, 0, &pSvc ); |
98 | require_action( SUCCEEDED( hres ), exit, err = kUnknownErr ); | |
4aea607d A |
99 | |
100 | // Set the IWbemServices proxy so that impersonation | |
101 | // of the user (client) occurs. | |
102 | ||
103 | hres = CoSetProxyBlanket( pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE ); | |
67c8f8a1 | 104 | require_action( SUCCEEDED( hres ), exit, err = kUnknownErr ); |
4aea607d A |
105 | |
106 | // Use the IWbemServices pointer to make requests of WMI. | |
107 | // Make requests here: | |
108 | ||
109 | hres = pSvc->ExecQuery( bstr_t("WQL"), bstr_t("SELECT * from Win32_BaseBoard"), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator); | |
110 | ||
67c8f8a1 | 111 | require_action( SUCCEEDED( hres ), exit, err = kUnknownErr ); |
4aea607d A |
112 | |
113 | do | |
114 | { | |
115 | IWbemClassObject* pInstance = NULL; | |
116 | ULONG dwCount = NULL; | |
117 | ||
118 | hres = pEnumerator->Next( WBEM_INFINITE, 1, &pInstance, &dwCount); | |
119 | ||
120 | if ( pInstance ) | |
121 | { | |
122 | VARIANT v; | |
123 | BSTR strClassProp = SysAllocString(L"Manufacturer"); | |
124 | HRESULT hr; | |
125 | ||
126 | hr = pInstance->Get(strClassProp, 0, &v, 0, 0); | |
127 | SysFreeString(strClassProp); | |
128 | ||
129 | // check the HRESULT to see if the action succeeded. | |
130 | ||
131 | if (SUCCEEDED(hr) && (V_VT(&v) == VT_BSTR)) | |
132 | { | |
133 | wchar_t * wstring = wcslwr( V_BSTR( &v ) ); | |
134 | ||
135 | if (wcscmp( wstring, L"microsoft corporation" ) == 0 ) | |
136 | { | |
67c8f8a1 | 137 | *inVirtualPC = TRUE; |
4aea607d A |
138 | } |
139 | } | |
140 | ||
141 | VariantClear(&v); | |
142 | } | |
143 | } while (hres == WBEM_S_NO_ERROR); | |
144 | ||
145 | exit: | |
146 | ||
147 | if ( pSvc != NULL ) | |
148 | { | |
149 | pSvc->Release(); | |
150 | } | |
151 | ||
152 | if ( pLoc != NULL ) | |
153 | { | |
154 | pLoc->Release(); | |
155 | } | |
156 | ||
157 | if ( coInit ) | |
158 | { | |
159 | CoUninitialize(); | |
160 | } | |
161 | ||
67c8f8a1 | 162 | if ( service ) |
4aea607d | 163 | { |
67c8f8a1 A |
164 | CloseServiceHandle( service ); |
165 | } | |
619ee211 | 166 | |
67c8f8a1 A |
167 | if ( scm ) |
168 | { | |
169 | CloseServiceHandle( scm ); | |
170 | } | |
171 | ||
172 | if ( *inVirtualPC ) | |
173 | { | |
174 | dlog( kDebugLevelTrace, "Virtual PC detected" ); | |
4aea607d A |
175 | } |
176 | ||
67c8f8a1 | 177 | return err; |
4aea607d | 178 | } |