//+------------------------------------------------------------------------- // // 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; }