389 lines
9.7 KiB
C++
389 lines
9.7 KiB
C++
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
//
|
||
|
// Copyright (C) Microsoft Corporation, 1998 - 1999
|
||
|
//
|
||
|
// File: irprops.cpp
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
// irprops.cpp : Defines the initialization routines for the DLL.
|
||
|
//
|
||
|
|
||
|
#include "precomp.hxx"
|
||
|
#include "irprops.h"
|
||
|
#include "irpropsheet.h"
|
||
|
#include "debug.h"
|
||
|
|
||
|
|
||
|
BOOL InitInstance();
|
||
|
INT ExitInstance();
|
||
|
BOOL IsFirstInstance();
|
||
|
INT_PTR WINAPI DoPropertiesA(HWND hwnd, LPCSTR CmdLine);
|
||
|
INT_PTR WINAPI DoPropertiesW(HWND hwnd, LPCWSTR CmdLine);
|
||
|
|
||
|
|
||
|
HINSTANCE gHInst;
|
||
|
|
||
|
//
|
||
|
// This records the current active property sheet window handle created
|
||
|
// by this instance. It is set/reset by CIrPropSheet object.
|
||
|
//
|
||
|
HWND g_hwndPropSheet = NULL;
|
||
|
HANDLE g_hMutex = NULL;
|
||
|
BOOL g_bFirstInstance = TRUE;
|
||
|
|
||
|
//
|
||
|
// This records our registered message for inter-instances communications
|
||
|
// The message is registered in CIrpropsApp::InitInstance.
|
||
|
//
|
||
|
UINT g_uIPMsg;
|
||
|
|
||
|
#ifdef _DEBUG
|
||
|
#define new DEBUG_NEW
|
||
|
#undef THIS_FILE
|
||
|
static char THIS_FILE[] = __FILE__;
|
||
|
#endif
|
||
|
|
||
|
|
||
|
extern "C" {
|
||
|
|
||
|
BOOL APIENTRY
|
||
|
DllMain(HANDLE hDll,
|
||
|
DWORD dwReason,
|
||
|
LPVOID lpReserved)
|
||
|
{
|
||
|
IRINFO((_T("DllMain reason %x"), dwReason));
|
||
|
switch (dwReason) {
|
||
|
case DLL_PROCESS_ATTACH:
|
||
|
gHInst = (HINSTANCE) hDll;
|
||
|
return InitInstance();
|
||
|
break;
|
||
|
|
||
|
case DLL_PROCESS_DETACH:
|
||
|
return ExitInstance();
|
||
|
break;
|
||
|
|
||
|
case DLL_THREAD_DETACH:
|
||
|
break;
|
||
|
|
||
|
case DLL_THREAD_ATTACH:
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////
|
||
|
//some globals
|
||
|
|
||
|
APPLETS IRApplet[NUM_APPLETS] = {
|
||
|
{IDI_IRPROPS, IDS_APPLETNAME, IDS_APPLETDESC}
|
||
|
};
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////
|
||
|
// CPlApplet function for the control panel
|
||
|
//
|
||
|
LONG CALLBACK CPlApplet(
|
||
|
HWND hwndCPL,
|
||
|
UINT uMsg,
|
||
|
LPARAM lParam1,
|
||
|
LPARAM lParam2)
|
||
|
{
|
||
|
int i;
|
||
|
LPCPLINFO lpCPlInfo;
|
||
|
|
||
|
i = (int) lParam1;
|
||
|
|
||
|
IRINFO((_T("CplApplet message %x"), uMsg));
|
||
|
switch (uMsg)
|
||
|
{
|
||
|
case CPL_INIT: // first message, sent once
|
||
|
if (!IrPropSheet::IsIrDASupported()) {
|
||
|
HPSXA hpsxa;
|
||
|
//
|
||
|
// Check for any installed extensions.
|
||
|
//
|
||
|
hpsxa = SHCreatePropSheetExtArray(HKEY_LOCAL_MACHINE, sc_szRegWireless, 8);
|
||
|
if (hpsxa) {
|
||
|
//
|
||
|
// We have extensions installed so we have to show the CPL,
|
||
|
// whether IRDA exists or not.
|
||
|
//
|
||
|
SHDestroyPropSheetExtArray(hpsxa);
|
||
|
return TRUE;
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
return TRUE;
|
||
|
case CPL_GETCOUNT: // second message, sent once
|
||
|
return NUM_APPLETS;
|
||
|
break;
|
||
|
case CPL_INQUIRE: // third message, sent once per application
|
||
|
lpCPlInfo = (LPCPLINFO) lParam2;
|
||
|
lpCPlInfo->lData = 0;
|
||
|
lpCPlInfo->idIcon = IRApplet[i].icon;
|
||
|
lpCPlInfo->idName = IRApplet[i].namestring;
|
||
|
lpCPlInfo->idInfo = IRApplet[i].descstring;
|
||
|
break;
|
||
|
|
||
|
case CPL_STARTWPARMSA:
|
||
|
if (-1 == DoPropertiesA(hwndCPL, (LPCSTR)lParam2))
|
||
|
MsgBoxWinError(hwndCPL);
|
||
|
// return true so that we won't get CPL_DBLCLK.
|
||
|
return 1;
|
||
|
break;
|
||
|
case CPL_STARTWPARMSW:
|
||
|
if (-1 == DoPropertiesW(hwndCPL, (LPCWSTR)lParam2))
|
||
|
MsgBoxWinError(hwndCPL);
|
||
|
// return true so that we won't get CPL_DBLCLK.
|
||
|
return 1;
|
||
|
break;
|
||
|
case CPL_DBLCLK: // application icon double-clicked
|
||
|
if (-1 == DoPropertiesA(hwndCPL, (LPCSTR)lParam2))
|
||
|
MsgBoxWinError(hwndCPL);
|
||
|
return 1;
|
||
|
break;
|
||
|
case CPL_STOP: // sent once per application before CPL_EXIT
|
||
|
break;
|
||
|
case CPL_EXIT: // sent once before FreeLibrary is called
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// This function presents the Wireless link property sheet.
|
||
|
// INPUT:
|
||
|
// hwndParent -- window handle to be used as parent window of
|
||
|
// the property sheet
|
||
|
// lpCmdLine -- optional command line
|
||
|
// 'n" (n in decimal) is start page number(zero-based).
|
||
|
// OUTPUT:
|
||
|
// Return value of PropertySheet API
|
||
|
INT_PTR
|
||
|
DoPropertiesW(
|
||
|
HWND hwndParent,
|
||
|
LPCWSTR lpCmdLine
|
||
|
)
|
||
|
{
|
||
|
INT_PTR Result;
|
||
|
INT StartPage;
|
||
|
|
||
|
IRINFO((_T("DoPropertiesW")));
|
||
|
//
|
||
|
// Assuming no start page was specified.
|
||
|
//
|
||
|
StartPage = -1;
|
||
|
//
|
||
|
// Command line specifies start page number
|
||
|
//
|
||
|
if (lpCmdLine)
|
||
|
{
|
||
|
// skip white chars
|
||
|
while (_T('\0') != *lpCmdLine &&
|
||
|
(_T(' ') == *lpCmdLine || _T('\t') == *lpCmdLine))
|
||
|
{
|
||
|
lpCmdLine++;
|
||
|
}
|
||
|
if (_T('0') <= *lpCmdLine && _T('9') >= *lpCmdLine)
|
||
|
{
|
||
|
StartPage = 0;
|
||
|
do
|
||
|
{
|
||
|
StartPage = StartPage * 10 + *lpCmdLine - _T('0');
|
||
|
lpCmdLine++;
|
||
|
} while (_T('0') <= *lpCmdLine && _T('9') >= *lpCmdLine);
|
||
|
}
|
||
|
}
|
||
|
if (!IsFirstInstance() || NULL != g_hwndPropSheet)
|
||
|
{
|
||
|
IRINFO((_T("Not the first instance")));
|
||
|
HWND hwndPropSheet = HWND_DESKTOP;
|
||
|
if (NULL == g_hwndPropSheet)
|
||
|
{
|
||
|
IRINFO((_T("No window created")));
|
||
|
//
|
||
|
// We are not the first instance. Look for the property sheet
|
||
|
// window created by the first instance.
|
||
|
//
|
||
|
EnumWindows(EnumWinProc, (LPARAM)&hwndPropSheet);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
IRINFO((_T("Window active")));
|
||
|
//
|
||
|
// This is not the first call and we have a
|
||
|
// property sheet active(same process, multiple calls)
|
||
|
//
|
||
|
hwndPropSheet = g_hwndPropSheet;
|
||
|
}
|
||
|
if (HWND_DESKTOP != hwndPropSheet)
|
||
|
{
|
||
|
IRINFO((_T("Found the active property sheet.")));
|
||
|
//
|
||
|
// We found the active property sheet
|
||
|
//
|
||
|
// Select the new active page if necessary
|
||
|
//
|
||
|
if (-1 != StartPage)
|
||
|
PropSheet_SetCurSel(hwndPropSheet, NULL, StartPage);
|
||
|
|
||
|
//
|
||
|
// bring the property sheet to the foreground.
|
||
|
//
|
||
|
::SetForegroundWindow(hwndPropSheet);
|
||
|
}
|
||
|
Result = IDCANCEL;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
IRINFO((_T("First instance, creating propertysheet")));
|
||
|
IrPropSheet PropSheet(gHInst, IDS_APPLETNAME, hwndParent, StartPage);
|
||
|
}
|
||
|
return Result;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// This is our callback function for EnumWindows API.
|
||
|
// It probes for each window handle to see if it is the property sheet
|
||
|
// window created by the previous instance. If it is, it returns
|
||
|
// the window handle in the provided buffer, lParam)
|
||
|
// Input:
|
||
|
// hWnd -- the window handle
|
||
|
// lParam -- (HWND *)
|
||
|
// Output:
|
||
|
// TRUE -- Let Windows continue to call us
|
||
|
// FALSE -- Stop Windows from calling us again
|
||
|
//
|
||
|
BOOL
|
||
|
CALLBACK
|
||
|
EnumWinProc(
|
||
|
HWND hWnd,
|
||
|
LPARAM lParam
|
||
|
)
|
||
|
{
|
||
|
//
|
||
|
// Verify with this window to see if it is the one we are looking for.
|
||
|
//
|
||
|
LRESULT lr;
|
||
|
lr = ::SendMessage(hWnd, g_uIPMsg, (WPARAM)IPMSG_SIGNATURECHECK,
|
||
|
(LPARAM)IPMSG_REQUESTSIGNATURE);
|
||
|
if (IPMSG_REPLYSIGNATURE == lr)
|
||
|
{
|
||
|
if (lParam)
|
||
|
{
|
||
|
// this is the one
|
||
|
*((HWND *)(lParam)) = hWnd;
|
||
|
}
|
||
|
//
|
||
|
// We are done with enumeration.
|
||
|
//
|
||
|
return FALSE;
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
INT_PTR
|
||
|
DoPropertiesA(
|
||
|
HWND hwndParent,
|
||
|
LPCSTR lpCmdLine
|
||
|
)
|
||
|
{
|
||
|
WCHAR CmdLineW[MAX_PATH];
|
||
|
UINT Size;
|
||
|
if (!lpCmdLine)
|
||
|
return DoPropertiesW(hwndParent, NULL);
|
||
|
MultiByteToWideChar(CP_ACP, 0, lpCmdLine, -1, CmdLineW, sizeof(CmdLineW) / sizeof(WCHAR));
|
||
|
return DoPropertiesW(hwndParent, CmdLineW);
|
||
|
}
|
||
|
|
||
|
|
||
|
// This function creates and displays a message box for the given
|
||
|
// win32 error(or last error)
|
||
|
// INPUT:
|
||
|
// hwndParent -- the parent window for the will-be-created message box
|
||
|
// Type -- message styles(MB_xxxx)
|
||
|
// Error -- Error code. If the value is 0
|
||
|
// GetLastError() will be called to retreive the
|
||
|
// real error code.
|
||
|
// CaptionId -- optional string id for caption
|
||
|
// OUTPUT:
|
||
|
// the value return from MessageBox
|
||
|
//
|
||
|
int
|
||
|
MsgBoxWinError(
|
||
|
HWND hwndParent,
|
||
|
DWORD Options,
|
||
|
DWORD Error,
|
||
|
int CaptionId
|
||
|
)
|
||
|
{
|
||
|
if (ERROR_SUCCESS == Error)
|
||
|
Error = GetLastError();
|
||
|
|
||
|
// nonsense to report success!
|
||
|
if (ERROR_SUCCESS == Error)
|
||
|
return IDOK;
|
||
|
|
||
|
TCHAR szMsg[MAX_PATH];
|
||
|
TCHAR szCaption[MAX_PATH];
|
||
|
|
||
|
if (!CaptionId)
|
||
|
CaptionId = IDS_APPLETNAME;
|
||
|
::LoadString(gHInst, CaptionId, szCaption, sizeof(szCaption) / sizeof(TCHAR));
|
||
|
FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
|
||
|
NULL, Error, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
|
||
|
szMsg, sizeof(szMsg) / sizeof(TCHAR), NULL);
|
||
|
return MessageBox(hwndParent, szMsg, szCaption, Options);
|
||
|
}
|
||
|
|
||
|
BOOL InitInstance()
|
||
|
{
|
||
|
//
|
||
|
// Try to create a named mutex. This give us a clue
|
||
|
// if we are the first instance. We will not close
|
||
|
// the mutex until exit.
|
||
|
//
|
||
|
g_hMutex = CreateMutex(NULL, TRUE, SINGLE_INST_MUTEX);
|
||
|
if (g_hMutex)
|
||
|
{
|
||
|
g_bFirstInstance = ERROR_ALREADY_EXISTS != GetLastError();
|
||
|
//
|
||
|
// register a message for inter-instances communication
|
||
|
//
|
||
|
g_uIPMsg = RegisterWindowMessage(WIRELESSLINK_INTERPROCESSMSG);
|
||
|
SHFusionInitializeFromModuleID(gHInst, 124);
|
||
|
return TRUE;
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
BOOL ExitInstance()
|
||
|
{
|
||
|
if (g_hMutex)
|
||
|
{
|
||
|
CloseHandle(g_hMutex);
|
||
|
g_hMutex = NULL;
|
||
|
}
|
||
|
SHFusionUninitialize();
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
BOOL IsFirstInstance()
|
||
|
{
|
||
|
return g_bFirstInstance;
|
||
|
}
|
||
|
|
||
|
|