Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

456 lines
14 KiB

/***************************************************************************************************
**
** 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> // for strncmp() and wcstrok()
#include <crtdbg.h>
#include <hidsdi.h> // HID parsing library
#include <hidusage.h>
#include <HID.H>
#include "public.h"
#include "CLASS.H"
#include "IOCTL.H"
PWSTR wcGetNullDelimitedItemFromList( PWSTR pszzList );
PWSTR UnicodeString = L"This is Unicode\0Dis is more\0\0";
char szFrame[] = "HIDMON frame"; // Class name for "frame" window
char szChild[] = "HIDMON child"; // Class name for MDI window
/****************
TESTING!!!!!!!
****************/
typedef char* PGUID;
NTSTATUS
IoGetDeviceClassAssociations(
IN PGUID ClassGuid,
OUT PWSTR *SymbolicLinkList
);
/****
NTSTATUS
IoGetDeviceClassAssociations(
IN PGUID ClassGuid,
OUT PWSTR *SymbolicLinkList
)
{
*SymbolicLinkList = UnicodeString;
return TRUE;
}
****/
/***
BOOLEAN
HidD_GetGuidString (
OUT PCHAR * GuidClassInputString
)
{ return TRUE; }
***/
/***************************************************************************************************
**
** InitializeApplication.
**
** DESCRIPTION: Sets up the class data structures and does a one-time,
** initialization of the app by registering the window classes
**
** PARAMETERS:
**
** RETURNS: TRUE if successful else FALSE.
**
***************************************************************************************************/
ULONG InitializeApplication(VOID)
{
WNDCLASS wc;
// Register the frame class
wc.style = CS_DBLCLKS;
wc.lpfnWndProc = HIDFrameWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst;
wc.hIcon = LoadIcon(hInst, IDHIDFRAME);
wc.hCursor = LoadCursor(NULL,IDC_ARROW);
wc.hbrBackground = (HBRUSH) (COLOR_APPWORKSPACE+1);
wc.lpszMenuName = IDHIDMENU;
wc.lpszClassName = szFrame;
if(RegisterClass(&wc))
{
// Register the MDI child class
wc.lpfnWndProc = HIDMDIChildWndProc;
wc.hIcon = LoadIcon(hInst,IDHIDCHILD);
wc.lpszMenuName = NULL;
wc.cbWndExtra = CBWNDEXTRA;
wc.lpszClassName = szChild;
if(RegisterClass(&wc))
return TRUE;
}
return FALSE;
}
/***************************************************************************************************
**
** InitializeInstance.
**
** DESCRIPTION: Performs a per-instance initialization of HIDMDI. It
** also creates the frame and one MDI child window.
**
** PARAMETERS:
**
** RETURNS: TRUE if successful else FALSE.
**
***************************************************************************************************/
ULONG InitializeInstance(LPSTR lpCmdLine, INT WindowState)
{
extern HWND hWndMDIClient;
CHAR sz[80];
// Get the base window title
LoadString (hInst, IDS_APPNAME, sz, sizeof(sz));
// Create the frame
// MDI Client window is created in frame's WM_CREATE case
hWndFrame = CreateWindow(szFrame,
sz,
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
CW_USEDEFAULT,
0,
CW_USEDEFAULT,
0,
NULL,
NULL,
hInst,
NULL);
if(hWndFrame && hWndMDIClient)
{
// Display the frame window
ShowWindow (hWndFrame, WindowState);
UpdateWindow (hWndFrame);
// Open all the Class device objects
OpenClassObjects();
return TRUE;
}
return FALSE;
}
/***************************************************************************************************
**
** OpenClassObjects.
**
** DESCRIPTION: Creates a new MDI child window.
**
** PARAMETERS:
**
** RETURNS: TRUE if successful else FALSE.
**
***************************************************************************************************/
#define MAX_DEVICE_NAME_LEN 255
VOID OpenClassObjects(VOID)
{
HANDLE hDevice,hGetDeviceClassDriver;
BOOL rc;
//PWSTR pwszDeviceList; // UNICODE strings
WORD wszDeviceList[1024];
PWSTR pwszDeviceName;
PCHAR pszGUID;
char pszDeviceName[MAX_DEVICE_NAME_LEN];
char pszHumanName[MAX_DEVICE_NAME_LEN];
DWORD dwReturn;
if( 1 )//rc = HidD_GetGuidString( &pszGUID ) )
{
//
// If we got a GUID string, retrieve a list of null terminated device
// name UNICODE strings similar to \\.\Device. This list is terminated
// by a double NULL
//rc = IoGetDeviceClassAssociations(pszGUID,&pwszDeviceList);
hGetDeviceClassDriver = CreateFile(TEST_DEVICE,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL);
if( hGetDeviceClassDriver != INVALID_HANDLE_VALUE)
rc = DeviceIoControl(hGetDeviceClassDriver,
IOCTL_GET_DEVICE_CLASS_ASSOC,
NULL,
0,
wszDeviceList,
1024*2,
&dwReturn,
NULL);
else
MessageBox(NULL,"Failed to load Test driver TEST.SYS","Error",MB_OK);
CloseHandle(hGetDeviceClassDriver);
pwszDeviceName = wcGetNullDelimitedItemFromList( wszDeviceList );
do{
// Convert the device name to ANSI
WideCharToMultiByte( CP_ACP, // ANSI Code Page
0, // No flags
pwszDeviceName, // UNICODE string
-1, // String is NULL terminated
pszDeviceName, // ANSI string
MAX_DEVICE_NAME_LEN, // Lenght of ANSI string buffer
NULL, // No default character
NULL );
// Open the Class device
hDevice = CreateFile(pszDeviceName,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL);
if(hDevice != INVALID_HANDLE_VALUE )
{
// Turn our DeviceName into a Human Readable name
GetDeviceDescription(pszDeviceName, pszHumanName);
// Create the window
MakeNewChild(pszHumanName, hDevice);
}
else
MessageBox(NULL,"CreateFile(pszDeviceName) failed","Get On The Bus!",MB_OK);
// Get the next device name
}while( pwszDeviceName = wcGetNullDelimitedItemFromList( NULL ) ); //wcstok(NULL,L"\0") );
// TESTING!!!! remove comments from free()
// Remember to free the GUID string memory
//free(pszGUID);
}
}
/***************************************************************************************************
**
** GetDeviceDescription( char *pszDevice, char *pszName)
**
** DESCRIPTION: Given DeviceName string as returned from IoGetDeviceClassAssociations,
** place a NULL terminated string retrieved from HKLM\Enum\USB(...)\DeviceDescription
** in pszName
**
** PARAMETERS: char* pszDevice - Pointer to an ANSII string returned from IoGetDeviceClassAssociations
** char* pszName - Pointer to string to return name of device in
**
** RETURNS: void
**
***************************************************************************************************/
void GetDeviceDescription(char *pszDevice, char *pszName)
{
HKEY hkReg;
LONG rc;
LONG BytesWritten=MAX_DEVICE_NAME_LEN;
char *head;
char szRegPath[MAX_DEVICE_NAME_LEN];
head = pszDevice;
// first whack off the \\.\USB#
while( *head++ != '#' );
pszDevice = head;
// then replace all instances of # with \
while( *head )
{
if( *head == '#' )
*head = '\\';
head++;
}
// now, whack off the GUID string (begins with a { ) and preceding \
head = pszDevice;
while( *head != '{' )
head++;
// null terminate it
*--head = '\0';
// Create our registry path
wsprintf(szRegPath,"ENUM\\USB\\%s",pszDevice);
// open up the Reg and get our human readable name
rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE,szRegPath,0,KEY_ALL_ACCESS,&hkReg);
if( rc == ERROR_SUCCESS )
{
// add on the Named value we are looking for
rc = RegQueryValueEx(hkReg,"DeviceDesc",0,NULL,pszName,&BytesWritten);
RegCloseKey(hkReg);
}
}
/***************************************************************************************************
**
** wcGetNullDelimitedItemFromList( PWSTR pszzList)
**
** DESCRIPTION: Given a list of NULL terminated strings with the last member being a
** double NULL, will return the next string in the list. Operation is similar
** to strtok(): the first time the function is called, a valid list must be passed,
** there after to retrieve member strings, pass NULL in the pszzList param.
**
** PARAMETERS: PWSTR pszzList - Pointer to a UNICODE double null terminated list of
** NULL terminated strings.
**
**
** RETURNS: PWSTR Pointer to the next member of the list or NULL if at end of list.
**
***************************************************************************************************/
PWSTR wcGetNullDelimitedItemFromList( PWSTR pszzList )
{
static PWSTR CurrentMember=NULL; // Current pointer into the list
PWSTR tmp;
//
// Make sure pszzList is not NULL the first time in
if( !pszzList && !CurrentMember )
return NULL;
//
// If pszzList is not NULL, we are starting from scratch
if( pszzList )
CurrentMember = pszzList;
//
// If we have 2 NULL's then we are at the end of the list
if( (*CurrentMember == L'\0') && (*(CurrentMember+1) == L'\0') )
{
CurrentMember=NULL;
return NULL;
}
else
{
// Save a pointer to the current member
tmp = CurrentMember;
// Incriment to the next member
while( *CurrentMember++ );
// Return the current member
return tmp;
}
}
/***************************************************************************************************
**
** MakeNewChild.
**
** DESCRIPTION: Creates a new MDI child window.
**
** PARAMETERS:
**
** RETURNS: TRUE if successful else FALSE.
**
***************************************************************************************************/
/*
BOOLEAN __stdcall
HidD_MyGetPreparsedData (
IN HANDLE HidDeviceObject,
OUT PHIDP_PREPARSED_DATA * PreparsedData
);
*/
HWND MakeNewChild(char *pName, HANDLE hDevice)
{
HWND hWnd = 0;
MDICREATESTRUCT mcs;
PCHILD_INFO pChildInfo;
PHIDP_PREPARSED_DATA hidPreParsedData;
DWORD err;
NTSTATUS rc;
if(pName)
{
mcs.szTitle = (LPSTR)pName; // Fully qualified pathname
mcs.szClass = szChild;
mcs.hOwner = hInst;
mcs.x = mcs.cx = CW_USEDEFAULT; // Use the default size for the window
mcs.y = mcs.cy = CW_USEDEFAULT;
mcs.style = styleDefault; // Set the style DWORD of the window to default
// tell the MDI Client to create the child
hWnd = (HWND)SendMessage(hWndMDIClient,
WM_MDICREATE,
0,
(LONG)(LPMDICREATESTRUCT)&mcs);
if(hWnd)
{
//
// Create and fill in a device info struct for this window
pChildInfo = (PCHILD_INFO) GlobalAlloc(GPTR,sizeof(CHILD_INFO));
pChildInfo->hidCaps = (PHIDP_CAPS) GlobalAlloc(GPTR,sizeof(HIDP_CAPS));
// rc = HidD_MyGetPreparsedData( hDevice,&pChildInfo->hidPPData );
rc = HidD_GetPreparsedData( hDevice,&pChildInfo->hidPPData );
if( !rc )
err = GetLastError();
// Get a pointer to this devices capabilities
rc = HidP_GetCaps( pChildInfo->hidPPData, pChildInfo->hidCaps );
// Allocate space for and get a list of Value channel descriptions for this device
pChildInfo->pValueCaps = (PHIDP_VALUE_CAPS) GlobalAlloc(GPTR,pChildInfo->hidCaps->NumberInputValueCaps*sizeof(HIDP_VALUE_CAPS));
pChildInfo->NumValues = pChildInfo->hidCaps->NumberInputValueCaps;
rc = HidP_GetValueCaps( HidP_Input,
pChildInfo->pValueCaps,
&pChildInfo->NumValues,
pChildInfo->hidPPData
);
// Allocate space for and get a list of Button channel descriptions for this device
pChildInfo->pButtonCaps = (PHIDP_BUTTON_CAPS) GlobalAlloc(GPTR,pChildInfo->hidCaps->NumberInputButtonCaps*sizeof(HIDP_BUTTON_CAPS));
pChildInfo->NumButtons = pChildInfo->hidCaps->NumberInputButtonCaps;
rc = HidP_GetButtonCaps(HidP_Input,
pChildInfo->pButtonCaps,
&pChildInfo->NumButtons,
pChildInfo->hidPPData
);
// Save the info!
SetDeviceInfo(hWnd, pChildInfo);
SetDeviceHandle(hWnd, hDevice);
ShowWindow(hWnd, SW_SHOW);
//TESTING!!
//IOCTLRead(hWnd);
}
}
return hWnd;
}