/*++ Copyright (C) Microsoft Corporation, 1997 - 1999 Module Name: msgloop.cxx Abstract: This file contains the message pump for SENS. Author: Gopal Parupudi [Notes:] optional-notes Revision History: GopalP 11/5/1997 Start. --*/ #include #include #define SENS_WINDOW_CLASS_NAME SENS_STRING("SENS Hidden Window class") #define SENS_HIDDEN_WINDOW_NAME SENS_STRING("SENS") #if defined(SENS_NT4) #define SENS_MODULE_NAME SENS_STRING("SENS.EXE") #else // SENS_NT4 #define SENS_MODULE_NAME SENS_STRING("SENS.DLL") #endif // SENS_NT4 // // Globals // HWND ghwndSens; DWORD gMessageLoopTid; HANDLE ghCleanupEvent; SYSTEM_POWER_STATUS gSystemPowerState; LRESULT CALLBACK SensMainWndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ) /*++ Routine Description: Arguments: None. Return Value: None. --*/ { LRESULT lResult = TRUE; #ifdef DETAIL_DEBUG SensPrintA(SENS_INFO, ("SensMainWndProc(): Received a msg (0x%x) - (0x%x)\n", msg, wParam)); #endif // DETAIL_DEBUG switch (msg) { // // Power Management Notifications. // case WM_POWERBROADCAST: { DWORD dwPowerEvent = (DWORD) wParam; SYSTEM_POWER_STATUS CurSPstate; SENSEVENT_POWER Data; BOOL bRet; SensPrintA(SENS_INFO, ("SensMainWndProc(): Received WM_POWERBROADCAST msg - (0x%x)\n", wParam)); bRet = GetSystemPowerStatus(&CurSPstate); ASSERT(bRet); switch (dwPowerEvent) { case PBT_APMBATTERYLOW: { // Save the new state. A critsec is not necessary as this Message to be serialized. memcpy(&gSystemPowerState, &CurSPstate, sizeof(SYSTEM_POWER_STATUS)); Data.eType = SENS_EVENT_POWER_BATTERY_LOW; memcpy(&Data.PowerStatus, &CurSPstate, sizeof(SYSTEM_POWER_STATUS)); // Fire BatteryLow event SensFireEvent(&Data); break; } case PBT_APMPOWERSTATUSCHANGE: { // // OnACPower event is fired when // o previously the machine was not on AC // o now, it is on AC // if ( (CurSPstate.ACLineStatus == AC_LINE_ONLINE) && (gSystemPowerState.ACLineStatus != AC_LINE_ONLINE)) { Data.eType = SENS_EVENT_POWER_ON_ACPOWER; } else // // OnBatteryPower event is fired when // o previously the machine was on AC // o now, it is not on AC // o the machine has a system battery // if ( (CurSPstate.ACLineStatus == AC_LINE_OFFLINE) && (gSystemPowerState.ACLineStatus == AC_LINE_ONLINE) && ((CurSPstate.BatteryFlag & BATTERY_FLAG_NO_BATTERY) == 0)) { Data.eType = SENS_EVENT_POWER_ON_BATTERYPOWER; } // // A Power change we don't care about. // else { break; } // Save the new state. A critsec is not necessary as this Message to be serialized. memcpy(&gSystemPowerState, &CurSPstate, sizeof(SYSTEM_POWER_STATUS)); memcpy(&Data.PowerStatus, &CurSPstate, sizeof(SYSTEM_POWER_STATUS)); // Fire the event. SensFireEvent(&Data); break; } default: // Unrecognized Power event. break; } // switch (dwPowerEvent) break; } #if defined(SENS_CHICAGO) // // PnP Device Notifications. // case WM_DEVICECHANGE: { SensPrintA(SENS_INFO, ("SensMainWndProc(): Received a WM_DEVICECHANGE msg - (0x%x)\n", wParam)); PDEV_BROADCAST_NET pdbNet = (PDEV_BROADCAST_NET) lParam; switch (wParam) { case DBT_DEVICEARRIVAL: { if (pdbNet->dbcn_devicetype == DBT_DEVTYP_NET) { SENSEVENT_PNP Data; ASSERT(pdbNet->dbcn_size == sizeof(DEV_BROADCAST_NET)); Data.eType = SENS_EVENT_PNP_DEVICE_ARRIVED; Data.Size = pdbNet->dbcn_size; Data.DevType = pdbNet->dbcn_devicetype; Data.Resource = pdbNet->dbcn_resource; Data.Flags = pdbNet->dbcn_flags; SensFireEvent(&Data); // Force a recalculation of LAN Connectivity gdwLastLANTime -= (MAX_LAN_INTERVAL + 1); //EvaluateConnectivity(TYPE_LAN); } break; } case DBT_DEVICEREMOVECOMPLETE: { if (pdbNet->dbcn_devicetype == DBT_DEVTYP_NET) { SENSEVENT_PNP Data; ASSERT(pdbNet->dbcn_size == sizeof(DEV_BROADCAST_NET)); Data.eType = SENS_EVENT_PNP_DEVICE_REMOVED; Data.Size = pdbNet->dbcn_size; Data.DevType = pdbNet->dbcn_devicetype; Data.Resource = pdbNet->dbcn_resource; Data.Flags = pdbNet->dbcn_flags; SensFireEvent(&Data); // Force a recalculation of LAN Connectivity gdwLastLANTime -= (MAX_LAN_INTERVAL + 1); //EvaluateConnectivity(TYPE_LAN); } break; } } break; } #endif // SENS_CHICAGO case WM_SENS_CLEANUP: // // Cleanup the Window resources of SENS // PostQuitMessage(0); break; default: lResult = DefWindowProc(hwnd, msg, wParam, lParam); break; } // switch (msg) return lResult; } DWORD WINAPI SensMessageLoopThreadRoutine( LPVOID lpParam ) /*++ Routine Description: Arguments: None. Return Value: None. --*/ { WNDCLASS wc; BOOL f; BOOL bRet; HINSTANCE hInstance = NULL; MSG msg; // // Save away the ThreadId // gMessageLoopTid = GetCurrentThreadId(); // // Save a snapshot of the System Power State. // bRet = GetSystemPowerStatus(&gSystemPowerState); if (bRet == FALSE) { SensPrintA(SENS_ERR, ("SensMessageLoopThread(): GetSystemPowerStatus() failed with " "GLE = %d\n", GetLastError())); } // // Create an event to signal the cleanup of all window resources. // ghCleanupEvent = CreateEvent( NULL, // Handle cannot be inherited FALSE, // It is an auto-reset event FALSE, // Intial state is non-signalled SENS_STRING("Sens Hidden Window Cleanup Event") // Name of the event ); if (ghCleanupEvent == NULL) { SensPrintA(SENS_ERR, ("ServiceStart(): CreateEvent(ghCleanupEvent)" " failed with %d.", GetLastError())); } // // Register window class // hInstance = GetModuleHandle(SENS_MODULE_NAME); ASSERT(hInstance); memset(&wc, 0x0, sizeof(WNDCLASS)); wc.style = 0; wc.lpfnWndProc = (WNDPROC) SensMainWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hIcon = NULL; wc.hInstance = hInstance; wc.hCursor = NULL; wc.hbrBackground = NULL; wc.lpszMenuName = NULL; wc.lpszClassName = SENS_WINDOW_CLASS_NAME; f = RegisterClass(&wc); ASSERT(f); // Create a hidden window ghwndSens = CreateWindow( SENS_WINDOW_CLASS_NAME, // Class Name SENS_HIDDEN_WINDOW_NAME, // Window Name NULL, // Window Style 0, // Horizontal position 0, // Vertical position 0, // Window width 0, // Window height NULL, // Handle to parent window NULL, // Handle to menu hInstance, // Handle to application instance NULL // window creation data ); if (ghwndSens) { ShowWindow(ghwndSens, SW_HIDE); // // Message pump. // while ((bRet = GetMessage(&msg, ghwndSens, NULL, NULL)) > 0) { TranslateMessage(&msg); DispatchMessage(&msg); } #ifdef DETAIL_DEBUG SensPrintA(SENS_DBG, ("SensMessageLoopThread(): Out of message pump !\n")); #endif // DETAIL_DEBUG // Check for bad return value from GetMessage() if (bRet == -1) { SensPrintA(SENS_ERR, ("SensMessageLoopThread(): GetMessage() failed with GLE of %d\n", GetLastError())); } BOOL bRet; // Cleanup the window. bRet = DestroyWindow(ghwndSens); ASSERT(bRet); if (bRet != TRUE) { SensPrintA(SENS_ERR, ("SensMessageLoopThread(): DestroyWindow() failed with %d\n", GetLastError())); } // Unregister the window class bRet = UnregisterClass(SENS_WINDOW_CLASS_NAME, hInstance); ASSERT(bRet); // Window cleanup done. Set the event. if (ghCleanupEvent) { SetEvent(ghCleanupEvent); } } else { SensPrintA(SENS_ERR, ("SensMessageLoopThread(): CreateWindow() failed with GLE of %d\n", GetLastError())); } return 0; } BOOL InitMessageLoop( void ) /*++ Routine Description: Arguments: None. Return Value: None. --*/ { #if defined(SENS_CHICAGO) BOOL bStatus; HANDLE hThread; DWORD dwThreadId; bStatus = FALSE; hThread = CreateThread( NULL, 0, SensMessageLoopThreadRoutine, NULL, 0, &dwThreadId ); if (NULL != hThread) { bStatus = TRUE; CloseHandle(hThread); } else { SensPrintA(SENS_INFO, ("InitMessageLoop() returning %d with GLE of %d\n", bStatus, GetLastError())); } return bStatus; #else // SENS_CHICAGO return TRUE; #endif // SENS_CHICAGO }