windows-nt/Source/XPSP1/NT/shell/ext/systray/dll/usbui.c

385 lines
9.7 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
#include "stdafx.h"
#include "systray.h"
#include <stdio.h>
#include <initguid.h>
#include <usbioctl.h>
#include <wmium.h>
#include <tchar.h>
#include <setupapi.h>
#define USBUIMENU 100
#define NUM_HCS_TO_CHECK 10
typedef int (CALLBACK *USBERRORMESSAGESCALLBACK)
(PUSB_CONNECTION_NOTIFICATION,LPTSTR);
extern HINSTANCE g_hInstance;
static BOOL g_bUSBUIEnabled = FALSE;
static BOOL g_bUSBUIIconShown = FALSE;
static HINSTANCE g_hUsbWatch = NULL;
static USBERRORMESSAGESCALLBACK g_UsbHandler = NULL;
static BOOL g_bSubstituteDll = FALSE;
static TCHAR g_strSubstituteDll[MAX_PATH];
static HANDLE g_hWait = NULL;
int _cdecl main(){
return 0;
}
#define USBUI_OffsetToPtr(Base, Offset) ((PBYTE)((PBYTE)Base + Offset))
LPTSTR USBUI_CountedStringToSz(LPTSTR lpString)
{
SHORT usNameLength;
LPTSTR lpStringPlusNull;
usNameLength = * (USHORT *) lpString;
lpStringPlusNull = (LPTSTR) LocalAlloc(LMEM_ZEROINIT,
sizeof(TCHAR) * (usNameLength+1));
if (lpStringPlusNull != NULL) {
lpString = (LPTSTR) USBUI_OffsetToPtr(lpString, sizeof(USHORT));
wcsncpy( lpStringPlusNull, lpString, usNameLength );
lpStringPlusNull[usNameLength] = TEXT('0');
// _tcscpy( lpStringPlusNull + usNameLength, _TEXT("") );
}
return lpStringPlusNull;
}
void USBUI_EventCallbackRoutine(PWNODE_HEADER WnodeHeader, UINT_PTR NotificationContext)
{
PWNODE_SINGLE_INSTANCE wNode = (PWNODE_SINGLE_INSTANCE)WnodeHeader;
PUSB_CONNECTION_NOTIFICATION usbConnectionNotification;
LPGUID eventGuid = &WnodeHeader->Guid;
LPTSTR strInstanceName;
if (memcmp(&GUID_USB_WMI_STD_DATA, eventGuid, sizeof(GUID)) == 0) {
usbConnectionNotification = (PUSB_CONNECTION_NOTIFICATION)
USBUI_OffsetToPtr(wNode,
wNode->DataBlockOffset);
//
// Get the instance name
//
strInstanceName =
USBUI_CountedStringToSz((LPTSTR)
USBUI_OffsetToPtr(wNode,
wNode->OffsetInstanceName));
if (strInstanceName) {
if (g_hUsbWatch && g_UsbHandler) {
USBUIEngageHandler:
g_UsbHandler(usbConnectionNotification, strInstanceName);
} else {
if (g_bSubstituteDll) {
g_hUsbWatch = LoadLibrary(g_strSubstituteDll);
} else {
g_hUsbWatch = LoadLibrary(TEXT("usbui.dll"));
}
g_UsbHandler = (USBERRORMESSAGESCALLBACK)
GetProcAddress(g_hUsbWatch, "USBErrorHandler");
goto USBUIEngageHandler;
}
LocalFree(strInstanceName);
}
}
}
VOID USBUI_WaitRoutineCallback(WMIHANDLE Handle, BOOLEAN Unused) {
ASSERT(!Unused);
UnregisterWaitEx(g_hWait, NULL);
g_hWait = NULL;
WmiReceiveNotifications(1, &Handle, USBUI_EventCallbackRoutine, (ULONG_PTR)NULL);
RegisterWaitForSingleObject(&g_hWait,
Handle,
USBUI_WaitRoutineCallback,
Handle, // context
INFINITE,
WT_EXECUTELONGFUNCTION | WT_EXECUTEONLYONCE);
}
int USBUI_ErrorMessagesEnable(BOOL fEnable)
{
ULONG status = ERROR_SUCCESS;
BOOL result;
static WMIHANDLE hWmi = NULL;
if (fEnable) {
ASSERT(!g_hWait);
ASSERT(!hWmi);
status = WmiOpenBlock((LPGUID) &GUID_USB_WMI_STD_DATA,
WMIGUID_NOTIFICATION | SYNCHRONIZE,
&hWmi);
if (!status) {
result = RegisterWaitForSingleObject(&g_hWait,
hWmi,
USBUI_WaitRoutineCallback,
hWmi, // context
INFINITE,
WT_EXECUTELONGFUNCTION | WT_EXECUTEONLYONCE);
status = result ? 0 : ERROR_INVALID_FUNCTION;
}
} else {
ASSERT(hWmi);
if (g_hWait) {
result = UnregisterWait(g_hWait);
}
if (hWmi) {
status = WmiCloseBlock(hWmi);
}
hWmi = NULL;
g_hWait = NULL;
if (g_hUsbWatch) {
// This allows us to replace the library
FreeLibrary(g_hUsbWatch);
g_hUsbWatch = NULL;
g_UsbHandler = NULL;
}
}
return status;
}
void USBUI_Notify(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
switch (lParam)
{
case WM_RBUTTONUP:
{
USBUI_Menu(hwnd, 1, TPM_RIGHTBUTTON);
}
break;
case WM_LBUTTONDOWN:
{
SetTimer(hwnd, USBUI_TIMER_ID, GetDoubleClickTime()+100, NULL);
}
break;
case WM_LBUTTONDBLCLK:
{
KillTimer(hwnd, USBUI_TIMER_ID);
USBUI_Toggle();
}
break;
}
}
void USBUI_Toggle()
{
USBUI_SetState(!g_bUSBUIEnabled);
}
void USBUI_Timer(HWND hwnd)
{
KillTimer(hwnd, USBUI_TIMER_ID);
USBUI_Menu(hwnd, 0, TPM_LEFTBUTTON);
}
/*
HMENU USBUI_CreateMenu()
{
HMENU hmenu;
LPSTR lpszMenu1;
hmenu = CreatePopupMenu();
if (!hmenu)
{
return NULL;
}
lpszMenu1 = LoadDynamicString(g_bUSBUIEnabled?IDS_USBUIDISABLE:IDS_USBUIENABLE);
// AppendMenu(hmenu,MF_STRING,USBUIMENU,lpszMenu1);
SysTray_AppendMenuString (hmenu,USBUIMENU,lpszMenu1);
SetMenuDefaultItem(hmenu,USBUIMENU,FALSE);
DeleteDynamicString(lpszMenu1);
return hmenu;
}
*/
void USBUI_Menu(HWND hwnd, UINT uMenuNum, UINT uButton)
{
POINT pt;
UINT iCmd;
HMENU hmenu = 0;
GetCursorPos(&pt);
// hmenu = USBUI_CreateMenu();
if (!hmenu)
{
return;
}
SetForegroundWindow(hwnd);
iCmd = TrackPopupMenu(hmenu, uButton | TPM_RETURNCMD | TPM_NONOTIFY, pt.x, pt.y, 0, hwnd, NULL);
DestroyMenu(hmenu);
switch (iCmd)
{
case USBUIMENU:
{
USBUI_Toggle();
}
break;
}
}
BOOL USBUI_SetState(BOOL NewState)
{
int retValue;
if (g_bUSBUIEnabled != NewState) {
//
// Only enable it if not already enabled
//
retValue = (int) USBUI_ErrorMessagesEnable (NewState);
g_bUSBUIEnabled = retValue ? g_bUSBUIEnabled : NewState;
}
return g_bUSBUIEnabled;
}
BOOL
IsErrorCheckingEnabled()
{
DWORD ErrorCheckingEnabled = TRUE, size;
HKEY hKey;
//
// Check the registry value ErrorCheckingEnabled to make sure that we should
// be enabling this.
//
if (ERROR_SUCCESS ==
RegOpenKeyEx(HKEY_LOCAL_MACHINE,
TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Usb"),
0,
KEY_READ,
&hKey)) {
// Get the ErrorCheckingEnabled value
size = sizeof(DWORD);
RegQueryValueEx(hKey,
TEXT("ErrorCheckingEnabled"),
0,
NULL,
(LPBYTE) &ErrorCheckingEnabled,
&size);
if (ErrorCheckingEnabled) {
// Look for a substitute dll for usbui.dll
size = MAX_PATH*sizeof(TCHAR);
if (ERROR_SUCCESS ==
RegQueryValueEx(hKey,
TEXT("SubstituteDll"),
0,
NULL,
(LPBYTE) g_strSubstituteDll,
&size)) {
g_bSubstituteDll = TRUE;
} else {
g_bSubstituteDll = FALSE;
}
}
}
return (BOOL) ErrorCheckingEnabled;
}
BOOL USBUI_Init(HWND hWnd)
{
TCHAR HCName[16];
BOOL ControllerFound = FALSE;
int HCNum;
HDEVINFO hHCDev;
//
// Check the registry to make sure that it is turned on
//
if (!IsErrorCheckingEnabled()) {
return FALSE;
}
//
// Check for the existence of a USB controller.
// If there is one, load and initialize USBUI.dll which will check for
// usb error messages. If we can't open a controller, than we shouldn't
// load a USB watch dll.
//
for (HCNum = 0; HCNum < NUM_HCS_TO_CHECK; HCNum++)
{
wsprintf(HCName, TEXT("\\\\.\\HCD%d"), HCNum);
hHCDev = CreateFile(HCName,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
0,
NULL);
//
// If the handle is valid, then we've successfully opened a Host
// Controller.
//
if (hHCDev != INVALID_HANDLE_VALUE) {
CloseHandle(hHCDev);
return TRUE;
}
}
hHCDev = SetupDiGetClassDevs(&GUID_CLASS_USB_HOST_CONTROLLER,
NULL,
NULL,
(DIGCF_DEVICEINTERFACE | DIGCF_PRESENT));
if(hHCDev == INVALID_HANDLE_VALUE) {
return FALSE;
}
SetupDiDestroyDeviceInfoList(hHCDev);
return TRUE;
}
//
// Called at init time and whenever services are enabled/disabled.
//
BOOL USBUI_CheckEnable(HWND hWnd, BOOL bSvcEnabled)
{
BOOL bEnable = bSvcEnabled && USBUI_Init(hWnd);
if (bEnable != g_bUSBUIEnabled)
{
//
// state change
//
USBUI_SetState(bEnable);
}
return(bEnable);
}