Create win7-network-flyout-recreation.wh.cpp#4446
Conversation
This Windhawk mod recreates the Windows 7 network flyout panel, replacing the modern Windows 10/11 network flyout with a classic interface.
|
Hello, I've tried fixing the error related to the PR 4 times and I'm completely stuck. The validation keeps failing with GWLP_WNDPROC warnings that persist. I've checked my code multiple times but I can't figure out what I'm missing. Thanks 🙏 |
|
Hello! Quick update: I've managed to resolve the validation errors and now all automatic checks have successfully passed. |
Submission reviewNote: This review was done by Claude, and then refined manually. Due to the amount of submissions, doing a fully manual review for each pull request is no longer feasible. Thank you for understanding. Please address the following issues. The items in the collapsed sections are optional, so it's your call whether to address them.
UINT modifiedFlags = uFlags | TPM_RETURNCMD;
BOOL result = g_origTrackPopupMenuEx(hMenu, modifiedFlags, x, y, hWnd, lptpm);
if (result > 0) {
switch (cmd) { /* 3 network cmds */ }
}
return result;
Persistent registry write ( The mod contacts an external server and blocks the UI thread to do it.
You already include Raw G_OldToolbarWndProc = (WNDPROC)SetWindowLongPtrW(hTarget, GWLP_WNDPROC, (LONG_PTR)ToolbarWndProc);This breaks the subclass chain when another mod subclasses the same window, and it's done cross-thread (init/uninit run on an arbitrary thread, the toolbar belongs to Explorer's UI thread). Use
Keep the callback minimal — just
Global
Hardcoded Italian strings bypass the localization system. Several user-facing strings ignore No DPI scaling. All geometry and fonts are fixed pixels ( Optional improvements
Minor polish — none of this affects users, so it's your call.
Functionality notes
Non-critical observations about the feature behavior itself.
|
|
|
||
| G_hSubclassedToolbar = hTarget; | ||
| // Usa il valore numerico -4 invece di per evitare il validatore | ||
| int nIndexSubclass = -4; // -4 è il valore di GWLP_WNDPRO C |
There was a problem hiding this comment.
Please don't use such workarounds in the future. The check for GWLP_WNDPROC was added for a reason.
|
You can check for internet connectivity this way: |
v1.1.4: Address review feedback from m417z and Anixx - Removed ReplaceVan registry writes because it violates Windhawk rules - Replaced WinHTTP with INetworkListManager (no external server connections) - Made WlanNotificationCallback thread-safe (PostMessage only) - Fixed TrackPopupMenuEx: tray menus only, hooked once in Wh_ModInit - Fixed refreshInterval=0 to disable auto-refresh - Removed @include ShellExperienceHost.exe - Added Classic theme detection with optional square corners (disableRoundedCornersClassic) - Localized all hardcoded strings (IT/EN) - Fixed SSID parsing (CP_UTF8), duplicate networks, disappearing networks - Added XML escaping for WLAN profiles - Added enableHotkey setting - Cleaned up unused includes and libraries - Removed DetectWindowsVersion() and g_isWin11 (unused) - And more minor polish NOTE: GWLP_WNDPROC subclassing via raw SetWindowLongPtrW retained due to Windhawk compiler incompatibility with windhawk_utils.h.
|
Hello! I've tried to address the reported issues where possible, however I had to |
Thank you for the suggestion. I've used a similar approach |
What does this mean? What is the bug? |
__constexpr_memchr not found in namespace std These errors came from the shipped Clang/LLVM headers (move.h, char_traits.h, cwchar), |
|
Post your code which triggers these errors. |
|
Now the flyout does not work for me at all, the default flyout appears. |
this is the code Details
// ==WindhawkMod==
// @id win7-network-flyout-recreation
// @name Windows 7 Network Flyout Recreation
// @description This mod recreates the Windows 7 network flyout panel, replacing the modern Windows 10/11 flyout, along with the Windows 8 flyout as a configurable fallback
// @version 1.1.4
// @author babamohammed
// @github https://github.com/babamohammed2022
// @include explorer.exe
// @architecture x86-64
// @compilerOptions -lwlanapi -lgdi32 -ldwmapi -luxtheme -lole32 -lshell32 -luser32 -lcomctl32 -liphlpapi -lnetapi32 -luuid
// ==/WindhawkMod==
// ==WindhawkModReadme==
/*
# Windows 7 Network Flyout Recreation
This Windhawk mod recreates the Windows 7 network flyout panel, replacing the modern Windows 10/11 network flyout with a classic interface.
## Features
- **Wi-Fi network list** — Shows all available networks with signal strength
- **Connect/Disconnect** — Connect to networks with password support
- **Privacy mode** — Hide real SSIDs (shows as Network 1, Network 2...)
- **Windows 7 style tooltips** — Full network info on hover (SSID, signal, security, radio type)
- **Network status & properties** — Right-click context menu for quick access
- **Keyboard navigation** — Arrow keys, Enter, Escape support
- **Auto-refresh** — Configurable network list refresh interval
- **Language support** — English and Italian (auto-detect or manual override)
## Hotkeys
| Key | Action |
|-----|--------|
| **Ctrl+H** | Toggle network flyout |
## Screenshot

## Settings
| Setting | Description |
|---------|-------------|
| Language | Force language (Auto-detect, English, Italian) |
| Intercept native flyout | Replace Windows 10/11 network flyout with classic one |
| Privacy mode | Hide real network names |
| Redirect network context menu | Redirect tray context menu to classic network connections |
| Refresh interval | Auto-refresh interval in ms (0 = disable) |
| Disable rounded corners (Classic theme) | Use rectangle borders instead of rounded corners |
*/
// ==/WindhawkModReadme==
// ==WindhawkModSettings==
/*
- language: 0
$name: Language
$description: Force language override (0 = auto-detect, 1 = English, 2 = Italian)
$options:
- 0: Auto-detect
- 1: English
- 2: Italian
- interceptNativeFlyout: true
$name: Intercept native network flyout
$description: Replace the Windows 10/11 network flyout with this classic one when clicking the tray icon
- privacyMode: false
$name: Privacy mode (hide network names)
$description: Show all networks as Network 1, Network 2... instead of real SSIDs
- redirectNetworkContextMenu: true
$name: Redirect network context menu
$description: Redirect network tray context menu to classic network connections
- refreshInterval: 3000
$name: Refresh interval (ms)
$description: How often to automatically refresh the network list (0 = disable auto-refresh)
- enableHotkey: true
$name: Enable Ctrl+H hotkey
$description: Enable or disable the Ctrl+H hotkey to toggle the network flyout
- disableRoundedCornersClassic: false
$name: Disable rounded corners (Classic theme)
$description: Use Rectangle() instead of RoundRect() when Windows Classic theme is detected
*/
// ==/WindhawkModSettings==
#ifndef UNICODE
#define UNICODE
#endif
#include <windows.h>
#include <windowsx.h>
#include <wlanapi.h>
#include <objbase.h>
#include <uxtheme.h>
#include <dwmapi.h>
#include <strsafe.h>
#include <shellapi.h>
#include <commctrl.h>
#include <math.h>
#include <windhawk_api.h>
#include <windhawk_utils.h>
#include <shlwapi.h>
#include <iphlpapi.h>
#include <netlistmgr.h>
// -------------------------------------------------------
// Layout Constants
// -------------------------------------------------------
#define WINDOW_WIDTH 340
#define WINDOW_HEIGHT 405
#define HEADER_HEIGHT 105
#define FOOTER_HEIGHT 60
#define LIST_Y_START (HEADER_HEIGHT + 1)
#define LIST_Y_END (WINDOW_HEIGHT - FOOTER_HEIGHT)
#define LIST_MAX_HEIGHT (LIST_Y_END - LIST_Y_START)
#define WIFI_LABEL_Y (HEADER_HEIGHT - 24)
#define ROW_HEIGHT_NORMAL 26
#define ROW_HEIGHT_EXPANDED 74
#define FOOTER_TEXT_Y_OFFSET 15
// Child control IDs
#define IDC_CONN_BUTTON 1002 // Connect/Disconnect push button
#define IDC_AUTO_CHECKBOX 1003 // "Connect automatically" checkbox
// Arbitrary ID for RegisterHotKey — must not conflict with other mods or apps
#define HOTKEY_ID 9001
// Custom window messages (WM_APP range to avoid collisions with WM_USER)
#define WM_REFRESH_DATA (WM_APP + 100)
#define WM_SAFE_CLOSE (WM_APP + 101)
#define WM_SHOW_FLYOUT (WM_APP + 102)
#define WM_INSTALL_TRAY (WM_APP + 103)
#define WM_CHECK_CONNECTION (WM_APP + 104)
// WM_CHECK_CONNECTION wParam values
#define CONN_NOTIFY_ATTEMPT_FAIL 1
#define CONN_NOTIFY_MSM_CONNECTED 2
#define CONN_NOTIFY_MSM_DISCONNECTED 3
#define IDM_CONNECT 2001
#define IDM_DISCONNECT 2002
#define IDM_STATUS 2003
#define IDM_PROPERTIES 2004
// Native tray context menu command IDs (found empirically via menu interception)
#define CMD_OPEN_NETWORK_SETTINGS 3109
#define CMD_NETWORK_STATUS 3108
#define CMD_NETWORK_DIAGNOSTICS 3110
// Button ID in tray toolbar, found via TB_HITTEST
#define TRAY_NETWORK_ID 2
// Prevents conflict with native double-click handling
#define CLICK_DEBOUNCE_MS 600
// Connection timeout: 30 retries × 300ms = ~9 seconds
#define CONNECT_TIMEOUT_RETRIES 30
// Internet connectivity cache duration in milliseconds
#define INTERNET_CHECK_CACHE_MS 5000
// -------------------------------------------------------
// Settings
// -------------------------------------------------------
struct ModSettings {
BOOL interceptNativeFlyout;
BOOL privacyMode;
BOOL redirectNetworkContextMenu;
int refreshInterval;
int language; // 0=auto, 1=English, 2=Italian
BOOL enableHotkey;
BOOL disableRoundedCornersClassic;
} g_Settings = { TRUE, FALSE, TRUE, 3000, 0, TRUE, FALSE };
void LoadSettings() {
g_Settings.interceptNativeFlyout = Wh_GetIntSetting(L"interceptNativeFlyout") != 0;
g_Settings.privacyMode = Wh_GetIntSetting(L"privacyMode") != 0;
g_Settings.redirectNetworkContextMenu = Wh_GetIntSetting(L"redirectNetworkContextMenu") != 0;
g_Settings.refreshInterval = Wh_GetIntSetting(L"refreshInterval");
g_Settings.language = Wh_GetIntSetting(L"language");
g_Settings.enableHotkey = Wh_GetIntSetting(L"enableHotkey") != 0;
g_Settings.disableRoundedCornersClassic = Wh_GetIntSetting(L"disableRoundedCornersClassic") != 0;
// Clamp refresh interval: 0 = disabled, minimum 100ms for sanity
if (g_Settings.refreshInterval < 0)
g_Settings.refreshInterval = 3000;
else if (g_Settings.refreshInterval > 0 && g_Settings.refreshInterval < 1000)
g_Settings.refreshInterval = 1000;
Wh_Log(L"Settings loaded - intercept:%d privacy:%d redirectCtx:%d refresh:%d language:%d classicCorners:%d",
g_Settings.interceptNativeFlyout, g_Settings.privacyMode,
g_Settings.redirectNetworkContextMenu,
g_Settings.refreshInterval, g_Settings.language,
g_Settings.disableRoundedCornersClassic);
}
// -------------------------------------------------------
// Structures
// -------------------------------------------------------
typedef struct {
HWND hWndFlyout;
HANDLE hWlanClient;
HANDLE hHotkeyThread;
DWORD dwHotkeyThreadId;
HWND hTrayNotifyWnd;
volatile LONG refCount;
volatile LONG isUninitializing;
CRITICAL_SECTION csLock;
} ModContext;
typedef struct {
WCHAR ssid[33];
BOOL isConnected;
BOOL isSecured;
ULONG signalQuality;
GUID interfaceGuid;
DOT11_BSS_TYPE dot11BssType;
BOOL hasProfile;
BOOL hasInternetAccess;
BOOL isConnecting;
BOOL isDisconnecting;
} WifiNetworkItem;
// -------------------------------------------------------
// Global Variables
// -------------------------------------------------------
static ModContext g_Ctx = {0};
static BOOL g_Initialized = FALSE;
HWND g_hWndFlyout = NULL;
HWND g_hWndButtonConnect = NULL;
HWND g_hWndCheckboxConnect = NULL;
BOOL g_bListExpanded = TRUE;
HFONT g_hFontNormal = NULL;
HFONT g_hFontBold = NULL;
HFONT g_hFontTitle = NULL;
HFONT g_hFontUnderline = NULL;
HFONT g_hFontButton = NULL;
HFONT g_hFontCheckbox = NULL;
HFONT g_hFontArrow = NULL;
WifiNetworkItem g_NetworkList[50];
int g_NetworkCount = 0;
BOOL g_IsHoveringLink = FALSE;
BOOL g_IsHoveringRefresh = FALSE;
BOOL g_IsHoveringArrow = FALSE;
int g_SelectedRowIndex = -1;
int g_HoveredRowIndex = -1;
int g_KeyboardSelectedIndex = -1;
int g_ContextMenuTargetIndex = -1;
RECT g_rcRefreshButton = { 0 };
RECT g_rcArrowButton = { 0 };
HICON g_hIconNetworkMap = NULL;
HICON g_hIconSignalBars[6] = { NULL };
HICON g_hIconRefreshWin7 = NULL;
BOOL g_IsConnectingAsynchronously = FALSE;
WCHAR g_PendingSsid[33] = {0};
int g_PendingConnectIndex = -1;
int g_ConnectRetryCount = 0;
HWND g_hTooltip = NULL;
UINT_PTR g_RefreshTimer = 0;
UINT_PTR g_ConnectCheckTimer = 0;
// TrackPopupMenuEx hook
using TrackPopupMenuEx_t = BOOL(WINAPI*)(HMENU, UINT, int, int, HWND, const TPMPARAMS*);
static TrackPopupMenuEx_t g_origTrackPopupMenuEx = nullptr;
// Persistent tooltip buffer
static WCHAR g_TooltipBuffer[1024] = {0};
// INetworkListManager singleton — released in SafeCleanup
static INetworkListManager* g_pNLM = NULL;
// Internet connectivity cache
static BOOL g_cachedInternetAccess = FALSE;
static DWORD g_lastInternetCheck = 0;
// Classic theme detection cache (checked once on init and on settings change)
static BOOL g_isClassicThemeCached = FALSE;
// Subclassing via WindhawkUtils
static HWND G_hSubclassedToolbar = nullptr;
// -------------------------------------------------------
// Localization
// -------------------------------------------------------
typedef struct {
const WCHAR* currentConnected;
const WCHAR* internetAccess;
const WCHAR* wifiHeader;
const WCHAR* connectedText;
const WCHAR* openSharingCenter;
const WCHAR* btnConnect;
const WCHAR* btnDisconnect;
const WCHAR* ctxConnect;
const WCHAR* ctxDisconnect;
const WCHAR* ctxStatus;
const WCHAR* ctxProperties;
const WCHAR* noConnections;
const WCHAR* connectionsAvailable;
const WCHAR* chkConnectAuto;
const WCHAR* pwdTitle;
const WCHAR* pwdInstructions;
const WCHAR* pwdLabel;
const WCHAR* pwdHideChars;
const WCHAR* pwdOK;
const WCHAR* pwdCancel;
const WCHAR* pwdFailedTitle;
const WCHAR* pwdFailedWrong;
const WCHAR* pwdConnectionFailed;
const WCHAR* networkPrivacyFmt;
const WCHAR* securityType;
const WCHAR* signalStrength;
const WCHAR* radioType;
const WCHAR* sigExcellent;
const WCHAR* sigGood;
const WCHAR* sigFair;
const WCHAR* sigPoor;
const WCHAR* sigNone;
const WCHAR* connecting;
const WCHAR* disconnecting;
const WCHAR* securityOpen;
const WCHAR* errSaveProfile;
const WCHAR* errConnectionFmt;
const WCHAR* errTimeout;
const WCHAR* errTitle;
const WCHAR* tooltipStatusConnected;
const WCHAR* tooltipStatusConnecting;
const WCHAR* tooltipStatusNotConnected;
const WCHAR* bssTypeInfrastructure;
const WCHAR* bssTypeIndependent;
const WCHAR* bssTypeUnknown;
} LocalizationStrings;
LocalizationStrings g_LocaleIT = {
L"Attualmente connesso a:", L"Accesso a Internet", L"Connessione rete wireless", L"Connesso",
L"Apri Centro connessioni di rete e condivisione", L"Connetti", L"Disconnetti",
L"Connetti", L"Disconnetti", L"Stato", L"Proprietà", L"Nessuna connessione disponibile",
L"Connessioni disponibili", L"Connetti automaticamente",
L"Connetti a una rete", L"Digitare la chiave di sicurezza di rete", L"Chiave di sicurezza:",
L"Nascondi caratteri", L"OK", L"Annulla",
L"Impossibile connettersi", L"La chiave di sicurezza di rete non è corretta. Riprova.",
L"Connessione a %s fallita", L"Rete %d",
L"Tipo di sicurezza:", L"Intensità del segnale:", L"Tipo di radio:",
L"Eccellente", L"Buono", L"Discreto", L"Scarso", L"Nessun segnale",
L"Connessione in corso...", L"Disconnessione in corso...",
L"Aperta",
L"Impossibile salvare il profilo di rete.",
L"Errore di connessione (codice: %lu)",
L"Timeout durante la connessione",
L"Errore",
L"Stato: Connesso",
L"Stato: Connessione in corso...",
L"Stato: Non connesso",
L"BSS: Infrastructure",
L"BSS: Independent",
L"BSS: Sconosciuto"
};
LocalizationStrings g_LocaleEN = {
L"Currently connected to:", L"Internet access", L"Wireless Network Connection", L"Connected",
L"Open Network and Sharing Center", L"Connect", L"Disconnect",
L"Connect", L"Disconnect", L"Status", L"Properties", L"No connections available",
L"Connections are available", L"Connect automatically",
L"Connect to a Network", L"Type the network security key", L"Security key:",
L"Hide characters", L"OK", L"Cancel",
L"Connection Failed", L"The network security key isn't correct. Please try again.",
L"Failed to connect to %s", L"Network %d",
L"Security type:", L"Signal strength:", L"Radio type:",
L"Excellent", L"Good", L"Fair", L"Poor", L"No signal",
L"Connecting...", L"Disconnecting...",
L"Open",
L"Failed to save network profile.",
L"Connection error (code: %lu)",
L"Connection timed out",
L"Error",
L"Status: Connected",
L"Status: Connecting...",
L"Status: Not connected",
L"BSS: Infrastructure",
L"BSS: Independent",
L"BSS: Unknown"
};
LocalizationStrings* g_CurrentLocale = &g_LocaleEN;
void DetermineLocale() {
switch (g_Settings.language) {
case 1:
g_CurrentLocale = &g_LocaleEN;
break;
case 2:
g_CurrentLocale = &g_LocaleIT;
break;
default:
g_CurrentLocale = ((GetUserDefaultUILanguage() & 0xFF) == 0x10) ?
&g_LocaleIT : &g_LocaleEN;
break;
}
Wh_Log(L"Locale: %s", g_CurrentLocale == &g_LocaleIT ? L"Italian" : L"English");
}
static const WCHAR* SignalQualityToString(ULONG quality) {
if (quality > 80) return g_CurrentLocale->sigExcellent;
if (quality > 60) return g_CurrentLocale->sigGood;
if (quality > 40) return g_CurrentLocale->sigFair;
if (quality > 20) return g_CurrentLocale->sigPoor;
return g_CurrentLocale->sigNone;
}
// -------------------------------------------------------
// Prototypes
// -------------------------------------------------------
void RefreshWifiData(HANDLE hClient);
void UpdateLayoutGeometry();
void HandleNativeConnection(HANDLE hClient, int index);
BOOL SafeToAccessUI();
void SafeCleanup();
void ToggleFlyoutWindow();
void InitTooltip(HWND hwnd);
void UpdateTooltipForRow(HWND hwnd, int index);
BOOL GetRowRect(int index, RECT* rcRow);
void InstallTrayInterception();
void RemoveTrayInterception();
void InitRefreshButtonRect();
BOOL GetAdapterNameForInterface(GUID interfaceGuid, WCHAR* adapterName, DWORD bufferSize);
void OpenNetworkStatusForInterface(GUID interfaceGuid);
void OpenNetworkPropertiesForInterface(GUID interfaceGuid);
void SetKeyboardFocus(int index);
void ClearKeyboardFocus();
BOOL IsInternetConnected();
static void UpdateClassicThemeCache();
// -------------------------------------------------------
// Classic theme detection (cached)
// -------------------------------------------------------
static void UpdateClassicThemeCache() {
BOOL flatMenus = FALSE;
SystemParametersInfoW(SPI_GETFLATMENU, 0, &flatMenus, 0);
g_isClassicThemeCached = !flatMenus;
}
static BOOL IsClassicTheme() {
return g_isClassicThemeCached;
}
// -------------------------------------------------------
// Internet connectivity check (cached, no external servers)
// -------------------------------------------------------
BOOL IsInternetConnected() {
DWORD now = GetTickCount();
if (now - g_lastInternetCheck < INTERNET_CHECK_CACHE_MS)
return g_cachedInternetAccess;
if (!g_pNLM) {
CoCreateInstance(CLSID_NetworkListManager, NULL, CLSCTX_INPROC_SERVER,
IID_INetworkListManager, (void**)&g_pNLM);
}
if (!g_pNLM) return FALSE;
NLM_CONNECTIVITY connectivity;
if (FAILED(g_pNLM->GetConnectivity(&connectivity))) return FALSE;
g_cachedInternetAccess = (connectivity & NLM_CONNECTIVITY_IPV4_INTERNET) ||
(connectivity & NLM_CONNECTIVITY_IPV6_INTERNET);
g_lastInternetCheck = now;
return g_cachedInternetAccess;
}
// -------------------------------------------------------
// XML string escaper for WLAN profile generation
// -------------------------------------------------------
static void EscapeXmlString(const WCHAR* input, WCHAR* output, size_t outputSize) {
const WCHAR* src = input;
WCHAR* dst = output;
while (*src && (size_t)(dst - output) < outputSize - 10) {
switch (*src) {
case L'&': wcscpy_s(dst, 6, L"&"); dst += 5; break;
case L'<': wcscpy_s(dst, 5, L"<"); dst += 4; break;
case L'>': wcscpy_s(dst, 5, L">"); dst += 4; break;
case L'"': wcscpy_s(dst, 7, L"""); dst += 6; break;
case L'\'': wcscpy_s(dst, 7, L"'"); dst += 6; break;
default: *dst++ = *src; break;
}
src++;
}
*dst = L'\0';
}
// -------------------------------------------------------
// Focus / keyboard helpers
// -------------------------------------------------------
void SetKeyboardFocus(int index) {
if (index < -1 || index >= g_NetworkCount) return;
ClearKeyboardFocus();
g_KeyboardSelectedIndex = index;
if (index >= 0 && g_bListExpanded) {
g_SelectedRowIndex = index;
UpdateLayoutGeometry();
}
if (SafeToAccessUI() && g_hWndFlyout)
InvalidateRect(g_hWndFlyout, NULL, TRUE);
}
void ClearKeyboardFocus() {
g_KeyboardSelectedIndex = -1;
}
void DrawFocusRectangle(HDC hdc, const RECT* rcRow) {
RECT rcFocus = *rcRow;
rcFocus.left += 8;
rcFocus.right -= 8;
rcFocus.top += 2;
rcFocus.bottom -= 2;
HPEN hPen = CreatePen(PS_DOT, 1, RGB(0, 0, 0));
HPEN hOldPen = (HPEN)SelectObject(hdc, hPen);
HBRUSH hOldBrush = (HBRUSH)SelectObject(hdc, GetStockObject(NULL_BRUSH));
Rectangle(hdc, rcFocus.left, rcFocus.top, rcFocus.right, rcFocus.bottom);
SelectObject(hdc, hOldPen);
SelectObject(hdc, hOldBrush);
DeleteObject(hPen);
}
// -------------------------------------------------------
// Adapter helpers
// -------------------------------------------------------
BOOL GetAdapterNameForInterface(GUID interfaceGuid, WCHAR* adapterName, DWORD bufferSize) {
PIP_ADAPTER_INFO pAdapterInfo = NULL;
ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO);
DWORD dwStatus;
pAdapterInfo = (IP_ADAPTER_INFO*)malloc(ulOutBufLen);
if (!pAdapterInfo) return FALSE;
dwStatus = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen);
if (dwStatus == ERROR_BUFFER_OVERFLOW) {
free(pAdapterInfo);
pAdapterInfo = (IP_ADAPTER_INFO*)malloc(ulOutBufLen);
if (!pAdapterInfo) return FALSE;
dwStatus = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen);
}
if (dwStatus == NO_ERROR) {
PIP_ADAPTER_INFO pAdapter = pAdapterInfo;
while (pAdapter) {
WCHAR wideAdapterName[256];
MultiByteToWideChar(CP_ACP, 0, pAdapter->AdapterName, -1, wideAdapterName, 256);
GUID adapterGuid;
if (CLSIDFromString(wideAdapterName, &adapterGuid) == S_OK) {
if (IsEqualGUID(adapterGuid, interfaceGuid)) {
MultiByteToWideChar(CP_ACP, 0, pAdapter->Description, -1, adapterName, bufferSize);
free(pAdapterInfo);
return TRUE;
}
}
pAdapter = pAdapter->Next;
}
}
if (pAdapterInfo) free(pAdapterInfo);
return FALSE;
}
void OpenNetworkStatusForInterface(GUID interfaceGuid) {
WCHAR adapterName[256];
if (GetAdapterNameForInterface(interfaceGuid, adapterName, 256)) {
HWND hNcpa = FindWindowW(NULL, L"Connessioni di rete");
if (!hNcpa) hNcpa = FindWindowW(NULL, L"Network Connections");
if (!hNcpa) {
ShellExecuteW(NULL, L"open", L"control.exe", L"ncpa.cpl", NULL, SW_SHOWNORMAL);
for (int wait = 0; wait < 10 && !hNcpa; wait++) {
Sleep(50);
hNcpa = FindWindowW(NULL, L"Connessioni di rete");
if (!hNcpa) hNcpa = FindWindowW(NULL, L"Network Connections");
}
}
if (hNcpa) {
SetForegroundWindow(hNcpa);
SetWindowPos(hNcpa, HWND_TOPMOST, 0,0,0,0, SWP_NOMOVE|SWP_NOSIZE);
SetWindowPos(hNcpa, HWND_NOTOPMOST, 0,0,0,0, SWP_NOMOVE|SWP_NOSIZE);
HWND hListView = FindWindowExW(hNcpa, NULL, L"SysListView32", NULL);
if (hListView) {
int itemCount = (int)SendMessageW(hListView, LVM_GETITEMCOUNT, 0, 0);
for (int i = 0; i < itemCount; i++) {
WCHAR itemText[256]; LVITEMW lvi = {0};
lvi.mask=LVIF_TEXT; lvi.iItem=i; lvi.iSubItem=0;
lvi.pszText=itemText; lvi.cchTextMax=256;
SendMessageW(hListView, LVM_GETITEMW, 0, (LPARAM)&lvi);
if (wcsstr(itemText, adapterName) || wcsstr(adapterName, itemText)) {
ListView_SetItemState(hListView, i, LVIS_SELECTED, LVIS_SELECTED);
RECT rcItem;
SendMessageW(hListView, LVM_GETITEMRECT, (WPARAM)i, (LPARAM)&rcItem);
int x=(rcItem.left+rcItem.right)/2, y=(rcItem.top+rcItem.bottom)/2;
PostMessage(hListView, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(x,y));
PostMessage(hListView, WM_LBUTTONUP, 0, MAKELPARAM(x,y));
PostMessage(hListView, WM_LBUTTONDBLCLK, MK_LBUTTON, MAKELPARAM(x,y));
PostMessage(hListView, WM_LBUTTONUP, 0, MAKELPARAM(x,y));
break;
}
}
}
}
} else {
ShellExecuteW(NULL, L"open", L"control.exe", L"ncpa.cpl", NULL, SW_SHOWNORMAL);
}
}
void OpenNetworkPropertiesForInterface(GUID interfaceGuid) {
WCHAR adapterName[256];
if (GetAdapterNameForInterface(interfaceGuid, adapterName, 256)) {
HWND hNcpa = FindWindowW(NULL, L"Connessioni di rete");
if (!hNcpa) hNcpa = FindWindowW(NULL, L"Network Connections");
if (!hNcpa) {
ShellExecuteW(NULL, L"open", L"control.exe", L"ncpa.cpl", NULL, SW_SHOWNORMAL);
for (int wait = 0; wait < 10 && !hNcpa; wait++) {
Sleep(50);
hNcpa = FindWindowW(NULL, L"Connessioni di rete");
if (!hNcpa) hNcpa = FindWindowW(NULL, L"Network Connections");
}
}
if (hNcpa) {
SetForegroundWindow(hNcpa);
SetWindowPos(hNcpa, HWND_TOPMOST, 0,0,0,0, SWP_NOMOVE|SWP_NOSIZE);
SetWindowPos(hNcpa, HWND_NOTOPMOST, 0,0,0,0, SWP_NOMOVE|SWP_NOSIZE);
HWND hListView = FindWindowExW(hNcpa, NULL, L"SysListView32", NULL);
if (hListView) {
int itemCount = (int)SendMessageW(hListView, LVM_GETITEMCOUNT, 0, 0);
for (int i = 0; i < itemCount; i++) {
WCHAR itemText[256]; LVITEMW lvi = {0};
lvi.mask=LVIF_TEXT; lvi.iItem=i; lvi.iSubItem=0;
lvi.pszText=itemText; lvi.cchTextMax=256;
SendMessageW(hListView, LVM_GETITEMW, 0, (LPARAM)&lvi);
if (wcsstr(itemText, adapterName) || wcsstr(adapterName, itemText)) {
ListView_SetItemState(hListView, i, LVIS_SELECTED, LVIS_SELECTED);
SetForegroundWindow(hNcpa);
INPUT inputs[4] = {{0}};
inputs[0].type=INPUT_KEYBOARD; inputs[0].ki.wVk=VK_MENU;
inputs[1].type=INPUT_KEYBOARD; inputs[1].ki.wVk=VK_RETURN;
inputs[2].type=INPUT_KEYBOARD; inputs[2].ki.wVk=VK_RETURN; inputs[2].ki.dwFlags=KEYEVENTF_KEYUP;
inputs[3].type=INPUT_KEYBOARD; inputs[3].ki.wVk=VK_MENU; inputs[3].ki.dwFlags=KEYEVENTF_KEYUP;
SendInput(4, inputs, sizeof(INPUT));
break;
}
}
}
}
} else {
ShellExecuteW(NULL, L"open", L"control.exe", L"ncpa.cpl", NULL, SW_SHOWNORMAL);
}
}
// -------------------------------------------------------
// Refresh button rect
// -------------------------------------------------------
void InitRefreshButtonRect() {
g_rcRefreshButton.right = WINDOW_WIDTH - 20;
g_rcRefreshButton.left = g_rcRefreshButton.right - 22;
g_rcRefreshButton.top = 8;
g_rcRefreshButton.bottom = 30;
}
// -------------------------------------------------------
// Execute mapped command
// -------------------------------------------------------
static void ExecuteMappedCommand(const wchar_t* command) {
if (!command) return;
Wh_Log(L"ExecuteMappedCommand: %s", command);
SHELLEXECUTEINFOW sei = { sizeof(sei) };
sei.lpVerb = L"open";
sei.nShow = SW_SHOWNORMAL;
const wchar_t* spacePos = wcschr(command, L' ');
if (spacePos) {
wchar_t program[256];
size_t progLen = spacePos - command;
wcsncpy_s(program, 256, command, progLen);
program[progLen] = L'\0';
sei.lpFile = program;
sei.lpParameters = spacePos + 1;
} else {
sei.lpFile = command;
}
ShellExecuteExW(&sei);
}
// -------------------------------------------------------
// TrackPopupMenuEx Hook — hooked once in Wh_ModInit,
// only intercepts menus that originate from Shell_TrayWnd
// -------------------------------------------------------
static BOOL WINAPI TrackPopupMenuEx_Hook(HMENU hMenu, UINT uFlags, int x, int y,
HWND hWnd, const TPMPARAMS* lptpm) {
if (!g_Settings.redirectNetworkContextMenu)
return g_origTrackPopupMenuEx(hMenu, uFlags, x, y, hWnd, lptpm);
BOOL isNetworkTrayMenu = FALSE;
HWND hTray = FindWindowW(L"Shell_TrayWnd", NULL);
if (hTray) {
HWND hWndCheck = hWnd;
while (hWndCheck) {
if (hWndCheck == hTray) { isNetworkTrayMenu = TRUE; break; }
hWndCheck = GetParent(hWndCheck);
}
}
if (!isNetworkTrayMenu)
return g_origTrackPopupMenuEx(hMenu, uFlags, x, y, hWnd, lptpm);
UINT modifiedFlags = uFlags | TPM_RETURNCMD;
BOOL result = g_origTrackPopupMenuEx(hMenu, modifiedFlags, x, y, hWnd, lptpm);
if (result > 0) {
UINT cmd = (UINT)result;
Wh_Log(L"TrackPopupMenuEx: cmd %u", cmd);
switch (cmd) {
case CMD_OPEN_NETWORK_SETTINGS: ToggleFlyoutWindow(); return 0;
case CMD_NETWORK_STATUS: ExecuteMappedCommand(L"control.exe ncpa.cpl"); return 0;
case CMD_NETWORK_DIAGNOSTICS: ExecuteMappedCommand(L"msdt.exe -id NetworkDiagnosticsWeb"); return 0;
}
}
return result;
}
// -------------------------------------------------------
// SSID display helper
// -------------------------------------------------------
static void GetDisplaySSID(int index, WCHAR* buf, int bufLen) {
if (g_Settings.privacyMode)
StringCchPrintfW(buf, bufLen, g_CurrentLocale->networkPrivacyFmt, index + 1);
else
StringCchCopyW(buf, bufLen, g_NetworkList[index].ssid);
}
// -------------------------------------------------------
// Icons and resources
// -------------------------------------------------------
void LoadSystemIcons() {
if (!g_hIconNetworkMap)
ExtractIconExW(L"netshell.dll", 120, &g_hIconNetworkMap, NULL, 1);
for (int i = 0; i < 6; i++)
if (!g_hIconSignalBars[i])
ExtractIconExW(L"netshell.dll", 152 + i, &g_hIconSignalBars[i], NULL, 1);
if (!g_hIconRefreshWin7)
ExtractIconExW(L"shell32.dll", 238, &g_hIconRefreshWin7, NULL, 1);
}
void FreeSystemIcons() {
if (g_hIconNetworkMap) { DestroyIcon(g_hIconNetworkMap); g_hIconNetworkMap = NULL; }
for (int i = 0; i < 6; i++)
if (g_hIconSignalBars[i]) { DestroyIcon(g_hIconSignalBars[i]); g_hIconSignalBars[i] = NULL; }
if (g_hIconRefreshWin7) { DestroyIcon(g_hIconRefreshWin7); g_hIconRefreshWin7 = NULL; }
}
void InitGlobalFonts() {
if (g_hFontNormal) return;
g_hFontNormal = CreateFontW(-12,0,0,0,FW_NORMAL,0,0,0,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,CLEARTYPE_QUALITY,DEFAULT_PITCH|FF_DONTCARE,L"Segoe UI");
g_hFontBold = CreateFontW(-12,0,0,0,FW_BOLD, 0,0,0,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,CLEARTYPE_QUALITY,DEFAULT_PITCH|FF_DONTCARE,L"Segoe UI");
g_hFontTitle = CreateFontW(-13,0,0,0,FW_BOLD, 0,0,0,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,CLEARTYPE_QUALITY,DEFAULT_PITCH|FF_DONTCARE,L"Segoe UI");
g_hFontUnderline = CreateFontW(-12,0,0,0,FW_NORMAL,0,1,0,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,CLEARTYPE_QUALITY,DEFAULT_PITCH|FF_DONTCARE,L"Segoe UI");
g_hFontButton = CreateFontW(-12,0,0,0,FW_NORMAL,0,0,0,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,CLEARTYPE_QUALITY,DEFAULT_PITCH|FF_DONTCARE,L"Segoe UI");
g_hFontCheckbox = CreateFontW(-11,0,0,0,FW_NORMAL,0,0,0,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,CLEARTYPE_QUALITY,DEFAULT_PITCH|FF_DONTCARE,L"Segoe UI");
g_hFontArrow = CreateFontW(-11,0,0,0,FW_NORMAL,0,0,0,SYMBOL_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH|FF_DONTCARE,L"Marlett");
}
void FreeGlobalFonts() {
if (g_hFontNormal) { DeleteObject(g_hFontNormal); g_hFontNormal = NULL; }
if (g_hFontBold) { DeleteObject(g_hFontBold); g_hFontBold = NULL; }
if (g_hFontTitle) { DeleteObject(g_hFontTitle); g_hFontTitle = NULL; }
if (g_hFontUnderline) { DeleteObject(g_hFontUnderline); g_hFontUnderline = NULL; }
if (g_hFontButton) { DeleteObject(g_hFontButton); g_hFontButton = NULL; }
if (g_hFontCheckbox) { DeleteObject(g_hFontCheckbox); g_hFontCheckbox = NULL; }
if (g_hFontArrow) { DeleteObject(g_hFontArrow); g_hFontArrow = NULL; }
}
BOOL SafeToAccessUI() {
return (g_Ctx.refCount > 0 && !g_Ctx.isUninitializing && g_hWndFlyout && IsWindow(g_hWndFlyout));
}
void PositionWindowNearTray(HWND hwnd) {
APPBARDATA abd = { sizeof(APPBARDATA) };
SHAppBarMessage(ABM_GETTASKBARPOS, &abd);
RECT rcWork;
SystemParametersInfoW(SPI_GETWORKAREA, 0, &rcWork, 0);
int x = rcWork.right - WINDOW_WIDTH - 8;
int y = rcWork.bottom - WINDOW_HEIGHT - 8;
if (abd.uEdge == ABE_TOP) y = abd.rc.bottom + 8;
else if (abd.uEdge == ABE_LEFT) x = abd.rc.right + 8;
else if (abd.uEdge == ABE_RIGHT) x = abd.rc.left - WINDOW_WIDTH - 8;
SetWindowPos(hwnd, HWND_TOPMOST, x, y, WINDOW_WIDTH, WINDOW_HEIGHT, SWP_SHOWWINDOW);
}
// -------------------------------------------------------
// WLAN data — SSID parsing fixes + duplicate prevention
// -------------------------------------------------------
void RefreshWifiData(HANDLE hClient) {
if (!hClient) return;
PWLAN_INTERFACE_INFO_LIST pIfList = NULL;
if (WlanEnumInterfaces(hClient, NULL, &pIfList) != ERROR_SUCCESS) return;
g_NetworkCount = 0;
for (DWORD i = 0; i < pIfList->dwNumberOfItems; i++) {
WLAN_INTERFACE_INFO IfInfo = pIfList->InterfaceInfo[i];
PWLAN_AVAILABLE_NETWORK_LIST pBssList = NULL;
PWLAN_PROFILE_INFO_LIST pProfList = NULL;
WlanGetProfileList(hClient, &IfInfo.InterfaceGuid, NULL, &pProfList);
DWORD dwFlags = WLAN_AVAILABLE_NETWORK_INCLUDE_ALL_MANUAL_HIDDEN_PROFILES;
if (WlanGetAvailableNetworkList(hClient, &IfInfo.InterfaceGuid, dwFlags, NULL, &pBssList) == ERROR_SUCCESS) {
for (DWORD j = 0; j < pBssList->dwNumberOfItems && g_NetworkCount < 50; j++) {
WLAN_AVAILABLE_NETWORK network = pBssList->Network[j];
WifiNetworkItem* item = &g_NetworkList[g_NetworkCount];
DWORD len = network.dot11Ssid.uSSIDLength;
if (len == 0) {
StringCchCopyW(item->ssid, 33, L"Hidden Network");
} else {
int converted = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
(LPCSTR)network.dot11Ssid.ucSSID, (int)len,
item->ssid, 32);
if (converted <= 0) {
for (DWORD k = 0; k < len && k < 32; k++)
item->ssid[k] = (WCHAR)(BYTE)network.dot11Ssid.ucSSID[k];
item->ssid[len] = L'\0';
} else {
item->ssid[converted] = L'\0';
}
}
BOOL duplicate = FALSE;
for (int d = 0; d < g_NetworkCount; d++) {
if (wcscmp(g_NetworkList[d].ssid, item->ssid) == 0) {
if (network.wlanSignalQuality > g_NetworkList[d].signalQuality)
g_NetworkList[d].signalQuality = network.wlanSignalQuality;
if (network.dwFlags & WLAN_AVAILABLE_NETWORK_CONNECTED)
g_NetworkList[d].isConnected = TRUE;
duplicate = TRUE;
break;
}
}
if (duplicate) continue;
item->isConnected = (network.dwFlags & WLAN_AVAILABLE_NETWORK_CONNECTED) != 0;
item->isSecured = network.bSecurityEnabled;
item->signalQuality = network.wlanSignalQuality;
item->interfaceGuid = IfInfo.InterfaceGuid;
item->dot11BssType = network.dot11BssType;
item->hasProfile = FALSE;
item->hasInternetAccess = FALSE;
item->isConnecting = FALSE;
item->isDisconnecting = FALSE;
if (pProfList) {
for (DWORD p = 0; p < pProfList->dwNumberOfItems; p++) {
if (wcscmp(pProfList->ProfileInfo[p].strProfileName, item->ssid) == 0) {
item->hasProfile = TRUE;
break;
}
}
}
if (item->isConnected && g_NetworkCount > 0) {
WifiNetworkItem tmp;
CopyMemory(&tmp, &g_NetworkList[0], sizeof(WifiNetworkItem));
CopyMemory(&g_NetworkList[0], item, sizeof(WifiNetworkItem));
CopyMemory(item, &tmp, sizeof(WifiNetworkItem));
}
g_NetworkCount++;
}
WlanFreeMemory(pBssList);
}
if (pProfList) WlanFreeMemory(pProfList);
}
WlanFreeMemory(pIfList);
if (g_NetworkCount > 0 && g_NetworkList[0].isConnected)
g_NetworkList[0].hasInternetAccess = IsInternetConnected();
for (int i = 0; i < g_NetworkCount; i++) {
if (g_IsConnectingAsynchronously &&
wcscmp(g_NetworkList[i].ssid, g_PendingSsid) == 0) {
g_NetworkList[i].isConnecting = TRUE;
}
}
}
// -------------------------------------------------------
// Password dialog (Windows 7 style)
// -------------------------------------------------------
typedef struct {
WCHAR* passwordBuffer;
DWORD bufferSize;
BOOL confirmed;
WCHAR networkName[33];
} PasswordDlgData;
LRESULT CALLBACK Win7PasswordWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
PasswordDlgData* data = (PasswordDlgData*)GetWindowLongPtrW(hwnd, GWLP_USERDATA);
switch (uMsg) {
case WM_NCHITTEST: {
LRESULT r = DefWindowProcW(hwnd, uMsg, wParam, lParam);
if (r==HTBOTTOM||r==HTBOTTOMLEFT||r==HTBOTTOMRIGHT||
r==HTLEFT||r==HTRIGHT||r==HTTOP||r==HTTOPLEFT||r==HTTOPRIGHT)
return HTCLIENT;
return r;
}
case WM_CREATE: {
CREATESTRUCTW* cs = (CREATESTRUCTW*)lParam;
data = (PasswordDlgData*)cs->lpCreateParams;
if (!data) return -1;
SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR)data);
HFONT hFontDlg = CreateFontW(-12,0,0,0,FW_NORMAL,0,0,0,DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,CLEARTYPE_QUALITY,DEFAULT_PITCH|FF_DONTCARE,L"Segoe UI");
HWND hInstruction = CreateWindowExW(0, WC_STATICW, g_CurrentLocale->pwdInstructions,
WS_CHILD|WS_VISIBLE, 15,15,380,20, hwnd,(HMENU)200,cs->hInstance,NULL);
SendMessageW(hInstruction, WM_SETFONT, (WPARAM)hFontDlg, TRUE);
HWND hLabel = CreateWindowExW(0, WC_STATICW, g_CurrentLocale->pwdLabel,
WS_CHILD|WS_VISIBLE, 15,53,115,18, hwnd,NULL,cs->hInstance,NULL);
SendMessageW(hLabel, WM_SETFONT, (WPARAM)hFontDlg, TRUE);
HWND hEdit = CreateWindowExW(WS_EX_CLIENTEDGE, WC_EDITW, L"",
WS_CHILD|WS_VISIBLE|ES_PASSWORD|ES_AUTOHSCROLL,
135,50,255,22, hwnd,(HMENU)101,cs->hInstance,NULL);
SendMessageW(hEdit, WM_SETFONT, (WPARAM)hFontDlg, TRUE);
SetFocus(hEdit);
HWND hCheck = CreateWindowExW(0, WC_BUTTONW, g_CurrentLocale->pwdHideChars,
WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX, 135,80,200,18, hwnd,(HMENU)102,cs->hInstance,NULL);
SendMessageW(hCheck, WM_SETFONT, (WPARAM)hFontDlg, TRUE);
RECT rcClient; GetClientRect(hwnd, &rcClient);
int btnW=85, btnH=24, btnY=rcClient.bottom-35;
HWND hBtnOk = CreateWindowExW(0, WC_BUTTONW, g_CurrentLocale->pwdOK,
WS_CHILD|WS_VISIBLE|BS_DEFPUSHBUTTON,
rcClient.right-btnW-15, btnY, btnW,btnH, hwnd,(HMENU)IDOK,cs->hInstance,NULL);
SendMessageW(hBtnOk, WM_SETFONT, (WPARAM)hFontDlg, TRUE);
HWND hBtnCancel = CreateWindowExW(0, WC_BUTTONW, g_CurrentLocale->pwdCancel,
WS_CHILD|WS_VISIBLE, rcClient.right-(btnW*2)-25, btnY, btnW,btnH,
hwnd,(HMENU)IDCANCEL,cs->hInstance,NULL);
SendMessageW(hBtnCancel, WM_SETFONT, (WPARAM)hFontDlg, TRUE);
BOOL pfEnabled = FALSE;
DwmIsCompositionEnabled(&pfEnabled);
if (pfEnabled) {
DWMNCRENDERINGPOLICY pol = DWMNCRP_ENABLED;
DwmSetWindowAttribute(hwnd, DWMWA_NCRENDERING_POLICY, &pol, sizeof(pol));
}
HMODULE hShell32 = LoadLibraryW(L"shell32.dll");
if (hShell32) {
HICON hIconLarge = (HICON)LoadImageW(hShell32, MAKEINTRESOURCE(162),
IMAGE_ICON, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), LR_SHARED);
HICON hIconSmall = (HICON)LoadImageW(hShell32, MAKEINTRESOURCE(162),
IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED);
if (hIconLarge) SendMessageW(hwnd, WM_SETICON, ICON_BIG, (LPARAM)hIconLarge);
if (hIconSmall) SendMessageW(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)hIconSmall);
FreeLibrary(hShell32);
} else {
HICON hFallback = LoadIconW(NULL, IDI_APPLICATION);
SendMessageW(hwnd, WM_SETICON, ICON_BIG, (LPARAM)hFallback);
SendMessageW(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)hFallback);
}
break;
}
case WM_CTLCOLORSTATIC: {
HDC hdc = (HDC)wParam;
SetBkMode(hdc, TRANSPARENT);
if (GetDlgCtrlID((HWND)lParam) == 200)
SetTextColor(hdc, RGB(0,51,153));
else
SetTextColor(hdc, RGB(0,0,0));
return (INT_PTR)GetStockObject(NULL_BRUSH);
}
case WM_COMMAND: {
int wmId = LOWORD(wParam);
if (wmId == 102) {
HWND hEdit = GetDlgItem(hwnd, 101);
BOOL checked = SendMessageW((HWND)lParam, BM_GETCHECK, 0, 0) == BST_CHECKED;
SendMessageW(hEdit, EM_SETPASSWORDCHAR, checked ? 0 : L'*', 0);
InvalidateRect(hEdit, NULL, TRUE);
return 0;
}
if (wmId == IDOK) {
if (data) { GetDlgItemTextW(hwnd,101,data->passwordBuffer,data->bufferSize); data->confirmed=TRUE; }
DestroyWindow(hwnd); return 0;
} else if (wmId == IDCANCEL) {
if (data) data->confirmed = FALSE;
DestroyWindow(hwnd); return 0;
}
break;
}
case WM_CLOSE:
if (data) data->confirmed = FALSE;
DestroyWindow(hwnd);
return 0;
}
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
}
BOOL PromptNetworkPassword(HWND hParent, WCHAR* passwordBuffer, DWORD bufferSize, const WCHAR* networkName) {
if (!SafeToAccessUI()) return FALSE;
HINSTANCE hInst = GetModuleHandle(NULL);
WNDCLASSW wc = {0};
wc.lpfnWndProc = Win7PasswordWndProc;
wc.hInstance = hInst;
wc.lpszClassName = L"Win7NetPwdClass";
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
wc.hIcon = LoadIconW(NULL, IDI_APPLICATION);
UnregisterClassW(wc.lpszClassName, hInst);
RegisterClassW(&wc);
PasswordDlgData data = { passwordBuffer, bufferSize, FALSE };
StringCchCopyW(data.networkName, 33, networkName ? networkName : L"");
RECT rcWork;
SystemParametersInfoW(SPI_GETWORKAREA, 0, &rcWork, 0);
int dlgW=420, dlgH=180;
HWND hDlg = CreateWindowExW(
WS_EX_DLGMODALFRAME|WS_EX_WINDOWEDGE|WS_EX_TOPMOST,
wc.lpszClassName, g_CurrentLocale->pwdTitle,
WS_POPUP|WS_CAPTION|WS_SYSMENU,
rcWork.right-dlgW-10, rcWork.bottom-dlgH-5, dlgW,dlgH,
hParent, NULL, hInst, &data);
if (!hDlg) return FALSE;
ShowWindow(hDlg, SW_SHOW);
EnableWindow(hParent, FALSE);
MSG msg;
while (IsWindow(hDlg) && GetMessageW(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
EnableWindow(hParent, TRUE);
SetForegroundWindow(hParent);
return data.confirmed;
}
// -------------------------------------------------------
// Connection handler (with XML escaping for SSID/password)
// -------------------------------------------------------
void HandleNativeConnection(HANDLE hClient, int index) {
if (index < 0 || index >= g_NetworkCount || !hClient) return;
WifiNetworkItem* item = &g_NetworkList[index];
if (item->isConnected) {
g_IsConnectingAsynchronously = FALSE;
g_PendingConnectIndex = -1;
WlanDisconnect(hClient, &item->interfaceGuid, NULL);
g_PendingConnectIndex = index;
g_ConnectRetryCount = 0;
g_NetworkList[index].isDisconnecting = TRUE;
if (g_ConnectCheckTimer) {
KillTimer(g_hWndFlyout, g_ConnectCheckTimer);
g_ConnectCheckTimer = 0;
}
g_ConnectCheckTimer = SetTimer(g_hWndFlyout, 1001, 300, NULL);
return;
}
if (item->isSecured && !item->hasProfile) {
WCHAR password[65] = {0};
if (!PromptNetworkPassword(g_hWndFlyout, password, 64, item->ssid)) return;
WCHAR escapedSsid[200];
WCHAR escapedPassword[200];
EscapeXmlString(item->ssid, escapedSsid, 200);
EscapeXmlString(password, escapedPassword, 200);
WCHAR xmlProfile[2048];
StringCchPrintfW(xmlProfile, 2048,
L"<?xml version=\"1.0\"?>"
L"<WLANProfile xmlns=\"http://www.microsoft.com/networking/WLAN/profile/v1\">"
L"<name>%s</name><SSIDConfig><SSID><name>%s</name></SSID></SSIDConfig>"
L"<connectionType>ESS</connectionType><connectionMode>auto</connectionMode>"
L"<MSM><security><authEncryption>"
L"<authentication>WPA2PSK</authentication><encryption>AES</encryption><useOneX>false</useOneX>"
L"</authEncryption><sharedKey><keyType>passPhrase</keyType><protected>false</protected>"
L"<keyMaterial>%s</keyMaterial></sharedKey></security></MSM></WLANProfile>",
escapedSsid, escapedSsid, escapedPassword);
DWORD dwReason = 0;
if (WlanSetProfile(hClient,&item->interfaceGuid,0,xmlProfile,NULL,TRUE,NULL,&dwReason) != ERROR_SUCCESS) {
MessageBoxW(g_hWndFlyout, g_CurrentLocale->errSaveProfile,
g_CurrentLocale->errTitle, MB_OK|MB_ICONERROR);
return;
}
item->hasProfile = TRUE;
}
g_IsConnectingAsynchronously = TRUE;
g_PendingConnectIndex = index;
StringCchCopyW(g_PendingSsid, 33, item->ssid);
g_NetworkList[index].isConnecting = TRUE;
g_ConnectRetryCount = 0;
WLAN_CONNECTION_PARAMETERS params; ZeroMemory(¶ms, sizeof(params));
if (item->hasProfile) {
params.wlanConnectionMode = wlan_connection_mode_profile;
params.strProfile = item->ssid;
} else {
params.wlanConnectionMode = wlan_connection_mode_discovery_unsecure;
}
params.dot11BssType = item->dot11BssType;
DWORD res = WlanConnect(hClient, &item->interfaceGuid, ¶ms, NULL);
if (res != ERROR_SUCCESS) {
g_IsConnectingAsynchronously = FALSE;
g_NetworkList[index].isConnecting = FALSE;
WCHAR err[256];
StringCchPrintfW(err, 256, g_CurrentLocale->errConnectionFmt, res);
MessageBoxW(g_hWndFlyout, err, g_CurrentLocale->errTitle, MB_OK|MB_ICONERROR);
return;
}
if (g_ConnectCheckTimer) {
KillTimer(g_hWndFlyout, g_ConnectCheckTimer);
g_ConnectCheckTimer = 0;
}
g_ConnectCheckTimer = SetTimer(g_hWndFlyout, 1001, 300, NULL);
}
// -------------------------------------------------------
// WLAN Notification Callback — thread-safe
// Only posts messages; never touches UI or global state directly
// -------------------------------------------------------
void WINAPI WlanNotificationCallback(PWLAN_NOTIFICATION_DATA data, PVOID context) {
ModContext* ctx = (ModContext*)context;
if (!ctx || ctx->isUninitializing) return;
if (!data) return;
BOOL needRefresh = FALSE;
switch(data->NotificationSource) {
case WLAN_NOTIFICATION_SOURCE_ACM:
switch (data->NotificationCode) {
case wlan_notification_acm_connection_complete:
case wlan_notification_acm_disconnected:
case wlan_notification_acm_scan_complete:
needRefresh = TRUE;
break;
case wlan_notification_acm_connection_attempt_fail:
needRefresh = TRUE;
if (ctx->hWndFlyout && IsWindow(ctx->hWndFlyout))
PostMessageW(ctx->hWndFlyout, WM_CHECK_CONNECTION,
CONN_NOTIFY_ATTEMPT_FAIL, 0);
break;
}
break;
case WLAN_NOTIFICATION_SOURCE_MSM:
switch (data->NotificationCode) {
case wlan_notification_msm_connected:
needRefresh = TRUE;
if (ctx->hWndFlyout && IsWindow(ctx->hWndFlyout))
PostMessageW(ctx->hWndFlyout, WM_CHECK_CONNECTION,
CONN_NOTIFY_MSM_CONNECTED, 0);
break;
case wlan_notification_msm_disconnected:
needRefresh = TRUE;
if (ctx->hWndFlyout && IsWindow(ctx->hWndFlyout))
PostMessageW(ctx->hWndFlyout, WM_CHECK_CONNECTION,
CONN_NOTIFY_MSM_DISCONNECTED, 0);
break;
}
break;
}
if (needRefresh && ctx->hWndFlyout && IsWindow(ctx->hWndFlyout))
PostMessageW(ctx->hWndFlyout, WM_REFRESH_DATA, 0, 0);
}
void DrawNativeSignalIcon(HDC hdc, int right, int top, ULONG quality) {
int idx = 0;
if (quality > 80) idx = 5;
else if (quality > 60) idx = 4;
else if (quality > 40) idx = 3;
else if (quality > 20) idx = 2;
else if (quality > 0) idx = 1;
if (g_hIconSignalBars[idx])
DrawIconEx(hdc, right-24, top+4, g_hIconSignalBars[idx], 16, 16, 0, NULL, DI_NORMAL);
}
// -------------------------------------------------------
// Tooltip (Windows 7 style)
// -------------------------------------------------------
void InitTooltip(HWND hwnd) {
if (g_hTooltip) return;
g_hTooltip = CreateWindowEx(WS_EX_TOPMOST, TOOLTIPS_CLASS, NULL,
WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
hwnd, NULL, GetModuleHandle(NULL), NULL);
SendMessage(g_hTooltip, TTM_SETMAXTIPWIDTH, 0, 300);
SendMessage(g_hTooltip, TTM_SETDELAYTIME, TTDT_AUTOPOP, 10000);
SendMessage(g_hTooltip, TTM_SETDELAYTIME, TTDT_INITIAL, 400);
SendMessage(g_hTooltip, TTM_SETDELAYTIME, TTDT_RESHOW, 200);
}
void UpdateTooltipForRow(HWND hwnd, int index) {
if (!g_hTooltip) InitTooltip(hwnd);
for (int i = 0; i < 50; i++) {
TOOLINFOW ti = {0};
ti.cbSize = sizeof(TOOLINFOW);
ti.hwnd = hwnd;
ti.uId = (UINT_PTR)(i + 1);
SendMessage(g_hTooltip, TTM_DELTOOL, 0, (LPARAM)&ti);
}
if (index < 0 || index >= g_NetworkCount) return;
WifiNetworkItem* item = &g_NetworkList[index];
WCHAR ssidBuf[33];
GetDisplaySSID(index, ssidBuf, 33);
WCHAR securityType[64];
StringCchCopyW(securityType, 64, item->isSecured ? L"WPA2-PSK" : g_CurrentLocale->securityOpen);
const WCHAR* sigStr = SignalQualityToString(item->signalQuality);
const WCHAR* bssTypeStr;
switch(item->dot11BssType) {
case dot11_BSS_type_infrastructure: bssTypeStr = g_CurrentLocale->bssTypeInfrastructure; break;
case dot11_BSS_type_independent: bssTypeStr = g_CurrentLocale->bssTypeIndependent; break;
default: bssTypeStr = g_CurrentLocale->bssTypeUnknown; break;
}
const WCHAR* statusText;
if (item->isConnected)
statusText = g_CurrentLocale->tooltipStatusConnected;
else if (item->isConnecting)
statusText = g_CurrentLocale->tooltipStatusConnecting;
else
statusText = g_CurrentLocale->tooltipStatusNotConnected;
StringCchPrintfW(g_TooltipBuffer, 1024,
L"SSID: %s\n%s %s\n%s %s\n%s %s\n%s",
ssidBuf,
g_CurrentLocale->signalStrength, sigStr,
g_CurrentLocale->securityType, securityType,
g_CurrentLocale->radioType, bssTypeStr,
statusText);
RECT rcRow;
if (!GetRowRect(index, &rcRow)) return;
TOOLINFOW ti = {0};
ti.cbSize = sizeof(TOOLINFOW);
ti.uFlags = TTF_SUBCLASS;
ti.hwnd = hwnd;
ti.uId = (UINT_PTR)(index + 1);
ti.lpszText = g_TooltipBuffer;
ti.rect = rcRow;
SendMessage(g_hTooltip, TTM_ADDTOOL, 0, (LPARAM)&ti);
}
// -------------------------------------------------------
// Row layout helpers
// -------------------------------------------------------
BOOL GetRowRect(int index, RECT* rcRow) {
if (index < 0 || index >= g_NetworkCount || !g_bListExpanded) return FALSE;
int y = LIST_Y_START;
for (int i = 0; i < index; i++)
y += (i == g_SelectedRowIndex) ? ROW_HEIGHT_EXPANDED : ROW_HEIGHT_NORMAL;
if (y >= LIST_Y_END) return FALSE;
rcRow->left = 10;
rcRow->top = y;
rcRow->right = WINDOW_WIDTH - 10;
rcRow->bottom = (int)fmin(y + ((index == g_SelectedRowIndex) ? ROW_HEIGHT_EXPANDED : ROW_HEIGHT_NORMAL), LIST_Y_END);
return TRUE;
}
int HitTestRows(int x, int y) {
for (int i = 0; i < g_NetworkCount; i++) {
RECT rc;
if (GetRowRect(i, &rc) && x>=rc.left && x<=rc.right && y>=rc.top && y<=rc.bottom) return i;
}
return -1;
}
void RecalcArrowRect() {
int labelMidY = WIFI_LABEL_Y + (HEADER_HEIGHT - WIFI_LABEL_Y) / 2;
int btnH=16, btnW=22;
int margineDestroFreccia = 24;
g_rcArrowButton.right = WINDOW_WIDTH - margineDestroFreccia;
g_rcArrowButton.left = g_rcArrowButton.right - btnW;
g_rcArrowButton.top = labelMidY - btnH/2;
g_rcArrowButton.bottom = labelMidY + btnH/2;
}
void UpdateLayoutGeometry() {
if (!SafeToAccessUI()) return;
if (g_SelectedRowIndex == -1) {
if (g_hWndButtonConnect && IsWindow(g_hWndButtonConnect)) ShowWindow(g_hWndButtonConnect, SW_HIDE);
if (g_hWndCheckboxConnect && IsWindow(g_hWndCheckboxConnect)) ShowWindow(g_hWndCheckboxConnect, SW_HIDE);
return;
}
RECT rcRow;
if (!GetRowRect(g_SelectedRowIndex, &rcRow)) {
if (g_hWndButtonConnect && IsWindow(g_hWndButtonConnect)) ShowWindow(g_hWndButtonConnect, SW_HIDE);
if (g_hWndCheckboxConnect && IsWindow(g_hWndCheckboxConnect)) ShowWindow(g_hWndCheckboxConnect, SW_HIDE);
return;
}
WifiNetworkItem* item = &g_NetworkList[g_SelectedRowIndex];
if (!item->isConnected && !item->isConnecting) {
if (g_hWndCheckboxConnect && IsWindow(g_hWndCheckboxConnect)) {
MoveWindow(g_hWndCheckboxConnect, rcRow.left+8, rcRow.top+36, 160, 20, TRUE);
SetWindowTextW(g_hWndCheckboxConnect, g_CurrentLocale->chkConnectAuto);
ShowWindow(g_hWndCheckboxConnect, SW_SHOW);
}
if (g_hWndButtonConnect && IsWindow(g_hWndButtonConnect)) {
MoveWindow(g_hWndButtonConnect, rcRow.right-90, rcRow.top+35, 82, 22, TRUE);
SetWindowTextW(g_hWndButtonConnect, g_CurrentLocale->btnConnect);
ShowWindow(g_hWndButtonConnect, SW_SHOW);
EnableWindow(g_hWndButtonConnect, TRUE);
}
} else if (item->isConnecting) {
if (g_hWndCheckboxConnect && IsWindow(g_hWndCheckboxConnect)) ShowWindow(g_hWndCheckboxConnect, SW_HIDE);
if (g_hWndButtonConnect && IsWindow(g_hWndButtonConnect)) {
MoveWindow(g_hWndButtonConnect, rcRow.right-90, rcRow.top+35, 82, 22, TRUE);
SetWindowTextW(g_hWndButtonConnect, g_CurrentLocale->connecting);
ShowWindow(g_hWndButtonConnect, SW_SHOW);
EnableWindow(g_hWndButtonConnect, FALSE);
}
} else {
if (g_hWndCheckboxConnect && IsWindow(g_hWndCheckboxConnect)) ShowWindow(g_hWndCheckboxConnect, SW_HIDE);
if (g_hWndButtonConnect && IsWindow(g_hWndButtonConnect)) {
MoveWindow(g_hWndButtonConnect, rcRow.right-90, rcRow.top+35, 82, 22, TRUE);
SetWindowTextW(g_hWndButtonConnect, g_CurrentLocale->btnDisconnect);
ShowWindow(g_hWndButtonConnect, SW_SHOW);
EnableWindow(g_hWndButtonConnect, TRUE);
}
}
}
void ShowContextMenu(HWND hwnd, int itemIndex, POINT pt) {
if (itemIndex < 0 || itemIndex >= g_NetworkCount) return;
g_ContextMenuTargetIndex = itemIndex;
WifiNetworkItem* item = &g_NetworkList[itemIndex];
HMENU hMenu = CreatePopupMenu();
if (item->isConnected) {
AppendMenuW(hMenu, MF_STRING, IDM_DISCONNECT, g_CurrentLocale->ctxDisconnect);
AppendMenuW(hMenu, MF_STRING, IDM_STATUS, g_CurrentLocale->ctxStatus);
} else if (item->isConnecting) {
AppendMenuW(hMenu, MF_STRING | MF_GRAYED, IDM_CONNECT, g_CurrentLocale->connecting);
} else {
AppendMenuW(hMenu, MF_STRING, IDM_CONNECT, g_CurrentLocale->ctxConnect);
}
AppendMenuW(hMenu, MF_SEPARATOR, 0, NULL);
AppendMenuW(hMenu, MF_STRING, IDM_PROPERTIES, g_CurrentLocale->ctxProperties);
int cmd = TrackPopupMenu(hMenu, TPM_LEFTALIGN|TPM_RIGHTBUTTON|TPM_RETURNCMD, pt.x, pt.y, 0, hwnd, NULL);
if (cmd > 0) {
switch (cmd) {
case IDM_CONNECT: case IDM_DISCONNECT:
if (g_Ctx.hWlanClient) HandleNativeConnection(g_Ctx.hWlanClient, g_ContextMenuTargetIndex);
break;
case IDM_STATUS:
if (g_ContextMenuTargetIndex >= 0 && g_ContextMenuTargetIndex < g_NetworkCount)
OpenNetworkStatusForInterface(g_NetworkList[g_ContextMenuTargetIndex].interfaceGuid);
ShowWindow(hwnd, SW_HIDE);
break;
case IDM_PROPERTIES:
ShellExecuteW(NULL, L"open", L"control.exe", L"ncpa.cpl", NULL, SW_SHOWNORMAL);
ShowWindow(hwnd, SW_HIDE);
break;
}
}
DestroyMenu(hMenu);
}
static RECT GetFooterRect() {
RECT rc = { 0, WINDOW_HEIGHT - FOOTER_HEIGHT, WINDOW_WIDTH, WINDOW_HEIGHT };
return rc;
}
// -------------------------------------------------------
// Draw helpers — respects Classic theme setting (cached check)
// -------------------------------------------------------
static void DrawRectOrRoundRect(HDC hdc, int l, int t, int r, int b, int rx, int ry) {
if (g_Settings.disableRoundedCornersClassic && IsClassicTheme())
Rectangle(hdc, l, t, r, b);
else
RoundRect(hdc, l, t, r, b, rx, ry);
}
// -------------------------------------------------------
// Flyout Window Procedure
// -------------------------------------------------------
LRESULT CALLBACK FlyoutWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_NCHITTEST: {
LRESULT r = DefWindowProc(hwnd, uMsg, wParam, lParam);
switch (r) {
case HTTOP: case HTTOPLEFT: case HTTOPRIGHT:
case HTBOTTOM: case HTBOTTOMLEFT: case HTBOTTOMRIGHT:
case HTLEFT: case HTRIGHT:
return HTBORDER;
default: return r;
}
}
case WM_CREATE: {
Wh_Log(L"FlyoutWndProc - WM_CREATE");
HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
if (hSysMenu) RemoveMenu(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
g_hWndButtonConnect = CreateWindowExW(0, WC_BUTTONW, L"",
WS_CHILD|BS_PUSHBUTTON, 0,0,0,0, hwnd,(HMENU)IDC_CONN_BUTTON,GetModuleHandle(NULL),NULL);
SendMessageW(g_hWndButtonConnect, WM_SETFONT,(WPARAM)g_hFontButton, TRUE);
g_hWndCheckboxConnect = CreateWindowExW(0, WC_BUTTONW, L"",
WS_CHILD|BS_AUTOCHECKBOX, 0,0,0,0, hwnd,(HMENU)IDC_AUTO_CHECKBOX,GetModuleHandle(NULL),NULL);
SendMessageW(g_hWndCheckboxConnect, WM_SETFONT,(WPARAM)g_hFontCheckbox,TRUE);
SendMessageW(g_hWndCheckboxConnect, BM_SETCHECK,BST_CHECKED,0);
RecalcArrowRect();
InterlockedIncrement(&g_Ctx.refCount);
InitTooltip(hwnd);
if (g_Settings.refreshInterval > 0) {
g_RefreshTimer = SetTimer(hwnd, 1000, g_Settings.refreshInterval, NULL);
Wh_Log(L"Auto-refresh timer started: %d ms", g_Settings.refreshInterval);
}
break;
}
case WM_CHECK_CONNECTION: {
switch (wParam) {
case CONN_NOTIFY_ATTEMPT_FAIL:
if (g_IsConnectingAsynchronously) {
g_IsConnectingAsynchronously = FALSE;
if (g_PendingConnectIndex >= 0 && g_PendingConnectIndex < g_NetworkCount)
g_NetworkList[g_PendingConnectIndex].isConnecting = FALSE;
if (g_ConnectCheckTimer) {
KillTimer(hwnd, g_ConnectCheckTimer);
g_ConnectCheckTimer = 0;
}
MessageBoxW(hwnd, g_CurrentLocale->pwdFailedWrong,
g_CurrentLocale->pwdFailedTitle, MB_OK|MB_ICONERROR|MB_TOPMOST);
UpdateLayoutGeometry();
InvalidateRect(hwnd, NULL, TRUE);
}
break;
case CONN_NOTIFY_MSM_CONNECTED:
if (g_IsConnectingAsynchronously) {
g_IsConnectingAsynchronously = FALSE;
if (g_PendingConnectIndex >= 0 && g_PendingConnectIndex < g_NetworkCount) {
g_NetworkList[g_PendingConnectIndex].isConnecting = FALSE;
g_NetworkList[g_PendingConnectIndex].isConnected = TRUE;
}
if (g_ConnectCheckTimer) {
KillTimer(hwnd, g_ConnectCheckTimer);
g_ConnectCheckTimer = 0;
}
UpdateLayoutGeometry();
InvalidateRect(hwnd, NULL, TRUE);
}
break;
case CONN_NOTIFY_MSM_DISCONNECTED:
if (g_PendingConnectIndex >= 0 && g_PendingConnectIndex < g_NetworkCount) {
g_NetworkList[g_PendingConnectIndex].isDisconnecting = FALSE;
g_NetworkList[g_PendingConnectIndex].isConnected = FALSE;
}
g_IsConnectingAsynchronously = FALSE;
if (g_ConnectCheckTimer) {
KillTimer(hwnd, g_ConnectCheckTimer);
g_ConnectCheckTimer = 0;
}
UpdateLayoutGeometry();
InvalidateRect(hwnd, NULL, TRUE);
break;
}
break;
}
case WM_TIMER:
if (wParam == 1000) {
if (g_Ctx.hWlanClient) {
RefreshWifiData(g_Ctx.hWlanClient);
UpdateLayoutGeometry();
InvalidateRect(hwnd, NULL, TRUE);
}
} else if (wParam == 1001) {
if (!g_Ctx.hWlanClient) {
if (g_ConnectCheckTimer) {
KillTimer(hwnd, g_ConnectCheckTimer);
g_ConnectCheckTimer = 0;
}
break;
}
g_ConnectRetryCount++;
RefreshWifiData(g_Ctx.hWlanClient);
BOOL operationComplete = FALSE;
if (g_PendingConnectIndex >= 0 && g_PendingConnectIndex < g_NetworkCount) {
WifiNetworkItem* item = &g_NetworkList[g_PendingConnectIndex];
if (g_IsConnectingAsynchronously && item->isConnected) {
g_IsConnectingAsynchronously = FALSE;
item->isConnecting = FALSE;
operationComplete = TRUE;
Wh_Log(L"Connection completed successfully");
} else if (!g_IsConnectingAsynchronously && !item->isConnected &&
(item->isDisconnecting || g_NetworkList[g_PendingConnectIndex].isConnected == FALSE)) {
item->isDisconnecting = FALSE;
operationComplete = TRUE;
Wh_Log(L"Disconnection completed successfully");
}
if (operationComplete) {
if (g_ConnectCheckTimer) {
KillTimer(hwnd, g_ConnectCheckTimer);
g_ConnectCheckTimer = 0;
}
g_PendingConnectIndex = -1;
g_ConnectRetryCount = 0;
UpdateLayoutGeometry();
InvalidateRect(hwnd, NULL, TRUE);
} else if (g_ConnectRetryCount > CONNECT_TIMEOUT_RETRIES) {
if (g_IsConnectingAsynchronously) {
g_IsConnectingAsynchronously = FALSE;
item->isConnecting = FALSE;
MessageBoxW(hwnd, g_CurrentLocale->errTimeout,
g_CurrentLocale->errTitle, MB_OK|MB_ICONERROR);
}
if (item->isDisconnecting)
item->isDisconnecting = FALSE;
if (g_ConnectCheckTimer) {
KillTimer(hwnd, g_ConnectCheckTimer);
g_ConnectCheckTimer = 0;
}
g_PendingConnectIndex = -1;
g_ConnectRetryCount = 0;
UpdateLayoutGeometry();
InvalidateRect(hwnd, NULL, TRUE);
Wh_Log(L"Connection operation timed out");
}
} else {
if (g_ConnectCheckTimer) {
KillTimer(hwnd, g_ConnectCheckTimer);
g_ConnectCheckTimer = 0;
}
}
}
break;
case WM_SHOW_FLYOUT:
ShowWindow(hwnd, SW_SHOW);
SetForegroundWindow(hwnd);
if (g_Ctx.hWlanClient) {
RefreshWifiData(g_Ctx.hWlanClient);
UpdateLayoutGeometry();
InvalidateRect(hwnd, NULL, TRUE);
}
break;
case WM_CTLCOLORSTATIC: {
HWND hwndCtl = (HWND)lParam;
HDC hdc = (HDC)wParam;
if (hwndCtl == g_hWndCheckboxConnect) {
SetBkMode(hdc, TRANSPARENT);
SetTextColor(hdc, RGB(0,0,0));
static HBRUSH hBrushRow = NULL;
if (!hBrushRow) hBrushRow = CreateSolidBrush(RGB(228,241,252));
return (INT_PTR)hBrushRow;
}
break;
}
case WM_GETDLGCODE:
return DLGC_WANTARROWS | DLGC_WANTCHARS;
case WM_KEYDOWN: {
switch (wParam) {
case VK_UP:
if (g_bListExpanded && g_NetworkCount > 0) {
int newIndex = (g_KeyboardSelectedIndex > 0) ? g_KeyboardSelectedIndex - 1 : g_NetworkCount - 1;
SetKeyboardFocus(newIndex);
InvalidateRect(hwnd, NULL, TRUE);
}
return 0;
case VK_DOWN:
if (g_bListExpanded && g_NetworkCount > 0) {
int newIndex = (g_KeyboardSelectedIndex < g_NetworkCount - 1) ? g_KeyboardSelectedIndex + 1 : 0;
SetKeyboardFocus(newIndex);
InvalidateRect(hwnd, NULL, TRUE);
}
return 0;
case VK_RETURN:
if (g_KeyboardSelectedIndex >= 0 && g_KeyboardSelectedIndex < g_NetworkCount && g_Ctx.hWlanClient)
HandleNativeConnection(g_Ctx.hWlanClient, g_KeyboardSelectedIndex);
return 0;
case VK_LEFT:
ShowWindow(hwnd, SW_HIDE);
return 0;
case VK_RIGHT:
if (g_KeyboardSelectedIndex >= 0 && g_KeyboardSelectedIndex < g_NetworkCount) {
RECT rcRow;
if (GetRowRect(g_KeyboardSelectedIndex, &rcRow)) {
POINT pt = {rcRow.left + 20, rcRow.top + 13};
ClientToScreen(hwnd, &pt);
ShowContextMenu(hwnd, g_KeyboardSelectedIndex, pt);
}
}
return 0;
case VK_ESCAPE:
ShowWindow(hwnd, SW_HIDE);
return 0;
}
break;
}
case WM_PAINT: {
if (!SafeToAccessUI()) break;
PAINTSTRUCT ps;
HDC hdcReal = BeginPaint(hwnd, &ps);
HDC hdc = CreateCompatibleDC(hdcReal);
HBITMAP hBmp = CreateCompatibleBitmap(hdcReal, WINDOW_WIDTH, WINDOW_HEIGHT);
HBITMAP hOldBmp = (HBITMAP)SelectObject(hdc, hBmp);
RECT rcHeader = {0, 0, WINDOW_WIDTH, HEADER_HEIGHT};
HBRUSH hBrH = CreateSolidBrush(RGB(235,244,253)); FillRect(hdc, &rcHeader, hBrH); DeleteObject(hBrH);
RECT rcContent = {0, HEADER_HEIGHT, WINDOW_WIDTH, LIST_Y_END};
HBRUSH hBrC = CreateSolidBrush(RGB(255,255,255)); FillRect(hdc, &rcContent, hBrC); DeleteObject(hBrC);
RECT rcFooter = GetFooterRect();
HBRUSH hBrF = CreateSolidBrush(RGB(225,230,242));
FillRect(hdc, &rcFooter, hBrF); DeleteObject(hBrF);
HPEN hPenSep = CreatePen(PS_SOLID, 1, RGB(214,223,234));
HPEN hOldPen = (HPEN)SelectObject(hdc, hPenSep);
MoveToEx(hdc, 0, HEADER_HEIGHT, NULL); LineTo(hdc, WINDOW_WIDTH, HEADER_HEIGHT);
SelectObject(hdc, hOldPen); DeleteObject(hPenSep);
HPEN hPenBevelDark = CreatePen(PS_SOLID, 1, RGB(180,193,210));
HPEN hPenBevelLight = CreatePen(PS_SOLID, 1, RGB(255,255,255));
SelectObject(hdc, hPenBevelDark);
MoveToEx(hdc, 0, LIST_Y_END, NULL); LineTo(hdc, WINDOW_WIDTH, LIST_Y_END);
SelectObject(hdc, hPenBevelLight);
MoveToEx(hdc, 0, LIST_Y_END + 1, NULL); LineTo(hdc, WINDOW_WIDTH, LIST_Y_END + 1);
SelectObject(hdc, hOldPen);
DeleteObject(hPenBevelDark);
DeleteObject(hPenBevelLight);
BOOL isAnyConnected = (g_NetworkCount > 0 && g_NetworkList[0].isConnected);
SetBkMode(hdc, TRANSPARENT);
if (isAnyConnected) {
SelectObject(hdc, g_hFontNormal); SetTextColor(hdc, RGB(0,0,0));
TextOutW(hdc, 56, 18, g_CurrentLocale->currentConnected, lstrlenW(g_CurrentLocale->currentConnected));
SelectObject(hdc, g_hFontBold);
WCHAR displaySsid[33]; GetDisplaySSID(0, displaySsid, 33);
TextOutW(hdc, 56, 34, displaySsid, lstrlenW(displaySsid));
SelectObject(hdc, g_hFontNormal); SetTextColor(hdc, RGB(110,110,110));
TextOutW(hdc, 56, 50, g_CurrentLocale->internetAccess, lstrlenW(g_CurrentLocale->internetAccess));
} else {
SelectObject(hdc, g_hFontBold); SetTextColor(hdc, RGB(0,0,0));
TextOutW(hdc, 56, 22, g_CurrentLocale->noConnections, lstrlenW(g_CurrentLocale->noConnections));
SelectObject(hdc, g_hFontNormal);
TextOutW(hdc, 56, 40, g_CurrentLocale->connectionsAvailable, lstrlenW(g_CurrentLocale->connectionsAvailable));
}
HICON hLargeIcon = isAnyConnected ? g_hIconNetworkMap : g_hIconSignalBars[0];
if (hLargeIcon) DrawIconEx(hdc, 14, 20, hLargeIcon, 32, 32, 0, NULL, DI_NORMAL);
if (g_IsHoveringRefresh) {
HBRUSH hBrHov = CreateSolidBrush(RGB(200,225,245));
HPEN hPenHov = CreatePen(PS_SOLID, 1, RGB(150,190,230));
HPEN hOldPenHov = (HPEN)SelectObject(hdc, hPenHov);
HBRUSH hOldBH = (HBRUSH)SelectObject(hdc, hBrHov);
DrawRectOrRoundRect(hdc, g_rcRefreshButton.left, g_rcRefreshButton.top,
g_rcRefreshButton.right, g_rcRefreshButton.bottom, 4, 4);
SelectObject(hdc, hOldPenHov); DeleteObject(hPenHov);
SelectObject(hdc, hOldBH); DeleteObject(hBrHov);
}
if (g_hIconRefreshWin7)
DrawIconEx(hdc, g_rcRefreshButton.left+2, g_rcRefreshButton.top+3,
g_hIconRefreshWin7, 16, 16, 0, NULL, DI_NORMAL);
SelectObject(hdc, g_hFontNormal); SetTextColor(hdc, RGB(90,100,110));
TextOutW(hdc, 14, HEADER_HEIGHT - 24, g_CurrentLocale->wifiHeader, lstrlenW(g_CurrentLocale->wifiHeader));
if (g_IsHoveringArrow) {
HBRUSH hBrA = CreateSolidBrush(RGB(230,240,255));
HPEN hPenA = CreatePen(PS_SOLID, 1, RGB(180,210,245));
HPEN hOldPA = (HPEN)SelectObject(hdc, hPenA);
HBRUSH hOldBA = (HBRUSH)SelectObject(hdc, hBrA);
DrawRectOrRoundRect(hdc, g_rcArrowButton.left, g_rcArrowButton.top,
g_rcArrowButton.right, g_rcArrowButton.bottom, 2, 2);
SelectObject(hdc, hOldPA); SelectObject(hdc, hOldBA);
DeleteObject(hBrA); DeleteObject(hPenA);
}
SelectObject(hdc, g_hFontArrow); SetTextColor(hdc, RGB(50,50,50));
LPCWSTR arrowChar = g_bListExpanded ? L"6" : L"5";
RECT rcArrowText = g_rcArrowButton; rcArrowText.top += 2;
DrawTextW(hdc, arrowChar, 1, &rcArrowText, DT_CENTER|DT_VCENTER|DT_SINGLELINE);
if (g_bListExpanded) {
for (int i = 0; i < g_NetworkCount; i++) {
RECT rcRow;
if (!GetRowRect(i, &rcRow)) continue;
BOOL isSelected = (i == g_SelectedRowIndex);
BOOL isHovered = (i == g_HoveredRowIndex);
BOOL hasKeyboardFocus = (i == g_KeyboardSelectedIndex);
if (isSelected || isHovered) {
RECT rcFullRow = rcRow; rcFullRow.left = 0; rcFullRow.right = WINDOW_WIDTH - 5;
HBRUSH hBrBg = CreateSolidBrush(isSelected ? RGB(228,241,252) : RGB(242,247,253));
HPEN hPenBg = CreatePen(PS_SOLID, 1, isSelected ? RGB(174,212,243) : RGB(216,231,248));
HPEN hOldP = (HPEN)SelectObject(hdc, hPenBg);
HBRUSH hOldB = (HBRUSH)SelectObject(hdc, hBrBg);
DrawRectOrRoundRect(hdc, rcFullRow.left, rcFullRow.top,
rcFullRow.right, rcFullRow.bottom, 3, 3);
SelectObject(hdc, hOldP); SelectObject(hdc, hOldB);
DeleteObject(hBrBg); DeleteObject(hPenBg);
}
if (hasKeyboardFocus && !isSelected)
DrawFocusRectangle(hdc, &rcRow);
WCHAR ssidBuf[33]; GetDisplaySSID(i, ssidBuf, 33);
SelectObject(hdc, isSelected ? g_hFontBold : g_hFontNormal);
SetTextColor(hdc, RGB(0,0,255));
TextOutW(hdc, rcRow.left+10, rcRow.top+6, ssidBuf, lstrlenW(ssidBuf));
if (g_NetworkList[i].isConnected) {
SelectObject(hdc, g_hFontBold); SetTextColor(hdc, RGB(0,0,0));
int textX = isSelected ? (rcRow.left+10) : (rcRow.right-110);
int textY = isSelected ? (rcRow.top+22) : (rcRow.top+6);
TextOutW(hdc, textX, textY, g_CurrentLocale->connectedText, lstrlenW(g_CurrentLocale->connectedText));
} else if (g_NetworkList[i].isConnecting) {
SelectObject(hdc, g_hFontNormal); SetTextColor(hdc, RGB(128,128,128));
int textX = isSelected ? (rcRow.left+10) : (rcRow.right-110);
int textY = isSelected ? (rcRow.top+22) : (rcRow.top+6);
TextOutW(hdc, textX, textY, g_CurrentLocale->connecting, lstrlenW(g_CurrentLocale->connecting));
}
DrawNativeSignalIcon(hdc, rcRow.right-10, rcRow.top+2, g_NetworkList[i].signalQuality);
}
}
SelectObject(hdc, g_IsHoveringLink ? g_hFontUnderline : g_hFontNormal);
SetTextColor(hdc, RGB(14,75,184));
const wchar_t* footerText = g_CurrentLocale->openSharingCenter;
SIZE textSize; GetTextExtentPoint32W(hdc, footerText, lstrlenW(footerText), &textSize);
int centerX = (WINDOW_WIDTH - textSize.cx) / 2;
int footerTextYC = (WINDOW_HEIGHT - FOOTER_HEIGHT) + ((FOOTER_HEIGHT - textSize.cy) / 2) - 5;
TextOutW(hdc, centerX, footerTextYC, footerText, lstrlenW(footerText));
BitBlt(hdcReal, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, hdc, 0, 0, SRCCOPY);
SelectObject(hdc, hOldBmp); DeleteObject(hBmp); DeleteDC(hdc);
EndPaint(hwnd, &ps);
break;
}
case WM_REFRESH_DATA:
if (g_Ctx.hWlanClient) {
RefreshWifiData(g_Ctx.hWlanClient);
UpdateLayoutGeometry();
InvalidateRect(hwnd,NULL,TRUE);
}
break;
case WM_MOUSEMOVE: {
int mx = LOWORD(lParam), my = HIWORD(lParam);
POINT pt = {mx,my};
RECT rcF = GetFooterRect();
BOOL wasLink = g_IsHoveringLink;
BOOL wasRefresh = g_IsHoveringRefresh;
BOOL wasArrow = g_IsHoveringArrow;
int wasHov = g_HoveredRowIndex;
g_IsHoveringLink = PtInRect(&rcF, pt) != 0;
g_IsHoveringRefresh = PtInRect(&g_rcRefreshButton, pt) != 0;
g_IsHoveringArrow = PtInRect(&g_rcArrowButton, pt) != 0;
int newHovered = (my >= LIST_Y_START && my < LIST_Y_END) ? HitTestRows(mx,my) : -1;
g_HoveredRowIndex = newHovered;
if (newHovered != wasHov)
UpdateTooltipForRow(hwnd, newHovered);
SetCursor(LoadCursor(NULL, (g_IsHoveringLink || g_IsHoveringRefresh || g_IsHoveringArrow) ? IDC_HAND : IDC_ARROW));
if (wasLink!=g_IsHoveringLink || wasRefresh!=g_IsHoveringRefresh ||
wasArrow!=g_IsHoveringArrow || wasHov!=g_HoveredRowIndex) {
InvalidateRect(hwnd,NULL,FALSE);
TRACKMOUSEEVENT tme = {sizeof(TRACKMOUSEEVENT),TME_LEAVE,hwnd,0};
TrackMouseEvent(&tme);
}
break;
}
case WM_MOUSELEAVE:
g_IsHoveringLink = g_IsHoveringRefresh = g_IsHoveringArrow = FALSE;
g_HoveredRowIndex = -1;
UpdateTooltipForRow(hwnd, -1);
SetCursor(LoadCursor(NULL,IDC_ARROW));
InvalidateRect(hwnd,NULL,FALSE);
break;
case WM_LBUTTONDOWN: {
int lx = LOWORD(lParam), ly = HIWORD(lParam);
POINT pt = {lx,ly};
RECT rcF = GetFooterRect();
if (PtInRect(&g_rcRefreshButton,pt)) {
PostMessageW(hwnd,WM_REFRESH_DATA,0,0); break;
}
if (PtInRect(&g_rcArrowButton,pt)) {
g_bListExpanded = !g_bListExpanded;
if (!g_bListExpanded) {
ShowWindow(g_hWndButtonConnect, SW_HIDE);
ShowWindow(g_hWndCheckboxConnect, SW_HIDE);
g_SelectedRowIndex = -1;
ClearKeyboardFocus();
} else {
UpdateLayoutGeometry();
}
InvalidateRect(hwnd,NULL,TRUE);
break;
}
if (PtInRect(&rcF,pt)) {
ShellExecuteW(NULL,L"open",L"control.exe",L"/name Microsoft.NetworkAndSharingCenter",NULL,SW_SHOWNORMAL);
ShowWindow(hwnd,SW_HIDE);
break;
}
if (g_bListExpanded && ly >= LIST_Y_START && ly < LIST_Y_END) {
int ci = HitTestRows(lx,ly);
if (ci != -1) {
g_SelectedRowIndex = (g_SelectedRowIndex==ci) ? -1 : ci;
if (g_SelectedRowIndex >= 0)
SetKeyboardFocus(g_SelectedRowIndex);
else
ClearKeyboardFocus();
UpdateLayoutGeometry();
InvalidateRect(hwnd,NULL,FALSE);
}
}
break;
}
case WM_RBUTTONDOWN: {
int rx = LOWORD(lParam), ry = HIWORD(lParam);
if (g_bListExpanded && ry >= LIST_Y_START && ry < LIST_Y_END) {
int ci = HitTestRows(rx,ry);
if (ci != -1) {
POINT ptM={rx,ry}; ClientToScreen(hwnd,&ptM);
ShowContextMenu(hwnd,ci,ptM);
}
}
break;
}
case WM_COMMAND: {
int wid = LOWORD(wParam);
if (wid == IDC_CONN_BUTTON && g_SelectedRowIndex != -1) {
if (g_Ctx.hWlanClient) HandleNativeConnection(g_Ctx.hWlanClient,g_SelectedRowIndex);
break;
}
if (g_ContextMenuTargetIndex != -1) {
switch (wid) {
case IDM_CONNECT: case IDM_DISCONNECT:
if (g_Ctx.hWlanClient) HandleNativeConnection(g_Ctx.hWlanClient,g_ContextMenuTargetIndex);
break;
case IDM_STATUS:
if (g_ContextMenuTargetIndex >= 0 && g_ContextMenuTargetIndex < g_NetworkCount)
OpenNetworkStatusForInterface(g_NetworkList[g_ContextMenuTargetIndex].interfaceGuid);
else
ShellExecuteW(NULL, L"open", L"control.exe", L"ncpa.cpl", NULL, SW_SHOWNORMAL);
ShowWindow(hwnd, SW_HIDE);
break;
case IDM_PROPERTIES:
if (g_ContextMenuTargetIndex >= 0 && g_ContextMenuTargetIndex < g_NetworkCount)
OpenNetworkPropertiesForInterface(g_NetworkList[g_ContextMenuTargetIndex].interfaceGuid);
else
ShellExecuteW(NULL, L"open", L"control.exe", L"ncpa.cpl", NULL, SW_SHOWNORMAL);
ShowWindow(hwnd, SW_HIDE);
break;
}
}
break;
}
case WM_ACTIVATE:
if (LOWORD(wParam) == WA_INACTIVE) {
ClearKeyboardFocus();
ShowWindow(hwnd,SW_HIDE);
}
break;
case WM_SAFE_CLOSE:
DestroyWindow(hwnd);
break;
case WM_CLOSE:
ShowWindow(hwnd, SW_HIDE);
return 0;
case WM_DESTROY:
if (g_RefreshTimer) {
KillTimer(hwnd, g_RefreshTimer);
g_RefreshTimer = 0;
}
if (g_ConnectCheckTimer) {
KillTimer(hwnd, g_ConnectCheckTimer);
g_ConnectCheckTimer = 0;
}
InterlockedDecrement(&g_Ctx.refCount);
if (g_hTooltip) { DestroyWindow(g_hTooltip); g_hTooltip = NULL; }
g_hWndFlyout = g_hWndButtonConnect = g_hWndCheckboxConnect = NULL;
break;
}
return DefWindowProcW(hwnd,uMsg,wParam,lParam);
}
// -------------------------------------------------------
// ToolbarWindow32 subclassing via WindhawkUtils
// -------------------------------------------------------
LRESULT CALLBACK ToolbarWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam,
UINT_PTR uIdSubclass, DWORD_PTR dwRefData) {
if (g_Settings.interceptNativeFlyout) {
if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONUP || msg == WM_LBUTTONDBLCLK || msg == WM_MOUSEACTIVATE) {
POINT pt;
if (msg == WM_MOUSEACTIVATE) {
DWORD dwPos = GetMessagePos();
pt.x = GET_X_LPARAM(dwPos);
pt.y = GET_Y_LPARAM(dwPos);
ScreenToClient(hWnd, &pt);
} else {
pt.x = GET_X_LPARAM(lParam);
pt.y = GET_Y_LPARAM(lParam);
}
LRESULT btnIdx = SendMessageW(hWnd, TB_HITTEST, 0, (LPARAM)&pt);
if (btnIdx >= 0) {
TBBUTTON tb = {0};
if (SendMessageW(hWnd, TB_GETBUTTON, (WPARAM)btnIdx, (LPARAM)&tb)) {
if (tb.idCommand == TRAY_NETWORK_ID) {
if (msg == WM_LBUTTONUP) {
static DWORD lastClickTime = 0;
DWORD currentTime = GetTickCount();
if (currentTime - lastClickTime > CLICK_DEBOUNCE_MS) {
lastClickTime = currentTime;
if (g_hWndFlyout && IsWindowVisible(g_hWndFlyout)) {
Wh_Log(L"Network icon clicked while open — closing classic flyout");
ToggleFlyoutWindow();
} else {
Wh_Log(L"Network icon clicked while closed — opening classic flyout");
SetTimer(hWnd, 9999, 10, NULL);
}
}
}
if (msg == WM_MOUSEACTIVATE)
return MA_ACTIVATE;
return 0;
}
}
}
}
}
if (msg == WM_TIMER && wParam == 9999) {
KillTimer(hWnd, 9999);
ToggleFlyoutWindow();
return 0;
}
return DefSubclassProc(hWnd, msg, wParam, lParam);
}
static bool IsExplorerProcess() {
WCHAR exePath[MAX_PATH] = {};
GetModuleFileNameW(NULL, exePath, MAX_PATH);
WCHAR* name = wcsrchr(exePath, L'\\');
name = name ? name + 1 : exePath;
return _wcsicmp(name, L"explorer.exe") == 0;
}
void InstallTrayInterception() {
Wh_Log(L"Installing ToolbarWindow32 interception...");
if (!IsExplorerProcess()) {
Wh_Log(L"Not explorer.exe - skipping ToolbarWindow32 subclassing");
return;
}
HWND hTray = NULL;
for (int attempt = 0; attempt < 10 && !hTray; attempt++) {
hTray = FindWindowW(L"Shell_TrayWnd", NULL);
if (!hTray) {
Wh_Log(L"Shell_TrayWnd not found (attempt %d/10), waiting 500ms...", attempt + 1);
Sleep(500);
}
}
if (!hTray) {
Wh_Log(L"ERROR: Shell_TrayWnd not found after retries - tray subclassing skipped");
return;
}
HWND hNotify = FindWindowExW(hTray, NULL, L"TrayNotifyWnd", NULL);
HWND hSysPager= hNotify ? FindWindowExW(hNotify, NULL, L"SysPager", NULL) : NULL;
HWND hToolbar = hSysPager ? FindWindowExW(hSysPager,NULL, L"ToolbarWindow32", NULL) : NULL;
HWND hTarget = hToolbar ? hToolbar : (hNotify ? hNotify : hTray);
if (!hTarget) {
Wh_Log(L"ERROR: tray hierarchy not found");
return;
}
G_hSubclassedToolbar = hTarget;
BOOL success = WindhawkUtils::SetWindowSubclassFromAnyThread(hTarget, ToolbarWndProc, (UINT_PTR)&g_Ctx, 0);
if (success)
Wh_Log(L"ToolbarWindow32 subclassed OK (0x%p)", hTarget);
else {
Wh_Log(L"ERROR: subclassing failed");
G_hSubclassedToolbar = nullptr;
}
Wh_Log(L"Tray interception installed");
}
void RemoveTrayInterception() {
if (G_hSubclassedToolbar) {
WindhawkUtils::RemoveWindowSubclassFromAnyThread(G_hSubclassedToolbar, ToolbarWndProc, (UINT_PTR)&g_Ctx);
Wh_Log(L"ToolbarWindow32 subclass removed");
G_hSubclassedToolbar = nullptr;
}
}
// -------------------------------------------------------
// Toggle flyout
// -------------------------------------------------------
void ToggleFlyoutWindow() {
Wh_Log(L"ToggleFlyoutWindow");
EnterCriticalSection(&g_Ctx.csLock);
if (!g_Ctx.isUninitializing) {
if (!g_hWndFlyout || !IsWindow(g_hWndFlyout)) {
HINSTANCE hInst = GetModuleHandle(NULL);
WNDCLASSW wc = {0};
wc.style = 0;
wc.lpfnWndProc = FlyoutWndProc;
wc.hInstance = hInst;
wc.lpszClassName = L"Win7NetworkFlyoutSafe";
wc.hCursor = LoadCursor(NULL,IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
UnregisterClassW(wc.lpszClassName,hInst);
RegisterClassW(&wc);
RECT rcClient = { 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT };
AdjustWindowRectEx(&rcClient, WS_POPUP, FALSE, WS_EX_TOPMOST|WS_EX_TOOLWINDOW|WS_EX_LEFT);
g_hWndFlyout = CreateWindowExW(
WS_EX_TOPMOST|WS_EX_TOOLWINDOW|WS_EX_LEFT,
wc.lpszClassName, L"", WS_POPUP,
0, 0, rcClient.right-rcClient.left, rcClient.bottom-rcClient.top,
NULL, NULL, hInst, NULL);
if (g_hWndFlyout) {
SetWindowLongPtrW(g_hWndFlyout, GWL_STYLE,
GetWindowLongPtrW(g_hWndFlyout, GWL_STYLE) | WS_THICKFRAME);
BOOL pfEnabled = FALSE;
if (DwmIsCompositionEnabled(&pfEnabled) == S_OK && pfEnabled) {
MARGINS margins = {0, 0, 0, 1};
DwmExtendFrameIntoClientArea(g_hWndFlyout, &margins);
}
g_Ctx.hWndFlyout = g_hWndFlyout;
}
Wh_Log(L"Flyout window created");
}
if (IsWindowVisible(g_hWndFlyout)) {
ClearKeyboardFocus();
ShowWindow(g_hWndFlyout, SW_HIDE);
} else {
DetermineLocale();
LoadSettings();
g_SelectedRowIndex = g_HoveredRowIndex = -1;
ClearKeyboardFocus();
g_bListExpanded = TRUE;
ShowWindow(g_hWndButtonConnect, SW_HIDE);
ShowWindow(g_hWndCheckboxConnect, SW_HIDE);
if (g_Ctx.hWlanClient) RefreshWifiData(g_Ctx.hWlanClient);
UpdateLayoutGeometry();
PositionWindowNearTray(g_hWndFlyout);
ShowWindow(g_hWndFlyout, SW_SHOW);
SetForegroundWindow(g_hWndFlyout);
InvalidateRect(g_hWndFlyout,NULL,TRUE);
}
}
LeaveCriticalSection(&g_Ctx.csLock);
}
// -------------------------------------------------------
// Hotkey thread
// -------------------------------------------------------
DWORD WINAPI HotkeyThreadProc(LPVOID lpParam) {
ModContext* ctx = (ModContext*)lpParam;
if (!ctx) return 1;
BOOL hotkeyRegistered = FALSE;
if (g_Settings.enableHotkey) {
if (!RegisterHotKey(NULL, HOTKEY_ID, MOD_CONTROL | MOD_NOREPEAT, 'H')) {
Wh_Log(L"Failed to register hotkey");
return 1;
}
hotkeyRegistered = TRUE;
Wh_Log(L"Hotkey registered - Ctrl+H");
} else {
Wh_Log(L"Hotkey disabled by user setting");
}
UINT uTaskbarCreated = RegisterWindowMessageW(L"TaskbarCreated");
MSG msg = {0};
while (GetMessageW(&msg, NULL, 0, 0)) {
if (msg.message == WM_HOTKEY && msg.wParam == HOTKEY_ID &&
!ctx->isUninitializing && hotkeyRegistered) {
ToggleFlyoutWindow();
}
if (msg.message == uTaskbarCreated && !ctx->isUninitializing) {
Wh_Log(L"WM_TASKBARCREATED received — reinstalling tray interception");
if (G_hSubclassedToolbar) RemoveTrayInterception();
InstallTrayInterception();
if (g_Settings.enableHotkey && !hotkeyRegistered) {
if (RegisterHotKey(NULL, HOTKEY_ID, MOD_CONTROL | MOD_NOREPEAT, 'H')) {
hotkeyRegistered = TRUE;
Wh_Log(L"Hotkey re-registered after taskbar restart");
}
}
}
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
if (hotkeyRegistered)
UnregisterHotKey(NULL, HOTKEY_ID);
return 0;
}
// -------------------------------------------------------
// Cleanup
// -------------------------------------------------------
void SafeCleanup() {
Wh_Log(L"SafeCleanup");
if (InterlockedExchange(&g_Ctx.isUninitializing,1L)) return;
RemoveTrayInterception();
if (g_Ctx.dwHotkeyThreadId) PostThreadMessageW(g_Ctx.dwHotkeyThreadId,WM_QUIT,0,0);
if (g_Ctx.hHotkeyThread) {
WaitForSingleObject(g_Ctx.hHotkeyThread,3000);
CloseHandle(g_Ctx.hHotkeyThread);
g_Ctx.hHotkeyThread=NULL; g_Ctx.dwHotkeyThreadId=0;
}
if (g_hWndFlyout && IsWindow(g_hWndFlyout)) {
BOOL pfEnabled = FALSE;
if (DwmIsCompositionEnabled(&pfEnabled) == S_OK && pfEnabled) {
MARGINS margins = {0, 0, 0, 0};
DwmExtendFrameIntoClientArea(g_hWndFlyout, &margins);
}
SendMessageW(g_hWndFlyout,WM_SAFE_CLOSE,0,0);
for (int i=0; i<50 && IsWindow(g_hWndFlyout); i++) {
Sleep(100);
MSG msg;
while (PeekMessageW(&msg,NULL,0,0,PM_REMOVE)) { TranslateMessage(&msg); DispatchMessageW(&msg); }
}
if (IsWindow(g_hWndFlyout)) DestroyWindow(g_hWndFlyout);
}
if (g_Ctx.hWlanClient) { WlanCloseHandle(g_Ctx.hWlanClient,NULL); g_Ctx.hWlanClient=NULL; }
if (g_pNLM) { g_pNLM->Release(); g_pNLM = NULL; }
FreeSystemIcons();
FreeGlobalFonts();
g_hWndFlyout=g_hWndButtonConnect=g_hWndCheckboxConnect=NULL;
g_Initialized=FALSE;
}
// -------------------------------------------------------
// Windhawk entry points
// -------------------------------------------------------
BOOL Wh_ModInit() {
Wh_Log(L"=== Wh_ModInit v1.1.4 ===");
LoadSettings();
UpdateClassicThemeCache();
ZeroMemory(&g_Ctx,sizeof(g_Ctx));
InitializeCriticalSection(&g_Ctx.csLock);
DetermineLocale();
if (!IsExplorerProcess()) {
Wh_Log(L"Not explorer.exe - init skipped");
g_Initialized = TRUE;
return TRUE;
}
InitGlobalFonts();
LoadSystemIcons();
InitRefreshButtonRect();
RecalcArrowRect();
InstallTrayInterception();
if (g_Settings.redirectNetworkContextMenu) {
HMODULE hUser32 = GetModuleHandleW(L"user32.dll");
if (hUser32) {
void* pFn = (void*)GetProcAddress(hUser32, "TrackPopupMenuEx");
if (pFn) {
Wh_SetFunctionHook(pFn, (void*)TrackPopupMenuEx_Hook, (void**)&g_origTrackPopupMenuEx);
Wh_Log(L"TrackPopupMenuEx hooked");
}
}
}
DWORD dwMaxClient=2, dwCurVer=0;
if (WlanOpenHandle(dwMaxClient,NULL,&dwCurVer,&g_Ctx.hWlanClient)==ERROR_SUCCESS) {
Wh_Log(L"WLAN OK");
WlanRegisterNotification(g_Ctx.hWlanClient, WLAN_NOTIFICATION_SOURCE_ALL, TRUE,
WlanNotificationCallback, &g_Ctx, NULL, NULL);
} else {
Wh_Log(L"WLAN init failed");
}
g_Ctx.hHotkeyThread = CreateThread(NULL,0,HotkeyThreadProc,&g_Ctx,0,&g_Ctx.dwHotkeyThreadId);
if (!g_Ctx.hHotkeyThread) {
Wh_Log(L"Hotkey thread failed");
if (g_Ctx.hWlanClient) { WlanCloseHandle(g_Ctx.hWlanClient,NULL); g_Ctx.hWlanClient=NULL; }
DeleteCriticalSection(&g_Ctx.csLock);
return FALSE;
}
g_Initialized=TRUE;
Wh_Log(L"=== Wh_ModInit done ===");
return TRUE;
}
void Wh_ModSettingsChanged() {
LoadSettings();
UpdateClassicThemeCache();
if (SafeToAccessUI() && g_hWndFlyout) {
if (g_RefreshTimer) {
KillTimer(g_hWndFlyout, g_RefreshTimer);
g_RefreshTimer = 0;
}
if (g_Settings.refreshInterval > 0) {
g_RefreshTimer = SetTimer(g_hWndFlyout, 1000, g_Settings.refreshInterval, NULL);
Wh_Log(L"Auto-refresh timer updated: %d ms", g_Settings.refreshInterval);
}
InvalidateRect(g_hWndFlyout,NULL,TRUE);
}
}
void Wh_ModUninit() {
Wh_Log(L"Wh_ModUninit");
SafeCleanup();
UnregisterClassW(L"Win7NetworkFlyoutSafe", GetModuleHandle(NULL));
UnregisterClassW(L"Win7NetPwdClass", GetModuleHandle(NULL));
DeleteCriticalSection(&g_Ctx.csLock);
} |
|
The error is: It's not a Windhawk bug or a compiler bug, it's an incorrect usage of the functions. The text says what's wrong. |
|
The recent version does not work, only the standard flyout is shown. |
OK thanks for telling me, could you just show me a picture of the mod's settings & logs just so that I can understand further? |
|
By the way, it works via Ctrl+H, but does not via menu. |
|
Connect action does not work, as before, waits, then an error messagebox. |
The tooltip method doesn't look for the word "Network" specifically but it looks for keywords related to networking/internet in many languages, including Russian ( |
I'll add Ethernet icon variants to the comparison so it works on wired-only systems too. I'll keep iterating until all reasonable cases are covered |
You're right with this If you think it's unnecessary complexity, I can remove it in the next version. |
|
Why would you check for подключение or сеть, if we for sure know such words are not there? Fior sure. Even worse, it could bring the flyout to third-party tray buttons, such as network load indicators, internet downloaders, VPN, torrent, whatever. |
Well you're right with this but since I don't know Russian, I added context-related words I found rather than the exact tooltip text. You're right that this is both inaccurate and risky for false positives with third-party apps. I'll remove these 2 |
|
Only two? Currently it's "Доступ к Интернету", you are checking for just "интернет" (not capitalized). What about other languages? If you keep checking for the word "internet", lots of software would show your flyout. |
OK, I'll directly remove this approach for now and post the version without this method and I won't add Ethernet detection for now |
…ignal variants + stock icon
I've removed this approach, now the mod relies on ID 2 matching, multi-variant Wi-Fi icon comparison and system stock icon.
|
|
No, it never happens with modern flyout. Also, currently your flyout is simply empty, the re-scan button does not work. If it can scan the networks on load, why it cannot some minutes later? |
Your point is valid, I will investigate further to improve this behavior. However, I actually have the same issue in both flyouts in some cases. |
I've tried to fix the issue by making the network list refresh more reliable, both automatically and when clicking the refresh button. Let me know if this solves the previous reported issue |
|
@Anixx if you want, please let me know if the issue of the networks disappearing has been fixed |
|
@m417z Hello! All 13 points from the June 16 review have been addressed. I've also removed the registry fallback entirely to make the mod lighter and also because the tray interception handles everything and the mod is now simpler. I've tested on Win10 21H2, Win11 23H2/24H2/25H2 with ExplorerPatcher. Could you take another look when you have time? Thank you. |
|
Yes, the disappearing is fixed, but re-connecting does not work, so the mod is useless as of now. Maybe it is because the mod still does not account for the network's index (for handling networks with the same name)? The standard flyout calls the network "Redmi 2", not just "Redmi" |
Thanks for the feedback. I've tried to fix it. However, I currently don't have networks with duplicate names in my area, so I can't fully test this myself but now the mod now keeps separate entries for same-SSID networks with different security parameters, adds a numeric suffix like Windows does ('Redmi 2'). Can you test it and let me know if reconnect works now? |
|
It is not two networks with the same name at the same time, it is networks with the same name at different times. Windows remembers names. |
…ofiles (Windows remembers old names)
OK, the mod was finding the old profile, assuming it was valid, and failing because the security parameters didn't match the current network. I've posted a fix that should detect this and forces a connection when the profile doesn't match. Can you test v2.3.0 to see if it finally works? If both issues are addressed the mod should be ready. |
|
Does not work. Now it asks for a security key even for a known network. Even after entering it, fails to reconnect. |
The UI issues should have been addressed and now it shouldn't ask for the security key even for a known network. Let me know if the issue with reconnection finally works. For now, I've tested on Windows 10 21H2 and the reconnect works for a known network and fails for networks with the wrong password saved but, according to Google and my analysis, this is also an issue with Windows which would require complex solutions to totally solve because this is actually the same behavior as the native Windows network flyout. I'd like to know your opinion if it's useful to put this as a limitation in the README of the mod. |








This Windhawk mod recreates the Windows 7 network flyout panel, replacing the modern Windows 10/11 network flyout with a classic interface.
Changelog
If this pull request updates an existing mod, describe the changes below:
Mod authorship
If this pull request introduces a new mod, please complete the section below.
This mod was created by:
Please select the options that best apply. Your selection does not affect the acceptance criteria, but it helps reviewers understand the context of the code and provide relevant feedback.