]> git.saurik.com Git - apple/mdnsresponder.git/blame - mDNSWindows/VPCDetect.cpp
mDNSResponder-214.3.2.tar.gz
[apple/mdnsresponder.git] / mDNSWindows / VPCDetect.cpp
CommitLineData
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
20Revision 1.3 2006/08/14 23:25:20 cheshire
21Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
22
23Revision 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
26Revision 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
39static BOOL g_doneCheck = FALSE;
40static BOOL g_isVPC = FALSE;
41
42
67c8f8a1
A
43mStatus
44IsVPCRunning( 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
145exit:
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}