ESC_TWAIN_CAPABILITY Escape Code
To carry out a capability operation on a private TWAIN capability, a TWAIN application notifies the TWAIN compatibility layer, which then calls the WIA driver's IStiUSD::Escape method, passing the ESC_TWAIN_CAPABILITY escape code. The pseudocode in the following example demonstrates how the Escape method should be implemented, and how it should respond to the escape code.
STDMETHODIMP CWIADevice::Escape(STI_RAW_CONTROL_CODE EscapeFunction,
LPVOID lpInData,
DWORD cbInDataSize,
LPVOID pOutData,
DWORD dwOutDataSize,
LPDWORD pdwActualData)
{
//
// Only process EscapeFunction codes that are known to your driver.
// Any application can send escape calls to your driver using the
// IWiaItemExtras interface Escape() method call. The driver must
// be prepared to validate all incoming calls to Escape().
//
//
// Because this driver does not support any escape functions, it will
// reject all incoming EscapeFunction codes.
//
// If your driver supports an EscapeFunction, then add your function
// code to the switch statement, and set hr = S_OK. This will allow
// the function to continue to the incoming/outgoing buffer
// validation.
HRESULT hr = E_NOTIMPL;
switch(EscapeFunction) {
case ESC_TWAIN_CAPABILITY: // processing the TWAIN capability Escapecode
hr = S_OK;
break;
default:
break;
}
//
// If an EscapeFunction code is supported, then first validate the
// incoming and outgoing buffers.
//
if(S_OK == hr) {
//
// Validate the incoming data buffer.
//
if(IsBadReadPtr(lpInData,cbInDataSize)) {
hr = E_UNEXPECTED;
}
//
// If the incoming buffer is valid, proceed to validate the
// outgoing buffer.
//
if(S_OK == hr) {
if(IsBadWritePtr(pOutData,dwOutDataSize)) {
hr = E_UNEXPECTED;
} else {
//
// Validate the outgoing size pointer.
//
if(IsBadWritePtr(pdwActualData,sizeof(DWORD))) {
hr = E_UNEXPECTED;
}
}
}
//
// Now that buffer validation is complete, proceed to process the
// proper EscapeFunction code.
//
if(S_OK == hr) {
//
// Only process a validated EscapeFunction code, and buffers.
//
if(EscapeFunction == ESC_TWAIN_CAPABILITY) {
//
// Process a TWAIN capability message.
//
// Collect the lpInData and pOutData headers.
//
// 1. Create two TWAIN_CAPABILITY pointers in which
// to store the addresses in lpInData and pOutData.
// 2. Set these local pointers to the addresses in
// lpInData and pOutData.
// 3. Use these local pointers to access the
// members of the TWAIN_CAPABILITY structures.
TWAIN_CAPABILITY *pInHeader = NULL;
TWAIN_CAPABILITY *pOutHeader = NULL;
pInHeader = (TWAIN_CAPABILITY*)lpInData;
pOutHeader = (TWAIN_CAPABILITY*)pOutData;
if(pInHeader && pOutHeader) {
// Check the headers to determine the operation to perform.
switch(pInHeader->lCapID) {
case ICAP_MY_PRIVATE_CAP1:
{
// Check lMSG to determine which TWAIN
// message/operation is being requested.
switch(pInHeader->lMSG) {
case MSG_GETCURRENT: // Return the current value.
case MSG_GETDEFAULT: // Return the default value.
case MSG_GET: // Return the valid values.
{
// Check lDataSize to determine
// which operation to perform.
if(pInHeader->lDataSize == 0) {
// If lDataSize is zero:
// a. Set pOutHeader->lDataSize to the size
// in bytes needed to store the entire
// TWAIN capability data.
// b. Set *pchActualData to the size of
// a TWAIN_CAPABILITY header.
// c. Set the TWAIN return codes,
// pOutHeader->lRC and pOutHeader->lCC.
// d. Set the HRESULT to S_OK, and return.
pOutHeader->lDataSize = sizeof(TW_ENUMERATION) +
(sizeof(TW_UINT32) * 3);
*pdwActualData = sizeof(TWAIN_CAPABILITY);
pOutHeader->lRC = TWRC_SUCCESS;
pOutHeader->lCC = TWCC_SUCCESS;
hr = S_OK;
} else if(pInHeader->lDataSize > 0) {
// If lDataSize is positive:
// a. Fill the pOutHeader->Data member with
// the TWAIN capability data.
// (This is the container and data only).
// b. Set pOutHeader->lConType to the type of
// TWAIN container used.
// c. Set pOutHeader->lDataSize to
// (size of the TWAIN container + size of
// the TWAIN container data).
// d. Set *pchActualData to
// (size of the TWAIN container + size of
// the TWAIN container data +
// size of the TWAIN_CAPABILITY header).
// e. Set the TWAIN return codes,
// pOutHeader->lRC and pOutHeader->lCC.
// f. Set the HRESULT to S_OK, and return.
pEnumeration = (TW_ENUMERATION*)pOutHeader->Data;
if(pEnumeration) {
pEnumeration->ItemType = TWTY_UINT32;
pEnumeration->NumItems = 3;
pEnumeration->CurrentIndex = 0;
pEnumeration->DefaultIndex = 1;
TW_UINT32 *pData = (TW_UINT32*)pEnumeration->ItemList;
if(pData) {
pData[0] = 123;
pData[1] = 456;
pData[2] = 789;
pOutHeader->lConType = TWON_ENUMERATION;
pOutHeader->lDataSize = sizeof(TW_ENUMERATION) +
(sizeof(TW_UINT32) * 3);
*pdwActualData = sizeof(TWAIN_CAPABILITY) +
sizeof(TW_ENUMERATION) +
(sizeof(TW_UINT32) * 3);
pOutHeader->lRC = TWRC_SUCCESS;
pOutHeader->lCC = TWCC_SUCCESS;
hr = S_OK;
} else {
//
// Could not get the item list pointer.
//
hr = E_INVALIDARG;
}
} // if (Enumeration)
} // if (pInHeader->lDataSize > 0)
break;
} // case MSG_GET
case MSG_SET: // Set the incoming value.
{
// Check the TWAIN container type, and use
// the contained values.
//
// 1. Create a pointer to a TWAIN container
// of the desired type.
// 2. Set the pointer of the previous step
// to the address in pInHeader->Data.
// 3. Access the values in the TWAIN
// container.
// 4. Carry out any private operations
// with those values.
// 5. Set *pchActualData to the size of a
// TWAIN_CAPABILITY header.
// 6. Set the TWAIN return codes,
// pOutHeader->lRC and pOutHeader->lCC.
// 7. Set the HRESULT to S_OK, and return.
switch(pInHeader->lConType) {
case TWON_ONEVALUE:
{
pOneValue = (TW_ONEVALUE*)pInHeader->Data;
if(pOneValue) {
if(pOneValue->ItemType == TWTY_UINT32) {
if(WriteMyPrivateTWAINValue((TW_UINT32)pOneValue->Item)) {
*pdwActualData = sizeof(TWAIN_CAPABILITY);
pOutHeader->lRC = TWRC_SUCCESS;
pOutHeader->lCC = TWCC_SUCCESS;
} else {
pOutHeader->lRC = TWRC_FAILURE;
pOutHeader->lCC = TWCC_BADVALUE;
}
hr = S_OK;
}
} // if(pOneValue)
break;
} // case TWON_ONEVALUE:
default:
break;
} // End switch(pInHeader->lConType)
break;
} // case MSG_SET
case MSG_RESET: // reset TWAIN capability
{
break;
}
default:
{
// Messages other than MSG_GETCURRENT,
// MSG_GETDEFAULT, MSG_GET, MSG_SET
break;
}
} // switch(pInHeader->lMSG)
} // case ICAP_MY_PRIVATE1
case ICAP_MY_PRIVATE2:
{
break;
}
default:
{
// Unknown capability - set TWAIN failure codes.
pOutHeader->lRC = TWRC_FAILURE;
pOutHeader->lCC = TWCC_BADCAP;
break;
}
} // End switch(pInHeader->lCapID)
} // End if (pInHeader && pOutHeader)
}
}
}
//
// If your driver will not support this entry point, then
// it must return E_NOTIMPL (error, not implemented).
//
return hr;
}