/*************************************************************************************************** ** ** 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 #include // for strncmp() and wcstrok() #include #include // HID parsing library #include #include #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; }