Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1345 lines
33 KiB

/*****************************************************************************
*
* Copyright (C) Microsoft Corporation, 1995 - 1999
*
* File: irmon.c
*
* Description: Infrared monitor
*
* Author: mbert/mikezin
*
* Date: 3/1/98
*
*/
#define UNICODE
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <winsock2.h>
#include <af_irda.h>
#include <shellapi.h>
#include <resource.h>
#include <resrc1.h>
#include <irioctl.h>
// allocate storage! and initialize the GUIDS
#include <initguid.h>
#include <devguid.h>
#include <setupapi.h>
#include <cfgmgr32.h>
#include <mmsystem.h>
#include <wtsapi32.h>
#include <strsafe.h>
#include "internal.h"
#include <devlist.h>
#include <irtypes.h>
#include <irmon.h>
#include "irdisc.h"
#include <irmonftp.h>
#define WM_IP_DEVICE_CHANGE (WM_USER+500)
#define WM_IR_DEVICE_CHANGE (WM_USER+501)
#define WM_IR_LINK_CHANGE (WM_USER+502)
#define IRXFER_DLL TEXT("irxfer.dll")
#define IAS_LSAP_SEL "IrDA:TinyTP:LsapSel"
#define IRXFER_CLASSNAME "OBEX:IrXfer"
#define IRXFER_CLASSNAME2 "OBEX"
#define IRMON_SERVICE_NAME TEXT("irmon")
#define IRMON_CONFIG_KEY TEXT("System\\CurrentControlSet\\Services\\Irmon")
#define IRMON_SHOW_ICON_KEY TEXT("ShowTrayIcon")
#define IRMON_NO_SOUND_KEY TEXT("NoSound")
#define TRANSFER_EXE TEXT("irxfer")
#define PROPERTIES_EXE TEXT("irxfer /s")
#define IRDA_DEVICE_NAME TEXT("\\Device\\IrDA")
#define DEVICE_LIST_LEN 5
#define TOOL_TIP_STR_SIZE 64
#define EMPTY_STR TEXT("")
#define SYSTRAYEVENTID WM_USER + 1
#define EV_STOP_EVENT 0
#define EV_REG_CHANGE_EVENT 1
#define EV_TRAY_STATUS_EVENT 2
#define WAIT_EVENT_CNT 3
#define MAX_ATTRIB_LEN 64
#define MAKE_LT_UPDATE(a,b) (a << 16) + b
#define RETRY_DSCV_TIMER 1
#define RETRY_DSCV_INTERVAL 10000 // 10 seconds
#define CONN_ANIMATION_TIMER 2
#define CONN_ANIMATION_INTERVAL 250
#define RETRY_TRAY_UPDATE_TIMER 3
#define RETRY_TRAY_UPDATE_INTERVAL 4000 // 4 seconds
typedef enum
{
ICON_ST_NOICON,
ICON_ST_CONN1 = 1,
ICON_ST_CONN2,
ICON_ST_CONN3,
ICON_ST_CONN4,
ICON_ST_IN_RANGE,
ICON_ST_IP_IN_RANGE,
ICON_ST_INTR
} ICON_STATE;
typedef struct _IRMON_CONTROL {
CRITICAL_SECTION Lock;
PVOID IrxferContext;
HWND hWnd;
WSAOVERLAPPED Overlapped;
HANDLE DiscoveryObject;
BOOL SoundOn;
} IRMON_CONTROL, *PIRMON_CONTROL;
IRMON_CONTROL GlobalIrmonControl;
HANDLE hIrmonEvents[WAIT_EVENT_CNT];
BYTE FoundDevListBuf[ sizeof(OBEX_DEVICE_LIST) + sizeof(OBEX_DEVICE)*MAX_OBEX_DEVICES];
OBEX_DEVICE_LIST * const pDeviceList=(POBEX_DEVICE_LIST)FoundDevListBuf;
TCHAR IrmonClassName[] = TEXT("IrmonClass");
BOOLEAN IconInTray;
BOOLEAN IrmonStopped;
HICON hInRange;
HICON hIpInRange;
HICON hInterrupt;
HICON hConn1;
HICON hConn2;
HICON hConn3;
HICON hConn4;
IRLINK_STATUS LinkStatus;
HINSTANCE ghInstance;
BOOLEAN UserLoggedIn;
BOOLEAN TrayEnabled;
BOOLEAN DeviceListUpdated;
UINT LastTrayUpdate; // debug purposes
UINT_PTR RetryTrayUpdateTimerId;
BOOLEAN RetryTrayUpdateTimerRunning;
int TrayUpdateFailures;
UINT_PTR ConnAnimationTimerId;
TCHAR ConnDevName[64];
UINT ConnIcon;
int ConnAddition;
BOOLEAN InterruptedSoundPlaying;
HKEY ghCurrentUserKey = 0;
BOOLEAN ShowBalloonTip;
BOOLEAN IrxferDeviceInRange;
HMODULE hIrxfer;
extern BOOL ShowSendWindow();
extern BOOL ShowPropertiesPage();
extern
void
UpdateDiscoveredDevices(
const OBEX_DEVICE_LIST *IrDevices
);
VOID
InitiateLazyDscv(
PIRMON_CONTROL IrmonControl
);
VOID
InitiateLinkStatusQuery(
PIRMON_CONTROL IrmonControl
);
#if DBG
TCHAR *
GetLastErrorText()
{
switch (WSAGetLastError())
{
case WSAEINTR:
return (TEXT("WSAEINTR"));
break;
case WSAEBADF:
return(TEXT("WSAEBADF"));
break;
case WSAEACCES:
return(TEXT("WSAEACCES"));
break;
case WSAEFAULT:
return(TEXT("WSAEFAULT"));
break;
case WSAEINVAL:
return(TEXT("WSAEINVAL"));
break;
case WSAEMFILE:
return(TEXT("WSAEMFILE"));
break;
case WSAEWOULDBLOCK:
return(TEXT("WSAEWOULDBLOCK"));
break;
case WSAEINPROGRESS:
return(TEXT("WSAEINPROGRESS"));
break;
case WSAEALREADY:
return(TEXT("WSAEALREADY"));
break;
case WSAENOTSOCK:
return(TEXT("WSAENOTSOCK"));
break;
case WSAEDESTADDRREQ:
return(TEXT("WSAEDESTADDRREQ"));
break;
case WSAEMSGSIZE:
return(TEXT("WSAEMSGSIZE"));
break;
case WSAEPROTOTYPE:
return(TEXT("WSAEPROTOTYPE"));
break;
case WSAENOPROTOOPT:
return(TEXT("WSAENOPROTOOPT"));
break;
case WSAEPROTONOSUPPORT:
return(TEXT("WSAEPROTONOSUPPORT"));
break;
case WSAESOCKTNOSUPPORT:
return(TEXT("WSAESOCKTNOSUPPORT"));
break;
case WSAEOPNOTSUPP:
return(TEXT("WSAEOPNOTSUPP"));
break;
case WSAEPFNOSUPPORT:
return(TEXT("WSAEPFNOSUPPORT"));
break;
case WSAEAFNOSUPPORT:
return(TEXT("WSAEAFNOSUPPORT"));
break;
case WSAEADDRINUSE:
return(TEXT("WSAEADDRINUSE"));
break;
case WSAEADDRNOTAVAIL:
return(TEXT("WSAEADDRNOTAVAIL"));
break;
case WSAENETDOWN:
return(TEXT("WSAENETDOWN"));
break;
case WSAENETUNREACH:
return(TEXT("WSAENETUNREACH"));
break;
case WSAENETRESET:
return(TEXT("WSAENETRESET"));
break;
case WSAECONNABORTED:
return(TEXT("WSAECONNABORTED"));
break;
case WSAECONNRESET:
return(TEXT("WSAECONNRESET"));
break;
case WSAENOBUFS:
return(TEXT("WSAENOBUFS"));
break;
case WSAEISCONN:
return(TEXT("WSAEISCONN"));
break;
case WSAENOTCONN:
return(TEXT("WSAENOTCONN"));
break;
case WSAESHUTDOWN:
return(TEXT("WSAESHUTDOWN"));
break;
case WSAETOOMANYREFS:
return(TEXT("WSAETOOMANYREFS"));
break;
case WSAETIMEDOUT:
return(TEXT("WSAETIMEDOUT"));
break;
case WSAECONNREFUSED:
return(TEXT("WSAECONNREFUSED"));
break;
case WSAELOOP:
return(TEXT("WSAELOOP"));
break;
case WSAENAMETOOLONG:
return(TEXT("WSAENAMETOOLONG"));
break;
case WSAEHOSTDOWN:
return(TEXT("WSAEHOSTDOWN"));
break;
case WSAEHOSTUNREACH:
return(TEXT("WSAEHOSTUNREACH"));
break;
case WSAENOTEMPTY:
return(TEXT("WSAENOTEMPTY"));
break;
case WSAEPROCLIM:
return(TEXT("WSAEPROCLIM"));
break;
case WSAEUSERS:
return(TEXT("WSAEUSERS"));
break;
case WSAEDQUOT:
return(TEXT("WSAEDQUOT"));
break;
case WSAESTALE:
return(TEXT("WSAESTALE"));
break;
case WSAEREMOTE:
return(TEXT("WSAEREMOTE"));
break;
case WSAEDISCON:
return(TEXT("WSAEDISCON"));
break;
case WSASYSNOTREADY:
return(TEXT("WSASYSNOTREADY"));
break;
case WSAVERNOTSUPPORTED:
return(TEXT("WSAVERNOTSUPPORTED"));
break;
case WSANOTINITIALISED:
return(TEXT("WSANOTINITIALISED"));
break;
/*
case WSAHOST:
return(TEXT("WSAHOST"));
break;
case WSATRY:
return(TEXT("WSATRY"));
break;
case WSANO:
return(TEXT("WSANO"));
break;
*/
default:
return(TEXT("Unknown Error"));
}
}
#endif
HKEY
OpenCurrentUserKey()
{
HKEY hUserKey;
//
// Open all our keys. If we can't open the user's key
// or the key to watch for changes, we bail.
//
if (RegOpenKeyEx(HKEY_CURRENT_USER, NULL, 0, KEY_READ, &hUserKey)) {
DEBUGMSG(("IRMON-FTP: RegOpenKey1 failed %d\n", GetLastError()));
return 0;
}
return hUserKey;
}
VOID
LoadTrayIconImages()
{
hInRange = LoadImage(ghInstance, MAKEINTRESOURCE(IDI_IN_RANGE),
IMAGE_ICON, 16,16,0);
hInterrupt= LoadImage(ghInstance, MAKEINTRESOURCE(IDI_INTR),
IMAGE_ICON, 16,16,0);
hConn1 = LoadImage(ghInstance, MAKEINTRESOURCE(IDI_CONN1),
IMAGE_ICON, 16,16,0);
hConn2 = LoadImage(ghInstance, MAKEINTRESOURCE(IDI_CONN2),
IMAGE_ICON, 16,16,0);
hConn3 = LoadImage(ghInstance, MAKEINTRESOURCE(IDI_CONN3),
IMAGE_ICON, 16,16,0);
hConn4 = LoadImage(ghInstance, MAKEINTRESOURCE(IDI_CONN4),
IMAGE_ICON, 16,16,0);
hIpInRange= LoadImage(ghInstance, MAKEINTRESOURCE(IDI_IP),
IMAGE_ICON, 16,16,0);
}
VOID
UpdateTray(
PIRMON_CONTROL IrmonControl,
ICON_STATE IconState,
DWORD MsgId,
LPTSTR DeviceName,
UINT Baud
)
{
NOTIFYICONDATA NotifyIconData;
DWORD Cnt;
TCHAR FormatStr[256];
BOOL Result = TRUE;
BOOLEAN TrayUpdateFailed = FALSE;
if (!TrayEnabled && IconState != ICON_ST_NOICON)
{
return;
}
if (!hInRange)
{
LoadTrayIconImages();
}
NotifyIconData.cbSize = sizeof(NOTIFYICONDATA);
NotifyIconData.uID = 0;
NotifyIconData.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP | NIF_INFO;
NotifyIconData.uCallbackMessage = SYSTRAYEVENTID;
NotifyIconData.hWnd = IrmonControl->hWnd;
NotifyIconData.hIcon = 0;
NotifyIconData.szInfo[0] = 0;
NotifyIconData.szInfoTitle[0] = 0;
if (MsgId == 0)
{
NotifyIconData.szTip[0] = L'\0';
}
else
{
if (LoadString(ghInstance, MsgId, FormatStr, sizeof(FormatStr)/sizeof(TCHAR)))
{
StringCbPrintf(NotifyIconData.szTip, sizeof(NotifyIconData.szTip), FormatStr, DeviceName, Baud);
}
}
if (IrmonStopped && IconState != ICON_ST_NOICON)
return;
switch (IconState)
{
case ICON_ST_NOICON:
ShowBalloonTip = TRUE;
if (IconInTray)
{
NotifyIconData.uFlags = 0;
IconInTray = FALSE;
if (Shell_NotifyIcon(NIM_DELETE, &NotifyIconData)) {
LastTrayUpdate = MAKE_LT_UPDATE(NIM_DELETE,ICON_ST_NOICON);
if (IrmonControl->SoundOn) {
PlayIrSound(OUTOFRANGE_SOUND);
}
} else {
DEBUGMSG(("IRMON-FTP: Shell_NotifyIcon(Delete) failed %d, %d\n", TrayUpdateFailures, GetLastError()));
}
}
return;
case ICON_ST_IN_RANGE:
case ICON_ST_IP_IN_RANGE:
if (IconState == ICON_ST_IP_IN_RANGE) {
NotifyIconData.hIcon = hIpInRange;
} else {
NotifyIconData.hIcon = hInRange;
}
if (ShowBalloonTip)
{
ShowBalloonTip = FALSE;
if (IrxferDeviceInRange &&
LoadString(ghInstance, IDS_BALLOON_TITLE,
NotifyIconData.szInfoTitle,
sizeof(NotifyIconData.szInfoTitle)/sizeof(TCHAR)))
{
NotifyIconData.uFlags |= NIF_INFO;
NotifyIconData.uTimeout = 10000; // in milliseconds
// NotifyIconData.dwInfoFlags = NIIF_INFO;
if (DeviceName)
{
LoadString(ghInstance, IDS_BALLOON_TXT,
FormatStr,
sizeof(FormatStr)/sizeof(TCHAR));
StringCbPrintf(NotifyIconData.szInfo, sizeof(NotifyIconData.szInfo), FormatStr, DeviceName);
}
else
{
LoadString(ghInstance, IDS_BALLOON_TXT2,
NotifyIconData.szInfo,
sizeof(NotifyIconData.szInfo)/sizeof(TCHAR));
}
}
}
break;
case ICON_ST_CONN1:
NotifyIconData.hIcon = hConn1;
break;
case ICON_ST_CONN2:
NotifyIconData.hIcon = hConn2;
break;
case ICON_ST_CONN3:
NotifyIconData.hIcon = hConn3;
break;
case ICON_ST_CONN4:
NotifyIconData.hIcon = hConn4;
break;
case ICON_ST_INTR:
NotifyIconData.hIcon = hInterrupt;
if (LoadString(ghInstance, IDS_BLOCKED_TITLE,
NotifyIconData.szInfoTitle,
sizeof(NotifyIconData.szInfoTitle)/sizeof(TCHAR)) &&
LoadString(ghInstance, IDS_BLOCKED_TXT,
NotifyIconData.szInfo,
sizeof(NotifyIconData.szInfo)/sizeof(TCHAR)))
{
NotifyIconData.uFlags |= NIF_INFO;
NotifyIconData.uTimeout = 10000; // in milliseconds
NotifyIconData.dwInfoFlags = NIIF_WARNING;
}
break;
}
if (IconState == ICON_ST_INTR) {
if (IrmonControl->SoundOn) {
PlayIrSound(INTERRUPTED_SOUND);
InterruptedSoundPlaying = TRUE;
}
} else {
if (InterruptedSoundPlaying) {
InterruptedSoundPlaying = FALSE;
PlayIrSound(END_INTERRUPTED_SOUND);
}
}
if (!IconInTray)
{
if (Shell_NotifyIcon(NIM_ADD, &NotifyIconData))
{
LastTrayUpdate = MAKE_LT_UPDATE(NIM_ADD, IconState);
if (IrmonControl->SoundOn) {
PlayIrSound(INRANGE_SOUND);
}
IconInTray = TRUE;
}
else
{
TrayUpdateFailures++;
DEBUGMSG(("IRMON-FTP: Shell_NotifyIcon(ADD) failed %d, %d\n", TrayUpdateFailures, GetLastError()));
NotifyIconData.uFlags = 0;
NotifyIconData.cbSize = sizeof(NOTIFYICONDATA);
NotifyIconData.uID = 0;
NotifyIconData.uCallbackMessage = SYSTRAYEVENTID;
NotifyIconData.hWnd = IrmonControl->hWnd;
NotifyIconData.hIcon = 0;
NotifyIconData.szInfo[0] = 0;
NotifyIconData.szInfoTitle[0] = 0;
Shell_NotifyIcon(NIM_DELETE, &NotifyIconData);
TrayUpdateFailed = TRUE;
ShowBalloonTip = TRUE;
}
}
else
{
if (!Shell_NotifyIcon(NIM_MODIFY, &NotifyIconData))
{
TrayUpdateFailures++;
DEBUGMSG(("IRMON-FTP: Shell_NotifyIcon(Modify) failed %d, %d\n", TrayUpdateFailures, GetLastError()));
TrayUpdateFailed = TRUE;
}
else
{
LastTrayUpdate = MAKE_LT_UPDATE(NIM_MODIFY, IconState);
}
}
if (TrayUpdateFailed && !RetryTrayUpdateTimerRunning)
{
RetryTrayUpdateTimerId = SetTimer(IrmonControl->hWnd, RETRY_TRAY_UPDATE_TIMER,
RETRY_TRAY_UPDATE_INTERVAL, NULL);
RetryTrayUpdateTimerRunning = TRUE;
}
}
VOID
ConnAnimationTimerExp(
PIRMON_CONTROL IrmonControl
)
{
UpdateTray(
IrmonControl,ConnIcon,
IDS_CONNECTED_TO,
ConnDevName,
LinkStatus.ConnectSpeed
);
ConnIcon += ConnAddition;
if (ConnIcon == 4)
{
ConnAddition = -1;
}
else if (ConnIcon == 1)
{
ConnAddition = 1;
}
}
VOID
IsIrxferDeviceInRange()
{
int i, LsapSel, Attempt, Status;
IrxferDeviceInRange = FALSE;
for (i = 0; i < (int)pDeviceList->DeviceCount; i++) {
if (pDeviceList->DeviceList[i].DeviceSpecific.s.Irda.ObexSupport) {
IrxferDeviceInRange = TRUE;
break;
}
}
return;
}
VOID
DevListChangeOrUpdatedLinkStatus(
PIRMON_CONTROL IrmonControl
)
{
if (!UserLoggedIn)
{
DEBUGMSG(("IRMON-FTP: User not logged in, ignoring device change\n"));
return;
}
if (DeviceListUpdated)
{
IsIrxferDeviceInRange();
}
if (LinkStatus.Flags & LF_INTERRUPTED)
{
KillTimer(IrmonControl->hWnd, ConnAnimationTimerId);
UpdateTray(IrmonControl,ICON_ST_INTR, IDS_INTERRUPTED, NULL, 0);
}
else if ((LinkStatus.Flags & LF_CONNECTED) && (pDeviceList->DeviceCount > 0))
{
ULONG i;
ConnDevName[0] = 0;
ConnIcon = 1;
ConnAddition = 1;
for (i = 0; i < pDeviceList->DeviceCount; i++)
{
if (memcmp(&pDeviceList->DeviceList[i].DeviceSpecific.s.Irda.DeviceId,
LinkStatus.ConnectedDeviceId, 4) == 0)
{
//
// the name is in unicode
//
ZeroMemory(ConnDevName,sizeof(ConnDevName));
StringCbCopy(ConnDevName, sizeof(ConnDevName),
pDeviceList->DeviceList[i].DeviceName);
break;
}
}
ConnAnimationTimerExp(IrmonControl);
ConnAnimationTimerId = SetTimer(IrmonControl->hWnd, CONN_ANIMATION_TIMER,
CONN_ANIMATION_INTERVAL, NULL);
}
else
{
KillTimer(IrmonControl->hWnd, ConnAnimationTimerId);
if ((pDeviceList->DeviceCount == 0)) {
//
// no devices in range
//
UpdateTray(IrmonControl,ICON_ST_NOICON, 0, NULL, 0);
} else {
//
// atleast one device in range
//
if ((pDeviceList->DeviceCount == 1) ) {
//
// one ir device in range
//
StringCbCopy(ConnDevName, sizeof(ConnDevName),
pDeviceList->DeviceList[0].DeviceName
);
UpdateTray(IrmonControl,ICON_ST_IN_RANGE, IDS_IN_RANGE, ConnDevName, 0);
} else {
//
// more than one device total
//
UpdateTray(IrmonControl,ICON_ST_IN_RANGE, IDS_DEVS_IN_RANGE, NULL, 0);
}
}
}
if (DeviceListUpdated)
{
HANDLE hThread;
DWORD ThreadId;
DeviceListUpdated = FALSE;
// PnP Printers, Notify transfer app
if (GlobalIrmonControl.IrxferContext != NULL) {
UpdateDiscoveredDevices(pDeviceList);
}
}
}
VOID
UserLogonEvent(
PIRMON_CONTROL IrmonControl
)
{
UINT DevListLen;
NTSTATUS Status;
OBJECT_ATTRIBUTES ObjAttr;
UNICODE_STRING DeviceName;
IO_STATUS_BLOCK IoStatusBlock;
UserLoggedIn = TRUE;
//
// Create the window that will receive the taskbar menu messages.
// The window has to be created after opening the user's desktop
// or the call to SetThreadDesktop() will if the thread has
// any windows
//
IrmonControl->hWnd = CreateWindow(
IrmonClassName,
NULL,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
ghInstance,
&GlobalIrmonControl
);
ShowWindow(IrmonControl->hWnd, SW_HIDE);
UpdateWindow(IrmonControl->hWnd);
WTSRegisterSessionNotification(IrmonControl->hWnd,NOTIFY_FOR_THIS_SESSION);
ghCurrentUserKey = OpenCurrentUserKey();
InitializeSound(
ghCurrentUserKey,
hIrmonEvents[EV_REG_CHANGE_EVENT]
);
ShowBalloonTip = TRUE;
IrmonControl->DiscoveryObject=CreateIrDiscoveryObject(
IrmonControl->hWnd,
WM_IR_DEVICE_CHANGE,
WM_IR_LINK_CHANGE
);
if (IrmonControl->DiscoveryObject == NULL) {
#if DBG
DbgPrint("IRMON-FTP: could not create ir discovery object\n");
#endif
return;
}
}
VOID
UserLogoffEvent(
PIRMON_CONTROL IrmonControl
)
{
DEBUGMSG(("IRMON-FTP: User logoff event\n"));
UserLoggedIn = FALSE;
if (IrmonControl->DiscoveryObject != NULL) {
CloseIrDiscoveryObject(IrmonControl->DiscoveryObject);
IrmonControl->DiscoveryObject = NULL;
}
UninitializeSound();
if (ghCurrentUserKey)
{
RegCloseKey(ghCurrentUserKey);
ghCurrentUserKey = 0;
}
if (IrmonControl->hWnd) {
KillTimer(IrmonControl->hWnd, ConnAnimationTimerId);
UpdateTray(&GlobalIrmonControl,ICON_ST_NOICON, 0, NULL, 0);
DestroyWindow(IrmonControl->hWnd);
IrmonControl->hWnd = 0;
}
}
VOID
SetSoundStatus(
PVOID Context,
BOOL SoundOn
)
{
PIRMON_CONTROL IrmonControl=(PIRMON_CONTROL)Context;
// DbgPrint("IRMON-FTP: sound %d\n",SoundOn);
IrmonControl->SoundOn=SoundOn;
return;
}
VOID
SetTrayStatus(
PVOID Context,
BOOL lTrayEnabled
)
{
PIRMON_CONTROL IrmonControl=(PIRMON_CONTROL)Context;
if (lTrayEnabled)
{
DEBUGMSG(("IRMON-FTP: Tray enabled\n"));
TrayEnabled = TRUE;
}
else
{
DEBUGMSG(("IRMON-FTP: Tray disabled\n"));
TrayEnabled = FALSE;
}
SetEvent(hIrmonEvents[EV_TRAY_STATUS_EVENT]);
}
LONG_PTR FAR PASCAL
WndProc(
HWND hWnd,
unsigned message,
WPARAM wParam,
LPARAM lParam)
{
PIRMON_CONTROL IrmonControl=(PIRMON_CONTROL)GetWindowLongPtr(hWnd,GWLP_USERDATA);
switch (message)
{
case WM_CREATE: {
LPCREATESTRUCT CreateStruct=(LPCREATESTRUCT)lParam;
SetWindowLongPtr(hWnd,GWLP_USERDATA,(LONG_PTR)CreateStruct->lpCreateParams);
return 0;
}
break;
case WM_COMMAND:
{
switch (wParam)
{
case IDC_TX_FILES:
ShowSendWindow();
break;
case IDC_PROPERTIES:
DEBUGMSG(("IRMON-FTP: Launch Properties page\n"));
ShowPropertiesPage();
break;
default:
;
//DEBUGMSG(("Other WM_COMMAND %X\n", wParam));
}
break;
}
case SYSTRAYEVENTID:
{
POINT pt;
HMENU hMenu, hMenuPopup;
switch (lParam)
{
case WM_LBUTTONDOWN:
ShowSendWindow();
break;
case WM_RBUTTONDOWN:
SetForegroundWindow(hWnd);
GetCursorPos(&pt);
hMenu = LoadMenu(ghInstance, MAKEINTRESOURCE(IDR_TRAY_MENU));
if (!hMenu)
{
DEBUGMSG(("IRMON-FTP: failed to load menu\n"));
break;
}
hMenuPopup = GetSubMenu(hMenu, 0);
SetMenuDefaultItem(hMenuPopup, 0, TRUE);
TrackPopupMenuEx(hMenuPopup,
TPM_LEFTALIGN | TPM_RIGHTBUTTON,
pt.x, pt.y, hWnd, NULL);
DestroyMenu(hMenu);
break;
//default:DEBUGMSG(("IRMON-FTP: Systray other %d\n", lParam));
}
break;
}
case WM_TIMER:
if (wParam == ConnAnimationTimerId)
{
ConnAnimationTimerExp(IrmonControl);
}
else if (wParam == RetryTrayUpdateTimerId)
{
DEBUGMSG(("IRMON-FTP: RetryTrayUpdateTimer expired\n"));
KillTimer(IrmonControl->hWnd, RetryTrayUpdateTimerId);
RetryTrayUpdateTimerRunning = FALSE;
DevListChangeOrUpdatedLinkStatus(IrmonControl);
}
break;
case WM_QUERYENDSESSION:
{
extern BOOL IrxferHandlePowerMessage( HWND hWnd, unsigned message, WPARAM wParam, LPARAM lParam );
return IrxferHandlePowerMessage( hWnd, message, wParam, lParam );
break;
}
case WM_ENDSESSION:
break;
case WM_POWERBROADCAST:
{
extern BOOL IrxferHandlePowerMessage( HWND hWnd, unsigned message, WPARAM wParam, LPARAM lParam );
return IrxferHandlePowerMessage( hWnd, message, wParam, lParam );
break;
}
case WM_IR_DEVICE_CHANGE: {
ULONG BufferSize=sizeof(FoundDevListBuf);
GetDeviceList(
IrmonControl->DiscoveryObject,
pDeviceList,
&BufferSize
);
DeviceListUpdated = TRUE;
DEBUGMSG(("IRMON-FTP: %d IR device(s) found:\n", pDeviceList->DeviceCount));
DevListChangeOrUpdatedLinkStatus(IrmonControl);
}
break;
case WM_IR_LINK_CHANGE: {
GetLinkStatus(
IrmonControl->DiscoveryObject,
&LinkStatus
);
DEBUGMSG(("IRMON-FTP: link state change %x\n",LinkStatus.Flags));
DevListChangeOrUpdatedLinkStatus(IrmonControl);
}
break;
case WM_WTSSESSION_CHANGE:
DEBUGMSG(("IRMON-FTP: session change %d %d\n",wParam,lParam));
if (wParam == WTS_CONSOLE_DISCONNECT) {
if (GlobalIrmonControl.IrxferContext != NULL) {
pDeviceList->DeviceCount=0;
UpdateTray(&GlobalIrmonControl,ICON_ST_NOICON, 0, NULL, 0);
// UpdateDiscoveredDevices(pDeviceList,IpDeviceList);
Sleep(100);
CloseDownUI();
}
// TerminateProcess(GetCurrentProcess(),0);
}
break;
default:
//DEBUGMSG(("Msg %X, wParam %d, lParam %d\n", message, wParam, lParam));
return (DefWindowProc(hWnd, message, wParam, lParam));
}
return 0;
}
VOID
ServiceMain(
DWORD cArgs,
LPWSTR *pArgs)
{
DWORD Error = NO_ERROR;
DWORD Status;
WNDCLASS Wc;
MSG Msg;
HKEY hKey;
LONG rc;
WSADATA WSAData;
WORD WSAVerReq = MAKEWORD(2,0);
char c;
BOOL bResult;
hIrmonEvents[EV_STOP_EVENT] = CreateEvent(NULL, FALSE, FALSE, NULL);
hIrmonEvents[EV_REG_CHANGE_EVENT] = CreateEvent(NULL, FALSE, FALSE, NULL);
hIrmonEvents[EV_TRAY_STATUS_EVENT] = CreateEvent(NULL, FALSE, FALSE, NULL);
// Initialize all necessary globals to 0, FALSE, or NULL because
// we might be restarting within the same services process
pDeviceList->DeviceCount = 0;
IconInTray = FALSE;
IrmonStopped = FALSE;
UserLoggedIn = FALSE;
TrayEnabled = FALSE;
DeviceListUpdated = FALSE;
LastTrayUpdate = 0;
// RetryLazyDscvTimerRunning = FALSE;
RetryTrayUpdateTimerRunning = FALSE;
hInRange = 0;
RtlZeroMemory(&LinkStatus, sizeof(LinkStatus));
ZeroMemory(&GlobalIrmonControl,sizeof(GlobalIrmonControl));
try
{
InitializeCriticalSection(&GlobalIrmonControl.Lock);
}
except (STATUS_NO_MEMORY == GetExceptionCode())
{
DEBUGMSG(("IRMON-FTP: Failed to InitializeCriticalSection, Aborting.\n"));
return;
}
if (WSAStartup(WSAVerReq, &WSAData) != 0)
{
DEBUGMSG(("IRMON-FTP: WSAStartup failed\n"));
Error = 1;
goto done;
}
Wc.style = CS_NOCLOSE;
Wc.cbClsExtra = 0;
Wc.cbWndExtra = 0;
Wc.hInstance = ghInstance;
Wc.hIcon = NULL;
Wc.hCursor = NULL;
Wc.hbrBackground = NULL;
Wc.lpszMenuName = NULL;
Wc.lpfnWndProc = WndProc;
Wc.lpszClassName = IrmonClassName;
if (!RegisterClass(&Wc))
{
DEBUGMSG(("IRMON-FTP: failed to register class\n"));
}
// Initialize OBEX and IrTran-P:
//
bResult=InitializeIrxfer(
&GlobalIrmonControl,
SetTrayStatus,
SetSoundStatus,
&GlobalIrmonControl.IrxferContext
);
if (bResult) {
DEBUGMSG(("IRMON-FTP: Irxfer initialized\n"));
} else {
DEBUGMSG(("IRMON-FTP: Irxfer initializtion failed\n"));
goto done;
}
IrmonStopped = FALSE;
DEBUGMSG(("IRMON-FTP: Service running\n"));
UserLogonEvent(&GlobalIrmonControl);
while (!IrmonStopped)
{
Status = MsgWaitForMultipleObjectsEx(WAIT_EVENT_CNT, hIrmonEvents, INFINITE,
QS_ALLINPUT | QS_ALLEVENTS | QS_ALLPOSTMESSAGE,
MWMO_ALERTABLE);
switch (Status)
{
case WAIT_OBJECT_0 + EV_STOP_EVENT:
IrmonStopped = TRUE;
break;
case WAIT_OBJECT_0 + EV_REG_CHANGE_EVENT:
if (UserLoggedIn)
{
GetRegSoundData(hIrmonEvents[EV_REG_CHANGE_EVENT]);
}
break;
case WAIT_OBJECT_0 + EV_TRAY_STATUS_EVENT:
if (TrayEnabled)
{
DevListChangeOrUpdatedLinkStatus(&GlobalIrmonControl);
}
else if (IconInTray)
{
UpdateTray(&GlobalIrmonControl,ICON_ST_NOICON, 0, NULL, 0);
}
break;
case WAIT_IO_COMPLETION:
break;
default:
while (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE))
{
if (Msg.message == WM_QUIT)
{
IrmonStopped = TRUE;
break;
}
if (!IsDialogMessage(GlobalIrmonControl.hWnd, &Msg))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
}
}
}
if (UserLoggedIn) {
UserLogoffEvent(&GlobalIrmonControl);
}
if (!UninitializeIrxfer(GlobalIrmonControl.IrxferContext)) {
DEBUGMSG(("IRMON-FTP: Failed to unitialize irxfer!!\n"));
IrmonStopped = FALSE;
} else {
DEBUGMSG(("IRMON-FTP: irxfer unitialized\n"));
}
UpdateTray(&GlobalIrmonControl,ICON_ST_NOICON, 0, NULL, 0);
done:
DeleteCriticalSection(&GlobalIrmonControl.Lock);
DEBUGMSG(("IRMON-FTP: Service stopped\n"));
}
VOID
SetInstance(
HINSTANCE hInst
)
{
ghInstance=hInst;
return;
}
VOID
SignalIrmonExit(
VOID
)
{
SetEvent(hIrmonEvents[EV_STOP_EVENT]);
}