windows-nt/Source/XPSP1/NT/drivers/wdm/input/tools/hidmon/ioctl.c
2020-09-26 16:20:57 +08:00

519 lines
17 KiB
C

/***************************************************************************************************
**
** MODULE:
**
**
** DESCRIPTION:
**
**
** AUTHOR: Daniel Dean.
**
**
**
** CREATED:
**
**
**
**
** (C) C O P Y R I G H T D A N I E L D E A N 1 9 9 6.
***************************************************************************************************/
#include <WINDOWS.H>
#include <string.h>
#include <hidsdi.h>
#include <hidusage.h>
#include "CLASS.H"
#include "IOCTL.H"
#include "resource.h"
/***************************************************************************************************
**
** IOCTLChannelDesc.
**
** DESCRIPTION:
**
** PARAMETERS:
**
** RETURNS:
**
***************************************************************************************************/
LPARAM IOCTLChannelDesc(HWND hWnd)
{
FARPROC lpfnProc;
HINSTANCE hInstance = (HINSTANCE) GetWindowLong(hWnd, GWL_HINSTANCE);
if((lpfnProc=(FARPROC)MakeProcInstance(ChannelDialogProc, hInstance)) != NULL)
{
DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_CHANNELDIALOG), hWnd, lpfnProc,(LPARAM)hWnd);
FreeProcInstance(lpfnProc);
}
return SUCCESS;
}
/***************************************************************************************************
**
** ChannelDialogProc()
**
** DESCRIPTION: Dialog Box procedure fot the Channel Info dialog
**
** PARAMETERS:
**
** RETURNS:
**
***************************************************************************************************/
BOOL CALLBACK ChannelDialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static HWND hwndMama;
static PCHILD_INFO pChildInfo;
static ULONG Index = 0;
static BOOL fValues = TRUE; // Are we displaying 'Value' channels?
// If not we are displaying 'Button' channels
HANDLE hListBox;
char buff[32];
switch(uMsg)
{
case WM_INITDIALOG:
hwndMama = (HWND)lParam;
pChildInfo = (PCHILD_INFO)GetDeviceInfo(hwndMama);
SendMessage(hDlg,WM_COMMAND,IDC_NEXT,0);
return TRUE;
case WM_COMMAND:
{
switch(wParam)
{
case IDOK:
EndDialog(hDlg,0);
return TRUE;
case IDC_NEXT:
hListBox = GetDlgItem(hDlg,IDC_ITEMLIST);
SendMessage(hListBox,LB_RESETCONTENT,0,0);
if( fValues )
{
wsprintf(buff,"Value Channel %d",Index);
SetWindowText(hDlg,buff);
if( Index < pChildInfo->NumValues )
{
wsprintf(buff,"UsagePage = %d",pChildInfo->pValueCaps[Index].UsagePage);
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
wsprintf(buff,"ReportID = %d",pChildInfo->pValueCaps[Index].ReportID);
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
if( pChildInfo->pValueCaps[Index].IsRange)
{
wsprintf(buff,"UsageMin = %d",pChildInfo->pValueCaps[Index].Range.UsageMin);
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
wsprintf(buff,"UsageMax = %d",pChildInfo->pValueCaps[Index].Range.UsageMax);
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
wsprintf(buff,"StringMin = %d",pChildInfo->pValueCaps[Index].Range.StringMin);
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
wsprintf(buff,"StringMax = %d",pChildInfo->pValueCaps[Index].Range.StringMax);
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
wsprintf(buff,"DesignatorMin = %d",pChildInfo->pValueCaps[Index].Range.DesignatorMin);
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
wsprintf(buff,"DesignatorMax = %d",pChildInfo->pValueCaps[Index].Range.DesignatorMax);
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
}
else
{
wsprintf(buff,"Usage = %d",pChildInfo->pValueCaps[Index].NotRange.Usage);
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
wsprintf(buff,"StringIndex = %d",pChildInfo->pValueCaps[Index].NotRange.StringIndex);
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
wsprintf(buff,"DesignatorIndex = %d",pChildInfo->pValueCaps[Index].NotRange.DesignatorIndex);
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
}
if( pChildInfo->pValueCaps[Index].HasNull )
{
wsprintf(buff,"NULL = %d",pChildInfo->pValueCaps[Index].Null);
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
}
wsprintf(buff,"LogicalMin = %d",pChildInfo->pValueCaps[Index].LogicalMin);
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
wsprintf(buff,"LogicalMax = %d",pChildInfo->pValueCaps[Index].LogicalMax);
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
wsprintf(buff,"PhysicalMin = %d",pChildInfo->pValueCaps[Index].PhysicalMin);
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
wsprintf(buff,"PhysicalMax = %d",pChildInfo->pValueCaps[Index].PhysicalMax);
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
Index++;
}
else
{
Index = 0;
fValues = FALSE;
}
}
else
if( Index < pChildInfo->NumButtons )
{
hListBox = GetDlgItem(hDlg,IDC_ITEMLIST);
wsprintf(buff,"Button Channel %d",Index);
SetWindowText(hDlg,buff);
wsprintf(buff,"UsagePage = %d",pChildInfo->pValueCaps[Index].UsagePage);
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
wsprintf(buff,"ReportID = %d",pChildInfo->pValueCaps[Index].ReportID);
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
if( pChildInfo->pValueCaps[Index].IsRange)
{
wsprintf(buff,"UsageMin = %d",pChildInfo->pValueCaps[Index].Range.UsageMin);
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
wsprintf(buff,"UsageMax = %d",pChildInfo->pValueCaps[Index].Range.UsageMax);
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
wsprintf(buff,"StringMin = %d",pChildInfo->pValueCaps[Index].Range.StringMin);
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
wsprintf(buff,"StringMax = %d",pChildInfo->pValueCaps[Index].Range.StringMax);
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
wsprintf(buff,"DesignatorMin = %d",pChildInfo->pValueCaps[Index].Range.DesignatorMin);
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
wsprintf(buff,"DesignatorMax = %d",pChildInfo->pValueCaps[Index].Range.DesignatorMax);
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
}
else
{
wsprintf(buff,"Usage = %d",pChildInfo->pValueCaps[Index].NotRange.Usage);
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
wsprintf(buff,"StringIndex = %d",pChildInfo->pValueCaps[Index].NotRange.StringIndex);
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
wsprintf(buff,"DesignatorIndex = %d",pChildInfo->pValueCaps[Index].NotRange.DesignatorIndex);
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
}
Index++;
}
else
{
fValues = TRUE;
Index = 0;
}
return TRUE;
}
}//end case WM_COMMAND
}//end switch(uMsg)
return FALSE;
}
/***************************************************************************************************
**
** IOCTLDeviceDesc.
**
** DESCRIPTION:
**
** PARAMETERS:
**
** RETURNS:
**
***************************************************************************************************/
LPARAM IOCTLDeviceDesc(HWND hWnd)
{
return SUCCESS;
}
/***************************************************************************************************
**
** IOCTLRead.
**
** DESCRIPTION:
**
** PARAMETERS:
**
** RETURNS:
**
***************************************************************************************************/
LPARAM IOCTLRead(HWND hWnd)
{
ULONG dwThreadID;
HANDLE hThread;
PREADTHREAD pThreadData;
OutputDebugString(">>>>HIDMON.EXE: IOCTLRead() Enter\n");
// If a read or a write is in progress stop it
if(GetThreadData(hWnd))
IOCTLStop(hWnd);
// Get the number of bytes of data for this device
// Allocate and setup a thread variables
pThreadData = (PREADTHREAD) GlobalAlloc(GPTR, sizeof(READTHREAD));
if(!pThreadData)
{
MessageBox(hWnd,"IOCTLRead(): GlobalAlloc fialed","Ooops!",MB_OK);
return FALSE;
}
pThreadData->hEditWin = GetEditWin(hWnd);
pThreadData->ThisThread = TRUE;
pThreadData->hDevice = GetDeviceHandle(hWnd);
pThreadData->hWnd = hWnd;
// Create Data notification thread
hThread = CreateThread((LPSECURITY_ATTRIBUTES) NULL,
(DWORD) 0,
(LPTHREAD_START_ROUTINE) ReadWatch,
(LPVOID) pThreadData,
CREATE_SUSPENDED,
&dwThreadID);
if(!hThread)
{
GlobalFree(pThreadData);
MessageBox(hWnd,"IOCTLRead(): CreateThread fialed","Ooops!",MB_OK);
return FAILURE;
}
SetThreadData(hWnd, pThreadData);
// Set Thread priority and start thread
SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL);
ResumeThread(hThread);
return SUCCESS;
}
/***************************************************************************************************
**
** IOCTLWrite.
**
** DESCRIPTION:
**
** PARAMETERS:
**
** RETURNS:
**
***************************************************************************************************/
LPARAM IOCTLWrite(HWND hWnd)
{
ULONG dwReturn = 0;
OVERLAPPED Overlapped;
// If a read or a write is in progress stop it
if(GetThreadData(hWnd))
IOCTLStop(hWnd);
// Need a way to get data froom user
// Need a way to get channel number from user
Overlapped.Offset = 3;
Overlapped.hEvent = NULL;
dwReturn = 0;
WriteFile(GetDeviceHandle(hWnd), (PVOID) "Hello", sizeof("Hello"), &dwReturn, &Overlapped);
return SUCCESS;
}
/***************************************************************************************************
**
** IOCTLStop.
**
** DESCRIPTION:
**
** PARAMETERS:
**
** RETURNS:
**
***************************************************************************************************/
LPARAM IOCTLStop(HWND hWnd)
{
PREADTHREAD pThreadData;
OutputDebugString(">>>>HIDMON.EXE: IOCTLStop() Enter\n");
pThreadData = GetThreadData(hWnd);
if(pThreadData)
{
SetThreadData(hWnd, 0);
pThreadData->ThisThread = FALSE;
}
// Allow the thread to die
//Sleep(250);
OutputDebugString(">>>>HIDMON.EXE: IOCTLStop() Exit\n");
return SUCCESS;
}
/*******************************************************************************
**
** FUNCTION: ReadWatch()
**
** PURPOSE: Read next available packet and display in child window
**
**
**
*******************************************************************************/
#define MAX_CHARS_PER_LINE 128
VOID CALLBACK ReadWatch(HWND hWnd, UINT uMsg, UINT TimerID, DWORD dwTime)
{
PUCHAR WriteBuffer;
PUCHAR ReadBuffer;
ULONG NumChannels;
ULONG NumBytes;
ULONG LogicalReturn;
READTHREAD ThreadData;
OVERLAPPED OV;
PCHILD_INFO pChildInfo;
OutputDebugString(">>>>HIDMON.EXE: ReadWatch() Enter\n");
// Retrieve info for this child
pChildInfo = (PCHILD_INFO)GetDeviceInfo(hWnd);
NumChannels = pChildInfo->hidCaps->NumberInputValueCaps +
pChildInfo->hidCaps->NumberInputButtonCaps;
NumBytes = pChildInfo->hidCaps->InputReportByteLength;
// Allocate memory for our ReadBuffer
ReadBuffer = (PUCHAR) GlobalAlloc(GPTR,NumBytes);
if(!ReadBuffer)
return;// FALSE;
// Allocate memory for our 'screen' buffer
WriteBuffer = (PUCHAR) GlobalAlloc(GPTR,NumChannels*MAX_CHARS_PER_LINE);
if(!WriteBuffer)
{
GlobalFree(ReadBuffer);
return;// FALSE;
}
// Setup read buffer
memset(ReadBuffer, 0, NumBytes);
// Setup overlapped structure
memset(&OV, 0, sizeof(OVERLAPPED));
// Start read
LogicalReturn = ReadFileEx(GetDeviceHandle(hWnd),
(LPVOID) ReadBuffer,
NumBytes,
&OV,
NULL);
// Print error message if failed
if(!LogicalReturn)
SendMessage(ThreadData.hEditWin,
WM_SETTEXT,
(WPARAM) sizeof("ReadFile FAILED!"),
(LPARAM) "ReadFile FAILED!");
else
if( LogicalReturn )
{
PCHAR pChar = WriteBuffer;
NTSTATUS rc;
char tmpBuff[256],tmpBuff2[256];
ULONG i,Value;
//
// Parse the data from our last Read
//
// Clear the buffer
memset(WriteBuffer,'\0',NumChannels*MAX_CHARS_PER_LINE);
// Make Text strings
// First do the Value channels
for(i=0;i<pChildInfo->hidCaps->NumberInputValueCaps;i++)
{
rc = HidP_GetUsageValue(HidP_Input,
pChildInfo->pValueCaps[i].UsagePage,
0,
pChildInfo->pValueCaps[i].NotRange.Usage,
&Value,
pChildInfo->hidPPData,
ReadBuffer,
NumBytes );
wsprintf(tmpBuff,"Value: Usage[%02d]:[%02d] = %d\r\n",
pChildInfo->pValueCaps[i].UsagePage,
pChildInfo->pValueCaps[i].NotRange.Usage,
Value );
strcat(WriteBuffer,tmpBuff);
}
// Then do the button channels
for(i=0;i<pChildInfo->hidCaps->NumberInputButtonCaps;i++)
{
PUCHAR pUsageList;
DWORD ulUsageListLen;
//UCHAR TempBuff[256];
// Get the maximum usage list length
ulUsageListLen = HidP_MaxUsageListLength( HidP_Input,
pChildInfo->pButtonCaps[i].UsagePage,
pChildInfo->hidPPData );
pUsageList = (PUCHAR)GlobalAlloc(GMEM_FIXED,ulUsageListLen);
wsprintf( tmpBuff,"Buttons:[%02d]:[%02d] = ",pChildInfo->pButtonCaps[i].UsagePage,
pChildInfo->pButtonCaps[i].NotRange.Usage);
ulUsageListLen++;
rc = HidP_GetUsages(HidP_Input,
pChildInfo->pButtonCaps[i].UsagePage,
pChildInfo->pButtonCaps[i].LinkCollection,
pUsageList,
&ulUsageListLen,
pChildInfo->hidPPData,
ReadBuffer,
NumBytes );
// if Buttons are pressed
if( ulUsageListLen )
{
ULONG i;
for(i=0;i<ulUsageListLen;i++)
{
wsprintf(tmpBuff2,"0x%02X ",pUsageList[i]);
strcat(tmpBuff,tmpBuff2);
}
}
strcat(tmpBuff,"\r\n");
strcat(WriteBuffer,tmpBuff);
GlobalFree(pUsageList);
//i=pChildInfo->NumButtons;
}
SendMessage(GetEditWin(hWnd),//ThreadData.hEditWin,
WM_SETTEXT,
(WPARAM) strlen(WriteBuffer),
(LPARAM) WriteBuffer);
}// end if(LogicalReturn)
//
GlobalFree(ReadBuffer);
GlobalFree(WriteBuffer);
//TESTING!!
OutputDebugString(">>>>HIDMON.EXE: ReadWatch() Exit\n");
return;// TRUE;
}