Access violation using refresher (when blocking port in Firewall)
- From: tango <tango@xxxxxxxxxxxxxxxx>
- Date: Wed, 1 Aug 2007 04:34:00 -0700
I think we have found a bug when trying to connect to a remote computer from
Windows XP SP2 (but we think the bug happens in W2003 too) when the
connection fails (but just in one especial configuration of the remote
Firewall).
The problem only happens when we configure the Firewall in the remote
computer as this:
- We open the port number 135 for incoming.
- When a WMI connection using refreshers is opened there are 2 new ports
that we need to open. The port numbers change in each restart of the client.
If we allow in the remote firewall incoming connections for the first
incoming port but we reject connections for the second port we get an access
violation when executing the following code (compiled in Visual Studio 2003).
The following code is a dumb example we have created to produce the error.
It does not does anythin useful:
==== Begin code ====
#define _WIN32_DCOM
#define _WIN32_WINNT 0x0400
#define PERF_NULL -1
#define isZero(x) (fabs(x) < 0.000001)
#pragma warning(disable:4786)
#pragma warning(disable:4503)
#include <afx.h>
#include <cstring>
#include <stdio.h>
#include <wbemcli.h>
#include <iostream>
#include <comdef.h>
#include <assert.h>
#include <strsafe.h>
using namespace std;
SEC_WINNT_AUTH_IDENTITY_W *pAuthIdentity;
// elementos básicos COM WMI
IWbemLocator * pLocator;
IWbemServices * pServices;
IUnknown* pUnkServ;
// elementos para trabajar con refreshers
IWbemRefresher *pRefresher;
IWbemConfigureRefresher *pConfig;
IWbemHiPerfEnum* pPerfEnum;
long pPerfId;
char errorstr[4096];
int _tmain(int argc, _TCHAR* argv[])
{
HRESULT hres;
pLocator = NULL;
pServices = NULL;
pUnkServ = NULL;
pRefresher = NULL;
pConfig = NULL;
printf("Constructor wmi2::wmi2()\n");
pAuthIdentity = new SEC_WINNT_AUTH_IDENTITY_W;
ZeroMemory(pAuthIdentity, sizeof(*pAuthIdentity));
for(;;)
{
HRESULT hres = 0;
OutputDebugString("Inicializando\n");
hres = CoInitializeEx(0, COINIT_MULTITHREADED); // Initialize COM.
// hres es 0 si el thread no habia inicializado COM y 1 si ya esta
inicializado
if (FAILED(hres)) // failed is true if hres != 0 and hres != 1
{
OutputDebugString("Error while Initializing COM");
}
else if(hres == 1)
{
OutputDebugString("The COM library is already initialized on this thread.
The thread should wait until it has been unitialized again\n");
CoUninitialize();
CoInitializeEx(0, COINIT_MULTITHREADED);
}
OutputDebugString("Trying to get Locator\n");
hres = CoCreateInstance(CLSID_WbemLocator, 0,
CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &pLocator);
OutputDebugString("ConnectServer\n");
hres = pLocator->ConnectServer(
_bstr_t(L"\\\\HOST\\root\\CIMV2"), // network resource
_bstr_t(L"DOMAIN\\USER"), // user
_bstr_t(L"PASSWORD"), // password
NULL, // locale
0, // security flags
_bstr_t(L"NTLMDOMAIN:"), // autority
NULL, // context
&pServices // namespace
);
if (FAILED(hres))
{
sprintf(errorstr, "Error %x while connecting to server", hres);
OutputDebugString(errorstr);
}
pAuthIdentity->User = new WCHAR[32];
StringCbCopyW(pAuthIdentity->User,sizeof(L"USER"),L"USER");
pAuthIdentity->UserLength = wcslen(pAuthIdentity->User);
pAuthIdentity->Domain = new WCHAR[32];
StringCbCopyW(pAuthIdentity->Domain,sizeof(L"DOMAIN"),L"DOMAIN");
pAuthIdentity->DomainLength = wcslen(pAuthIdentity->Domain);
pAuthIdentity->Password = new WCHAR[32];
StringCbCopyW(pAuthIdentity->Password,sizeof(L"PASSWORD"),L"PASSWORD");
pAuthIdentity->PasswordLength = wcslen( pAuthIdentity->Password);
pAuthIdentity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
hres = CoSetProxyBlanket(pServices,
RPC_C_AUTHN_WINNT,
RPC_C_AUTHZ_NONE,
NULL,
RPC_C_AUTHN_LEVEL_PKT,
RPC_C_IMP_LEVEL_IMPERSONATE,
pAuthIdentity,
EOAC_NONE
);
OutputDebugString("Trying to get Unknown Services\n");
hres = pServices->QueryInterface(IID_IUnknown, (void**) &pUnkServ);
hres = CoSetProxyBlanket(pUnkServ,
RPC_C_AUTHN_WINNT,
RPC_C_AUTHZ_NONE,
NULL,
RPC_C_AUTHN_LEVEL_PKT,
RPC_C_IMP_LEVEL_IMPERSONATE,
pAuthIdentity,
EOAC_NONE
);
OutputDebugString("objetowmi->consultar();");
hres = CoCreateInstance(CLSID_WbemRefresher, 0,
CLSCTX_INPROC_SERVER, IID_IWbemRefresher, (LPVOID *) &pRefresher);
if (hres != S_OK)
{
sprintf(errorstr, "Error %x while querying to WMI (getting refresher
instance)", hres);
OutputDebugString(errorstr);
}
hres = (pRefresher)->QueryInterface( IID_IWbemConfigureRefresher,(void**)
&pConfig);
if (hres != S_OK)
{
sprintf(errorstr, "Error %x while querying to WMI (getting refresher
configuration)", hres);
OutputDebugString(errorstr);
}
pPerfEnum = NULL;
// Add the instance to be refreshed
hres = pConfig->AddEnum(
pServices, // IWbemServices
_bstr_t(L"Win32_perfrawdata_perfproc_process"), // Class name
WBEM_FLAG_USE_AMENDED_QUALIFIERS, // Flags
NULL, // Context
&pPerfEnum, // HiPerfEnumerator
&pPerfId // refresh enumerator id
);
if (FAILED(hres))
{
sprintf(errorstr, "Error %x while querying performance data", hres);
OutputDebugString(errorstr);
}
else
{
hres = pRefresher->Refresh(0L);
}
//The error happens because of this!!
if (pRefresher)
{
OutputDebugString("pRefresher");
pRefresher->Release();
}
if (pServices)
{
OutputDebugString("-->pServices->Release();");
pServices->Release();
}
if (pUnkServ)
{
OutputDebugString("-->pUnkServ->Release();");
pUnkServ->Release();
}
if (pLocator)
{
OutputDebugString("-->pLocator->Release();");
pLocator->Release();
}
if (pPerfEnum)
{
OutputDebugString("pPerfEnum");
pPerfEnum->Release();
}
if (pConfig)
{
OutputDebugString("pConfig");
pConfig->Release();
}
if (pAuthIdentity)
{
OutputDebugString("-->pAuthIdentity");
if (pAuthIdentity->User)
delete [] pAuthIdentity->User;
if (pAuthIdentity->Domain)
delete [] pAuthIdentity->Domain;
if (pAuthIdentity->Password)
delete [] pAuthIdentity->Password;
}
CoUninitialize();
Sleep(40000);
OutputDebugString("Finishing\n");
}
OutputDebugString("Application Exit()");
return 0; // Program successfully completed.
}
==== End code ====
When configuring the firewall as said, the WMI connection can be stablished
but the pRefresher->Refresh function call fails with an RPC error. After
that, an access violation happens during the Sleep call after the
CoUninitialize call (I suppose it is due to a "garbage collector" issue in
COM ?)
As I said, we have been able to reproduce the problem only when the Firewall
is configured in that way, but some customers had the same error in other
cases. We have tested the code and the same code works fine:
- When the full connection can be established sucessfully (when we open
all the needed ports in the Firewall).
- When the connection can not be stablished (if we close all the ports in
the firewall), because the pRefresher is not created.
Furthermore, modifying the code we have seen that this code only fails when
we release the pRefresher is performed before the other "COM pointers"
(pLocator, pUnkServ, etc). If we change the order everything works.
In this sample code the workaround is obvious: Just execute the
pRefresher->Release just before the CoUninitialize. In the real (complete)
code we use several refreshers using the same WMI connection, so we need to
release them before calling the release method for the rest of COM pointers.
Doing some more testing we have found that the bug did not happen if we do
not call the CoUninitialize funcion.
Do you have any idea about what is happening?
.
- Follow-Ups:
- RE: Access violation using refresher (when blocking port in Firewall)
- From: "Jeffrey Tan[MSFT]"
- RE: Access violation using refresher (when blocking port in Firewall)
- From: "Jeffrey Tan[MSFT]"
- RE: Access violation using refresher (when blocking port in Firewall)
- Next by Date: Select * from win_32_process for all users
- Next by thread: RE: Access violation using refresher (when blocking port in Firewall)
- Index(es):
Relevant Pages
|
Loading