502 lines
12 KiB
C
502 lines
12 KiB
C
/*******************************************************************************
|
|
*
|
|
* (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);
|
|
}
|