|
|
/*++
Copyright (C) Microsoft Corporation, 1996 - 1999
Module Name:
ComInitr
Abstract:
This module implements the methods for the Communications Initiation Class.
Author:
Doug Barlow (dbarlow) 10/30/1996
Environment:
Win32, C++ w/ Exceptions
Notes:
--*/
#define __SUBROUTINE__
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <limits.h>
#include <WinSCard.h>
#include <CalMsgs.h>
#include <CalCom.h>
#include <stdlib.h>
#include <aclapi.h>
HANDLE g_hCalaisShutdown = NULL; // This is used by the Send and Receive
// methods of the CComChannel. It stays
// NULL.
//
//==============================================================================
//
// CComInitiator
//
/*++
Initiate:
This method creates a communications channel object to the supplied target.
Arguments:
szName supplies the full file name of the target with which to initiate a connection.
Return Value:
None
Throws:
DWORDs representing any error conditions encountered.
Author:
Doug Barlow (dbarlow) 10/30/1996
--*/ #undef __SUBROUTINE__
#define __SUBROUTINE__ DBGT("CComInitiator::Initiate")
CComChannel * CComInitiator::Initiate( LPCTSTR szName, LPDWORD pdwVersion) const { LPCTSTR szPipeHdr = CalaisString(CALSTR_PIPEDEVICEHEADER); CComChannel *pChannel = NULL; CHandleObject hComPipe(DBGT("Comm Pipe Handle from CComInitiator::Initiate"));
try { BOOL fSts; DWORD dwSts; DWORD cbPipeHeader = lstrlen(szPipeHdr) * sizeof(TCHAR); CBuffer bfPipeName; DWORD dwLen; HANDLE hStarted; DWORD nPipeNo; HKEY hCurrentKey; TCHAR szPipeNo[sizeof(nPipeNo)*2 + 1]; // Twice as many hex digits + zero
DWORD cbData; DWORD ValueType;
//
// Build the pipe name.
//
dwLen = lstrlen(szName) * sizeof(TCHAR); bfPipeName.Presize(cbPipeHeader + dwLen + sizeof(szPipeNo));
//
// Build our Connect Request block.
//
CComChannel::CONNECT_REQMSG creq; CComChannel::CONNECT_RSPMSG crsp;
hStarted = AccessStartedEvent(); if ((NULL == hStarted) || (WAIT_OBJECT_0 != WaitForSingleObject(hStarted, 0))) { throw (DWORD)SCARD_E_NO_SERVICE; }
//
// Open the Current key.
//
dwSts = RegOpenKeyEx( HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Cryptography\\Calais\\Current"), 0, // options (ignored)
KEY_QUERY_VALUE, &hCurrentKey ); if (ERROR_SUCCESS != dwSts) { CalaisWarning( __SUBROUTINE__, DBGT("Comm Initiator could not access the Current key: %1"), dwSts); throw dwSts; }
cbData = sizeof(nPipeNo); dwSts = RegQueryValueEx( hCurrentKey, NULL, // Use key's unnamed value
0, &ValueType, (LPBYTE) &nPipeNo, &cbData);
RegCloseKey(hCurrentKey);
if (dwSts != ERROR_SUCCESS || ValueType != REG_DWORD) { CalaisWarning( __SUBROUTINE__, DBGT("Comm Initiator failed to query the Current value: %1"), dwSts); throw dwSts; }
_itot(nPipeNo, szPipeNo, 16);
bfPipeName.Set((LPCBYTE)szPipeHdr, cbPipeHeader); bfPipeName.Append((LPCBYTE)szName, dwLen); bfPipeName.Append((LPCBYTE)szPipeNo, sizeof(szPipeNo));
{ PSID pPipeOwnerSid; PSID pLocalServiceSid = NULL; PSECURITY_DESCRIPTOR pSD = NULL; SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
RetryGetInfo: dwSts = GetNamedSecurityInfo( (LPTSTR)(LPCTSTR)bfPipeName, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION, &pPipeOwnerSid, NULL, NULL, NULL, &pSD); if (ERROR_SUCCESS != dwSts) { if (ERROR_PIPE_BUSY == dwSts) { fSts = WaitNamedPipe((LPCTSTR)bfPipeName, NMPWAIT_USE_DEFAULT_WAIT); if (!fSts) { dwSts = GetLastError(); CalaisWarning( __SUBROUTINE__, DBGT("Comm Initiator could not wait for a communication pipe: %1"), dwSts); throw dwSts; } goto RetryGetInfo; } CalaisWarning( __SUBROUTINE__, DBGT("Comm Initiator could not get the security info: %1"), dwSts); throw dwSts; }
if (!AllocateAndInitializeSid( &NtAuthority, 1, SECURITY_LOCAL_SERVICE_RID, 0, 0, 0, 0, 0, 0, 0, &pLocalServiceSid)) { dwSts = GetLastError(); CalaisWarning( __SUBROUTINE__, DBGT("Comm Initiator could not create SID: %1"), dwSts); } else { if (!EqualSid(pLocalServiceSid, pPipeOwnerSid)) { dwSts = GetLastError(); CalaisWarning( __SUBROUTINE__, DBGT("Comm Initiator could not verify the owner of the pipe: %1"), dwSts); }
FreeSid(pLocalServiceSid); }
LocalFree(pSD); if (ERROR_SUCCESS != dwSts) { throw dwSts; } }
RetryCreate: hComPipe = CreateFile( (LPCTSTR)bfPipeName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (!hComPipe.IsValid()) { dwSts = hComPipe.GetLastError(); switch (dwSts) {
//
// The resource manager isn't started.
case ERROR_FILE_NOT_FOUND: CalaisWarning( __SUBROUTINE__, DBGT("Comm Initiator could not create communication pipe: %1"), dwSts); throw (DWORD)SCARD_E_NO_SERVICE; break;
//
// The pipe is busy.
case ERROR_PIPE_BUSY: fSts = WaitNamedPipe((LPCTSTR)bfPipeName, NMPWAIT_USE_DEFAULT_WAIT); if (!fSts) { dwSts = GetLastError(); CalaisWarning( __SUBROUTINE__, DBGT("Comm Initiator could not wait for a communication pipe: %1"), dwSts); throw dwSts; } goto RetryCreate; break;
//
// A hard error.
default: CalaisWarning( __SUBROUTINE__, DBGT("Comm Initiator could not create communication pipe: %1"), dwSts); throw dwSts; } }
creq.dwSync = 0; creq.dwVersion = *pdwVersion;
//
// Establish the communication.
//
pChannel = new CComChannel(hComPipe); if (NULL == pChannel) { dwSts = SCARD_E_NO_MEMORY; CalaisWarning( __SUBROUTINE__, DBGT("Com Initiator could not allocate a Comm Channel: %1"), dwSts); throw dwSts; } hComPipe.Relinquish(); pChannel->Send(&creq, sizeof(creq)); pChannel->Receive(&crsp, sizeof(crsp)); if (ERROR_SUCCESS != crsp.dwStatus) throw crsp.dwStatus;
//
// Check the response.
// In future versions, we may have to negotiate a version.
//
if (crsp.dwVersion != *pdwVersion) throw (DWORD)SCARD_F_COMM_ERROR; *pdwVersion = crsp.dwVersion; }
catch (...) { if (NULL != pChannel) delete pChannel; if (hComPipe.IsValid()) hComPipe.Close(); throw; }
return pChannel; }
|