/******************************************************************************* * * (C) COPYRIGHT MICROSOFT CORP., 1993-1994 * * TITLE: PCCARD.C * * VERSION: 1.0 * * AUTHOR: RAL * * DATE: 11/01/94 * ******************************************************************************** * * CHANGE LOG: * * DATE REV DESCRIPTION * ----------- --- ------------------------------------------------------------- * Nov. 11, 94 RAL Original * Oct 23, 95 Shawnb UNICODE enabled * *******************************************************************************/ #include "stdafx.h" #include "systray.h" #define PCMCIAMENU_PROPERTIES 100 #define PCMCIAMENU_DISABLE 101 #define PCMCIAMENU_SOCKET 200 extern HANDLE g_hPCCARD; extern HINSTANCE g_hInstance; static BOOL g_bPCMCIAEnabled = FALSE; static BOOL g_bPCMCIAIconShown = FALSE; static HICON g_hPCMCIAIcon = NULL; #define MAX_DEVNODES 20 static DWORD g_aDevnodes[MAX_DEVNODES]; static BYTE g_aSktState[MAX_DEVNODES] = {0}; static UINT g_numskts = 0; static DWORD g_PCMCIAFlags = 0; static TCHAR g_szDevNodeKeyFmt[] = REGSTR_PATH_DYNA_ENUM TEXT ("\\%X"); static const TCHAR g_szEnumKeyPrefix[] = REGSTR_PATH_ENUM TEXT ("\\"); static const TCHAR g_szPCMCIAFlags[] = REGSTR_VAL_SYSTRAYPCCARDFLAGS; static const TCHAR g_szClass[] = REGSTR_VAL_CLASS; static const TCHAR g_szModemClass[] = REGSTR_KEY_MODEM_CLASS; #if NOTYET static const TCHAR g_szDiskDriveClass[] = REGSTR_KEY_DISKDRIVE_CLASS; #endif #define SKTSTATE_GOODEJECT 1 #define SKTSTATE_SHOULDWARN 2 #define SKTSTATE_TYPEKNOWN 4 HKEY OpenDevnodeDynKey(DWORD dwDevnode) { TCHAR szScratch[MAX_PATH]; HKEY hkDyn = NULL; wsprintf(szScratch, g_szDevNodeKeyFmt, dwDevnode); if (RegOpenKey(HKEY_DYN_DATA, szScratch, &hkDyn) != ERROR_SUCCESS) { return(NULL); } return hkDyn; } UINT GetDynInfo(DWORD dwDevNode, LPCTSTR lpszValName, LPVOID lpBuffer, UINT cbBuffer) { UINT cbSize = 0; HKEY hkDyn = OpenDevnodeDynKey(dwDevNode); if (hkDyn) { if (RegQueryValueEx(hkDyn, lpszValName, NULL, NULL, lpBuffer, &cbBuffer) == ERROR_SUCCESS) { cbSize = cbBuffer; } RegCloseKey(hkDyn); } return(cbSize); } HKEY OpenDevnodeHwKey(DWORD dwDevnode) { TCHAR szScratch[MAX_PATH]; HKEY hkDyn, hkHw = NULL; UINT cbSize; UINT cchOffset; if ((hkDyn = OpenDevnodeDynKey(dwDevnode)) == NULL) { return(NULL); } lstrcpy(szScratch, g_szEnumKeyPrefix); cbSize = sizeof(szScratch) - sizeof(g_szEnumKeyPrefix); cchOffset = ARRAYSIZE(g_szEnumKeyPrefix) - 1; if (RegQueryValueEx(hkDyn, REGSTR_VAL_HARDWARE_KEY, NULL, NULL, (LPSTR)&(szScratch[cchOffset]), &cbSize) == ERROR_SUCCESS) { if (RegOpenKey(HKEY_LOCAL_MACHINE, szScratch, &hkHw) != ERROR_SUCCESS) { hkHw = NULL; } } RegCloseKey(hkDyn); return(hkHw); } UINT GetHwInfo(DWORD dwDevNode, LPCTSTR lpszValName, LPVOID lpBuffer, UINT cbBuffer) { UINT cbSize = 0; HKEY hkHw = OpenDevnodeHwKey(dwDevNode); if (hkHw) { if (RegQueryValueEx(hkHw, lpszValName, NULL, NULL, lpBuffer, &cbBuffer) == ERROR_SUCCESS) { cbSize = cbBuffer; } RegCloseKey(hkHw); } return(cbSize); } void UpdateSktTypes() { UINT i; TCHAR szClassName[32]; for (i = 0; i < g_numskts; i++) { if (g_aSktState[i] == 0 && g_aDevnodes[i] != 0) { if (GetHwInfo(g_aDevnodes[i], g_szClass, szClassName, sizeof(szClassName))) { g_aSktState[i] |= SKTSTATE_TYPEKNOWN; if (lstrcmpi(g_szModemClass, szClassName) != 0) { g_aSktState[i] |= SKTSTATE_SHOULDWARN; } } } } } void UpdateSocketInfo() { UINT cbReturned; if (DeviceIoControl(g_hPCCARD, PCCARD_IOCTL_GET_DEVNODES, NULL, 0, g_aDevnodes, sizeof(g_aDevnodes), &cbReturned, NULL)) { g_numskts = cbReturned / 4; } else { g_numskts = 0; } UpdateSktTypes(); } void UpdateGlobalFlags() { HKEY hk; if (RegOpenKey(HKEY_CURRENT_USER, REGSTR_PATH_SYSTRAY, &hk) == ERROR_SUCCESS) { UINT cb = sizeof(g_PCMCIAFlags); if (RegQueryValueEx(hk, g_szPCMCIAFlags, NULL, NULL, (LPSTR)(&g_PCMCIAFlags), &cb) != ERROR_SUCCESS) { g_PCMCIAFlags = 0; } RegCloseKey(hk); } } BOOL PCMCIA_Init(HWND hWnd) { if (g_hPCCARD == INVALID_HANDLE_VALUE) { g_hPCCARD = CreateFile(TEXT ("\\\\.\\PCCARD"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); UpdateGlobalFlags(); } return(g_hPCCARD != INVALID_HANDLE_VALUE); } // // NOTE: This function expects the caller to have called UpdateSocketInfo // prior to calling it. // void PCMCIA_UpdateStatus(HWND hWnd, BOOL bShowIcon, DWORD dnRemove) { if (bShowIcon) { UINT i; bShowIcon = FALSE; // Assume no devnodes for (i = 0; i < g_numskts; i++) { if (g_aDevnodes[i] != 0 && g_aDevnodes[i] != dnRemove) { bShowIcon = TRUE; break; } } } if (bShowIcon != g_bPCMCIAIconShown) { g_bPCMCIAIconShown = bShowIcon; if (bShowIcon) { LPTSTR pStr = LoadDynamicString(IDS_PCMCIATIP); g_hPCMCIAIcon = LoadImage(g_hInstance, MAKEINTRESOURCE(IDI_PCMCIA), IMAGE_ICON, 16, 16, 0); SysTray_NotifyIcon(hWnd, STWM_NOTIFYPCMCIA, NIM_ADD, g_hPCMCIAIcon, pStr); DeleteDynamicString(pStr); } else { SysTray_NotifyIcon(hWnd, STWM_NOTIFYPCMCIA, NIM_DELETE, NULL, NULL); if (g_hPCMCIAIcon) { DestroyIcon(g_hPCMCIAIcon); } } } } #define DEVNODE_NOT_IN_LIST -1 int FindSocketIndex(DWORD dn) { int i; for (i = 0; i < (int)g_numskts; i++) { if (g_aDevnodes[i] == dn) { return(i); } } return(DEVNODE_NOT_IN_LIST); } void PCMCIA_DeviceChange(HWND hDlg, WPARAM wParam, LPARAM lParam) { int i; #define lpdbd ((PDEV_BROADCAST_DEVNODE)lParam) #define DN_STARTED 0x00000008 // WARNING KEEP THIS IN SYNC WITH CONFIGMG.H if ((wParam != DBT_DEVICEREMOVEPENDING && wParam != DBT_DEVICEARRIVAL && wParam != DBT_DEVICEREMOVECOMPLETE) || lpdbd->dbcd_devicetype != DBT_DEVTYP_DEVNODE) { return; } switch (wParam) { case DBT_DEVICEREMOVEPENDING: // Query remove succeeded i = FindSocketIndex(lpdbd->dbcd_devnode); if (i != DEVNODE_NOT_IN_LIST) { g_aSktState[i] |= SKTSTATE_GOODEJECT; } break; case DBT_DEVICEARRIVAL: UpdateSocketInfo(); i = FindSocketIndex(lpdbd->dbcd_devnode); if (i != DEVNODE_NOT_IN_LIST) { g_aSktState[i] = 0; UpdateSktTypes(); PCMCIA_UpdateStatus(hDlg, TRUE, 0); } break; case DBT_DEVICEREMOVECOMPLETE: { ULONG Status = 0L; ULONG Size = sizeof(ULONG); TCHAR szDevNode[REGSTR_MAX_VALUE_LENGTH]; HKEY hkDevDyna; wsprintf(szDevNode, TEXT ("%s\\%8X"),REGSTR_PATH_DYNA_ENUM,lpdbd->dbcd_devnode); if (RegOpenKey( HKEY_DYN_DATA, szDevNode, &hkDevDyna ) == ERROR_SUCCESS) { RegQueryValueEx( hkDevDyna, REGSTR_VAL_STATUS, 0, NULL, (LPSTR)&Status, &Size ); RegCloseKey(hkDevDyna); } if (Status & DN_STARTED) { i = FindSocketIndex(lpdbd->dbcd_devnode); if (i != DEVNODE_NOT_IN_LIST) { // // Check to see if we're supposed to warn the user about this // eject. Only warn if NOT good eject and class is one we warn // about. // BOOL fWarnUser = (g_aSktState[i] & (SKTSTATE_SHOULDWARN | SKTSTATE_GOODEJECT)) == SKTSTATE_SHOULDWARN; g_aSktState[i] = 0; UpdateSocketInfo(); PCMCIA_UpdateStatus(hDlg, TRUE, lpdbd->dbcd_devnode); if (fWarnUser) { // Make sure the user did not turn this off earlier UpdateGlobalFlags(); if (!(g_PCMCIAFlags & PCMCIA_REGFLAG_NOWARN)) { const TCHAR szOpen[] = TEXT ("open"); const TCHAR szRunDLL[] = TEXT ("RUNDLL32.EXE"); const TCHAR szParams[] = TEXT ("RUNDLL mspcic.dll,EjectWarningDlg"); ShellExecute(NULL, szOpen, szRunDLL, szParams, NULL, SW_SHOW); } } } } break; } } #undef lpdbd } // // Called at init time and whenever services are enabled/disabled. // Returns false if PCMCIA services are not active. // BOOL PCMCIA_CheckEnable(HWND hWnd, BOOL bSvcEnabled) { BOOL bEnable = bSvcEnabled && PCMCIA_Init(hWnd); if (bEnable != g_bPCMCIAEnabled) { g_bPCMCIAEnabled = bEnable; UpdateSocketInfo(); PCMCIA_UpdateStatus(hWnd, bEnable, 0); if (!bEnable) { CloseIfOpen(&g_hPCCARD); } } return(bEnable); } /*---------------------------------------------------------------------------- * PCMCIA_CreateMenu() * * build a menu containing all sockets. * *----------------------------------------------------------------------------*/ //static CRITICAL_SECTION csMenu; static HMENU _hMenu[2] = {0}; HMENU PCMCIA_CreateMenu(LONG l) { //EnterCriticalSection(&csMenu); if (l > 0) { if (_hMenu[1] == NULL) { HMENU hmenu = _hMenu[l] = CreatePopupMenu(); LPTSTR lpszMenu; if ((lpszMenu = LoadDynamicString(IDS_PCCARDMENU1)) != NULL) { AppendMenu(hmenu,MF_STRING,PCMCIAMENU_PROPERTIES,lpszMenu); DeleteDynamicString(lpszMenu); } if ((lpszMenu = LoadDynamicString(IDS_PCCARDMENU2)) != NULL) { AppendMenu(hmenu,MF_STRING,PCMCIAMENU_DISABLE,lpszMenu); DeleteDynamicString(lpszMenu); } SetMenuDefaultItem(hmenu,PCMCIAMENU_PROPERTIES,FALSE); } } else { HMENU hMenu; if (_hMenu[0]) { DestroyMenu(_hMenu[0]); } hMenu = _hMenu[0] = CreatePopupMenu(); if (g_hPCCARD != INVALID_HANDLE_VALUE) { TCHAR szDesc[80]; LPTSTR lpszMenuText; UINT i; UpdateSocketInfo(); for (i = 0; i < g_numskts; i++) { if (g_aDevnodes[i] && GetHwInfo(g_aDevnodes[i], REGSTR_VAL_DEVDESC, szDesc, sizeof(szDesc))) { #if NOTYET DWORD dwChild; TCHAR szClassName[32]; TCHAR szDriveLetters[32]; if (GetDynInfo(g_aDevnodes[i], REGSTR_VAL_CHILD, &dwChild, sizeof(dwChild)) && GetHwInfo(dwChild, g_szClass, szClassName, sizeof(szClassName)) && lstrcmpi(g_szDiskDriveClass, szClassName) == 0 && GetHwInfo(dwChild, REGSTR_VAL_CURDRVLET, szDriveLetters, sizeof(szDriveLetters)) && lstrlen(szDriveLetters) > 0) { lpszMenuText = LoadDynamicString(IDS_EJECTFMTDISKDRIVE, szDesc, szDriveLetters[0]); } else #endif { lpszMenuText = LoadDynamicString(IDS_EJECTFMT, szDesc); } if (lpszMenuText) { AppendMenu(hMenu,MF_STRING,PCMCIAMENU_SOCKET+i,lpszMenuText); DeleteDynamicString(lpszMenuText); } } } } } //LeaveCriticalSection(&csMenu); return _hMenu[l]; } void PCMCIA_Menu(HWND hwnd, UINT uMenuNum, UINT uButton) { POINT pt; UINT iCmd; SetForegroundWindow(hwnd); GetCursorPos(&pt); iCmd = TrackPopupMenu(PCMCIA_CreateMenu(uMenuNum), uButton | TPM_RETURNCMD | TPM_NONOTIFY, pt.x, pt.y, 0, hwnd, NULL); if (iCmd >= PCMCIAMENU_SOCKET) { const TCHAR szOpen[] = TEXT ("open"); const TCHAR szRunDLL[] = TEXT ("RUNDLL32.EXE"); LPTSTR lpszCommand = LoadDynamicString(IDS_RUNEJECT, iCmd-PCMCIAMENU_SOCKET); if (lpszCommand == NULL) return; ShellExecute(NULL, szOpen, szRunDLL, lpszCommand, NULL, SW_SHOW); DeleteDynamicString(lpszCommand); } else { switch (iCmd) { case PCMCIAMENU_PROPERTIES: SysTray_RunProperties(IDS_RUNPCMCIAPROPERTIES); break; case PCMCIAMENU_DISABLE: PostMessage(hwnd, STWM_ENABLESERVICE, STSERVICE_PCMCIA, FALSE); break; } } } void PCMCIA_Notify(HWND hwnd, WPARAM wParam, LPARAM lParam) { switch (lParam) { case WM_RBUTTONUP: PCMCIA_Menu(hwnd, 1, TPM_RIGHTBUTTON); break; case WM_LBUTTONDOWN: SetTimer(hwnd, PCMCIA_TIMER_ID, GetDoubleClickTime()+100, NULL); break; case WM_LBUTTONDBLCLK: KillTimer(hwnd, PCMCIA_TIMER_ID); SysTray_RunProperties(IDS_RUNPCMCIAPROPERTIES); break; } } void PCMCIA_Timer(HWND hwnd) { KillTimer(hwnd, PCMCIA_TIMER_ID); PCMCIA_Menu(hwnd, 0, TPM_LEFTBUTTON); }