598 lines
18 KiB
C++
598 lines
18 KiB
C++
/*++
|
|
|
|
Copyright (C) 1997-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
CONNPNT.CPP
|
|
|
|
Abstract:
|
|
|
|
Declarations for CInitStub class which implements a special
|
|
stub whose only purpose is for establishing new connections.
|
|
|
|
History:
|
|
|
|
a-davj 04-Mar-97 Created.
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#include <anonpipe.h>
|
|
#ifdef TCPIP_MARSHALER
|
|
#include <tcpip.h>
|
|
#endif
|
|
#include <cominit.h>
|
|
|
|
#define SAFE_DELETE(px) if((px) != NULL) delete (px);
|
|
#define SAFE_CLOSE(hx) if((hx) != NULL) CloseHandle(hx);
|
|
|
|
struct PipeSharedMemoryMessage
|
|
{
|
|
DWORD m_Size ;
|
|
CHAR m_Buffer [ 256 ] ;
|
|
} ;
|
|
|
|
HANDLE g_Mutex = NULL ;
|
|
HANDLE g_StartedEvent ;
|
|
HANDLE g_ReplyEvent = NULL ;
|
|
HANDLE g_RequestEvent = NULL ;
|
|
HANDLE g_SharedMemory = NULL ;
|
|
PipeSharedMemoryMessage *g_SharedMemoryBuffer = NULL ;
|
|
|
|
CComLink *CreateAnonPipe (
|
|
|
|
IN HANDLE & a_ClientRead ,
|
|
IN HANDLE & a_ClientWrite ,
|
|
IN HANDLE & a_ClientTerm ,
|
|
IN DWORD a_ClientProcessID ,
|
|
IN HRESULT *t_Result
|
|
)
|
|
{
|
|
CComLink *t_ComLink = NULL ;
|
|
|
|
HANDLE t_ReadPipe1 = NULL ;
|
|
HANDLE t_WritePipe1 = NULL ;
|
|
HANDLE t_ReadPipe2 = NULL ;
|
|
HANDLE t_WritePipe2 = NULL ;
|
|
|
|
HANDLE t_ClientProcess = NULL ;
|
|
|
|
*t_Result = WBEM_E_OUT_OF_MEMORY;
|
|
|
|
DEBUGTRACE((LOG,"\nCreateLocalConn was called, Client proc=0x%x", a_ClientProcessID));
|
|
|
|
// create two pipes
|
|
|
|
if ( CreatePipe ( & t_ReadPipe1 , & t_WritePipe1 , NULL , 0 ) )
|
|
{
|
|
if ( CreatePipe ( & t_ReadPipe2 , & t_WritePipe2 , NULL , 0 ) )
|
|
{
|
|
// get a handle to the other process using its ID
|
|
|
|
t_ClientProcess = OpenProcess ( PROCESS_DUP_HANDLE , FALSE , a_ClientProcessID ) ;
|
|
if ( t_ClientProcess == NULL )
|
|
{
|
|
CloseHandle ( t_ReadPipe1 ) ;
|
|
CloseHandle ( t_WritePipe1 ) ;
|
|
CloseHandle ( t_ReadPipe2 ) ;
|
|
CloseHandle ( t_WritePipe2 ) ;
|
|
|
|
DEBUGTRACE((LOG,"\nCreateLocalConn failed calling OpenProcess, last error=0x%x",GetLastError()));
|
|
}
|
|
else
|
|
{
|
|
// duplicate a read handle from one pipe and the write handle from
|
|
// the other
|
|
|
|
DEBUGTRACE((LOG,"\nCreateLocal is about to duplicate handles"));
|
|
|
|
HANDLE t_Process = GetCurrentProcess () ;
|
|
|
|
BOOL t_Status = DuplicateHandle (
|
|
|
|
t_Process ,
|
|
t_ReadPipe1 ,
|
|
t_ClientProcess ,
|
|
& a_ClientRead ,
|
|
0 ,
|
|
FALSE ,
|
|
DUPLICATE_SAME_ACCESS
|
|
) ;
|
|
|
|
if ( ! t_Status )
|
|
{
|
|
CloseHandle ( t_ReadPipe1 ) ;
|
|
CloseHandle ( t_WritePipe1 ) ;
|
|
CloseHandle ( t_ReadPipe2 ) ;
|
|
CloseHandle ( t_WritePipe2 ) ;
|
|
CloseHandle ( t_ClientProcess ) ;
|
|
}
|
|
else
|
|
{
|
|
t_Status = DuplicateHandle (
|
|
|
|
t_Process ,
|
|
t_WritePipe2 ,
|
|
t_ClientProcess ,
|
|
& a_ClientWrite,
|
|
0 ,
|
|
FALSE ,
|
|
DUPLICATE_SAME_ACCESS
|
|
) ;
|
|
|
|
if ( ! t_Status )
|
|
{
|
|
CloseHandle ( t_ReadPipe1 ) ;
|
|
CloseHandle ( t_WritePipe1 ) ;
|
|
CloseHandle ( t_ReadPipe2 ) ;
|
|
CloseHandle ( t_WritePipe2 ) ;
|
|
CloseHandle ( a_ClientRead ) ;
|
|
CloseHandle ( t_ClientProcess ) ;
|
|
}
|
|
else
|
|
{
|
|
t_Status = DuplicateHandle (
|
|
|
|
t_Process ,
|
|
t_WritePipe1 ,
|
|
t_ClientProcess ,
|
|
& a_ClientTerm ,
|
|
0 ,
|
|
FALSE ,
|
|
DUPLICATE_SAME_ACCESS
|
|
) ;
|
|
|
|
if ( ! t_Status )
|
|
{
|
|
CloseHandle ( t_ReadPipe1 ) ;
|
|
CloseHandle ( t_WritePipe1 ) ;
|
|
CloseHandle ( t_ReadPipe2 ) ;
|
|
CloseHandle ( t_WritePipe2 ) ;
|
|
CloseHandle ( a_ClientRead ) ;
|
|
CloseHandle ( a_ClientWrite ) ;
|
|
CloseHandle ( t_ClientProcess ) ;
|
|
}
|
|
else
|
|
{
|
|
|
|
// allocate a new CComLink object
|
|
|
|
t_ComLink = new CComLink_LPipe ( NORMALSERVER , t_ReadPipe2, t_WritePipe1, t_WritePipe2);
|
|
if ( t_ComLink == NULL )
|
|
{
|
|
CloseHandle ( t_ReadPipe1 ) ;
|
|
CloseHandle ( t_WritePipe1 ) ;
|
|
CloseHandle ( t_ReadPipe2 ) ;
|
|
CloseHandle ( t_WritePipe2 ) ;
|
|
CloseHandle ( a_ClientRead ) ;
|
|
CloseHandle ( a_ClientWrite ) ;
|
|
CloseHandle ( a_ClientTerm ) ;
|
|
CloseHandle ( t_ClientProcess ) ;
|
|
}
|
|
else
|
|
{
|
|
DEBUGTRACE((LOG,"\nCreateLocal created a pipe with addr of 0x%x",t_ComLink ));
|
|
|
|
CloseHandle ( t_ReadPipe1 ) ;
|
|
CloseHandle ( t_ClientProcess ) ; // dont need this anymore.
|
|
|
|
*t_Result = S_OK ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CloseHandle ( t_ReadPipe1 ) ;
|
|
CloseHandle ( t_WritePipe1 ) ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
}
|
|
|
|
return t_ComLink ;
|
|
}
|
|
|
|
void InitialiseConnection (
|
|
|
|
CTransportStream *a_Read ,
|
|
CTransportStream *a_Write
|
|
)
|
|
{
|
|
HRESULT t_Result ;
|
|
|
|
DWORD t_ReadStreamStatus = CTransportStream::no_error;
|
|
DWORD t_WriteStreamStatus = CTransportStream::no_error;
|
|
|
|
// Read the rest of the connection type arguments.
|
|
// Get the initial arguments that are present for all calls.
|
|
|
|
DWORD t_ClientProcessID = 0 ;
|
|
|
|
t_ReadStreamStatus |= a_Read->ReadDWORD ( &t_ClientProcessID ) ;
|
|
|
|
if ( t_ReadStreamStatus != CTransportStream::no_error )
|
|
{
|
|
DEBUGTRACE((LOG,"\nCInitStub::InitConnection had failure reading stream."));
|
|
|
|
t_Result = WBEM_E_INVALID_STREAM;
|
|
|
|
t_WriteStreamStatus |= a_Write->WriteDWORD ( t_Result ) ;
|
|
t_WriteStreamStatus |= a_Write->WriteDWORD ( 0 ) ;
|
|
}
|
|
else
|
|
{
|
|
// Get an instance of CLSID_WbemLevel1Login. This is supplied by
|
|
// WINMGMT.exe and is a thin wrapper to the core's inproc level1login.
|
|
|
|
DEBUGTRACE((LOG,"\nCInitStub::HandleCall about to call CoCreateInstance"));
|
|
|
|
CServerLogin *t_Login = new CServerLogin ;
|
|
|
|
if ( t_Login == NULL )
|
|
{
|
|
t_WriteStreamStatus |= a_Write->WriteDWORD ( WBEM_E_OUT_OF_MEMORY ) ;
|
|
t_WriteStreamStatus |= a_Write->WriteDWORD ( 0 ) ;
|
|
|
|
DEBUGTRACE((LOG,"\nfailed calling locator RequestLogin, sc = %x",WBEM_E_OUT_OF_MEMORY));
|
|
}
|
|
else
|
|
{
|
|
// setup the output stream as successful and write the provider address
|
|
|
|
t_WriteStreamStatus |= a_Write->WriteDWORD ( WBEM_NO_ERROR ) ;
|
|
t_WriteStreamStatus |= a_Write->WriteDWORD ( ( DWORD ) t_Login ) ;
|
|
|
|
// Create an appropriate transport object
|
|
|
|
HANDLE t_ClientRead = NULL;
|
|
HANDLE t_ClientWrite = NULL;
|
|
HANDLE t_ClientTerm = NULL;
|
|
|
|
CComLink *t_ComLink = CreateAnonPipe ( t_ClientRead , t_ClientWrite , t_ClientTerm, t_ClientProcessID, &t_Result ) ;
|
|
if ( t_ComLink )
|
|
{
|
|
a_Write->WriteDWORD ( ( DWORD ) t_ClientRead ) ;
|
|
a_Write->WriteDWORD ( ( DWORD ) t_ClientWrite ) ;
|
|
a_Write->WriteDWORD ( ( DWORD ) t_ClientTerm ) ;
|
|
|
|
// Set the ref count for the new comlink and and the service to its
|
|
// list of objects.
|
|
|
|
t_ComLink->AddRef2 ( t_Login , LOGIN , RELEASEIT ) ;
|
|
|
|
t_ComLink->Release2 ( NULL , NONE ) ; // balances the initial count of 1
|
|
|
|
// Send back response including stub, handles etc
|
|
|
|
DEBUGTRACE((LOG,"\nCInitStub::HandleCall has hooked up with wbemcore, no error!"));
|
|
}
|
|
else
|
|
{
|
|
if ( t_Login )
|
|
{
|
|
t_Login->Release();
|
|
}
|
|
|
|
a_Write->Reset();
|
|
|
|
a_Write->WriteDWORD ( t_Result ) ;
|
|
a_Write->WriteDWORD ( 0 ) ; // no error object if here
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ServiceLocalConnectionRequest ()
|
|
{
|
|
CTransportStream t_Read ;
|
|
CTransportStream t_Write ;
|
|
|
|
t_Read.CMemStream :: Deserialize ( ( BYTE * ) g_SharedMemoryBuffer->m_Buffer , g_SharedMemoryBuffer->m_Size ) ;
|
|
|
|
InitialiseConnection ( & t_Read, & t_Write ) ;
|
|
|
|
BYTE *t_Buffer = NULL ;
|
|
DWORD t_Size = 0 ;
|
|
|
|
t_Write.CMemStream :: Serialize ( &t_Buffer , &t_Size ) ;
|
|
|
|
g_SharedMemoryBuffer->m_Size = t_Size ;
|
|
memcpy ( g_SharedMemoryBuffer->m_Buffer , t_Buffer , t_Size ) ;
|
|
|
|
HeapFree ( GetProcessHeap () , 0 , t_Buffer ) ;
|
|
|
|
ResetEvent ( g_RequestEvent ) ;
|
|
SetEvent( g_ReplyEvent ) ;
|
|
}
|
|
|
|
void PipeWaitingFunction ( HANDLE a_Terminate )
|
|
{
|
|
DEBUGTRACE((LOG_WINMGMT,"\nInside the waiting function"));
|
|
|
|
HANDLE hArray[2];
|
|
hArray[0] = a_Terminate;
|
|
hArray[1] = g_RequestEvent ;
|
|
|
|
while(1)
|
|
{
|
|
DWORD dwObj = WbemWaitForMultipleObjects(2, hArray, INFINITE);
|
|
if(dwObj == 0) // bail out for terminate event
|
|
{
|
|
DEBUGTRACE((LOG_WINMGMT,"\nGot a termination event"));
|
|
break;
|
|
}
|
|
if(dwObj == WAIT_OBJECT_0 + 1)
|
|
{
|
|
DEBUGTRACE((LOG_WINMGMT,"\nGot a request event"));
|
|
|
|
ServiceLocalConnectionRequest () ;
|
|
}
|
|
}
|
|
}
|
|
|
|
DWORD LaunchPipeConnectionThread ( HANDLE a_Parameter )
|
|
{
|
|
InitializeCom () ;
|
|
|
|
HANDLE t_Terminate = ( HANDLE ) a_Parameter ;
|
|
PipeWaitingFunction ( t_Terminate ) ;
|
|
|
|
MyCoUninitialize () ;
|
|
|
|
return 0 ;
|
|
}
|
|
|
|
HRESULT CreateSharedMemory ()
|
|
{
|
|
g_StartedEvent = CreateEvent (NULL , TRUE , FALSE , __TEXT("WBEM_PIPEMARSHALER_STARTED" ) );
|
|
if ( ! g_StartedEvent )
|
|
{
|
|
return WBEM_E_FAILED ;
|
|
}
|
|
|
|
if ( GetLastError () != ERROR_ALREADY_EXISTS )
|
|
{
|
|
SetObjectAccess ( g_StartedEvent ) ;
|
|
}
|
|
|
|
g_RequestEvent = CreateEvent (NULL , TRUE , FALSE , __TEXT("WBEM_PIPEMARSHALER_EEQUESTISREADY" )) ;
|
|
if ( ! g_RequestEvent )
|
|
{
|
|
CloseHandle ( g_StartedEvent ) ;
|
|
|
|
g_StartedEvent = NULL ;
|
|
|
|
return WBEM_E_FAILED ;
|
|
}
|
|
|
|
SetObjectAccess ( g_RequestEvent ) ;
|
|
|
|
g_ReplyEvent = CreateEvent (NULL , TRUE , FALSE , __TEXT("WBEM_PIPEMARSHALER_REPLYISREADY" ) );
|
|
if ( ! g_ReplyEvent )
|
|
{
|
|
CloseHandle ( g_StartedEvent ) ;
|
|
CloseHandle ( g_RequestEvent ) ;
|
|
|
|
g_StartedEvent = NULL ;
|
|
g_ReplyEvent = NULL ;
|
|
|
|
return WBEM_E_FAILED ;
|
|
}
|
|
|
|
SetObjectAccess ( g_ReplyEvent ) ;
|
|
|
|
g_Mutex = CreateMutex ( NULL , FALSE , __TEXT("WBEM_PIPEMARSHALER_MUTUALEXCLUSION" ) );
|
|
if ( ! g_Mutex )
|
|
{
|
|
CloseHandle ( g_StartedEvent ) ;
|
|
CloseHandle ( g_ReplyEvent ) ;
|
|
CloseHandle ( g_RequestEvent ) ;
|
|
|
|
g_StartedEvent = NULL ;
|
|
g_ReplyEvent = NULL ;
|
|
g_RequestEvent = NULL ;
|
|
|
|
return WBEM_E_FAILED ;
|
|
}
|
|
|
|
SetObjectAccess ( g_Mutex ) ;
|
|
|
|
g_SharedMemory = CreateFileMapping (
|
|
|
|
( HANDLE ) -1,
|
|
NULL,
|
|
PAGE_READWRITE,
|
|
0,
|
|
sizeof ( PipeSharedMemoryMessage ) ,
|
|
__TEXT("WBEM_PIPEMARSHALER_SHAREDMEMORY")
|
|
);
|
|
|
|
SetObjectAccess ( g_SharedMemory ) ;
|
|
|
|
if ( ! g_SharedMemory )
|
|
{
|
|
CloseHandle ( g_Mutex ) ;
|
|
CloseHandle ( g_StartedEvent ) ;
|
|
CloseHandle ( g_ReplyEvent ) ;
|
|
CloseHandle ( g_RequestEvent ) ;
|
|
|
|
g_StartedEvent = NULL ;
|
|
g_ReplyEvent = NULL ;
|
|
g_RequestEvent = NULL ;
|
|
g_Mutex = NULL ;
|
|
|
|
return WBEM_E_FAILED ;
|
|
}
|
|
|
|
g_SharedMemoryBuffer = ( PipeSharedMemoryMessage * ) MapViewOfFile (
|
|
|
|
g_SharedMemory ,
|
|
FILE_MAP_WRITE ,
|
|
0 ,
|
|
0 ,
|
|
0
|
|
) ;
|
|
|
|
if ( ! g_SharedMemoryBuffer )
|
|
{
|
|
CloseHandle ( g_Mutex ) ;
|
|
CloseHandle ( g_StartedEvent ) ;
|
|
CloseHandle ( g_ReplyEvent ) ;
|
|
CloseHandle ( g_RequestEvent ) ;
|
|
CloseHandle ( g_SharedMemory ) ;
|
|
|
|
g_StartedEvent = NULL ;
|
|
g_ReplyEvent = NULL ;
|
|
g_RequestEvent = NULL ;
|
|
g_Mutex = NULL ;
|
|
g_SharedMemory = NULL ;
|
|
|
|
return WBEM_E_FAILED ;
|
|
}
|
|
|
|
SetEvent ( g_StartedEvent ) ;
|
|
|
|
return S_OK ;
|
|
}
|
|
|
|
void DestroySharedMemory ()
|
|
{
|
|
CloseHandle ( g_Mutex ) ;
|
|
CloseHandle ( g_StartedEvent ) ;
|
|
CloseHandle ( g_ReplyEvent ) ;
|
|
CloseHandle ( g_RequestEvent ) ;
|
|
CloseHandle ( g_SharedMemory ) ;
|
|
|
|
UnmapViewOfFile ( g_SharedMemoryBuffer ) ;
|
|
|
|
g_StartedEvent = NULL ;
|
|
g_ReplyEvent = NULL ;
|
|
g_RequestEvent = NULL ;
|
|
g_Mutex = NULL ;
|
|
g_SharedMemory = NULL ;
|
|
}
|
|
|
|
#ifdef TCPIP_MARSHALER
|
|
|
|
void TcpipWaitingFunction ( HANDLE a_Terminate )
|
|
{
|
|
DEBUGTRACE((LOG_WINMGMT,"\nInside the waiting function"));
|
|
|
|
SOCKET t_Socket = socket (AF_INET, SOCK_STREAM, 0);
|
|
if ( t_Socket != SOCKET_ERROR )
|
|
{
|
|
struct sockaddr_in t_LocalAddress ;
|
|
t_LocalAddress .sin_family = AF_INET;
|
|
t_LocalAddress.sin_port = htons (4000);
|
|
t_LocalAddress.sin_addr.s_addr = ntohl (INADDR_ANY);
|
|
|
|
int t_Status = bind ( t_Socket , ( sockaddr * ) &t_LocalAddress, sizeof(t_LocalAddress) ) ;
|
|
if ( t_Status != SOCKET_ERROR )
|
|
{
|
|
t_Status = listen ( t_Socket , SOMAXCONN ) ;
|
|
if ( t_Status != SOCKET_ERROR )
|
|
{
|
|
struct sockaddr_in t_RemoteAddress ;
|
|
int t_RemoteAddressLength = sizeof ( t_RemoteAddress ) ;
|
|
|
|
while ( 1 )
|
|
{
|
|
|
|
fd_set t_fdset ;
|
|
FD_ZERO ( & t_fdset ) ;
|
|
FD_SET ( t_Socket , & t_fdset ) ;
|
|
|
|
timeval t_Timeval ;
|
|
ULONG t_Seconds = 30000 / 1000 ;
|
|
ULONG t_Microseconds = ( 30000 - ( t_Seconds * 1000 ) ) * 1000 ;
|
|
t_Timeval.tv_sec = t_Seconds ;
|
|
t_Timeval.tv_usec = t_Microseconds ;
|
|
|
|
int t_Number = select ( 1 , & t_fdset ,NULL , NULL , & t_Timeval ) ;
|
|
if ( t_Number == 0 )
|
|
{
|
|
DWORD t_Status = WbemWaitForMultipleObjects(1, &a_Terminate, 0);
|
|
if ( t_Status == WAIT_OBJECT_0 )
|
|
{
|
|
break ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SOCKET t_AcceptedSocket = accept ( t_Socket , ( sockaddr * ) & t_RemoteAddress, &t_RemoteAddressLength ) ;
|
|
if ( t_AcceptedSocket != SOCKET_ERROR )
|
|
{
|
|
DWORD t_WriteStreamStatus = CTransportStream::no_error;
|
|
CTransportStream t_WriteStream ;
|
|
|
|
CServerLogin *t_Login = new CServerLogin ;
|
|
if ( t_Login )
|
|
{
|
|
t_WriteStreamStatus |= t_WriteStream.WriteDWORD ( WBEM_NO_ERROR ) ;
|
|
t_WriteStreamStatus |= t_WriteStream.WriteDWORD ( ( DWORD ) t_Login ) ;
|
|
|
|
t_WriteStream.Serialize ( t_AcceptedSocket ) ;
|
|
|
|
CComLink *t_ComLink = new CComLink_Tcpip ( NORMALSERVER , t_AcceptedSocket );
|
|
if ( t_ComLink != NULL )
|
|
{
|
|
t_ComLink->AddRef2 ( t_Login , LOGIN , RELEASEIT ) ;
|
|
|
|
t_ComLink->Release2 ( NULL , NONE ) ; // balances the initial count of 1
|
|
}
|
|
}
|
|
else
|
|
{
|
|
t_WriteStreamStatus |= t_WriteStream.WriteDWORD ( WBEM_E_INVALID_STREAM ) ;
|
|
t_WriteStreamStatus |= t_WriteStream.WriteDWORD ( 0 ) ;
|
|
|
|
t_WriteStream.Serialize ( t_AcceptedSocket ) ;
|
|
|
|
closesocket ( t_AcceptedSocket ) ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DWORD t_Error = WSAGetLastError () ;
|
|
OutputDebugString ( "Accept Failure" ) ;
|
|
break ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
closesocket ( t_Socket ) ;
|
|
}
|
|
}
|
|
|
|
DWORD LaunchTcpipConnectionThread ( HANDLE a_Parameter )
|
|
{
|
|
InitializeCom () ;
|
|
|
|
HANDLE t_Terminate = ( HANDLE ) a_Parameter ;
|
|
|
|
BOOL status = FALSE ;
|
|
WORD wVersionRequested;
|
|
WSADATA wsaData;
|
|
|
|
wVersionRequested = MAKEWORD(1, 1);
|
|
status = ( WSAStartup ( wVersionRequested , &wsaData ) == 0 ) ;
|
|
if ( status )
|
|
{
|
|
TcpipWaitingFunction ( t_Terminate ) ;
|
|
WSACleanup () ;
|
|
}
|
|
|
|
MyCoUninitialize () ;
|
|
|
|
return 0 ;
|
|
}
|
|
|
|
#endif
|