|
|
//---------------------------------------------------------------------
// Copyright (C)1998 Microsoft Corporation, All Rights Reserved.
//
// irtranp.cpp
//
// This file holds the main entry points for the IrTran-P service.
// IrTranP() is the entry point that starts the listening, and
// UninitializeIrTranP() shuts it down (and cleans everything up).
//
// Author:
//
// Edward Reus (edwardr) 02-26-98 Initial coding.
//
//---------------------------------------------------------------------
#include "precomp.h"
#include <mbstring.h>
#include "irrecv.h"
#include "eventlog.h"
#define WSZ_REG_KEY_IRTRANP L"Control Panel\\Infrared\\IrTranP"
#define WSZ_REG_DISABLE_IRCOMM L"DisableIrCOMM"
//---------------------------------------------------------------------
// Listen ports array:
//---------------------------------------------------------------------
typedef struct _LISTEN_PORT { char *pszService; // Service to start.
BOOL fIsIrCOMM; // TRUE iff IrCOMM 9-wire mode.
DWORD dwListenStatus; // Status for port.
} LISTEN_PORT;
static LISTEN_PORT aListenPorts[] = { // Service Name IrCOMM ListenStatus
{IRTRANP_SERVICE, FALSE, STATUS_STOPPED }, {IRCOMM_9WIRE, TRUE, STATUS_STOPPED }, // {IR_TEST_SERVICE, FALSE, STATUS_STOPPED }, 2nd test listen port.
{0, FALSE, STATUS_STOPPED } };
#define INDEX_IRTRANPV1 0
#define INDEX_IRCOMM 1
CCONNECTION_MAP *g_pConnectionMap = 0; CIOSTATUS *g_pIoStatus = 0; HANDLE g_hShutdownEvent;
//
// The following globals and functions are defined in ..\irxfer\irxfer.cxx
//
extern "C" HINSTANCE ghInstance; extern "C" HANDLE g_UserToken; extern HKEY g_hUserKey; extern BOOL g_fDisableIrTranPv1; extern BOOL g_fDisableIrCOMM; extern BOOL g_fExploreOnCompletion; extern BOOL g_fSaveAsUPF; extern wchar_t g_DefaultPicturesFolder[]; extern wchar_t g_SpecifiedPicturesFolder[]; extern BOOL g_fAllowReceives;
extern BOOL IrTranPFlagChanged( IN const WCHAR *pwszDisabledValueName, IN BOOL NotPresentValue, IN OUT BOOL *pfDisabled );
//---------------------------------------------------------------------
// GetUserToken()
//
// The "main" part of irxfer.dll (in ..\irxfer) maintains a token
// for user that is currently logged in (if any).
//---------------------------------------------------------------------
HANDLE GetUserToken() { return g_UserToken; }
//---------------------------------------------------------------------
// GetUserKey()
//
//---------------------------------------------------------------------
HKEY GetUserKey() { return g_hUserKey; }
//---------------------------------------------------------------------
// GetModule()
//
//---------------------------------------------------------------------
HINSTANCE GetModule() { return ghInstance; }
//---------------------------------------------------------------------
// GetRpcBinding()
//
//---------------------------------------------------------------------
handle_t GetRpcBinding() { if (g_pIoStatus) { return g_pIoStatus->GetRpcBinding(); } else { return 0; } }
//---------------------------------------------------------------------
// CheckSaveAsUPF()
//
// Return TRUE iff pictures need to be saved in .UPF (as opposed to
// .JPEG) format.
//---------------------------------------------------------------------
BOOL CheckSaveAsUPF() { return g_fSaveAsUPF; }
//---------------------------------------------------------------------
// CheckExploreOnCompletion()
//
// Return TRUE iff we want to popup an explorer on the directory
// containing the newly transfered pictures.
//---------------------------------------------------------------------
BOOL CheckExploreOnCompletion() { return g_fExploreOnCompletion; }
//---------------------------------------------------------------------
// GetUserDirectory();
//
// The "main" part of irxfer.dll (in ..\irxfer) maintains the path
// for My Documents\My Pictures for the currently logged in user.
//
// The path is set when the user first logs on.
//---------------------------------------------------------------------
WCHAR *GetUserDirectory() { WCHAR *pwszPicturesFolder;
if (g_SpecifiedPicturesFolder[0]) { pwszPicturesFolder = g_SpecifiedPicturesFolder; } else if (g_DefaultPicturesFolder[0]) { pwszPicturesFolder = g_DefaultPicturesFolder; } else { DWORD dwLen;
if ( ((dwLen=GetWindowsDirectory(g_DefaultPicturesFolder,MAX_PATH)) > 0) && (dwLen < MAX_PATH) && (dwLen > 0) ) { g_DefaultPicturesFolder[2] = 0; // Just want "C:"...
wcscat(g_DefaultPicturesFolder,WSZ_BACKUP_MY_PICTURES); } else { wcscpy(g_DefaultPicturesFolder,WSZ_BACKUP_DRIVE); wcscat(g_DefaultPicturesFolder,WSZ_BACKUP_MY_PICTURES); }
pwszPicturesFolder = g_DefaultPicturesFolder; }
return pwszPicturesFolder; }
//---------------------------------------------------------------------
// ReceivesAllowed()
//
// Using the IR configuration window (available from the wireless network
// icon in the control panel) you can disable communications with IR
// devices. This function returns the state of IR communications, FALSE
// is disabled, TRUE is enabled.
//---------------------------------------------------------------------
BOOL ReceivesAllowed() { return g_fAllowReceives; }
//---------------------------------------------------------------------
// SetupListenConnection()
//
//---------------------------------------------------------------------
DWORD SetupListenConnection( IN CHAR *pszService, IN BOOL fIsIrCOMM, IN HANDLE hIoCompletionPort ) { DWORD dwStatus = NO_ERROR; CIOPACKET *pIoPacket; CCONNECTION *pConnection; BOOL fDisabled = FALSE;
if (g_pConnectionMap == NULL) {
return NO_ERROR; }
// See if the connection already exists:
if (g_pConnectionMap->LookupByServiceName(pszService)) { return NO_ERROR; } #if 0
// Check the registry to see if IrTran-P on this service port is
// enabled. If its disabled, the quit now...
DWORD dwLen = strlen(pszService); WCHAR wszService[255]; ASSERT(dwLen < 255); if (0 == MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, pszService, 1+dwLen, wszService, 1+dwLen )) { dwStatus = GetLastError(); #ifdef DBG_ERROR
DbgPrint("SetupForListen(): InitializeForListen(%s): MultiByteToWideChar() Failed: %d\n", pszService, dwStatus); #endif
// Ignore this error and continue on...
} else { IrTranPFlagChanged( wszService, fIsIrCOMM,&fDisabled ); if (fDisabled) { return NO_ERROR; } } #endif
// Makeup and initialize a new connection object:
pConnection = new CCONNECTION; if (!pConnection) { return E_OUTOFMEMORY; }
dwStatus = pConnection->InitializeForListen( pszService, fIsIrCOMM, hIoCompletionPort ); if (dwStatus) { #ifdef DBG_ERROR
DbgPrint("SetupForListen(): InitializeForListen(%s) failed: %d\n", pszService, dwStatus ); #endif
return dwStatus; }
pIoPacket = new CIOPACKET; if (!pIoPacket) { #ifdef DBG_ERROR
DbgPrint("SetupForListen(): new CIOPACKET failed.\n"); #endif
return E_OUTOFMEMORY; }
// Setup the IO packet:
dwStatus = pIoPacket->Initialize( PACKET_KIND_LISTEN, pConnection->GetListenSocket(), INVALID_SOCKET, hIoCompletionPort ); if (dwStatus != NO_ERROR) { return dwStatus; }
// Post the listen packet on the IO completion port:
dwStatus = pConnection->PostMoreIos(pIoPacket); if (dwStatus != NO_ERROR) { return dwStatus; }
pConnection->SetSocket(pIoPacket->GetSocket());
if (!g_pConnectionMap->Add(pConnection,pIoPacket->GetListenSocket())) { #ifdef DBG_ERROR
DbgPrint("SetupForListen(): Add(pConnection) ConnectionMap Failed.\n"); #endif
return 1; }
return dwStatus; }
//---------------------------------------------------------------------
// TeardownListenConnection()
//
//---------------------------------------------------------------------
DWORD TeardownListenConnection( IN char *pszService ) { DWORD dwStatus = NO_ERROR; CCONNECTION *pConnection;
// Look for the connection associated with the service name:
if (!g_pConnectionMap) { // nothing to tear down...
return dwStatus; }
pConnection = g_pConnectionMap->LookupByServiceName(pszService);
if (pConnection) { g_pConnectionMap->RemoveConnection(pConnection); pConnection->CloseSocket(); pConnection->CloseListenSocket(); }
return dwStatus; }
//---------------------------------------------------------------------
// EnableDisableIrCOMM()
//
//---------------------------------------------------------------------
DWORD EnableDisableIrCOMM( IN BOOL fDisable ) { DWORD dwStatus; DWORD dwEventStatus = 0; EVENT_LOG EventLog(WS_EVENT_SOURCE,&dwEventStatus);
#ifdef DBG_ERROR
if (dwEventStatus) { DbgPrint("IrTranP: Open EventLog failed: %d\n",dwEventStatus); } #endif
if (g_pIoStatus == NULL) {
return 0; }
if (fDisable) { dwStatus = TeardownListenConnection( aListenPorts[INDEX_IRCOMM].pszService); #ifdef DBG_REGISTRY
DbgPrint("IrTranP: TeardownListenConnection(%s): %d\n", aListenPorts[INDEX_IRCOMM].pszService,dwStatus); #endif
if ((dwStatus == 0) && (dwEventStatus == 0)) { EventLog.ReportInfo(CAT_IRTRANP, MC_IRTRANP_STOPPED_IRCOMM); } } else { dwStatus = SetupListenConnection( aListenPorts[INDEX_IRCOMM].pszService, aListenPorts[INDEX_IRCOMM].fIsIrCOMM, g_pIoStatus->GetIoCompletionPort() ); #ifdef DBG_REGISTRY
DbgPrint("IrTranP: SetupListenConnection(%s): %d\n", aListenPorts[INDEX_IRCOMM].pszService, dwStatus); #endif
if (dwEventStatus == 0) { if (dwStatus) { EventLog.ReportError(CAT_IRTRANP, MC_IRTRANP_IRCOM_FAILED, dwStatus); } #ifdef DBG
else { EventLog.ReportInfo(CAT_IRTRANP, MC_IRTRANP_STARTED_IRCOMM); } #endif
} }
return dwStatus; }
//---------------------------------------------------------------------
// EnableDisableIrTranPv1()
//
//---------------------------------------------------------------------
DWORD EnableDisableIrTranPv1( IN BOOL fDisable ) { DWORD dwStatus;
if (g_pIoStatus == NULL) {
return 0; }
if (fDisable) { dwStatus = TeardownListenConnection( aListenPorts[INDEX_IRTRANPV1].pszService); #ifdef DBG_REGISTRY
DbgPrint("IrTranP: TeardownListenConnection(%s): %d\n", aListenPorts[INDEX_IRCOMM].pszService,dwStatus); #endif
} else { dwStatus = SetupListenConnection( aListenPorts[INDEX_IRTRANPV1].pszService, aListenPorts[INDEX_IRTRANPV1].fIsIrCOMM, g_pIoStatus->GetIoCompletionPort() ); #ifdef DBG_REGISTRY
DbgPrint("IrTranP: SetupListenConnection(%s): %d\n", aListenPorts[INDEX_IRCOMM].pszService, dwStatus); #endif
}
return dwStatus; }
//---------------------------------------------------------------------
// IrTranp()
//
// Thread function for the IrTran-P service. pvRpcBinding is the RPC
// connection to the IR user interface and is used to display the
// "transmission in progress" dialog when pictures are being received.
//---------------------------------------------------------------------
DWORD WINAPI IrTranP( IN void *pvRpcBinding ) { int i = 0; WSADATA wsaData; WORD wVersion = MAKEWORD(1,1); DWORD dwStatus; DWORD dwEventStatus; CCONNECTION *pConnection;
// Initialize Memory Management:
dwStatus = InitializeMemory(); if (dwStatus) { return dwStatus; }
// Initialize Winsock2:
if (WSAStartup(wVersion,&wsaData) == SOCKET_ERROR) { dwStatus = WSAGetLastError(); #ifdef DBG_ERROR
DbgPrint("WSAStartup(0x%x) failed with error %d\n", wVersion, dwStatus ); #endif
return dwStatus; }
// Event used to signal back to "main" thread that the
// IrTran-P thread is exiting.
g_hShutdownEvent = CreateEvent( NULL, // No security.
FALSE, // Auto-reset.
FALSE, // Initially not signaled.
NULL ); // No name.
if (!g_hShutdownEvent) { dwStatus = GetLastError(); return dwStatus; }
// Create/initialize a object to keep track of the threading...
g_pIoStatus = new CIOSTATUS; if (!g_pIoStatus) { #ifdef DBG_ERROR
DbgPrint("new CIOSTATUS failed.\n"); #endif
WSACleanup(); return E_OUTOFMEMORY; }
g_pIoStatus->SaveRpcBinding( (handle_t*)pvRpcBinding );
dwStatus = g_pIoStatus->Initialize(); if (dwStatus != NO_ERROR) { #ifdef DBG_ERROR
DbgPrint("g_pIoStatus->Initialize(): Failed: %d\n",dwStatus); #endif
WSACleanup(); return dwStatus; }
// Need to keep track of the open sockets and the number of
// pending IOs on each...
g_pConnectionMap = new CCONNECTION_MAP; if (!g_pConnectionMap) { WSACleanup(); return E_OUTOFMEMORY; }
if (!g_pConnectionMap->Initialize()) { delete g_pConnectionMap; g_pConnectionMap = 0; return 1; } #if 0
// Create a CIOPACKET for each defined listen port. These are
// what we will listen on.
while (aListenPorts[i].pszService) { dwStatus = SetupListenConnection( aListenPorts[i].pszService, aListenPorts[i].fIsIrCOMM, g_pIoStatus->GetIoCompletionPort() );
if (dwStatus) { delete g_pConnectionMap; g_pConnectionMap = 0; return dwStatus; }
aListenPorts[i++].dwListenStatus = STATUS_RUNNING; } #else
//
// just irtanpv1
//
i=INDEX_IRTRANPV1; dwStatus = SetupListenConnection( aListenPorts[i].pszService, aListenPorts[i].fIsIrCOMM, g_pIoStatus->GetIoCompletionPort() );
if (dwStatus) {
delete g_pConnectionMap; g_pConnectionMap = 0; return dwStatus; }
aListenPorts[i].dwListenStatus = STATUS_RUNNING;
#endif
//
// IrTran-P started, log it to the system log...
//
#ifdef DBG
{ EVENT_LOG EventLog(WS_EVENT_SOURCE,&dwEventStatus);
if (dwEventStatus == 0) { EventLog.ReportInfo(CAT_IRTRANP,MC_IRTRANP_STARTED); } } #endif
//
// Wait on incomming connections and data, then process it.
//
dwStatus = ProcessIoPackets(g_pIoStatus);
// Cleanup and close any open handles:
while (pConnection=g_pConnectionMap->RemoveNext()) { delete pConnection; }
delete g_pConnectionMap; g_pConnectionMap = 0; delete g_pIoStatus; g_pIoStatus = 0;
// Signal the shutdown event that the IrTran-P thread is exiting:
if (g_hShutdownEvent) { SetEvent(g_hShutdownEvent); }
return dwStatus; }
//---------------------------------------------------------------------
// IrTranPEnableIrCOMMFailed()
//
//---------------------------------------------------------------------
void IrTranPEnableIrCOMMFailed( DWORD dwErrorCode ) { DWORD dwStatus;
// An error occured on enable, make sure the registry value
// is set to disable (so UI will match the actual state).
HKEY hKey = 0; HKEY hUserKey = GetUserKey(); HANDLE hUserToken = GetUserToken(); HINSTANCE hInstance = GetModule(); DWORD dwDisposition;
if (RegCreateKeyExW(hUserKey, WSZ_REG_KEY_IRTRANP, 0, // reserved MBZ
0, // class name
REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, 0, // security attributes
&hKey, &dwDisposition)) { #ifdef DBG_ERROR
DbgPrint("IrTranP: RegCreateKeyEx(): '%S' failed %d", WSZ_REG_KEY_IRTRANP, GetLastError()); #endif
}
if ( (hKey) && (hUserToken) && (::ImpersonateLoggedOnUser(hUserToken))) { DWORD dwDisableIrCOMM = TRUE; dwStatus = RegSetValueExW(hKey, WSZ_REG_DISABLE_IRCOMM, 0, REG_DWORD, (UCHAR*)&dwDisableIrCOMM, sizeof(dwDisableIrCOMM) ); #ifdef DBG_ERROR
if (dwStatus != ERROR_SUCCESS) { DbgPrint("IrTranP: Can't set DisableIrCOMM to TRUE in registry. Error: %d\n",dwStatus); } #endif
::RevertToSelf(); }
if (hKey) { RegCloseKey(hKey); }
WCHAR *pwszMessage = NULL; WCHAR *pwszCaption = NULL; DWORD dwFlags = ( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE);
dwStatus = FormatMessageW(dwFlags, hInstance, CAT_IRTRANP, MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), (LPTSTR)(&pwszCaption), 0, // Minimum size to allocate.
NULL); // va_list args...
if (dwStatus == 0) { #ifdef DBG_ERROR
DbgPrint("IrTranP: FormatMessage() failed: %d\n",GetLastError() ); #endif
return; }
//
// Hack: Make sure the caption doesn't end with newline-formfeed...
//
WCHAR *pwsz = pwszCaption;
while (*pwsz) { if (*pwsz < 0x20) // 0x20 is always a space...
{ *pwsz = 0; break; } else { pwsz++; } }
WCHAR wszErrorCode[20]; WCHAR *pwszErrorCode = (WCHAR*)wszErrorCode;
wsprintfW(wszErrorCode,L"%d",dwErrorCode);
dwFlags = ( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY | FORMAT_MESSAGE_FROM_HMODULE);
dwStatus = FormatMessageW(dwFlags, hInstance, MC_IRTRANP_IRCOM_FAILED, MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), (LPTSTR)(&pwszMessage), 0, // Minimum size to allocate.
(va_list*)&pwszErrorCode); if (dwStatus == 0) { #ifdef DBG_ERROR
DbgPrint("IrTranP: FormatMessage() failed: %d\n",GetLastError() ); #endif
if (pwszMessage) { LocalFree(pwszMessage); }
return; }
dwStatus = MessageBoxW( NULL, pwszMessage, pwszCaption, (MB_OK|MB_ICONERROR|MB_SETFOREGROUND|MB_TOPMOST) );
if (pwszMessage) { LocalFree(pwszMessage); }
if (pwszCaption) { LocalFree(pwszCaption); } }
//---------------------------------------------------------------------
// UninitializeIrTranP()
//
//---------------------------------------------------------------------
BOOL UninitializeIrTranP( HANDLE hThread ) { BOOL fSuccess = TRUE; DWORD dwStatus; HANDLE hIoCP = g_pIoStatus->GetIoCompletionPort();
if (hIoCP != INVALID_HANDLE_VALUE) { if (!PostQueuedCompletionStatus(hIoCP,0,IOKEY_SHUTDOWN,0)) { // Unexpected error...
dwStatus = GetLastError(); #ifdef DBG_IO
DbgPrint("UninitializeIrTranP(): PostQueuedCompletionStatus() Failed: %d\n",dwStatus); #endif
}
while (WAIT_TIMEOUT == WaitForSingleObject(g_hShutdownEvent,0)) { Sleep(100); }
CloseHandle(g_hShutdownEvent); }
// Shutdown memory management:
dwStatus = UninitializeMemory();
return fSuccess; }
#if FALSE
//---------------------------------------------------------------------
// main()
//
//---------------------------------------------------------------------
int __cdecl main( int argc, char **argv ) { DWORD dwStatus;
dwStatus = IrTranP( NULL );
return 0; } #endif
|