/****************************************************************************** wsti.cpp WDM Still Imaging interface Copyright (C) Microsoft Corporation, 1997 - 1998 All rights reserved Notes: THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. ******************************************************************************/ #include "stillvue.h" // // globals defined in Stivar.h // extern PDEVLOG pdevPtr, // pointer to current device log device pdevRoot; // base of the device log table extern PSTR pszStr1,pszStr2,pszStr3, // utility strings pszStr4; extern HINSTANCE hThisInstance; // instance of this app extern HANDLE hNTLog; // NT log handle extern HMENU hMenu; // current menu extern int *pSuite; // pointer to test Suite to run extern int nError, nICanScan, // global flags nNextTest, // index into pSuite nNameOnly, nScanCount, nTestID, nUnSubscribeSemaphore, // semaphore for StiSubscribe nUnSubscribe; // flag to request UnSubscribe // // STI.H - STI_DEVICE_MJ_TYPE // STRINGTABLE StStiDeviceType[] = { 0, "StiDeviceTypeDefault",0, 1, "StiDeviceTypeScanner",0, 2, "StiDeviceTypeDigitalCamera",0, 0, "Unknown device type",-1 }; // // STIERR.H - errors // STRINGTABLE StStiError[] = { STI_OK, "STI_OK",0, STI_NOTCONNECTED, "STI_NOTCONNECTED",0, STI_CHANGENOEFFECT, "STI_CHANGENOEFFECT",0, STIERR_OLD_VERSION, "STIERR_OLD_VERSION",0, STIERR_BETA_VERSION, "STIERR_BETA_VERSION",0, STIERR_BADDRIVER, "STIERR_BADDRIVER",0, STIERR_DEVICENOTREG, "STIERR_DEVICENOTREG",0, STIERR_OBJECTNOTFOUND, "STIERR_OBJECTNOTFOUND",0, STIERR_INVALID_PARAM, "STIERR_INVALID_PARAM",0, STIERR_NOINTERFACE, "STIERR_NOINTERFACE",0, STIERR_GENERIC, "STIERR_GENERIC", 0, STIERR_OUTOFMEMORY, "STIERR_OUTOFMEMORY", 0, STIERR_UNSUPPORTED, "STIERR_UNSUPPORTED", 0, STIERR_NOT_INITIALIZED, "STIERR_NOT_INITIALIZED", 0, STIERR_ALREADY_INITIALIZED, "STIERR_ALREADY_INITIALIZED", 0, STIERR_DEVICE_LOCKED, "STIERR_DEVICE_LOCKED", 0, STIERR_READONLY, "STIERR_READONLY", 0, STIERR_NOTINITIALIZED, "STIERR_NOTINITIALIZED", 0, STIERR_NEEDS_LOCK, "STIERR_NEEDS_LOCK", 0, STIERR_SHARING_VIOLATION, "STIERR_SHARING_VIOLATION", 0, STIERR_HANDLEEXISTS, "STIERR_HANDLEEXISTS", 0, STIERR_INVALID_DEVICE_NAME, "STIERR_INVALID_DEVICE_NAME", 0, STIERR_INVALID_HW_TYPE, "STIERR_INVALID_HW_TYPE", 0, STIERR_INVALID_HW_TYPE, "STIERR_INVALID_HW_TYPE", 0, STIERR_NOEVENTS, "STIERR_NOEVENTS", 0, 0, "Unknown STI error",-1 }; // // WINNT.H - Predefined Value Types. // STRINGTABLE StRegValType[] = { 0, "REG_NONE",0, 1, "REG_SZ",0, 3, "REG_BINARY",0, 4, "REG_DWORD",0, 0, "Unknown reg type",-1 }; // // global still image // PSTI pSti = NULL; // handle to Sti subsystem PVOID pStiInfo = NULL; // Sti device info buffer PSTI_DEVICE_INFORMATION pStiInfoPtr = NULL; // pointer to device in pStiBuffer PSTIDEVICE pStiDevice = NULL; // Sti device being used HANDLE hWaitEvent; // Subscribe Event handle int nStiNumber = 0; // 0 based index into pStiInfo DWORD dwStiTotal = 0; // total number of Sti devices found WCHAR szInternalName[STI_MAX_INTERNAL_NAME_LENGTH]; // user selected Sti device name WCHAR szFriendlyName[STI_MAX_INTERNAL_NAME_LENGTH]; // user selected Sti friendly name /***************************************************************************** define ACQUIRE to load device specific command handler for stub functions defined in STIDDK.CPP *****************************************************************************/ #ifdef ACQUIRE // // device specific image acquire code // #include "acquire.cpp" #else // // only exercise Sti services // #include "stisvc.cpp" #endif /***************************************************************************** void IStillImageMenu(DWORD dwState) Enable or Disable the menus for the IStillDevice interface. Parameters: MF_ENABLED or MF_GRAYED Return: none *****************************************************************************/ void IStillImageMenu(DWORD dwState) { EnableMenuItem(hMenu, IDM_IMAGE_RELEASE, dwState); EnableMenuItem(hMenu, IDM_GET_DEVLIST, dwState); EnableMenuItem(hMenu, IDM_CREATE_DEV, dwState); EnableMenuItem(hMenu, IDM_REGISTER_LAUNCH, dwState); EnableMenuItem(hMenu, IDM_UNREGISTER_LAUNCH, dwState); EnableMenuItem(hMenu, IDM_WRITE_ERRORLOG, dwState); } /***************************************************************************** void IStillNameMenu(DWORD dwState) Enable or Disable the menus for the IStillImage interface that only require a device name. Parameters: MF_ENABLED or MF_GRAYED Return: none *****************************************************************************/ void IStillNameMenu(DWORD dwState) { EnableMenuItem(hMenu, IDM_GET_DEVINFO, dwState); EnableMenuItem(hMenu, IDM_GET_DEVVAL, dwState); EnableMenuItem(hMenu, IDM_SET_DEVVAL, dwState); EnableMenuItem(hMenu, IDM_GET_LAUNCHINFO, dwState); EnableMenuItem(hMenu, IDM_ENABLE_HWNOTIF, dwState); EnableMenuItem(hMenu, IDM_GET_HWNOTIF, dwState); EnableMenuItem(hMenu, IDM_REFRESH_DEVBUS, dwState); EnableMenuItem(hMenu, IDM_LAUNCH_APP_FOR_DEV, dwState); EnableMenuItem(hMenu, IDM_SETUP_DEVPARAMS, dwState); } /***************************************************************************** void IStillDeviceMenu(DWORD dwState) Enable or Disable the menus for the IStillDevice interface. Parameters: MF_ENABLED or MF_GRAYED Return: none *****************************************************************************/ void IStillDeviceMenu(DWORD dwState) { EnableMenuItem(hMenu, IDM_GET_CAPS, dwState); EnableMenuItem(hMenu, IDM_GET_STATUS_A, dwState); EnableMenuItem(hMenu, IDM_GET_STATUS_B, dwState); EnableMenuItem(hMenu, IDM_GET_STATUS_C, dwState); EnableMenuItem(hMenu, IDM_DEVICERESET, dwState); EnableMenuItem(hMenu, IDM_DIAGNOSTIC, dwState); EnableMenuItem(hMenu, IDM_ESCAPE_A, dwState); EnableMenuItem(hMenu, IDM_ESCAPE_B, dwState); EnableMenuItem(hMenu, IDM_GET_LASTERRINFO, dwState); EnableMenuItem(hMenu, IDM_LOCKDEV, dwState); EnableMenuItem(hMenu, IDM_UNLOCKDEV, dwState); EnableMenuItem(hMenu, IDM_RAWREADDATA_A, dwState); EnableMenuItem(hMenu, IDM_RAWREADDATA_B, dwState); EnableMenuItem(hMenu, IDM_RAWWRITEDATA_A, dwState); EnableMenuItem(hMenu, IDM_RAWWRITEDATA_B, dwState); EnableMenuItem(hMenu, IDM_RAWREADCOMMAND_A, dwState); EnableMenuItem(hMenu, IDM_RAWREADCOMMAND_B, dwState); EnableMenuItem(hMenu, IDM_RAWWRITECOMMAND_A, dwState); EnableMenuItem(hMenu, IDM_RAWWRITECOMMAND_B, dwState); EnableMenuItem(hMenu, IDM_SUBSCRIBE, dwState); EnableMenuItem(hMenu, IDM_UNSUBSCRIBE, dwState); EnableMenuItem(hMenu, IDM_DEVICE_RELEASE, dwState); } /***************************************************************************** void IStillScanMenu(DWORD dwState) Enable or Disable the menus for scanning. Parameters: MF_ENABLED or MF_GRAYED Return: none *****************************************************************************/ void IStillScanMenu(DWORD dwState) { EnableMenuItem(hMenu, IDM_LAMPON, dwState); EnableMenuItem(hMenu, IDM_LAMPOFF, dwState); EnableMenuItem(hMenu, IDM_SCAN, dwState); } /***************************************************************************** int NextStiDevice() Select next valid Sti device Parameters: none Return: number of next sti device (0 == first) *****************************************************************************/ int NextStiDevice() { // // select next device from static list (go to first at end of list) // nStiNumber++; if ( nStiNumber >= (int) dwStiTotal ) { // // point to head of list // nStiNumber = 0; } // // select next device from device log (go to first at end of list) // if ( pdevPtr->pNext ) { pdevPtr = pdevPtr->pNext; } else { // // point to head of list // pdevPtr = pdevRoot; } return nStiNumber; } /***************************************************************************** HRESULT StiCreateInstance(BOOL *) Opens Sti subsystem Parameters: Pointer to receive PASS/FAIL status Return: HRESULT of last Sti call *****************************************************************************/ HRESULT StiCreateInstance(BOOL *bPass) { HRESULT hres = STI_OK; BOOL bReturn; // // close any open devices before enumeration // StiClose(&bReturn); // // The StiCreateInstance interface locates the primary still image interface. // Use this call to optain the pointer to the IStillImage interface. // hres = StiCreateInstance( GetModuleHandle(NULL), // instance handle of this application STI_VERSION, // Sti version &pSti, // pointer to IStillImage interface NULL // pointer to controlling unknown of OLE aggregation ); if ( ! SUCCEEDED(hres) ) { StiDisplayError(hres,"StiCreateInstance",TRUE); *bPass = FALSE; return (STIERR_GENERIC); } *bPass = TRUE; DisplayOutput(" The Sti subsystem is opened"); DisplayOutput(""); // // Enable the menu items for IStillImage interface calls available // IStillImageMenu(MF_ENABLED); EnableMenuItem(hMenu, IDM_CREATE_INSTANCE, MF_GRAYED); return (hres); } /***************************************************************************** HRESULT StiClose(BOOL *) Close any open devices and Sti subsystem Parameters: pointer to receive Pass/Fail result Return: HRESULT of last Sti call *****************************************************************************/ HRESULT StiClose(BOOL *bPass) { HRESULT hres = STI_OK; *bPass = TRUE; // stop subscribing nUnSubscribe = 0; // close any open devices and then close Sti subsystem hres = StiDeviceRelease(bPass); hres = StiImageRelease(bPass); // // clear the internal device name and the friendly user name // ZeroMemory(szInternalName,STI_MAX_INTERNAL_NAME_LENGTH); ZeroMemory(szFriendlyName,STI_MAX_INTERNAL_NAME_LENGTH); return (hres); } /***************************************************************************** HRESULT StiDeviceRelease(BOOL *) Close the Sti subsystem Parameters: pointer to receive Pass/Fail result Return: HRESULT of last failed Sti call *****************************************************************************/ HRESULT StiDeviceRelease(BOOL *bPass) { HRESULT hres = STI_OK, hError = STI_OK; *bPass = TRUE; // // Need to UnSuscribe if the semaphore is set. // if ( nUnSubscribeSemaphore ) { // // clear the semaphores // nUnSubscribe = nUnSubscribeSemaphore = 0; // UnSubscribe is called when an application no longer wants to receive // events from a device. // hres = pStiDevice->UnSubscribe(); if ( ! SUCCEEDED(hres) ) { StiDisplayError(hres,"UnSubscribe",TRUE); hError = hres; *bPass = FALSE; } // // we're done with the event // CloseHandle(hWaitEvent); DisplayOutput(" StiDeviceRelease has UnSubscribed"); } // // The STI_DEVICE_INFORMATION array returned by GetDeviceList needs to // be freed with LocalFree(). Also, resetting internal Sti device counter. // if ( pStiInfo ) LocalFree(pStiInfo); pStiInfo = pStiInfoPtr = NULL; // // close device if any are open // if ( pStiDevice ) { // // Close an open device. // hres = pStiDevice->Release(); if ( ! SUCCEEDED(hres) ) { StiDisplayError(hres,"Release (Device)",TRUE); hError = hres; *bPass = FALSE; } else DisplayOutput(" Device Released"); DisplayOutput(""); // // clear the Sti device pointer // pStiDevice = NULL; // // disable IStiDevice menu items // IStillDeviceMenu(MF_GRAYED); IStillNameMenu(MF_GRAYED); IStillScanMenu(MF_GRAYED); EnableMenuItem(hMenu, IDM_IMAGE_RELEASE, MF_ENABLED); CheckMenuItem(hMenu, IDM_ENABLE_HWNOTIF, MF_UNCHECKED); } return (hError); } /***************************************************************************** HRESULT StiImageRelease(BOOL *) Close the Sti subsystem Parameters: pointer to receive Pass/Fail result Return: HRESULT of last Sti call *****************************************************************************/ HRESULT StiImageRelease(BOOL *bPass) { HRESULT hres = STI_OK; *bPass = TRUE; // // if Sti subsystem is open, close it // if ( pSti ) { // // Close the Still Imaging subsystem. // hres = pSti->Release(); if ( ! SUCCEEDED(hres) ) { StiDisplayError(hres,"Release (Image)",TRUE); *bPass = FALSE; } else DisplayOutput(" Imaging subsystem Released"); DisplayOutput(""); // // clear the Sti subsystem pointer // pSti = NULL; // // Disable the menu items for IStillImage interface calls // IStillNameMenu(MF_GRAYED); IStillImageMenu(MF_GRAYED); EnableMenuItem(hMenu, IDM_CREATE_INSTANCE, MF_ENABLED); } return (hres); } /***************************************************************************** HRESULT StiEnum(BOOL *) Opens Sti subsystem and enumerates any still image devices found Parameters: Pointer to receive PASS/FAIL status Return: HRESULT of last Sti call *****************************************************************************/ HRESULT StiEnum(BOOL *bPass) { HRESULT hres = STI_OK; DWORD dwCounter; DWORD dwStiCount = 0; PSTI_DEVICE_INFORMATION pI = NULL; BOOL bReturn; PCSTR pszStringTablePtr = NULL; // // check that Sti subsystem is loaded // if ( ! pSti ) { *bPass = FALSE; StiDisplayError(STIERR_GENERIC,"StiNotLoaded",TRUE); return (STIERR_GENERIC); } // // Enumerate devices // dwStiTotal = 0; pStiInfo = NULL; // // The GetDeviceList interface is used to get a list of the installed still // image devices. Use this call to obtain a STI_DEVICE_INFORMATION array // filled with info on all currently installed Sti devices. // * NOTE: the STI subsystem allocates memory for the Sti device information // buffer, but the caller needs to free this memory with LocalFree(). // hres = pSti->GetDeviceList( NULL, // Type (reserved, use NULL) NULL, // Flags (reserved, use NULL) &dwStiTotal, // address of variable to return number of devices found &pStiInfo // Sti device info buffer ); if ( ! SUCCEEDED(hres) || ! pStiInfo ) { StiDisplayError(hres,"GetDeviceList",TRUE); StiClose(&bReturn); *bPass = FALSE; return (STIERR_GENERIC); } *bPass = TRUE; // // Display Sti info on each device found // for ( dwCounter = 0,pStiInfoPtr = (PSTI_DEVICE_INFORMATION) pStiInfo; dwCounter < dwStiTotal; dwCounter++, pStiInfoPtr++ ) { DisplayOutput(" Device number %2d",dwCounter + 1); pszStringTablePtr = StrFromTable(GET_STIDEVICE_TYPE(pStiInfoPtr->DeviceType), StStiDeviceType); DisplayOutput(" Device type %xh %s", GET_STIDEVICE_TYPE(pStiInfoPtr->DeviceType), pszStringTablePtr); DisplayOutput(" Device subtype %xh", GET_STIDEVICE_SUBTYPE(pStiInfoPtr->DeviceType)); DisplayOutput(" Internal name \"%S\"", pStiInfoPtr->szDeviceInternalName); DisplayOutput(" Device capabilities %xh", pStiInfoPtr->DeviceCapabilities); DisplayOutput(" Hardware configuration %xh", pStiInfoPtr->dwHardwareConfiguration); DisplayOutput(" Vendor description \"%S\"", pStiInfoPtr->pszVendorDescription); DisplayOutput(" Device description \"%S\"", pStiInfoPtr->pszDeviceDescription); DisplayOutput(" Port Name \"%S\"", pStiInfoPtr->pszPortName); DisplayOutput(" Prop provider \"%S\"", pStiInfoPtr->pszPropProvider); DisplayOutput(" Local name \"%S\"", pStiInfoPtr->pszLocalName); DisplayOutput(""); } // // point to most recently selected device again // pStiInfoPtr = (PSTI_DEVICE_INFORMATION) pStiInfo + nStiNumber; DisplayOutput(" GetDeviceList found %d device%s",dwStiTotal, dwStiTotal == 1 ? "" : "s"); if ( dwStiTotal != dwCounter ) { DisplayOutput("* Get DeviceList actually returned %d devices",dwCounter); dwStiTotal = dwCounter; nError++; pdevPtr-nError++; } DisplayOutput(""); return (hres); } /***************************************************************************** HRESULT StiEnumPrivate(PVOID *, DWORD *) Call GetDeviceList and return pointer to struct Parameters: Pointer to private DeviceList Pointer to number of devices found counter Return: HRESULT of last Sti call *****************************************************************************/ HRESULT StiEnumPrivate(PVOID *pPtr, DWORD *dwHowMany) { HRESULT hres = STI_OK; BOOL bReturn; // // check that Sti subsystem is loaded // if ( ! pSti ) return (STIERR_GENERIC); // // The GetDeviceList interface is used to get a list of the installed still // image devices. Use this call to obtain a STI_DEVICE_INFORMATION array // filled with info on all currently installed Sti devices. // * NOTE: the STI subsystem allocates memory for the Sti device information // buffer, but the caller needs to free this memory with LocalFree(). // hres = pSti->GetDeviceList( NULL, // Type (reserved, use NULL) NULL, // Flags (reserved, use NULL) dwHowMany, // address of variable to return number of devices found pPtr // Sti device info buffer ); if ( ! SUCCEEDED(hres) || ! *pPtr ) { StiDisplayError(hres,"GetDeviceList",TRUE); StiClose(&bReturn); return (STIERR_GENERIC); } return (hres); } /***************************************************************************** INT StiSelect(HWND hWnd,int nContext,BOOL *) Select and open a specific Still Image device Parameters: handle to current window context we were called from pointer to receive Pass/Fail Return: 0 on success, -1 on error *****************************************************************************/ INT StiSelect(HWND hWnd,int nContext,BOOL *bPass) { HRESULT hres = STI_OK; BOOL bReturn; // // check that Sti subsystem is loaded // if ( ! pSti ) { *bPass = FALSE; StiDisplayError(STIERR_GENERIC,"StiNotLoaded",TRUE); return (-1); } *bPass = TRUE; // // look for devices if count of available is 0 // if ( dwStiTotal == 0 ) { StiEnum(&bReturn); } // // if still no devices, inform user and leave // if ( dwStiTotal == 0 ) { ZeroMemory(szInternalName,sizeof(szInternalName)); ZeroMemory(szFriendlyName,sizeof(szFriendlyName)); DisplayOutput("* No Sti devices found!"); DisplayOutput(""); *bPass = FALSE; return (-1); } switch ( nContext ) { case EVENT: // // Sti push event or automated test // if ( nStiNumber == -1 ) { // // we could not select the correct device, just return // nStiNumber = 0; return (0); } break; case MANUAL: // // manual device selection // bReturn = fDialog(IDD_SELECT, hWnd, (FARPROC) SelectDevice); // // just return if user pressed CANCEL in dialog // if ( bReturn == FALSE ) { return (0); } break; } // // close any currently active imaging device // if ( pStiDevice ) StiDeviceRelease(&bReturn); // // get pointer to device selected in dialog // pStiInfoPtr = (PSTI_DEVICE_INFORMATION) pStiInfo + nStiNumber; if ( ! *(pStiInfoPtr->szDeviceInternalName) ) { DisplayOutput("* Invalid device name !"); nError++; pdevPtr-nError++; *bPass = FALSE; return (-1); } // // copy the internal device name and the friendly user name // wcscpy(szInternalName,pStiInfoPtr->szDeviceInternalName); wcscpy(szFriendlyName,pStiInfoPtr->pszLocalName); IStillNameMenu(MF_ENABLED); DisplayOutput(" Selected device %d \"%S\"",nStiNumber + 1,szInternalName); DisplayOutput(" Friendly name \"%S\"",szFriendlyName); // // Are we selecting the device or just its name? // if ( ! nNameOnly ) { // // The CreateDevice interface creates an IStiDevice object. // The IStiDevice object provides access to the IStiDevice interface // and device specific Imaging functionality. // hres = pSti->CreateDevice( pStiInfoPtr->szDeviceInternalName, // internal device name STI_DEVICE_CREATE_BOTH, // device creation mode &pStiDevice, // pointer where IStiDevice object is to be stored NULL ); // pointer to controlling unknown of OLE aggregation if ( ! SUCCEEDED(hres) || ! pStiDevice ) { StiDisplayError(hres,"CreateDevice",TRUE); DisplayOutput("* \"%S\" (%S) cannot be tested", pStiInfoPtr->pszLocalName,pStiInfoPtr->szDeviceInternalName); DisplayOutput(""); *bPass = FALSE; return (-1); } // // enable Sti menu items // IStillDeviceMenu(MF_ENABLED); CheckMenuItem(hMenu, IDM_ENABLE_HWNOTIF, MF_CHECKED); EnableMenuItem(hMenu, IDM_IMAGE_RELEASE, MF_GRAYED); // // Do we have scan commands for this device? // if ( nICanScan = IsScanDevice(pStiInfoPtr) ) { IStillScanMenu(MF_ENABLED); } DisplayOutput(" \"%S\" is ready for Testing",szFriendlyName); } DisplayOutput(""); return (0); } /****************************************************************************** BOOL FAR PASCAL SelectDevice(HWND,UINT,WPARAM,LPARAM) Put up a dialog for user to select a Still Image device Parameters: The usual dialog box parameters. Return: Result of the call. ******************************************************************************/ BOOL FAR PASCAL SelectDevice(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam) { PSTI_DEVICE_INFORMATION pTmpInfoPtr; DWORD dwCounter; int iIndex; static int iLastPick = 0; switch ( msg ) { case WM_INITDIALOG: // // fill dialog with Sti Device Internal Names // for ( dwCounter = 0, pTmpInfoPtr = (PSTI_DEVICE_INFORMATION) pStiInfo; dwCounter < dwStiTotal;dwCounter++, pTmpInfoPtr++ ) { // // convert UNICODE string to ANSI // wsprintf(pszStr1,"%ls",pTmpInfoPtr->pszLocalName); iIndex = SendDlgItemMessage(hDlg,IDC_SELECT_DEVICE, CB_ADDSTRING,0,(LPARAM) (LPCTSTR) pszStr1); } SendDlgItemMessage(hDlg,IDC_SELECT_DEVICE,CB_SETCURSEL,iLastPick,0); return (TRUE); case WM_COMMAND: switch ( wParam ) { case IDOK: nStiNumber = SendDlgItemMessage(hDlg,IDC_SELECT_DEVICE, CB_GETCURSEL,0,0); nNameOnly = SendDlgItemMessage(hDlg,IDC_SELECT_NAME, BM_GETCHECK,0,0); // // ensure device number not greater than total // (NOTE: dwStiTotal is 1's base, while nStiNumber is 0 based) // if ( nStiNumber >= (int) dwStiTotal ) nStiNumber = (int) dwStiTotal - 1; if ( nStiNumber < 0 ) nStiNumber = 0; iLastPick = nStiNumber; EndDialog(hDlg, TRUE); return (TRUE); case IDCANCEL: EndDialog(hDlg, FALSE); return (TRUE); } } return (FALSE); } /***************************************************************************** void StiDisplayError(HRESULT,char *,BOOL) Display verbose error information Parameters: HRESULT from failed call TRUE = record error as compliance failure Return: none *****************************************************************************/ void StiDisplayError(HRESULT hres,char *szCall,BOOL bFail) { PERRECORD pR = pdevPtr->pRecord; BOOL bReturn; StiGetLastErrorInfo(&bReturn); LastError(TRUE); // // record the error // pR += nTestID; pR->nCount++; // BUG BUG can't copy the string correctly to UNICODE string // sprintf(pszStr4,"%s",StrFromTable(hres,StStiError)); // swprintf(pR->szErrorString,L"%s",pszStr4); // // compliance test failure error? // if ( bFail ) { nError++; pdevPtr-nError++; pR->bFatal = TRUE; DisplayOutput("* Sti Compliance test error"); tlLog(hNTLog,TL_LOG,"* Sti Compliance test error"); } else { DisplayOutput("* Allowed error"); } DisplayOutput("* %s returned %xh (%d)",szCall,hres,hres); if ( bFail ) tlLog(hNTLog,TL_LOG,"* %s returned %xh (%d)",szCall,hres,hres); DisplayOutput(" \"%s\"",StrFromTable(hres,StStiError)); if ( bFail ) tlLog(hNTLog,TL_LOG," \"%s\"",StrFromTable(hres,StStiError)); return; } /****************************************************************************** int InitPrivateList(PDEVLOG,int *) Initialize private test structures Parameters: pointer to Devicelog to initialize pointer to test suite Return: total number of devices found (-1 on failure) ******************************************************************************/ int InitPrivateList(PDEVLOG *pDev,int *pSuiteList) { DWORD dwStiDevCount = 0; PVOID pList = NULL; PSTI_DEVICE_INFORMATION pInfoPrivatePtr = NULL; // pointer to device in pStiBuffer PDEVLOG pPtr = NULL; PERRECORD precPtr = NULL; int i,k,nNumberTests,nTotalDevices; BOOL bReturn; // // get the current number of devices and their names // StiCreateInstance(&bReturn); StiEnumPrivate(&pList,&dwStiDevCount); if ( ! pList ) { DisplayOutput("* No Sti device attached !"); } else { pInfoPrivatePtr = (PSTI_DEVICE_INFORMATION) pList; } // // create at least one list entry (even if no devices are found) // if ( ! dwStiDevCount ) { dwStiDevCount = 1; nTotalDevices = 0; } else nTotalDevices = (int) dwStiDevCount; // // create a device log for each device // pPtr = (PDEVLOG) calloc(dwStiDevCount,sizeof(DEVLOG)); if ( pPtr == NULL ) { FatalError("Could not initialize private structures"); return (-1); } *pDev = pPtr; // // count the number of tests in suite // for ( nNumberTests = 0;pSuiteList[nNumberTests] != -1;nNumberTests++ ) ; // // initialize linked list pointers and error records for each device log // for ( i = 0;i < (int) dwStiDevCount;i++,pPtr++,pInfoPrivatePtr++ ) { if ( i ) { (pPtr - 1)->pNext = pPtr; pPtr->pPrev = pPtr - 1; } if ( nTotalDevices ) { wcscpy(pPtr->szInternalName,pInfoPrivatePtr->szDeviceInternalName); wcscpy(pPtr->szLocalName,pInfoPrivatePtr->pszLocalName); } else { wcscpy(pPtr->szInternalName,L"* Invalid !"); wcscpy(pPtr->szLocalName,L"* No Sti device attached !"); } // // create one error log for each test (nNumberTests) // pPtr->pRecord = (PERRECORD) calloc(nNumberTests,sizeof(ERRECORD)); if ( pPtr->pRecord == NULL ) { FatalError("Could not initialize private structures"); return (-1); } // // initialize linked list pointers and error records for each record // for ( k = 0,precPtr = pPtr->pRecord;k < nNumberTests;k++,precPtr++ ) { precPtr->nIndex = k; precPtr->nTest = pSuite[k]; if ( k ) { (precPtr - 1)->pNext = precPtr; precPtr->pPrev = precPtr - 1; } } } // // free the device list // LocalFree(pList); StiClose(&bReturn); return (nTotalDevices); } /****************************************************************************** int ClosePrivateList(PDEVLOG) Remove private test structures Parameters: pointer to Devicelog to close Return: 0 on success -1 on failure ******************************************************************************/ int ClosePrivateList(PDEVLOG *pDev) { PDEVLOG pPtr = (PDEVLOG) *pDev; if ( pDev == NULL ) return (0); // // free each device log's error record // for ( ;pPtr->pNext;pPtr++ ) { if ( pPtr->pRecord ) free(pPtr->pRecord); } // // free the device log // if ( *pDev ) { free(*pDev); *pDev = NULL; } return (0); } /***************************************************************************** HRESULT StiGetDeviceValue(LPWSTR,LPWSTR,DWORD *,BOOL *) Get driver information Parameters: szDevname - internal device name szKeyname - key to access dwType - pointer to data type pointer to receive Pass/Fail result Return: HRESULT of last Sti call *****************************************************************************/ HRESULT StiGetDeviceValue(LPWSTR szDevname,LPWSTR szKeyname,LPBYTE pData, DWORD *dwType,DWORD cbData,BOOL *bPass) { HRESULT hres = STI_OK; // // WINNT.H - Predefined Value Types // STRINGTABLE StRegType[] = { REG_NONE, "REG_NONE",0, REG_SZ, "REG_SZ",0, REG_BINARY, "REG_BINARY",0, REG_DWORD, "REG_DWORD",0, 0, "Unknown Reg Type",-1 }; // // check that Sti subsystem is loaded // if ( ! pSti ) { *bPass = FALSE; StiDisplayError(STIERR_GENERIC,"StiNotLoaded",TRUE); return (STIERR_GENERIC); } *bPass = TRUE; ZeroMemory(pData,cbData); DisplayOutput(" GetDeviceValue for device \"%S\"",szDevname); DisplayOutput(" Key requested: \"%S\"",szKeyname); // // The GetDeviceValue function is used to retrieve data associated with a // still image device. Essentially, data is associated with a device // through a key/data type/value triplet. The only reserved standard // ValueNames, as defined in STI.H, are the following: // // ICMProfiles - string containing a comma-sperated list of ICM profiles // TwainDS - TWAIN data source display name // ISISDriverName - ISIS driver name // hres = pSti->GetDeviceValue( szDevname, // internal device name szKeyname, // value tag string dwType, // pointer where data type will be stored pData, // pointer where value will be stored &cbData // size of value pointer storage ); if ( !SUCCEEDED(hres) ) { // // The only required registry item is STI_DEVICE_VALUE_ICM_PROFILE // if ( hres == STIERR_OBJECTNOTFOUND ) { if ( ! wcscmp(STI_DEVICE_VALUE_ICM_PROFILE,szKeyname) ) { // // Only STI_DEVICE_VALUE_ICM_PROFILE is a required key // Therefore, only this one Failure is a COMPLIANCE test failure // *bPass = FALSE; StiDisplayError(hres,"GetDeviceValue",TRUE); } else { StiDisplayError(hres,"GetDeviceValue",FALSE); } } else { *bPass = FALSE; StiDisplayError(hres,"GetDeviceValue",TRUE); } } else { DisplayOutput(" Reg Type %d %s",* dwType, StrFromTable(*dwType,StRegType)); DisplayOutput(" The following %d bytes were read from the Registry:", cbData); DisplayOutput(" \"%s\"",pData); } DisplayOutput(""); return (hres); } /***************************************************************************** HRESULT StiSetDeviceValue(LPWSTR,LPWSTR,LPWSTR,DWORD,BOOL *) Set driver information Parameters: szDevname - internal device name szKeyname - key to access pData - value to write dwType - data type pointer to receive Pass/Fail result Return: HRESULT of last Sti call *****************************************************************************/ HRESULT StiSetDeviceValue(LPWSTR szDevname,LPWSTR szKeyname,LPBYTE pData, DWORD dwType,DWORD cbData,BOOL *bPass) { HRESULT hres = STI_OK; // // WINNT.H - Predefined Value Types // STRINGTABLE StRegType[] = { REG_NONE, "REG_NONE",0, REG_SZ, "REG_SZ",0, REG_BINARY, "REG_BINARY",0, REG_DWORD, "REG_DWORD",0, 0, "Unknown Reg Type",-1 }; // // check that Sti subsystem is loaded // if ( ! pSti ) { *bPass = FALSE; StiDisplayError(STIERR_GENERIC,"StiNotLoaded",TRUE); return (STIERR_GENERIC); } *bPass = TRUE; DisplayOutput(" SetDeviceValue for device \"%S\"",szDevname); DisplayOutput(" Key \"%S",szKeyname); // // The SetDeviceValue function is used to associate any additional data // with a still image device. It is used internally to store the values of // strings that are required to communicate information to imaging APIs // during use of push model behavoir. However, this function can be used // to associate any ancillary data with a device. The only reserved // ValueNames, as defined in STI.H, are the following: // // ICMProfiles - string containing a comma-sperated list of ICM profiles // TwainDS - TWAIN data source display name // ISISDriverName - ISIS driver name // hres = pSti->SetDeviceValue( szDevname, // internal device name szKeyname, // value tag string dwType, // data type sent pData, // pointer to data to send cbData // byte size of data ); if ( !SUCCEEDED(hres) ) { // // SetDeviceValue is not required under NT // StiDisplayError(hres,"SetDeviceValue",FALSE); } else { //pszStr1 = StrFromTable(dwType,StRegType); DisplayOutput(" Reg Type %d %s",dwType,StrFromTable(dwType,StRegType)); DisplayOutput(" The following %d bytes were written to the Registry:", cbData); DisplayOutput(" \"%s\"",(char *) pData); } DisplayOutput(""); return (hres); } /***************************************************************************** HRESULT StiRegister(HWND,int,BOOL *) Register or Unregister the application to receive Sti Launch events. Parameters: Handle to the window to display image in. Instance for access to string table int nOnOff == ON to register, OFF to unregister pointer to receive Pass/Fail result Return: HRESULT of last failed Sti call *****************************************************************************/ HRESULT StiRegister(HWND hWnd,HINSTANCE hInstance,int nOnOff,BOOL *bPass) { HRESULT hres = STI_OK, hError = STI_OK; CHAR szModulePath[MAX_PATH+1]; WCHAR szModulePathW[MAX_PATH+1], szAppName[MEDSTRING]; DWORD cch; // // check that Sti subsystem is loaded // if ( ! pSti ) { *bPass = FALSE; StiDisplayError(STIERR_GENERIC,"StiNotLoaded",TRUE); return (STIERR_GENERIC); } *bPass = TRUE; // // Retrieve name of this application from STRING table // and convert to UNICODE. // LoadString(hInstance,IDS_APPNAME,pszStr1,MEDSTRING); cch = MultiByteToWideChar(CP_ACP, 0, pszStr1, -1, szAppName,MEDSTRING); if ( ! cch ) { LastError(TRUE); *bPass = FALSE; return (STIERR_GENERIC); } // // Register/deregister app // if ( nOnOff == ON ) { // // Register our application. // Get full path to executable and convert to UNICODE. // cch = GetModuleFileName(NULL,szModulePath,sizeof(szModulePath)); if ( ! cch ) { LastError(TRUE); *bPass = FALSE; return (STIERR_GENERIC); } cch = MultiByteToWideChar(CP_ACP, 0, szModulePath, -1, szModulePathW, sizeof(szModulePathW)); // // The RegisterLaunchApplication function should be called by // applications that would like to be launched in response to an // Sti push event. This function can be called more than once, // and should be called each time the application rus in case // the user relocates the application. // hres = pSti->RegisterLaunchApplication( szAppName, // short name of app szModulePathW // full path to executable ); if ( ! SUCCEEDED(hres) ) { StiDisplayError(hres,"RegisterLaunchApplication",TRUE); *bPass = FALSE; hError = hres; } else { DisplayOutput(" %s registered for Sti Launch Application",pszStr1); } } else { // // Unregister our application // hres = pSti->UnregisterLaunchApplication( szAppName // short name of app ); if ( ! SUCCEEDED(hres) ) { StiDisplayError(hres,"UnregisterLaunchApplication",TRUE); hError = hres; } else { DisplayOutput(" %s Unregistered from Sti Launch",pszStr1); } } DisplayOutput(""); return (hError); } /***************************************************************************** HRESULT StiEvent(HWND hWnd) Handle a push model event. This function is called when the test app has been a) registered as a push event handler b) launched by a push event Parameters: Handle to the window to display image in. Return: HRESULT of last Sti call *****************************************************************************/ HRESULT StiEvent(HWND hWnd) { HRESULT hres = STI_OK; WCHAR szDeviceName[STI_MAX_INTERNAL_NAME_LENGTH + 1], szEventName[LONGSTRING]; DWORD cch, dwEventCode = 0, cbData = LONGSTRING; int nCounter; BOOL bBadFlag = FALSE; // // check that Sti subsystem is loaded // if ( ! pSti ) { StiDisplayError(STIERR_GENERIC,"StiNotLoaded",TRUE); return (STIERR_GENERIC); } ZeroMemory(szDeviceName,STI_MAX_INTERNAL_NAME_LENGTH + 1); ZeroMemory(szEventName,LONGSTRING); // // For an application started through push model launch, // GetSTILaunchInformation returns the associated information. This // information is used to determine which device to use and what // event caused the application to be launched. // hres = pSti->GetSTILaunchInformation( szDeviceName, // pointer to where device name will be stored &dwEventCode, // reserved szEventName // pointer to where GUID will be stored ); if ( !SUCCEEDED(hres) ) { StiDisplayError(hres,"GetSTILaunchInformation",TRUE); return (STIERR_GENERIC); } ZeroMemory(pszStr2,LONGSTRING); ZeroMemory(pszStr4,LONGSTRING); cch = WideCharToMultiByte(CP_ACP,0, szDeviceName,-1, pszStr1,STI_MAX_INTERNAL_NAME_LENGTH + 1, pszStr2,&bBadFlag); if ( ! cch ) LastError(TRUE); if ( bBadFlag ) { DisplayOutput("* UNICODE translation error"); bBadFlag = FALSE; } DisplayOutput(" %s launched via Sti push",pszStr1); DisplayOutput(" Event code %d (%xh)",dwEventCode,dwEventCode); cch = WideCharToMultiByte(CP_ACP,0, szEventName,-1, pszStr1,STI_MAX_INTERNAL_NAME_LENGTH + 1, pszStr2,&bBadFlag); if ( ! cch ) LastError(TRUE); if ( bBadFlag ) { DisplayOutput("* UNICODE translation error"); bBadFlag = FALSE; } DisplayOutput(" Event name %s",pszStr1); // // find the Sti device that sent the event // set nStiNumber to -1 (no device), then set to event device when found // for ( nStiNumber = -1,nCounter = 0, pStiInfoPtr = (PSTI_DEVICE_INFORMATION) pStiInfo; nCounter < (int) dwStiTotal;pStiInfoPtr++,nCounter++ ) { if ( ! wcscmp(szDeviceName,pStiInfoPtr->szDeviceInternalName) ) nStiNumber = nCounter; } DisplayOutput(""); return (hres); } /***************************************************************************** HRESULT StiGetDeviceInfo(LPWSTR szDevName,BOOL *pPass) Display information about the selected device Parameters: WCHAR string of the selected device pointer to receive Pass/Fail result Return: HRESULT of last Sti call *****************************************************************************/ HRESULT StiGetDeviceInfo(LPWSTR szDevname,BOOL *bPass) { HRESULT hres = STI_OK; PVOID pInfo = NULL; PSTI_DEVICE_INFORMATION pInfoPtr = NULL; // // check that Sti subsystem is loaded // if ( ! pSti ) { *bPass = FALSE; StiDisplayError(STIERR_GENERIC,"StiNotLoaded",TRUE); return (STIERR_GENERIC); } *bPass = TRUE; // // Given a device name, the GetDeviceInfo interface makes available a // structure that describes the various attributes of the device. // * NOTE: the STI subsystem allocates memory for the Sti device information // buffer, but the caller needs to free this memory with LocalFree(). // hres = pSti->GetDeviceInfo( szDevname, // pointer to the internal device name &pInfo); // Sti device info buffer if ( ! SUCCEEDED(hres) ) { StiDisplayError(hres,"GetDeviceInfo",TRUE); *bPass = FALSE; } pInfoPtr = (PSTI_DEVICE_INFORMATION) pInfo; DisplayOutput(" GetDeviceInfo for \"%S\"",szDevname); //pszStr1 = StrFromTable(GET_STIDEVICE_TYPE(pInfoPtr->DeviceType),StStiDeviceType); DisplayOutput(" Device type %xh %s", GET_STIDEVICE_TYPE(pInfoPtr->DeviceType), StrFromTable(GET_STIDEVICE_TYPE(pInfoPtr->DeviceType),StStiDeviceType)); DisplayOutput(" Device subtype %xh", GET_STIDEVICE_SUBTYPE(pInfoPtr->DeviceType)); DisplayOutput(" Internal name \"%S\"", pInfoPtr->szDeviceInternalName); DisplayOutput(" Device capabilities %xh", pInfoPtr->DeviceCapabilities); DisplayOutput(" Hardware configuration %xh", pInfoPtr->dwHardwareConfiguration); DisplayOutput(" Vendor description \"%S\"", pInfoPtr->pszVendorDescription); DisplayOutput(" Device description \"%S\"", pInfoPtr->pszDeviceDescription); DisplayOutput(" Port Name \"%S\"", pInfoPtr->pszPortName); DisplayOutput(" Prop provider \"%S\"", pInfoPtr->pszPropProvider); DisplayOutput(" Local name \"%S\"", pInfoPtr->pszLocalName); DisplayOutput(""); // free the STI_DEVICE_INFORMATION buffer if ( pInfo ) LocalFree(pInfo); return (hres); } /***************************************************************************** HRESULT StiEnableHwNotification(LPWSTR,int *,BOOL *) Determine the current notification handling state and if requested, change it. Parameters: internal device name pointer to state request (current state returned in pointer) ON = turn on polling OFF = turn off polling PEEK = return current polling state pointer to receive Pass/Fail result Return: HRESULT of last failed Sti call *****************************************************************************/ HRESULT StiEnableHwNotification(LPWSTR szDevnameW,int *nState,BOOL *bPass) { HRESULT hres = STI_OK, hError = STI_OK; BOOL bState = OFF; // // check that Sti subsystem is loaded // if ( ! pSti ) { *bPass = FALSE; StiDisplayError(STIERR_GENERIC,"StiNotLoaded",TRUE); return (STIERR_GENERIC); } *bPass = TRUE; // // GetHwNotificationState gets the current state of notification handling. // The state parameter returns TRUE if the notification is enabled. // hres = pSti->GetHwNotificationState( szDevnameW, // internal device name &bState // pointer where state will be stored ); if ( ! SUCCEEDED(hres) ) { StiDisplayError(hres,"GetHwNotificationState",TRUE); *bPass = FALSE; hError = hres; } else { DisplayOutput(" Hardware Notification state is %s", bState ? "TRUE (ON)" : "FALSE (OFF)"); } if ( *nState != PEEK ) { // // EnableHwNotifications is used to turn event notification on and off. // For polled devices, this function will turn polling on and off. // hres = pSti->EnableHwNotifications( szDevnameW, // internal device name *nState // new state to be set ); if ( ! SUCCEEDED(hres) ) { StiDisplayError(hres,"GetHwNotificationState",TRUE); *bPass = FALSE; return (hres); } // // Ensure the state was changed // hres = pSti->GetHwNotificationState( szDevnameW, // internal device name &bState // pointer where state will be stored ); if ( ! SUCCEEDED(hres) ) { StiDisplayError(hres,"GetHwNotificationState",TRUE); *bPass = FALSE; hError = hres; } else { DisplayOutput(" Hw state has been set to %s", bState ? "TRUE (ON)" : "FALSE (OFF)"); } if ( bState ) { if ( GetMenuState(hMenu, IDM_ENABLE_HWNOTIF, NULL) == MF_UNCHECKED ) CheckMenuItem(hMenu, IDM_ENABLE_HWNOTIF, MF_CHECKED); } else { if ( GetMenuState(hMenu, IDM_ENABLE_HWNOTIF, NULL) == MF_CHECKED ) CheckMenuItem(hMenu, IDM_ENABLE_HWNOTIF, MF_UNCHECKED); } } DisplayOutput(""); return (hError); } /***************************************************************************** HRESULT StiRefresh(LPWSTR,BOOL *) Refresh the bus for non-PNP devices Parameters: internal device name pointer to receive Pass/Fail result Return: HRESULT of last failed Sti call *****************************************************************************/ HRESULT StiRefresh(LPWSTR szDevnameW,BOOL *bPass) { HRESULT hres = STI_OK, hError = STI_OK; BOOL bState = OFF; /**/ // // check that Sti subsystem is loaded // if ( ! pSti ) { *bPass = FALSE; StiDisplayError(STIERR_GENERIC,"StiNotLoaded",TRUE); return (STIERR_GENERIC); } *bPass = TRUE; // // GetHwNotificationState gets the current state of notification handling. // The state parameter returns TRUE if the notification is enabled. // hres = pSti->RefreshDeviceBus( szDevnameW // internal device name ); if ( ! SUCCEEDED(hres) ) { StiDisplayError(hres,"RefreshDeviceBus",TRUE); *bPass = TRUE; hError = hres; } else DisplayOutput(" RefreshDeviceBus called on \"%S\"",szDevnameW); DisplayOutput(""); /**/ return (hError); } /***************************************************************************** HRESULT StiWriteErrLog(DWORD,LPCWSTR,BOOL *) Write a string to the error log Parameters: DWORD severity, which can be STI_TRACE_INFORMATION STI_TRACE_WARNING STI_TRACE_ERROR Wide character message to write to log. pointer to receive Pass/Fail result Return: HRESULT of last Sti call *****************************************************************************/ HRESULT StiWriteErrLog(DWORD dwSeverity,LPCWSTR pszMessage,BOOL *bPass) { HRESULT hres = STI_OK; // // check that Sti subsystem is loaded // if ( ! pSti ) { *bPass = FALSE; StiDisplayError(STIERR_GENERIC,"StiNotLoaded",TRUE); return (STIERR_GENERIC); } *bPass = TRUE; // // WriteToErrorLog can be used to write debugging and diagnostic // information into the Sti log file, located in the Windows directory // STI_TRACE.LOG. The user can control whether informational, warning or // error messages, or any combination of these three are put in the log // file through the Scanners & Cameras control panel. // hres = pSti->WriteToErrorLog( dwSeverity, // severity of error pszMessage // string to write to log ); if ( ! SUCCEEDED(hres) ) { StiDisplayError(hres,"WriteToErrorLog",TRUE); *bPass = FALSE; } else DisplayOutput(" WriteToErrorLog wrote \"%S\"",pszMessage); DisplayOutput(""); return (hres); } /***************************************************************************** HRESULT StiGetStatus(int,BOOL *) Retrieve the user mode status of the driver. Parameters: StatusMask to retrieve status for. Can be a combination of: STI_DEV_ONLINE_STATE STI_DEV_EVENTS_STATE pointer to receive Pass/Fail result Return: HRESULT of last failed Sti call *****************************************************************************/ HRESULT StiGetStatus(int nMask,BOOL *bPass) { HRESULT hres = STI_OK, hError = STI_OK; DWORD dwTimeout = 2000; STI_DEVICE_STATUS StiStatus; // // STI.H - STI_DEVICE_MJ_TYPE // STRINGTABLE StStiStatusMask[] = { STI_DEVSTATUS_ONLINE_STATE, "STI_DEVSTATUS_ONLINE_STATE",0, STI_DEVSTATUS_EVENTS_STATE, "STI_DEVSTATUS_EVENTS_STATE",0, STI_DEVSTATUS_ONLINE_STATE | STI_DEVSTATUS_EVENTS_STATE, "STI_DEVSTATUS_ONLINE_STATE | STI_DEVSTATUS_EVENTS_STATE",0, 0, "Unknown status mask",-1 }; // // check that an Sti device is selected // if ( pStiDevice == NULL ) { *bPass = FALSE; StiDisplayError(STIERR_GENERIC,"NoStiDevice",TRUE); return (STIERR_GENERIC); } *bPass = TRUE; // // Must lock device before GetStatus // // The LockDevice locks the apparatus for a single application to access. // Each LockDevice should be paired with a matching UnLockDevice call. // hres = pStiDevice->LockDevice( dwTimeout // timeout in milliseconds ); if ( ! SUCCEEDED(hres) ) { StiDisplayError(hres,"LockDevice",TRUE); hError = hres; *bPass = FALSE; } else { DisplayOutput(" Device is locked for GetStatus"); // // Get and display status // ZeroMemory(&StiStatus,sizeof(StiStatus)); // // The STI_DEVICE_STATUS dwSize field MUST be set by the caller. // StiStatus.dwSize = sizeof(STI_DEVICE_STATUS); // // The STI_DEVICE_STATUS StatusMask field MUST be set to the desired // status to retrieve. // StiStatus.StatusMask = nMask; DisplayOutput(" %s mask",StrFromTable(nMask,StStiStatusMask)); // // The GetStatus interface gets the status from the user-mode // minidriver. Status returned can indicate online status and/or // device event activity. // hres = pStiDevice->GetStatus( &StiStatus // pointer to a STI_DEVICE_STATUS struct ); if ( ! SUCCEEDED(hres) ) { StiDisplayError(hres,"GetStatus",TRUE); hError = hres; *bPass = FALSE; } else { DisplayOutput(" GetStatus on %S",szFriendlyName); } // // Is the device on? // if ( (StiStatus.dwOnlineState == 0) && (nMask & STI_DEVSTATUS_ONLINE_STATE) ) { DisplayOutput("* Device is TURNED OFF OR OFFLINE!!"); } DisplayOutput(" %xh (%d) StatusMask", StiStatus.StatusMask,StiStatus.StatusMask); DisplayOutput(" %xh (%d) dwOnlineState", StiStatus.dwOnlineState,StiStatus.dwOnlineState); DisplayOutput(" %xh (%d) dwHardwareStatusCode", StiStatus.dwHardwareStatusCode,StiStatus.dwHardwareStatusCode); DisplayOutput(" %xh (%d) dwEventHandlingState", StiStatus.dwEventHandlingState,StiStatus.dwEventHandlingState); DisplayOutput(" %xh (%d) dwPollingInterval", StiStatus.dwPollingInterval,StiStatus.dwPollingInterval); if ( StiStatus.dwSize != sizeof(STI_DEVICE_STATUS) ) { DisplayOutput("* Expected STI_DEVICE_STATUS dwSize %d, got %d", sizeof(STI_DEVICE_STATUS),StiStatus.dwSize); } } // // The UnLockDevice interface unlocks a device that was previously locked. // hres = pStiDevice->UnLockDevice(); if ( ! SUCCEEDED(hres) ) { StiDisplayError(hres,"UnLockDevice",TRUE); hError = hres; *bPass = FALSE; } else DisplayOutput(" Device is unlocked"); DisplayOutput(""); return (hError); } /***************************************************************************** HRESULT StiGetCaps(BOOL *) Return the device capabilities Parameters: pointer to receive Pass/Fail result Return: HRESULT of last Sti call *****************************************************************************/ HRESULT StiGetCaps(BOOL *bPass) { HRESULT hres = STI_OK; STI_DEV_CAPS StiDevCaps = { 0}; // // check that an Sti device is selected // if ( ! pStiDevice ) { *bPass = FALSE; StiDisplayError(STIERR_GENERIC,"NoStiDevice",TRUE); return (STIERR_GENERIC); } *bPass = TRUE; // // The GetCapabilities function returns the capabilities of the device. // hres = pStiDevice->GetCapabilities( &StiDevCaps // pointer to a STI_DEV_CAPS struct ); if ( ! SUCCEEDED(hres) ) { StiDisplayError(hres,"GetCapabilities",TRUE); *bPass = FALSE; } else { DisplayOutput(" GetCapabilities on \"%S\'",szFriendlyName); DisplayOutput(" %xh (%d) dwGeneric", StiDevCaps.dwGeneric,StiDevCaps.dwGeneric); } DisplayOutput(""); return (hres); } /***************************************************************************** HRESULT StiReset(BOOL *) Puts the device into a known state. Parameters: pointer to receive Pass/Fail result Return: HRESULT of last failed Sti call *****************************************************************************/ HRESULT StiReset(BOOL *bPass) { HRESULT hres = STI_OK, hError = STI_OK; DWORD dwTimeout = 2000; // // check that an Sti device is selected // if ( ! pStiDevice ) { *bPass = FALSE; StiDisplayError(STIERR_GENERIC,"NoStiDevice",TRUE); return (STIERR_GENERIC); } *bPass = TRUE; // // Must lock device before DeviceReset // // The LockDevice locks the apparatus for a single application to access. // Each LockDevice should be paired with a matching UnLockDevice call. // hres = pStiDevice->LockDevice( dwTimeout // timeout in milliseconds ); if ( ! SUCCEEDED(hres) ) { StiDisplayError(hres,"LockDevice",TRUE); hError = hres; *bPass = FALSE; } else { DisplayOutput(" Device is locked for DeviceReset"); // // The DeviceReset interface requests that a device be returned to a // known state. // hres = pStiDevice->DeviceReset(); if ( ! SUCCEEDED(hres) ) { StiDisplayError(hres,"DeviceReset",TRUE); hError = hres; *bPass = FALSE; } else DisplayOutput(" DeviceReset on \"%S\"",szFriendlyName); } // // The UnLockDevice interface unlocks a device that was previously locked. // hres = pStiDevice->UnLockDevice(); if ( ! SUCCEEDED(hres) ) { StiDisplayError(hres,"UnLockDevice",TRUE); hError = hres; *bPass = FALSE; } else DisplayOutput(" Device is unlocked"); DisplayOutput(""); return (hError); } /***************************************************************************** HRESULT StiDiagnostic(BOOL *) Return user mode driver diagnostic info Parameters: pointer to receive Pass/Fail result Return: HRESULT of last failed Sti call *****************************************************************************/ HRESULT StiDiagnostic(BOOL *bPass) { HRESULT hres = STI_OK, hError = STI_OK; DIAG diag; DWORD dwTimeout = 2000; // // check that an Sti device is selected // if ( ! pStiDevice ) { *bPass = FALSE; StiDisplayError(STIERR_GENERIC,"NoStiDevice",TRUE); return (STIERR_GENERIC); } *bPass = TRUE; // // Must lock device before Diagnostic // // The LockDevice locks the apparatus for a single application to access. // Each LockDevice should be paired with a matching UnLockDevice call. // hres = pStiDevice->LockDevice( dwTimeout // timeout in milliseconds ); if ( ! SUCCEEDED(hres) ) { StiDisplayError(hres,"LockDevice",TRUE); hError = hres; *bPass = FALSE; } else { DisplayOutput(" Device is locked for Diagnostic"); // // get diagnostic info // ZeroMemory(&diag,sizeof(diag)); // // The DIAG dwSize field MUST be set by the caller. // diag.dwSize = sizeof(DIAG); // // The dwBasicDiagCode of this structure should be initialized with // the desired request code. Currently, only one request code is // defined, STI_DIAGCODE_HWPRESENCE. diag.dwBasicDiagCode = STI_DIAGCODE_HWPRESENCE; // // There is also a vendor defined field called dwVendorDiagCode that // can optionally be filled in. // diag.dwVendorDiagCode = 0; // // The Diagnostic interface executes the diagnostic method of the user // mode minidriver. // hres = pStiDevice->Diagnostic( &diag // pointer to STI_DIAG structure ); if ( ! SUCCEEDED(hres) ) { StiDisplayError(hres,"Diagnostic",TRUE); hError = hres; *bPass = FALSE; } else { DisplayOutput(" Diagnostic on \"%S\"",szFriendlyName); } DisplayOutput(" %xh (%d) dwBasicDiagCode", diag.dwBasicDiagCode,diag.dwBasicDiagCode); DisplayOutput(" %xh (%d) dwVendorDiagCode", diag.dwVendorDiagCode,diag.dwVendorDiagCode); DisplayOutput(" %xh (%d) dwStatusMask", diag.dwStatusMask,diag.dwStatusMask); if ( diag.dwSize != sizeof(DIAG) ) DisplayOutput("* Expected DIAG dwSize %d, got %d", sizeof(DIAG),diag.dwSize); // // any extended error info? // if ( diag.sErrorInfo.dwSize == 0 ) { DisplayOutput(" No Extended Errors"); } else { if ( diag.sErrorInfo.dwSize != sizeof(STI_ERROR_INFO) ) DisplayOutput("* Expected STI_ERROR_INFO dwSize %d, got %d", sizeof(STI_ERROR_INFO),diag.sErrorInfo.dwSize); DisplayOutput(" %xh (%d) sErrorInfo.dwGenericError", diag.sErrorInfo.dwGenericError,diag.sErrorInfo.dwGenericError); DisplayOutput(" %xh (%d) sErrorInfo.dwVendorError", diag.sErrorInfo.dwVendorError,diag.sErrorInfo.dwVendorError); if ( * diag.sErrorInfo.szExtendedErrorText ) DisplayOutput(" sErrorInfo.szExtendedErrorText %s", diag.sErrorInfo.szExtendedErrorText); } } // // The UnLockDevice interface unlocks a device that was previously locked. // hres = pStiDevice->UnLockDevice(); if ( ! SUCCEEDED(hres) ) { StiDisplayError(hres,"UnLockDevice",TRUE); hError = hres; *bPass = FALSE; } else DisplayOutput(" Device is unlocked"); DisplayOutput(""); return (hError); } /***************************************************************************** HRESULT StiGetLastErrorInfo(BOOL *) Get and display last error from Sti device. Parameters: pointer to receive Pass/Fail result Return: HRESULT of last Sti call *****************************************************************************/ HRESULT StiGetLastErrorInfo(BOOL *bPass) { HRESULT hres = STI_OK; STI_ERROR_INFO StiError; // // check that an Sti device is selected // if ( ! pStiDevice ) { *bPass = FALSE; DisplayOutput("* NoStiDevice !"); return (STIERR_GENERIC); } *bPass = TRUE; // // get last error info // ZeroMemory(&StiError,sizeof(StiError)); // // The STI_ERROR_INFO dwSize field MUST be set by the caller. // StiError.dwSize = sizeof(STI_ERROR_INFO); // // The GetLastErrorInfo interface returns the last known error from // the user-mode minidriver. // hres = pStiDevice->GetLastErrorInfo( &StiError // pointer to STI_ERROR_INFO structure ); if ( ! SUCCEEDED(hres) ) { DisplayOutput("* NoStiDevice !"); *bPass = FALSE; } else DisplayOutput(" GetLastErrorInfo on %S",szFriendlyName); // // any extended error info? // if ( StiError.dwSize == 0 ) { DisplayOutput("No Extended Errors"); } else { if ( StiError.dwSize != sizeof(STI_ERROR_INFO) ) DisplayOutput("* Expected STI_ERROR_INFO dwSize %d, got %d", sizeof(STI_ERROR_INFO),StiError.dwSize); DisplayOutput(" %xh (%d) sErrorInfo.dwGenericError", StiError.dwGenericError,StiError.dwGenericError); DisplayOutput(" %xh (%d) sErrorInfo.dwVendorError", StiError.dwVendorError,StiError.dwVendorError); if ( * StiError.szExtendedErrorText ) DisplayOutput(" sErrorInfo.szExtendedErrorText %s", StiError.szExtendedErrorText); } return (hres); } /***************************************************************************** HRESULT StiSubscribe(BOOL *) Demonstrate Subscribe, UnSubscribe and GetLastNotificationData Parameters: pointer to receive Pass/Fail result Return: HRESULT of last failed Sti call *****************************************************************************/ HRESULT StiSubscribe(BOOL *bPass) { HRESULT hres = STI_OK, hError = STI_OK; STISUBSCRIBE sSubscribe; DWORD dwErr = 0x56565656; int nWait = TRUE; BOOL fWaiting = TRUE; // // check that an Sti device is selected // if ( ! pStiDevice ) { *bPass = FALSE; StiDisplayError(STIERR_GENERIC,"NoStiDevice",TRUE); return (STIERR_GENERIC); } *bPass = TRUE; // // create an unnamed event object for notification structure // hWaitEvent = CreateEvent(NULL, // security attributes FALSE, // manual reset event flag FALSE, // initial state flag NULL ); // event-object name pointer if ( ! hWaitEvent ) { *bPass = FALSE; return STIERR_GENERIC; } // // prepare the event notification structure // ZeroMemory(&sSubscribe,sizeof(sSubscribe)); // // The STISUBSCRIBE dwSize field MUST be set by the caller. // sSubscribe.dwSize = sizeof(STISUBSCRIBE); // // When flag is STI_SUBSCRIBE_FLAG_WINDOW, window handle is passed in as // parameter. When flag is STI_SUBSCRIBE_FLAG_EVENT, event handle is // passed in as a parameter. // sSubscribe.dwFlags = STI_SUBSCRIBE_FLAG_EVENT; // // not used // sSubscribe.dwFilter = 0; // // When STI_SUBSCRIBE_FLAG_WINDOW bit is set, following field should // be set to handle of window which will receive notification message. // sSubscribe.hWndNotify = NULL; // // Handle of WIN32 auto-reset event, which will be signalled whenever // device has notification pending. // sSubscribe.hEvent = hWaitEvent; // // Code of notification message, sent to window // sSubscribe.uiNotificationMessage = 0; // // Subscribe is called by an application that wants to start receiving event // notifications from a device. This is useful for control center-style // applications. Each call to Subscribe should be paired with a call to // UnSubscribe. // hres = pStiDevice->Subscribe( &sSubscribe // pointer to STISUBSCRIBE structure ); if ( ! SUCCEEDED(hres) ) { StiDisplayError(hres,"Subscribe",TRUE); CloseHandle(hWaitEvent); *bPass = FALSE; return (hres); } // // set the flag and semaphore for Subscribe mode // nUnSubscribe = nUnSubscribeSemaphore = 1; // // Now we wait for an event // DisplayOutput(" Subscribe on %S",szFriendlyName); while ( nUnSubscribe ) { dwErr = WaitForSingleObject(hWaitEvent,1000); switch ( dwErr ) { case WAIT_OBJECT_0: { STINOTIFY sNotify; // // received a notification // DisplayOutput(" WAIT_OBJECT_0 %xh (%d)",dwErr,dwErr); DisplayOutput(" Received notification"); // // prepare the notification description structure // ZeroMemory(&sNotify,sizeof(sNotify)); // // The STINOTIFY dwSize field MUST be set by the caller. // sNotify.dwSize = sizeof(STINOTIFY); // // GetLastNotifyData returns information about the last // event on the device. // hres = pStiDevice->GetLastNotificationData( &sNotify // pointer to STINOTIFY structure ); if ( ! SUCCEEDED(hres) ) { StiDisplayError(hres,"GetLastNotificationData",TRUE); hError = hres; *bPass = FALSE; } else { DisplayOutput(" GetLastNotificationData"); DisplayOutput(" GUID {%8x-%4x-%4x-%x}", sNotify.guidNotificationCode.Data1, sNotify.guidNotificationCode.Data2, sNotify.guidNotificationCode.Data3, sNotify.guidNotificationCode.Data4 ); } } break; case WAIT_TIMEOUT: // // no notification // DisplayOutput(" WAIT_TIMEOUT %xh (%d)",dwErr,dwErr); DisplayOutput(" (select UnSubscribe from the IStillDevice "\ "menu to quit)"); break; case WAIT_ABANDONED: DisplayOutput(" WAIT_ABANDONED %xh (%d)",dwErr,dwErr); break; default: DisplayOutput(" default %xh (%d)",dwErr,dwErr); break; } } // // if the device is gone, StiDeviceRelease has already been // unsubscribed elsewhere in this app // if ( ! pStiDevice ) return (STIERR_GENERIC); // // UnSubscribe is called when an application no longer wants to receive // events from a device. // hres = pStiDevice->UnSubscribe(); if ( ! SUCCEEDED(hres) ) { StiDisplayError(hres,"UnSubscribe",TRUE); hError = hres; *bPass = FALSE; } // // we're done with the event // CloseHandle(hWaitEvent); // // clear the semaphore // nUnSubscribeSemaphore = 0; DisplayOutput(""); return (hError); } /***************************************************************************** HRESULT StiEscape(DWORD,char *,BOOL *) The Escape function is dependent on the vendor's implementation. Even if a device does not require the Escape function, the driver must provide it. A non-functional Escape must return an error. Parameters: DWORD EscapeFunction - driver defined code char *lpInData - pointer to data to be sent to device pointer to receive Pass/Fail result Return: HRESULT of last failed Sti call *****************************************************************************/ HRESULT StiEscape(DWORD EscapeFunction,char *lpInData,BOOL *bPass) { HRESULT hres = STI_OK, hError = STI_OK; DWORD dwTimeout = 2000; DWORD cbInDataSize, dwOutDataSize, pdwActualData; char pOutData[LONGSTRING]; // // check that an Sti device is selected // if ( ! pStiDevice ) { *bPass = FALSE; StiDisplayError(STIERR_GENERIC,"NoStiDevice",TRUE); return (STIERR_GENERIC); } *bPass = TRUE; // // Must lock device before Escape // // The LockDevice locks the apparatus for a single application to access. // Each LockDevice should be paired with a matching UnLockDevice call. // hres = pStiDevice->LockDevice( dwTimeout // timeout in milliseconds ); if ( ! SUCCEEDED(hres) ) { StiDisplayError(hres,"LockDevice",TRUE); hError = hres; *bPass = FALSE; } else { DisplayOutput(" Device is locked for Escape"); // // Set up the command // cbInDataSize = strlen(lpInData + 1); // // zero out other parameters (for clarity's sake only) // ZeroMemory(pOutData,LONGSTRING); dwOutDataSize = pdwActualData = 0; // // The Escape function executes a multiparameter I/O call. The semantics // of this call is determined by the specific user-mode minidriver. // hres = pStiDevice->Escape( EscapeFunction, // General operation code. The meaning of this code // varies in each user mode minidriver. There is no // utilization of this code by the still image // minidriver. lpInData, // Pointer to an input memory buffer. If there are // multiple areas of memory to be read from, they // must be packaged in some sort of structure // before being passed to this API. cbInDataSize, // The length in bytes of the memory pointed to by // lpInData pOutData, // Pointer to a memory buffer usable for writing. // Access to this memory is checked to be sure it // is available for writing. dwOutDataSize, // The length in bytes of the memory pointed to by // lpOutData. &pdwActualData // Pointer to a DWORD that gets the number of bytes // actually transferred to pOutData. If this value // is less than dwOutDataSize, then an error // situation could exist. ); if ( ! SUCCEEDED(hres) ) { hError = hres; if ( hres == STIERR_UNSUPPORTED ) { // // COMPLIANCE test: // if the escape IOCTL is NOT supported, the driver MUST // return STIERR_UNSUPPORTED // StiDisplayError(hres,"Escape",FALSE); DisplayOutput(" Escape IOCTL %d unsupported",EscapeFunction); } else { StiDisplayError(hres,"Escape",TRUE); *bPass = FALSE; } } else { DisplayOutput(" Escape on %S",szFriendlyName); DisplayOutput(" %xh (%d) EscapeFunction", EscapeFunction,EscapeFunction); DisplayOutput(" %x %x %x %x %x %x %x %x - %x %x %x %x %x %x %x %x lpInData", lpInData[0], lpInData[1], lpInData[2], lpInData[3], lpInData[4], lpInData[5], lpInData[6], lpInData[7], lpInData[8], lpInData[9], lpInData[10], lpInData[11], lpInData[12], lpInData[13], lpInData[14], lpInData[15] ); DisplayOutput(" %xh (%d) cbInDataSize", cbInDataSize,cbInDataSize); DisplayOutput(" %x %x %x %x %x %x %x %x - %x %x %x %x %x %x %x %x pOutData", pOutData[0], pOutData[1], pOutData[2], pOutData[3], pOutData[4], pOutData[5], pOutData[6], pOutData[7], pOutData[8], pOutData[9], pOutData[10], pOutData[11], pOutData[12], pOutData[13], pOutData[14], pOutData[15] ); DisplayOutput(" %xh (%d) dwOutDataSize", dwOutDataSize,dwOutDataSize); DisplayOutput(" %xh (%d) pdwActualData", pdwActualData,pdwActualData); } } // // The UnLockDevice interface unlocks a device that was previously locked. // hres = pStiDevice->UnLockDevice(); if ( ! SUCCEEDED(hres) ) { StiDisplayError(hres,"UnLockDevice",TRUE); hError = hres; *bPass = FALSE; } else DisplayOutput(" Device is unlocked"); DisplayOutput(""); return (hError); } /***************************************************************************** HRESULT StiRawReadData(char *,LPDWORD,BOOL *) Obtains data from a device. The RawReadData function is dependent on the vendor's implementation. Even if a device does not require the RawReadData function, the driver must provide it. A non-functional RawReadData must return an error. Parameters: char *lpBuffer - Location in memory to transfer the data coming in from the device. LPDWORD lpdwNumberOfBytes - number of bytes to be read pointer to receive Pass/Fail result Return: HRESULT of last failed Sti call *****************************************************************************/ HRESULT StiRawReadData(char *lpBuffer,LPDWORD lpdwNumberOfBytes,BOOL *bPass) { HRESULT hres = STI_OK, hError = STI_OK; LPOVERLAPPED lpOverlapped; DWORD dwTimeout = 2000; // // check that an Sti device is selected // if ( ! pStiDevice ) { *bPass = FALSE; StiDisplayError(STIERR_GENERIC,"NoStiDevice",TRUE); return (STIERR_GENERIC); } *bPass = TRUE; // // Must lock device before RawReadData // // The LockDevice locks the apparatus for a single application to access. // Each LockDevice should be paired with a matching UnLockDevice call. // hres = pStiDevice->LockDevice( dwTimeout // timeout in milliseconds ); if ( ! SUCCEEDED(hres) ) { StiDisplayError(hres,"LockDevice",TRUE); hError = hres; *bPass = FALSE; } else { DisplayOutput(" Device is locked for RawReadData"); // // Set up the command // lpOverlapped = NULL; // // The RawReadData interface reads data from a device. This is a // general operation for obtaining data from a device. Depending on // the user-mode minidriver for the device, command streams and data // streams can be read with this call. Some devices may seperate // commands from data by using RawReadCommand. // hres = pStiDevice->RawReadData( lpBuffer, // Location in memory to transfer the data // coming from the device lpdwNumberOfBytes, // Number of bytes requested to be read lpOverlapped // This is used to signal that the operation // of this call should be asynchronous. The // value here conforms to the Win32 APIs. ); if ( ! SUCCEEDED(hres) ) { if ( hres == STIERR_UNSUPPORTED ) { // // COMPLIANCE test: // if RawReadData is NOT supported, the driver MUST // return STIERR_UNSUPPORTED // StiDisplayError(hres,"RawReadData",FALSE); DisplayOutput(" RawReadData unsupported"); } else { StiDisplayError(hres,"RawReadData",TRUE); *bPass = FALSE; } hError = hres; } else { DisplayOutput(" RawReadData on %S",szFriendlyName); DisplayOutput(" %x %x %x %x %x %x %x %x - %x %x %x %x %x %x %x %x lpBuffer", lpBuffer[0], lpBuffer[1], lpBuffer[2], lpBuffer[3], lpBuffer[4], lpBuffer[5], lpBuffer[6], lpBuffer[7], lpBuffer[8], lpBuffer[9], lpBuffer[10], lpBuffer[11], lpBuffer[12], lpBuffer[13], lpBuffer[14], lpBuffer[15] ); DisplayOutput(" %xh (%d) lpdwNumberOfBytes read", *lpdwNumberOfBytes,*lpdwNumberOfBytes); } } // // The UnLockDevice interface unlocks a device that was previously locked. // hres = pStiDevice->UnLockDevice(); if ( ! SUCCEEDED(hres) ) { StiDisplayError(hres,"UnLockDevice",TRUE); hError = hres; *bPass = FALSE; } else DisplayOutput(" Device is unlocked"); DisplayOutput(""); return (hError); } /***************************************************************************** HRESULT StiRawWriteData(char *,DWORD,BOOL *) Sends data to the device. The RawWriteData function is dependent on the vendor's implementation. Even if a device does not require the RawWriteData function, the driver must provide it. A non-functional RawWriteData must return an error. Parameters: char *lpBuffer - Location in memory to read from when sending data to a device. LPDWORD lpdwNumberOfBytes - number of bytes of data to be sent pointer to receive Pass/Fail result Return: HRESULT of last failed Sti call *****************************************************************************/ HRESULT StiRawWriteData(char *lpBuffer,DWORD dwNumberOfBytes,BOOL *bPass) { HRESULT hres = STI_OK, hError = STI_OK; LPOVERLAPPED lpOverlapped; DWORD dwTimeout = 2000; // // check that an Sti device is selected // if ( ! pStiDevice ) { *bPass = FALSE; StiDisplayError(STIERR_GENERIC,"NoStiDevice",TRUE); return (STIERR_GENERIC); } *bPass = TRUE; // // Must lock device before RawWriteData // // The LockDevice locks the apparatus for a single application to access. // Each LockDevice should be paired with a matching UnLockDevice call. // hres = pStiDevice->LockDevice( dwTimeout // timeout in milliseconds ); if ( ! SUCCEEDED(hres) ) { StiDisplayError(hres,"LockDevice",TRUE); hError = hres; *bPass = FALSE; } else { DisplayOutput(" Device is locked for RawWriteData"); // // Set up the command // lpOverlapped = NULL; // // The RawWriteData interface writes data to a device. This is a // general operation for sending data to a device. Depending on // the user-mode minidriver for the device, command streams and data // streams can be written with this call. Some devices may seperate // commands from data by using RawWriteCommand. // hres = pStiDevice->RawWriteData( lpBuffer, // Location in memory to read from when sending // data to a device dwNumberOfBytes, // Number of bytes of data to send lpOverlapped // This is used to signal that the operation // of this call should be asynchronous. The // value here conforms to the Win32 APIs. ); if ( ! SUCCEEDED(hres) ) { if ( hres == STIERR_UNSUPPORTED ) { // // COMPLIANCE test: // if RawWriteData is NOT supported, the driver MUST // return STIERR_UNSUPPORTED // StiDisplayError(hres,"RawWriteData",FALSE); DisplayOutput(" RawWriteData unsupported"); } else { StiDisplayError(hres,"RawWriteData",TRUE); *bPass = FALSE; } hError = hres; } else { DisplayOutput(" RawWriteData on %S",szFriendlyName); DisplayOutput(" %xh (%d) dwNumberOfBytes sent", dwNumberOfBytes,dwNumberOfBytes); } } // // The UnLockDevice interface unlocks a device that was previously locked. // hres = pStiDevice->UnLockDevice(); if ( ! SUCCEEDED(hres) ) { StiDisplayError(hres,"UnLockDevice",TRUE); hError = hres; *bPass = FALSE; } else DisplayOutput(" Device is unlocked"); DisplayOutput(""); return (hError); } /***************************************************************************** HRESULT StiRawReadCommand(char *,LPDWORD,BOOL *) Obtains command information from the device. Unique to the IStiDevice interface. The RawReadCommand function is dependent on the vendor's implementation. Even if a device does not require the RawReadCommand function, the driver must provide it. A non-functional RawReadCommand must return an error. Parameters: char *lpBuffer - Location in memory to transfer the data coming in from the device. LPDWORD lpdwNumberOfBytes - number of bytes to be read pointer to receive Pass/Fail result Return: HRESULT of last failed Sti call *****************************************************************************/ HRESULT StiRawReadCommand(char *lpBuffer,LPDWORD lpdwNumberOfBytes,BOOL *bPass) { HRESULT hres = STI_OK, hError = STI_OK; LPOVERLAPPED lpOverlapped; DWORD dwTimeout = 2000; // // check that an Sti device is selected // if ( ! pStiDevice ) { *bPass = FALSE; StiDisplayError(STIERR_GENERIC,"NoStiDevice",TRUE); return (STIERR_GENERIC); } *bPass = TRUE; // // Must lock device before RawReadCommand // // The LockDevice locks the apparatus for a single application to access. // Each LockDevice should be paired with a matching UnLockDevice call. // hres = pStiDevice->LockDevice( dwTimeout // timeout in milliseconds ); if ( ! SUCCEEDED(hres) ) { StiDisplayError(hres,"LockDevice",TRUE); hError = hres; *bPass = FALSE; } else { DisplayOutput(" Device is locked for RawReadCommand"); // // Set up the command // lpOverlapped = NULL; // // The RawReadCommand interface reads command information from a // device. The implementation of this call depends on the user-mode // minidriver for the device. Many devices will not require // separating commands and data. If this call is not used, the // user-mode minidriver should return STIERR_UNSUPPORTED. // hres = pStiDevice->RawReadCommand( lpBuffer, // Location in memory to transfer the command // information coming from the device lpdwNumberOfBytes, // Number of command bytes requested to be read lpOverlapped // This is used to signal that the operation // of this call should be asynchronous. The // value here conforms to the Win32 APIs. ); if ( ! SUCCEEDED(hres) ) { if ( hres == STIERR_UNSUPPORTED ) { // // COMPLIANCE test: // if RawReadCommand is NOT supported, the driver MUST // return STIERR_UNSUPPORTED // StiDisplayError(hres,"RawReadCommand",FALSE); DisplayOutput(" RawReadCommand unsupported"); } else { StiDisplayError(hres,"RawReadCommand",TRUE); *bPass = FALSE; } hError = hres; } else { DisplayOutput(" RawReadCommand on %S",szFriendlyName); DisplayOutput(" %x %x %x %x %x %x %x %x - %x %x %x %x %x %x %x %x lpBuffer", lpBuffer[0], lpBuffer[1], lpBuffer[2], lpBuffer[3], lpBuffer[4], lpBuffer[5], lpBuffer[6], lpBuffer[7], lpBuffer[8], lpBuffer[9], lpBuffer[10], lpBuffer[11], lpBuffer[12], lpBuffer[13], lpBuffer[14], lpBuffer[15] ); DisplayOutput(" %xh (%d) lpdwNumberOfBytes read", *lpdwNumberOfBytes,*lpdwNumberOfBytes); } } // // The UnLockDevice interface unlocks a device that was previously locked. // hres = pStiDevice->UnLockDevice(); if ( ! SUCCEEDED(hres) ) { StiDisplayError(hres,"UnLockDevice",TRUE); hError = hres; *bPass = FALSE; } else DisplayOutput(" Device is unlocked"); DisplayOutput(""); return (hError); } /***************************************************************************** HRESULT StiRawWriteCommand(char *,DWORD,BOOL *) Sends command information to the device. Unique to the IStiDevice interface. The RawWriteCommand function is dependent on the vendor's implementation. Even if a device does not require the RawWriteCommand function, the driver must provide it. A non-functional RawWriteCommand must return an error. Parameters: char *lpBuffer - Location in memory to read from when sending data to a device. LPDWORD lpdwNumberOfBytes - number of bytes of data to be sent pointer to receive Pass/Fail result Return: HRESULT of last failed Sti call *****************************************************************************/ HRESULT StiRawWriteCommand(char *lpBuffer,DWORD dwNumberOfBytes,BOOL *bPass) { HRESULT hres = STI_OK, hError = STI_OK; LPOVERLAPPED lpOverlapped; DWORD dwTimeout = 2000; // // check that an Sti device is selected // if ( ! pStiDevice ) { *bPass = FALSE; StiDisplayError(STIERR_GENERIC,"NoStiDevice",TRUE); return (STIERR_GENERIC); } *bPass = TRUE; // // Must lock device before RawWriteCommand // // The LockDevice locks the apparatus for a single application to access. // Each LockDevice should be paired with a matching UnLockDevice call. // hres = pStiDevice->LockDevice( dwTimeout // timeout in milliseconds ); if ( ! SUCCEEDED(hres) ) { StiDisplayError(hres,"LockDevice",TRUE); hError = hres; *bPass = FALSE; } else { DisplayOutput(" Device is locked for RawWriteCommand"); // // Set up the command // lpOverlapped = NULL; // // The RawWriteCommand interface sends command information to the // device. The implementation of this call depends on the user-mode // minidriver for the device. Many devices will not require // separating commands and data. If this call is not used, the // user-mode minidriver should return STIERR_UNSUPPORTED. // hres = pStiDevice->RawWriteCommand( lpBuffer, // Location in memory to read from when writing // command information to the device dwNumberOfBytes, // Number of bytes of data to send lpOverlapped // This is used to signal that the operation // of this call should be asynchronous. The // value here conforms to the Win32 APIs. ); if ( ! SUCCEEDED(hres) ) { if ( hres == STIERR_UNSUPPORTED ) { // // COMPLIANCE test: // if RawWriteData is NOT supported, the driver MUST // return STIERR_UNSUPPORTED // StiDisplayError(hres,"RawWriteCommand",FALSE); DisplayOutput(" RawWriteCommand unsupported"); } else { StiDisplayError(hres,"RawWriteCommand",TRUE); *bPass = FALSE; } hError = hres; } else { DisplayOutput(" RawWriteCommand on %S",szFriendlyName); DisplayOutput(" %xh (%d) dwNumberOfBytes sent", dwNumberOfBytes,dwNumberOfBytes); } } // // The UnLockDevice interface unlocks a device that was previously locked. // hres = pStiDevice->UnLockDevice(); if ( ! SUCCEEDED(hres) ) { StiDisplayError(hres,"UnLockDevice",TRUE); hError = hres; *bPass = FALSE; } else DisplayOutput(" Device is unlocked"); DisplayOutput(""); return (hError); }