Page 1 of 1

TWAIN Error Handling

Posted: Wed Jul 27, 2016 3:02 pm
by stewjames2000

I am having a problem trying to use the TWAIN functionality provided as part of the SDK. The issue I'm having is my call to SXC_InitTwain is returning failure, however I cannot for the life of me work out how to get the cause of the error out of the HRESULT. Would you be able to provide me with any assistance?

I've attached my code below, note it is still a work in progress - since I'm just trying to get SXC_InitTwain to work before I can do any further work.

Cheers, Stew

Code: Select all

bool scanner::perform_scan_twain(std::vector<std::string>& files)
	typedef TwainObject(FAR PASCAL createTwainObject)(LPCSTR, LPCSTR);
	typedef VOID(FAR PASCAL deleteTwainObject)(TwainObject);
	typedef HRESULT(FAR PASCAL initTwain)(TwainObject);
	typedef HRESULT(FAR PASCAL setProc)(TwainObject, pGetData , DWORD_PTR );
	typedef HRESULT(FAR PASCAL selectSourceGUI)(TwainObject);
	typedef HRESULT(FAR PASCAL openSource)(TwainObject);
	typedef HRESULT(FAR PASCAL enableSource)(TwainObject, HWND, BOOL);

	const raii_loadlibrary libraryloader("xcscan40.dll", "xcscan40.dll");
	auto lib_inst = libraryloader.get_hinstance();

	auto fn_createTwainObject = (createTwainObject FAR*)GetProcAddress(lib_inst, "SXC_CreateTwainObject");
	auto fn_deleteTwainObject = (deleteTwainObject FAR*)GetProcAddress(lib_inst, "SXC_DeleteTwainObject");
	auto fn_initTwain = (initTwain FAR*)GetProcAddress(lib_inst, "SXC_InitTwain");
	auto fn_setProc = (setProc FAR*)GetProcAddress(lib_inst, "SXC_SetProc");
	auto fn_selectSourceGUI = (selectSourceGUI FAR*)GetProcAddress(lib_inst, "SXC_SelectSourceGUI");
	auto fn_openSource = (openSource FAR*)GetProcAddress(lib_inst, "SXC_OpenSource");
	auto fn_enableSource = (enableSource FAR*)GetProcAddress(lib_inst, "SXC_EnableSource");

	TwainObject twain_obj = fn_createTwainObject("<private>", "<private>");
	if (!twain_obj)
		throw std::exception("Unable to create TWAIN object.");

	// Ensure the twain_obj is deleted when we exit scope.
	auto cleanup_twain = gsl::finally([&twain_obj, &fn_deleteTwainObject]() {fn_deleteTwainObject(twain_obj); });

	HRESULT hr = fn_initTwain(twain_obj);

	if (IS_DS_FAILED(hr))
		throw std::exception("Unable to initialise TWAIN.");
	if (IS_DS_FAILED(fn_setProc(twain_obj, [](DWORD_PTR u, const BYTE* b, DWORD s) { return reinterpret_cast<scanner*>(u)->get_data_callback(b, s); }, reinterpret_cast<DWORD_PTR>(this))))
		throw std::exception("Failed to set data-retrieval procedure.");

	if (IS_DS_FAILED(fn_selectSourceGUI(twain_obj)))
		throw std::exception("Unable to select source GUI.");

	if (IS_DS_FAILED(fn_openSource(twain_obj)))
		throw std::exception("Unable to open source.");

	if (IS_DS_FAILED(fn_enableSource(twain_obj, wxo_win_mainhwnd, true)))
		throw std::exception("Unable to enable source.");

	return true;

Re: TWAIN Error Handling

Posted: Wed Jul 27, 2016 9:10 pm
by stewjames2000
Ok turns out I had a valid error code the entire time, after searching for '1001' in all of the headers - a DS_ERR_BAD_POINTER error.

I'm assuming this is caused by the call to SXC_CreateTwainObject - the TwainObject returned is not NULL however.

Re: TWAIN Error Handling

Posted: Wed Jul 27, 2016 9:44 pm
by Ivan - Tracker Software
Can you let me know exact code error you got? I suspect it was not 1001 (low part), but 10001.

This code in Scanner Lib means SCAN_ERR_CANNOT_LOAD_DSM.

This error code is returned from SXC_InitTwain function when it cannot load twain_32.dll, or this DLL hasn't required entry points.

Re: TWAIN Error Handling

Posted: Thu Jul 28, 2016 7:32 am
by stewjames2000
Ah yes, my apologies it was a late night last night :) - The error code is indeed 10001. The exact HRESULT returned is 0x82092711.

However, we do not appear to have a source file with the SCAN_ERR_CANNOT_LOAD_DSM definition, may I inquire as to which source file these 'SCAN_ERR_...' definitions are supposed to be? I'm currently working off scaner.h, scannerWIA.h & ds_error_maker.h

Re: TWAIN Error Handling

Posted: Thu Jul 28, 2016 3:22 pm
by stewjames2000
Ok, I managed to get past the SXC_InitTwain issue (it was an issue with the scanners driver), but I'm now having a problem with SXC_GetSourcesInfo giving me TW_IDENTITY_4 data that is at the wrong offsets. Is there any byte packing/alignment issues I need to consider? Since it appears to be off by two bytes for the TW_STR32 data e.g

Manufacturer = '\0\0Hewlett-Packard\0'
ProductFamily = '\0\0HP Officejet Pro\0'
ProductName = '\0\0HP Officejet Pro\0'

Just wondering if you have any ideas, since I'm currently struggling


Re: TWAIN Error Handling

Posted: Wed Aug 03, 2016 5:49 pm
by Ivan - Tracker Software
Hi Stew,

No, we do not use any specific alignment for structures there, and we never seen this problem before. Can you check if our sample provided with Tools SDK has the same problem?