code_device/twain/dsm/dsm.cpp

3919 lines
127 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/***************************************************************************
* TWAIN Data Source Manager version 2.1
* Manages image acquisition data sources used by a machine.
* Copyright © 2007 TWAIN Working Group:
* Adobe Systems Incorporated,AnyDoc Software Inc., Eastman Kodak Company,
* Fujitsu Computer Products of America, JFL Peripheral Solutions Inc.,
* Ricoh Corporation, and Xerox Corporation.
* All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Contact the TWAIN Working Group by emailing the Technical Subcommittee at
* twainwg@twain.org or mailing us at 13090 Hwy 9, Suite 3, Boulder Creek, CA 95006.
*
***************************************************************************/
/**
* @file dsm.cpp
* Data Source Manager.
* This software manages the interactions between the application
* and the Source.
* @author TWAIN Working Group
* @date March 2007
*/
/*! \mainpage Data Source Manager
*
* The Source Manager provides the communication path between the
* Application and the Source, supports the users selection of a
* Source, and loads the Source for access by the Application.
* Communications from Application to Source Manager or the Source
* to Source Manager (via DAT_NULL) arrive in exclusively through
* the DSM_Entry() entry point.
*
*
*
*
*
*
*
*
* Copyright © 2007 TWAIN Working Group: Adobe Systems Incorporated,
* AnyDoc Software Inc., Eastman Kodak Company,
* Fujitsu Computer Products of America, JFL Peripheral Solutions Inc.,
* Ricoh Corporation, and Xerox Corporation.
* All rights reserved.
*/
#include "dsm.h"
/*
* These are all the globals we should ever have in this project...
*/
HINSTANCE g_hinstance = 0; /**< Windows Instance handle for the DSM DLL... */
CTwnDsm *g_ptwndsm = 0; /**< The main DSM object */
CTwnDsmLog *g_ptwndsmlog = 0; /**< The logging object, only access through macros */
/**
* Localization: we have the selection box on Windows that we have
* to deal with, so this table gives us all our strings in UTF-8 format.
* TWAIN defines a lot of languages, and it makes sense to reference
* all of them. Refer to the DSM_translations.txt file if you want to
* see the mapping between the hex UTF-8 and the viewable characters.
* The UTF-8 values are in hex so that the encoding of this file doesn't
* change the resulting output.
*
* Many languages still need translations...
*/
/*
* we need this because xcode insists on complaining about content
* inside of visual studio's code block
*/
#if (TWNDSM_OS == TWNDSM_OS_MACOSX)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wall"
#endif
#if (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP)
typedef struct
{
TW_INT16 Language; /**< Language */
BYTE CharSet; /**< Character Set*/
LANGID LangId; /**< Language Id*/
char *Title; /**< the Title string*/
char *Sources; /**< the Sources string */
char *Select; /**< the Select string */
char *Cancel; /**< the Cancel string */
} TwLocalize;
/**
* Localized strings for the select dialog
*/
static TwLocalize s_twlocalize[] =
{
{TWLG_AFRIKAANS, ANSI_CHARSET, MAKELANGID(LANG_AFRIKAANS,SUBLANG_NEUTRAL), "Select Source","Sources:","Select","\x4b\x61\x6e\x73\x65\x6c\x6c\x65\x65\x72"},
{TWLG_ALBANIA, EASTEUROPE_CHARSET, MAKELANGID(LANG_ALBANIAN,SUBLANG_NEUTRAL), "","","",""},
{TWLG_ARABIC, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_NEUTRAL), "","","",""},
{TWLG_ARABIC_ALGERIA, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_ALGERIA), "","","",""},
{TWLG_ARABIC_BAHRAIN, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_BAHRAIN), "","","",""},
{TWLG_ARABIC_EGYPT, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_EGYPT), "","","",""},
{TWLG_ARABIC_IRAQ, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_IRAQ), "","","",""},
{TWLG_ARABIC_JORDAN, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_JORDAN), "","","",""},
{TWLG_ARABIC_KUWAIT, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_KUWAIT), "","","",""},
{TWLG_ARABIC_LEBANON, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_LEBANON), "","","",""},
{TWLG_ARABIC_LIBYA, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_LIBYA), "","","",""},
{TWLG_ARABIC_MOROCCO, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_MOROCCO), "","","",""},
{TWLG_ARABIC_OMAN, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_OMAN), "","","",""},
{TWLG_ARABIC_QATAR, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_QATAR), "","","",""},
{TWLG_ARABIC_SAUDIARABIA, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_SAUDI_ARABIA), "","","",""},
{TWLG_ARABIC_SYRIA, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_SYRIA), "","","",""},
{TWLG_ARABIC_TUNISIA, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_TUNISIA), "","","",""},
{TWLG_ARABIC_UAE, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_UAE), "","","",""},
{TWLG_ARABIC_YEMEN, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_YEMEN), "","","",""},
{TWLG_ASSAMESE, ANSI_CHARSET, MAKELANGID(LANG_ASSAMESE,SUBLANG_NEUTRAL), "","","",""},
{TWLG_BASQUE, ANSI_CHARSET, MAKELANGID(LANG_BASQUE,SUBLANG_NEUTRAL), "Select Source","Sources:","Select","\x55\x74\x7a\x69"},
{TWLG_BENGALI, ANSI_CHARSET, MAKELANGID(LANG_BENGALI,SUBLANG_NEUTRAL), "","","",""},
{TWLG_BIHARI, 0, 0, "","","",""},
{TWLG_BODO, 0, 0, "","","",""},
{TWLG_BULGARIAN, RUSSIAN_CHARSET, MAKELANGID(LANG_BULGARIAN,SUBLANG_NEUTRAL), "","","",""},
{TWLG_BYELORUSSIAN, RUSSIAN_CHARSET, MAKELANGID(LANG_BELARUSIAN,SUBLANG_NEUTRAL), "","","",""},
{TWLG_CATALAN, ANSI_CHARSET, MAKELANGID(LANG_CATALAN,SUBLANG_NEUTRAL), "Select Source","Sources:","Select","\x43\x61\x6e\x63\x65\x6c\xc2\xb7\x6c\x61"},
{TWLG_CHINESE, GB2312_CHARSET, MAKELANGID(LANG_CHINESE,SUBLANG_NEUTRAL), "\xe9\x80\x89\xe6\x8b\xa9\xe6\x95\xb0\xe6\x8d\xae\xe6\xba\x90","\xe6\x95\xb0\xe6\x8d\xae\xe6\xba\x90\x3a","\xe9\x80\x89\xe6\x8b\xa9","\xe5\x8f\x96\xe6\xb6\x88"},
{TWLG_CHINESE_HONGKONG, CHINESEBIG5_CHARSET,MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_HONGKONG), "\xe9\x81\xb8\xe6\x93\x87\xe5\xbd\xb1\xe5\x83\x8f\xe4\xbe\x86\xe6\xba\x90","\xe5\xbd\xb1\xe5\x83\x8f\xe4\xbe\x86\xe6\xba\x90\x3a","\xe7\xa2\xba\xe5\xae\x9a","\xe5\x8f\x96\xe6\xb6\x88"},
{TWLG_CHINESE_PRC, GB2312_CHARSET, MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_SIMPLIFIED), "\xe9\x80\x89\xe6\x8b\xa9\xe6\x95\xb0\xe6\x8d\xae\xe6\xba\x90","\xe6\x95\xb0\xe6\x8d\xae\xe6\xba\x90\x3a","\xe9\x80\x89\xe6\x8b\xa9","\xe5\x8f\x96\xe6\xb6\x88"},
{TWLG_CHINESE_SIMPLIFIED, GB2312_CHARSET, MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_SIMPLIFIED), "\xe9\x80\x89\xe6\x8b\xa9\xe6\x95\xb0\xe6\x8d\xae\xe6\xba\x90","\xe6\x95\xb0\xe6\x8d\xae\xe6\xba\x90\x3a","\xe9\x80\x89\xe6\x8b\xa9","\xe5\x8f\x96\xe6\xb6\x88"},
{TWLG_CHINESE_SINGAPORE, GB2312_CHARSET, MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_SIMPLIFIED), "\xe9\x80\x89\xe6\x8b\xa9\xe6\x95\xb0\xe6\x8d\xae\xe6\xba\x90","\xe6\x95\xb0\xe6\x8d\xae\xe6\xba\x90\x3a","\xe9\x80\x89\xe6\x8b\xa9","\xe5\x8f\x96\xe6\xb6\x88"},
{TWLG_CHINESE_TAIWAN, CHINESEBIG5_CHARSET,MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_TRADITIONAL), "\xe9\x81\xb8\xe6\x93\x87\xe5\xbd\xb1\xe5\x83\x8f\xe4\xbe\x86\xe6\xba\x90","\xe5\xbd\xb1\xe5\x83\x8f\xe4\xbe\x86\xe6\xba\x90\x3a","\xe7\xa2\xba\xe5\xae\x9a","\xe5\x8f\x96\xe6\xb6\x88"},
{TWLG_CHINESE_TRADITIONAL,CHINESEBIG5_CHARSET,MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_TRADITIONAL), "\xe9\x81\xb8\xe6\x93\x87\xe5\xbd\xb1\xe5\x83\x8f\xe4\xbe\x86\xe6\xba\x90","\xe5\xbd\xb1\xe5\x83\x8f\xe4\xbe\x86\xe6\xba\x90\x3a","\xe7\xa2\xba\xe5\xae\x9a","\xe5\x8f\x96\xe6\xb6\x88"},
{TWLG_CROATIA, EASTEUROPE_CHARSET, MAKELANGID(LANG_CROATIAN,SUBLANG_NEUTRAL), "Select Source","Sources:","Select","\x4f\x64\x75\x73\x74\x61\x6e\x69"},
{TWLG_CZECH, EASTEUROPE_CHARSET, MAKELANGID(LANG_CZECH,SUBLANG_DEFAULT), "Select Source","Sources:","Select","\x53\x74\x6f\x72\x6e\x6f"},
{TWLG_DANISH, ANSI_CHARSET, MAKELANGID(LANG_DANISH,SUBLANG_NEUTRAL), "\x56\xC3\xA6\x6C\x67\x20\x45\x6E\x68\x65\x64","\x45\x6E\x68\x65\x64","\x56\xE6\x6C\x67","\x41\x6E\x6E\x75\x6C\x6C\x65\x72"},
{TWLG_DOGRI, 0, 0, "","","",""},
{TWLG_DUTCH, ANSI_CHARSET, MAKELANGID(LANG_DUTCH,SUBLANG_DUTCH), "\x53\x65\x6c\x65\x63\x74\x65\x65\x72\x20\x62\x72\x6f\x6e","\x42\x72\x6f\x6e\x6e\x65\x6e\x3a","\x53\x65\x6c\x65\x63\x74\x65\x72\x65\x6e","\x41\x6e\x6e\x75\x6c\x65\x72\x65\x6e"},
{TWLG_DUTCH_BELGIAN, ANSI_CHARSET, MAKELANGID(LANG_DUTCH,SUBLANG_DUTCH_BELGIAN), "\x53\x65\x6c\x65\x63\x74\x65\x65\x72\x20\x62\x72\x6f\x6e","\x42\x72\x6f\x6e\x6e\x65\x6e\x3a","\x53\x65\x6c\x65\x63\x74\x65\x72\x65\x6e","\x41\x6e\x6e\x75\x6c\x65\x72\x65\x6e"},
{TWLG_ENGLISH, ANSI_CHARSET, MAKELANGID(LANG_ENGLISH,SUBLANG_NEUTRAL), "Select Source","Sources:","Select","Cancel"},
{TWLG_ENGLISH_AUSTRALIAN, ANSI_CHARSET, MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_AUS), "Select Source","Sources:","Select","Cancel"},
{TWLG_ENGLISH_CANADIAN, ANSI_CHARSET, MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_CAN), "Select Source","Sources:","Select","Cancel"},
{TWLG_ENGLISH_IRELAND, ANSI_CHARSET, MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_EIRE), "Select Source","Sources:","Select","Cancel"},
{TWLG_ENGLISH_NEWZEALAND, ANSI_CHARSET, MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_NZ), "Select Source","Sources:","Select","Cancel"},
{TWLG_ENGLISH_SOUTHAFRICA,ANSI_CHARSET, MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_SOUTH_AFRICA), "Select Source","Sources:","Select","Cancel"},
{TWLG_ENGLISH_UK, ANSI_CHARSET, MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_UK), "Select Source","Sources:","Select","Cancel"},
{TWLG_ENGLISH_USA, ANSI_CHARSET, MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US), "Select Source","Sources:","Select","Cancel"},
{TWLG_ESTONIAN, BALTIC_CHARSET, MAKELANGID(LANG_ESTONIAN,SUBLANG_NEUTRAL), "Select Source","Sources:","Select","\x4b\x75\x73\x74\x75\x74\x61"},
{TWLG_FAEROESE, EASTEUROPE_CHARSET, MAKELANGID(LANG_FAEROESE,SUBLANG_NEUTRAL), "","","",""},
{TWLG_FARSI, ARABIC_CHARSET, MAKELANGID(LANG_FARSI,SUBLANG_NEUTRAL), "","","",""},
{TWLG_FINNISH, ANSI_CHARSET, MAKELANGID(LANG_FINNISH,SUBLANG_NEUTRAL), "Select Source","Sources:","Select","\x50\x65\x72\x75\x75\x74\x61"},
{TWLG_FRENCH, ANSI_CHARSET, MAKELANGID(LANG_FRENCH,SUBLANG_FRENCH), "\x53\xc3\xa9\x6c\x65\x63\x74\x69\x6f\x6e\x6e\x65\x72\x20\x73\x6f\x75\x72\x63\x65","\x53\x6f\x75\x72\x63\x65\x73\x3a","\x53\xc3\xa9\x6c\x65\x63\x74\x69\x6f\x6e\x6e\x65\x72","\x41\x6e\x6e\x75\x6c\x65\x72"},
{TWLG_FRENCH_BELGIAN, ANSI_CHARSET, MAKELANGID(LANG_FRENCH,SUBLANG_FRENCH_BELGIAN), "\x53\xc3\xa9\x6c\x65\x63\x74\x69\x6f\x6e\x6e\x65\x72\x20\x73\x6f\x75\x72\x63\x65","\x53\x6f\x75\x72\x63\x65\x73\x3a","\x53\xc3\xa9\x6c\x65\x63\x74\x69\x6f\x6e\x6e\x65\x72","\x41\x6e\x6e\x75\x6c\x65\x72"},
{TWLG_FRENCH_CANADIAN, ANSI_CHARSET, MAKELANGID(LANG_FRENCH,SUBLANG_FRENCH_CANADIAN), "\x53\xc3\xa9\x6c\x65\x63\x74\x69\x6f\x6e\x6e\x65\x72\x20\x73\x6f\x75\x72\x63\x65","\x53\x6f\x75\x72\x63\x65\x73\x3a","\x53\xc3\xa9\x6c\x65\x63\x74\x69\x6f\x6e\x6e\x65\x72","\x41\x6e\x6e\x75\x6c\x65\x72"},
{TWLG_FRENCH_LUXEMBOURG, ANSI_CHARSET, MAKELANGID(LANG_FRENCH,SUBLANG_FRENCH_LUXEMBOURG), "\x53\xc3\xa9\x6c\x65\x63\x74\x69\x6f\x6e\x6e\x65\x72\x20\x73\x6f\x75\x72\x63\x65","\x53\x6f\x75\x72\x63\x65\x73\x3a","\x53\xc3\xa9\x6c\x65\x63\x74\x69\x6f\x6e\x6e\x65\x72","\x41\x6e\x6e\x75\x6c\x65\x72"},
{TWLG_FRENCH_SWISS, ANSI_CHARSET, MAKELANGID(LANG_FRENCH,SUBLANG_FRENCH_SWISS), "\x53\xc3\xa9\x6c\x65\x63\x74\x69\x6f\x6e\x6e\x65\x72\x20\x73\x6f\x75\x72\x63\x65","\x53\x6f\x75\x72\x63\x65\x73\x3a","\x53\xc3\xa9\x6c\x65\x63\x74\x69\x6f\x6e\x6e\x65\x72","\x41\x6e\x6e\x75\x6c\x65\x72"},
{TWLG_GERMAN, ANSI_CHARSET, MAKELANGID(LANG_GERMAN,SUBLANG_GERMAN), "\x51\x75\x65\x6c\x6c\x65\x20\x77\xc3\xa4\x68\x6c\x65\x6e","\x51\x75\x65\x6c\x6c\x65\x6e\x3a","\x41\x75\x73\x77\xc3\xa4\x68\x6c\x65\x6e","\x41\x62\x62\x72\x65\x63\x68\x65\x6e"},
{TWLG_GERMAN_AUSTRIAN, ANSI_CHARSET, MAKELANGID(LANG_GERMAN,SUBLANG_GERMAN_AUSTRIAN), "\x51\x75\x65\x6c\x6c\x65\x20\x77\xc3\xa4\x68\x6c\x65\x6e","\x51\x75\x65\x6c\x6c\x65\x6e\x3a","\x41\x75\x73\x77\xc3\xa4\x68\x6c\x65\x6e","\x41\x62\x62\x72\x65\x63\x68\x65\x6e"},
{TWLG_GERMAN_LIECHTENSTEIN,ANSI_CHARSET, MAKELANGID(LANG_GERMAN,SUBLANG_GERMAN_LIECHTENSTEIN), "\x51\x75\x65\x6c\x6c\x65\x20\x77\xc3\xa4\x68\x6c\x65\x6e","\x51\x75\x65\x6c\x6c\x65\x6e\x3a","\x41\x75\x73\x77\xc3\xa4\x68\x6c\x65\x6e","\x41\x62\x62\x72\x65\x63\x68\x65\x6e"},
{TWLG_GERMAN_LUXEMBOURG, ANSI_CHARSET, MAKELANGID(LANG_GERMAN,SUBLANG_GERMAN_LUXEMBOURG), "\x51\x75\x65\x6c\x6c\x65\x20\x77\xc3\xa4\x68\x6c\x65\x6e","\x51\x75\x65\x6c\x6c\x65\x6e\x3a","\x41\x75\x73\x77\xc3\xa4\x68\x6c\x65\x6e","\x41\x62\x62\x72\x65\x63\x68\x65\x6e"},
{TWLG_GERMAN_SWISS, ANSI_CHARSET, MAKELANGID(LANG_GERMAN,SUBLANG_GERMAN_SWISS), "\x51\x75\x65\x6c\x6c\x65\x20\x77\xc3\xa4\x68\x6c\x65\x6e","\x51\x75\x65\x6c\x6c\x65\x6e\x3a","\x41\x75\x73\x77\xc3\xa4\x68\x6c\x65\x6e","\x41\x62\x62\x72\x65\x63\x68\x65\x6e"},
{TWLG_GREEK, GREEK_CHARSET, MAKELANGID(LANG_GREEK,SUBLANG_DEFAULT), "","","",""},
{TWLG_GUJARATI, GREEK_CHARSET, MAKELANGID(LANG_GUJARATI,SUBLANG_DEFAULT), "","","",""},
{TWLG_HARYANVI, 0, 0, "","","",""},
{TWLG_HEBREW, HEBREW_CHARSET, MAKELANGID(LANG_HEBREW,SUBLANG_NEUTRAL), "","","",""},
{TWLG_HINDI, HEBREW_CHARSET, MAKELANGID(LANG_HINDI,SUBLANG_NEUTRAL), "","","",""},
{TWLG_HUNGARIAN, EASTEUROPE_CHARSET, MAKELANGID(LANG_HUNGARIAN,SUBLANG_NEUTRAL), "Select Source","Sources:","Select","\x4d\xc3\xa9\x67\x73\x65"},
{TWLG_ICELANDIC, ANSI_CHARSET, MAKELANGID(LANG_ICELANDIC,SUBLANG_NEUTRAL), "","","",""},
{TWLG_INDONESIAN, ANSI_CHARSET, MAKELANGID(LANG_INDONESIAN,SUBLANG_NEUTRAL), "\x50\x69\x6c\x69\x74\x68\x20\x53\x75\x6d\x62\x65\x72","\x53\x75\x6d\x62\x65\x72\x3a","\x50\x69\x6c\x69\x74\x68","\x42\x61\x74\x61\x6c"},
{TWLG_ITALIAN, ANSI_CHARSET, MAKELANGID(LANG_ITALIAN,SUBLANG_ITALIAN), "\x53\x65\x6c\x65\x7a\x69\x6f\x6e\x61\x20\x6f\x72\x69\x67\x69\x6e\x65","\x4f\x72\x69\x67\x69\x6e\x69\x3a","\x53\x65\x6c\x65\x7a\x69\x6f\x6e\x61","\x41\x6e\x6e\x75\x6c\x6c\x61"},
{TWLG_ITALIAN_SWISS, ANSI_CHARSET, MAKELANGID(LANG_ITALIAN,SUBLANG_ITALIAN_SWISS), "\x53\x65\x6c\x65\x7a\x69\x6f\x6e\x61\x20\x6f\x72\x69\x67\x69\x6e\x65","\x4f\x72\x69\x67\x69\x6e\x69\x3a","\x53\x65\x6c\x65\x7a\x69\x6f\x6e\x61","\x41\x6e\x6e\x75\x6c\x6c\x61"},
{TWLG_JAPANESE, SHIFTJIS_CHARSET, MAKELANGID(LANG_JAPANESE,SUBLANG_DEFAULT), "\xe5\x8e\x9f\xe7\xa8\xbf\xe3\x81\xae\xe9\x81\xb8\xe6\x8a\x9e","\xe5\x8e\x9f\xe7\xa8\xbf\x3a","\xe9\x81\xb8\xe6\x8a\x9e","\xe3\x82\xad\xe3\x83\xa3\xe3\x83\xb3\xe3\x82\xbb\xe3\x83\xab"},
{TWLG_KANNADA, ANSI_CHARSET, MAKELANGID(LANG_KANNADA,SUBLANG_NEUTRAL), "","","",""},
{TWLG_KASHMIRI, ANSI_CHARSET, MAKELANGID(LANG_KASHMIRI,SUBLANG_NEUTRAL), "","","",""},
{TWLG_KOREAN, HANGUL_CHARSET, MAKELANGID(LANG_KOREAN,SUBLANG_KOREAN), "\xec\x9e\xa5\xec\xb9\x98\x20\xec\x84\xa0\xed\x83\x9d","\xec\x9e\xa5\xec\xb9\x98","\xec\x84\xa0\xed\x83\x9d","\xec\xb7\xa8\xec\x86\x8c"},
{TWLG_KOREAN_JOHAB, JOHAB_CHARSET, MAKELANGID(LANG_KOREAN,SUBLANG_KOREAN), "\xec\x9e\xa5\xec\xb9\x98\x20\xec\x84\xa0\xed\x83\x9d","\xec\x9e\xa5\xec\xb9\x98","\xec\x84\xa0\xed\x83\x9d","\xec\xb7\xa8\xec\x86\x8c"},
{TWLG_LATVIAN, BALTIC_CHARSET, MAKELANGID(LANG_LATVIAN,SUBLANG_NEUTRAL), "","","",""},
{TWLG_LITHUANIAN, BALTIC_CHARSET, MAKELANGID(LANG_LITHUANIAN,SUBLANG_NEUTRAL), "","","",""},
{TWLG_MALAYALAM, BALTIC_CHARSET, MAKELANGID(LANG_MALAYALAM,SUBLANG_NEUTRAL), "","","",""},
{TWLG_MARATHI, ANSI_CHARSET, MAKELANGID(LANG_MARATHI,SUBLANG_NEUTRAL), "","","",""},
{TWLG_MARWARI, 0, 0, "","","",""},
{TWLG_MEGHALAYAN, 0, 0, "","","",""},
{TWLG_MIZO, 0, 0, "","","",""},
{TWLG_NAGA, 0, 0, "","","",""},
{TWLG_NORWEGIAN, ANSI_CHARSET, MAKELANGID(LANG_NORWEGIAN,SUBLANG_NEUTRAL), "","","",""},
{TWLG_NORWEGIAN_BOKMAL, ANSI_CHARSET, MAKELANGID(LANG_NORWEGIAN,SUBLANG_NORWEGIAN_BOKMAL), "","","",""},
{TWLG_NORWEGIAN_NYNORSK, ANSI_CHARSET, MAKELANGID(LANG_NORWEGIAN,SUBLANG_NORWEGIAN_NYNORSK), "","","",""},
{TWLG_ORISSI, 0, 0, "","","",""},
{TWLG_POLISH, EASTEUROPE_CHARSET, MAKELANGID(LANG_POLISH,SUBLANG_NEUTRAL), "Select Source","Sources:","Select","\x41\x6e\x75\x6c\x75\x6a"},
{TWLG_PORTUGUESE, EASTEUROPE_CHARSET, MAKELANGID(LANG_PORTUGUESE,SUBLANG_PORTUGUESE), "\x53\x65\x6c\x65\x63\x69\x6f\x6e\x61\x72\x20\x4f\x72\x69\x67\x65\x6d","\x4f\x72\x69\x67\x65\x6e\x73\x3a","\x53\x65\x6c\x65\x63\x69\x6f\x6e\x61\x72","\x43\x61\x6e\x63\x65\x6c\x61\x72"},
{TWLG_PORTUGUESE_BRAZIL, ANSI_CHARSET, MAKELANGID(LANG_PORTUGUESE,SUBLANG_PORTUGUESE_BRAZILIAN), "\x53\x65\x6c\x65\x63\x69\x6f\x6e\x61\x72\x20\x4f\x72\x69\x67\x65\x6d","\x4f\x72\x69\x67\x65\x6e\x73\x3a","\x53\x65\x6c\x65\x63\x69\x6f\x6e\x61\x72","\x43\x61\x6e\x63\x65\x6c\x61\x72"},
{TWLG_PUNJABI, ANSI_CHARSET, MAKELANGID(LANG_PUNJABI,SUBLANG_NEUTRAL), "","","",""},
{TWLG_PUSHTU, 0, 0, "","","",""},
{TWLG_ROMANIAN, EASTEUROPE_CHARSET, MAKELANGID(LANG_ROMANIAN,SUBLANG_NEUTRAL), "","","",""},
{TWLG_RUSSIAN, RUSSIAN_CHARSET, MAKELANGID(LANG_RUSSIAN,SUBLANG_DEFAULT), "\xd0\x92\xd1\x8b\xd0\xb1\xd1\x80\xd0\xb0\xd1\x82\xd1\x8c\x20\xd0\xb8\xd1\x81\xd1\x82\xd0\xbe\xd1\x87\xd0\xbd\xd0\xb8\xd0\xba","\xd0\x98\xd1\x81\xd1\x82\xd0\xbe\xd1\x87\xd0\xbd\xd0\xb8\xd0\xba\xd0\xb8\x3a","\xd0\x92\xd1\x8b\xd0\xb1\xd1\x80\xd0\xb0\xd1\x82\xd1\x8c","\xd0\x9e\xd1\x82\xd0\xbc\xd0\xb5\xd0\xbd\xd0\xb8\xd1\x82\xd1\x8c"},
{TWLG_SERBIAN_CYRILLIC, ANSI_CHARSET, MAKELANGID(LANG_SERBIAN,SUBLANG_SERBIAN_CYRILLIC), "","","",""},
{TWLG_SERBIAN_LATIN, EASTEUROPE_CHARSET, MAKELANGID(LANG_SERBIAN,SUBLANG_SERBIAN_LATIN), "","","",""},
{TWLG_SIKKIMI, 0, 0, "","","",""},
{TWLG_SLOVAK, EASTEUROPE_CHARSET, MAKELANGID(LANG_SLOVAK,SUBLANG_NEUTRAL), "","","",""},
{TWLG_SLOVENIAN, EASTEUROPE_CHARSET, MAKELANGID(LANG_SLOVENIAN,SUBLANG_NEUTRAL), "Select Source","Sources:","Select","\x50\x72\x65\x6b\x69\x6e\x69"},
{TWLG_SPANISH, ANSI_CHARSET, MAKELANGID(LANG_SPANISH,SUBLANG_SPANISH), "\x53\x65\x6c\x65\x63\x63\x69\xc3\xb3\x6e\x20\x64\x65\x20\x66\x75\x65\x6e\x74\x65","\x46\x75\x65\x6e\x74\x65\x73\x3a","\x53\x65\x6c\x65\x63\x63\x69\x6f\x6e\x61\x72","\x43\x61\x6e\x63\x65\x6c\x61\x72"},
{TWLG_SPANISH_MEXICAN, ANSI_CHARSET, MAKELANGID(LANG_SPANISH,SUBLANG_SPANISH_MEXICAN), "\x53\x65\x6c\x65\x63\x63\x69\xc3\xb3\x6e\x20\x64\x65\x20\x66\x75\x65\x6e\x74\x65","\x46\x75\x65\x6e\x74\x65\x73\x3a","\x53\x65\x6c\x65\x63\x63\x69\x6f\x6e\x61\x72","\x43\x61\x6e\x63\x65\x6c\x61\x72"},
{TWLG_SPANISH_MODERN, ANSI_CHARSET, MAKELANGID(LANG_SPANISH,SUBLANG_SPANISH_MODERN), "\x53\x65\x6c\x65\x63\x63\x69\xc3\xb3\x6e\x20\x64\x65\x20\x66\x75\x65\x6e\x74\x65","\x46\x75\x65\x6e\x74\x65\x73\x3a","\x53\x65\x6c\x65\x63\x63\x69\x6f\x6e\x61\x72","\x43\x61\x6e\x63\x65\x6c\x61\x72"},
{TWLG_SWEDISH, ANSI_CHARSET, MAKELANGID(LANG_SWEDISH,SUBLANG_SWEDISH), "Select Source","Sources:","Select","\x41\x76\x62\x72\x79\x74"},
{TWLG_SWEDISH_FINLAND, ANSI_CHARSET, MAKELANGID(LANG_SWEDISH,SUBLANG_SWEDISH_FINLAND), "Select Source","Sources:","Select","\x41\x76\x62\x72\x79\x74"},
{TWLG_TAMIL, ANSI_CHARSET, MAKELANGID(LANG_TAMIL,SUBLANG_NEUTRAL), "","","",""},
{TWLG_TELUGU, ANSI_CHARSET, MAKELANGID(LANG_TELUGU,SUBLANG_NEUTRAL), "","","",""},
{TWLG_THAI, THAI_CHARSET, MAKELANGID(LANG_THAI,SUBLANG_NEUTRAL), "","","",""},
{TWLG_TRIPURI, 0, 0, "","","",""},
{TWLG_TURKISH, TURKISH_CHARSET, MAKELANGID(LANG_TURKISH,SUBLANG_DEFAULT), "\x4b\x61\x79\x6e\x61\x6b\x20\x73\x65\xc3\xa7\x69\x6e\x69\x7a","\x4b\x61\x79\x6e\x61\x6b","\x53\x65\xc3\xa7\x69\x6e\x69\x7a","\xc4\xb0\x70\x74\x61\x6c"},
{TWLG_UKRANIAN, RUSSIAN_CHARSET, MAKELANGID(LANG_UKRAINIAN,SUBLANG_NEUTRAL), "","","",""},
{TWLG_URDU, ANSI_CHARSET, MAKELANGID(LANG_URDU,SUBLANG_NEUTRAL), "","","",""},
{TWLG_VIETNAMESE, VIETNAMESE_CHARSET, MAKELANGID(LANG_VIETNAMESE,SUBLANG_NEUTRAL), "","","",""},
{-1, 0, 0, 0, 0, 0, 0} // must be last...
};
#elif (TWNDSM_CMP == TWNDSM_CMP_GNUGPP)
// We don't have anything for here...
#else
#error Sorry, we do not recognize this system...
#endif
#if (TWNDSM_OS == TWNDSM_OS_MACOSX)
#pragma clang diagnostic pop
#endif
#if TWNDSM_OS_64BIT
#define TWNDSM_DS_REG_LOC "Software\\Microsoft\\Windows NT\\CurrentVersion\\TWAIN64"
#else
#define TWNDSM_DS_REG_LOC "Software\\Microsoft\\Windows NT\\CurrentVersion\\TWAIN"
#endif
/**
* @defgroup MemFunctions declarations for our memory management functions...
* @{
*/
#if 0
/**
* Memory Allocate
* @param[in] _size the size of the memory to allocate
* @return the handle to the memory allocated
*/
static TW_HANDLE PASCAL DSM_MemAllocate(TW_UINT32 _size);
/**
* Memory Free
* @param[in] _handle the handle to the memory to free
*/
static void PASCAL DSM_MemFree(TW_HANDLE _handle);
/**
* Memory Lock
* @param[in] _handle the handle to the memory to lock
* @return locked pointer to the memory in the handle
*/
static TW_MEMREF PASCAL DSM_MemLock(TW_HANDLE _handle);
/**
* Memory Unlock
* @param[in] _handle the handle to the memory to unlock
*/
static void PASCAL DSM_MemUnlock(TW_HANDLE _handle);
// @}
#endif
/**
* Data Source Manager Entry Point.
*
* The only entry point into the Data Source Manager. This is the only
* function not a part of CTwnDsm. It's responsible for managing the
* class. We keep things organized this way to make sure that we don't
* allocate any resources until MSG_OPENDSM, and that we release all
* resources as a part of MSG_CLOSEDSM. If this is done correctly then
* we won't mind if the library isn't freed (which has been seen to
* happen sometimes with COM)...
*
* Defined in twain.h
*
* @param[in] _pOrigin Identifies the source module of the message. This could
* identify an Application, a Source, or the Source Manager.
*
* @param[in] _pDest Identifies the destination module for the message.
* This could identify an application or a data source.
* If this is NULL, the message goes to the Source Manager.
*
* @param[in] _DG The Data Group.
* Example: DG_IMAGE.
*
* @param[in] _DAT The Data Attribute Type.
* Example: DAT_IMAGEMEMXFER.
*
* @param[in] _MSG The message. Messages are interpreted by the destination module
* with respect to the Data Group and the Data Attribute Type.
* Example: MSG_GET.
*
* @param[in,out] _pData A pointer to the data structure or variable identified
* by the Data Attribute Type.
* Example: (TW_MEMREF)&ImageMemXfer
* where ImageMemXfer is a TW_IMAGEMEMXFER structure.
*
* @return a valid TWRC_xxxx return code.
* Example: TWRC_SUCCESS.
*/
DSMENTRY DSM_Entry(TW_IDENTITY *_pOrigin,
TW_IDENTITY *_pDest,
TW_UINT32 _DG,
TW_UINT16 _DAT,
TW_UINT16 _MSG,
TW_MEMREF _pData)
{
TW_UINT16 rcDSM;
// Validate...
if (0 == _pOrigin)
{
return TWRC_FAILURE;
}
// If we're processing DG_CONTROL/DAT_PARENT/MSG_OPENDSM then see
// if we need to create our CTwnDsm object. We don't want to
// allocate any resources prior to new CTwnDsm!!!
if ( (_MSG == MSG_OPENDSM)
&& (_DAT == DAT_PARENT)
&& (_DG == DG_CONTROL)
&& (0 == g_ptwndsm))
{
g_ptwndsm = new CTwnDsm;
if (0 == g_ptwndsm)
{
kPANIC("Failed to new CTwnDsm!!!");
return TWRC_FAILURE;
}
}
// If we have no CTwnDsm object, then we're in trouble, but
// try to handle DAT_STATUS in case it gets called before
// MSG_OPENDSM or after MSG_CLOSEDSM...
if (0 == g_ptwndsm)
{
if ( ( (_MSG == MSG_GET) || (_MSG == MSG_CHECKSTATUS) )
&& (_DAT == DAT_STATUS)
&& (_DG == DG_CONTROL)
&& (0 != _pData)
)
{
((TW_STATUS*)_pData)->ConditionCode = TWCC_BUMMER;
return (TWRC_SUCCESS);
}
else
{
//kLOG((kLOGERR,"DAT_STATUS called before MSG_OPENDSM or after MSG_CLOSEDSM..."));
return (TWRC_FAILURE);
}
}
// Transfer control over to our dsm object, otherwise we'll
// be doing g_ptwndsm all over the place...
rcDSM = g_ptwndsm->DSM_Entry(_pOrigin,_pDest,_DG,_DAT,_MSG,_pData);
// If we successfully processed DG_CONTROL/DAT_PARENT/MSG_CLOSEDSM,
// and don't have any other applications with it open,
// then destroy our object. We don't want to have any resources
// lingering around after we destroy our CTwnDsm object!!!
if ( (TWRC_SUCCESS == rcDSM)
&& (_MSG == MSG_CLOSEDSM)
&& (_DAT == DAT_PARENT)
&& (_DG == DG_CONTROL)
&& g_ptwndsm->DSMGetState() != dsmState_Open )
{
delete g_ptwndsm;
g_ptwndsm = 0;
}
// All done...
return rcDSM;
}
/*
* Our constructor...
* Clean out the pod and set stuff. Get logging set up so we
* can have a clue what's going on...
*/
CTwnDsm::CTwnDsm()
{
// Zero out the pod...
memset(&pod,0,sizeof(pod));
// Get our logging object...
g_ptwndsmlog = new CTwnDsmLog;
if (!g_ptwndsmlog)
{
kPANIC("Failed to new CTwnDsmLog!!!");
}
// If logging is on, then this is a good chance to dump information
// about ourselves...
kLOG((kLOGINFO,"************************************************"));
kLOG((kLOGINFO,"%s",TWNDSM_ORGANIZATION));
kLOG((kLOGINFO,"%s",TWNDSM_DESCRIPTION));
kLOG((kLOGINFO,"version: %s",TWNDSM_VERSION_STR));
// Get our application object...
pod.m_ptwndsmapps = new CTwnDsmApps();
if (!pod.m_ptwndsmapps)
{
kPANIC("Failed to new CTwnDsmApps!!!");
}
}
/*
* Our destructor...
* Free any resources we might have...
*/
CTwnDsm::~CTwnDsm()
{
if (pod.m_ptwndsmapps)
{
delete pod.m_ptwndsmapps;
}
if (g_ptwndsmlog)
{
delete g_ptwndsmlog;
}
memset(&pod,0,sizeof(pod));
}
/*
* This is where we finish up the DSM_Entry duties inside of the
* context of the class...
*/
TW_UINT16 CTwnDsm::DSM_Entry(TW_IDENTITY *_pOrigin,
TW_IDENTITY *_pDest,
TW_UINT32 _DG,
TW_UINT16 _DAT,
TW_UINT16 _MSG,
TW_MEMREF _pData)
{
TW_UINT16 rcDSM = TWRC_SUCCESS;
bool bPrinted;
TW_CALLBACK2 *ptwcallback2;
TW_IDENTITY *pAppId = _pOrigin;
TW_IDENTITY *pDSId = _pDest;
// Do a test to see if pOrigin is a DS instead of App, if so then switch pAppId and pDSId
// MSG_INVOKE_CALLBACK was only used on the Mac and is now deprecated (ver 2.1)
// it is here for backwords capabiltiy
if ( (_DAT == DAT_NULL /*&& _DG == DG_CONTROL */)
|| (_DAT == DAT_CALLBACK && _MSG == MSG_INVOKE_CALLBACK /*&& _DG == DG_CONTROL */) )
{
pAppId = _pDest;
pDSId = _pOrigin;
}
// Print the triplets to stdout for information purposes
bPrinted = printTripletsInfo(_pOrigin,_pDest,_DG,_DAT,_MSG,_pData);
// Sniff for the application forwarding an event to the
// DS. It may be possible that the app has a message waiting for
// it because it didn't register a callback.
if ( (DAT_EVENT == _DAT)
&& (MSG_PROCESSEVENT == _MSG))
{
// Check that the AppID and DSID are valid...
if (!pod.m_ptwndsmapps->AppValidateIds(pAppId,pDSId))
{
kLOG((kLOGINFO,"Bad TW_IDENTITY"));
pod.m_ptwndsmapps->AppSetConditionCode(0,TWCC_BADPROTOCOL);
rcDSM = TWRC_FAILURE;
}
else if (pod.m_ptwndsmapps->DsCallbackIsWaiting(pAppId,(TWID_T)pDSId->Id))
{
ptwcallback2 = pod.m_ptwndsmapps->DsCallback2Get(pAppId,(TWID_T)pDSId->Id);
((TW_EVENT*)(_pData))->TWMessage = ptwcallback2->Message;
if( g_ptwndsmlog )
{
char szMsg[64];
StringFromMsg(szMsg,NCHARS(szMsg),ptwcallback2->Message);
kLOG((kLOGINFO,"%.32s retrieving DAT_EVENT / %s\n", pAppId->ProductName, szMsg));
}
ptwcallback2->Message = 0;
pod.m_ptwndsmapps->DsCallbackSetWaiting(pAppId,(TWID_T)pDSId->Id,FALSE);
rcDSM = TWRC_DSEVENT;
}
// No callback, so fall on through...
}
// Is this msg for us?
if( TWRC_SUCCESS == rcDSM )
{
switch (_DAT)
{
case DAT_IDENTITY:
// If the pDSId is 0 then the message is intended for us. We're
// going to force the matter if _MSG is MSG_CLOSEDS, otherwise
// we send the MSG_CLOSEDS to the driver, but never process it
// ourselves, which seems like a terrible idea...
if ((pDSId == 0) || (_MSG == MSG_CLOSEDS))
{
rcDSM = DSM_Identity(pAppId,_MSG,(TW_IDENTITY*)_pData);
break;
}
// else we fall thru to send the message onto the DS
default:
// check if the application is open or not. If it isn't, we have a bad sequence
if (dsmState_Open == pod.m_ptwndsmapps->AppGetState(pAppId))
{
// Check that the AppID and DSID are valid...
if (!pod.m_ptwndsmapps->AppValidateIds(pAppId,pDSId))
{
kLOG((kLOGINFO,"Bad TW_IDENTITY"));
pod.m_ptwndsmapps->AppSetConditionCode(0,TWCC_BADPROTOCOL);
rcDSM = TWRC_FAILURE;
}
// Issue the command...
else if (0 != pod.m_ptwndsmapps->DsGetEntryProc(pAppId,(TWID_T)pDSId->Id))
{
// Don't send a new message if the DS is still processing a previous message
// or if the application has not returned back from recieving callback.
// Place a Try | Catch around the function so we can maintain correct state
// in the case of an exception
//
// We are only enforcing this new behavior for TWAIN 2.2 applications and
// and higher. Older apps can still use the 'wrong' behavior. We need this
// to preserve backwards compability, and to give ourselves a chance to
// inform developers of the new requirement...
//
if(((((pAppId->ProtocolMajor*10) + (pAppId->ProtocolMinor)) <= 201) ||
!pod.m_ptwndsmapps->DsIsProcessingMessage(pAppId,(TWID_T)pDSId->Id) ) &&
((((pAppId->ProtocolMajor*10) + (pAppId->ProtocolMinor)) <= 202) ||
!pod.m_ptwndsmapps->DsIsAppProcessingCallback(pAppId,(TWID_T)pDSId->Id) ) )
{
pod.m_ptwndsmapps->DsSetProcessingMessage(pAppId,(TWID_T)pDSId->Id,TRUE);
try
{
// Create a local copy of the AppIdentity
TW_IDENTITY AppId = *pod.m_ptwndsmapps->AppGetIdentity(pAppId);
rcDSM = (pod.m_ptwndsmapps->DsGetEntryProc(&AppId,(TWID_T)pDSId->Id))(
&AppId,
_DG,
_DAT,
_MSG,
_pData);
}
catch(...)
{
rcDSM = TWRC_FAILURE;
pod.m_ptwndsmapps->AppSetConditionCode(pAppId,TWCC_BUMMER);
kLOG((kLOGERR,"Exception caught while DS was processing message. Returning Failure."));
}
pod.m_ptwndsmapps->DsSetProcessingMessage(pAppId,(TWID_T)pDSId->Id,FALSE);
}
else
{
if( _DAT == DAT_EVENT && _MSG == MSG_PROCESSEVENT)
{
kLOG((kLOGINFO,"Nested DAT_EVENT / MSG_PROCESSEVENT Ignored"));
rcDSM = TWRC_NOTDSEVENT;
((TW_EVENT*)(_pData))->TWMessage = MSG_NULL;
}
else
{
kLOG((kLOGERR,"Nested calls back to the DS. Returning Failure."));
pod.m_ptwndsmapps->AppSetConditionCode(pAppId,TWCC_SEQERROR);
rcDSM = TWRC_FAILURE;
}
}
}
// For some reason we have no pointer to the dsentry function...
else
{
kLOG((kLOGERR,"Unable to find driver, check your AppId and DsId values..."));
pod.m_ptwndsmapps->AppSetConditionCode(pAppId,TWCC_OPERATIONERROR);
kLOG((kLOGERR,"DS_Entry is null...%ld",(TWID_T)pAppId->Id));
rcDSM = TWRC_FAILURE;
}
}
else
{
kLOG((kLOGINFO,"DS is not open"));
pod.m_ptwndsmapps->AppSetConditionCode(pAppId,TWCC_SEQERROR);
rcDSM = TWRC_FAILURE;
}
break;
case DAT_PARENT:
rcDSM = DSM_Parent(pAppId,_MSG,_pData);
break;
case DAT_TWUNKIDENTITY:
rcDSM = DSM_TwunkIdentity(pAppId,_MSG,(TW_TWUNKIDENTITY*)_pData);
break;
case DAT_ENTRYPOINT:
rcDSM = DSM_Entrypoint(pAppId,_MSG,(TW_ENTRYPOINT*)_pData);
break;
case DAT_STATUS:
if( _MSG == MSG_CHECKSTATUS )
{
_MSG = MSG_GET;
kLOG((kLOGINFO, "MSG_CHECKSTATUS is Depreciated using MSG_GET"));
}
// If we get a DSId then it is intended to be passed along to the driver.
// If the DSId is null then the request is handled by the DSM
// If we're talking to a driver (state 4 or higher), then we
// will pass the DAT_STATUS request down to it...
if ( 0 != pDSId
&& (dsmState_Open == pod.m_ptwndsmapps->AppGetState(pAppId))
&& pod.m_ptwndsmapps->AppValidateIds(pAppId,pDSId)
&& (0 != pod.m_ptwndsmapps->DsGetEntryProc(pAppId,(TWID_T)pDSId->Id)))
{
// Create a local copy of the AppIdentity
TW_IDENTITY AppId = *pod.m_ptwndsmapps->AppGetIdentity(pAppId);
rcDSM = (pod.m_ptwndsmapps->DsGetEntryProc(&AppId,(TWID_T)pDSId->Id))(
&AppId,
_DG,
_DAT,
_MSG,
_pData);
}
// Otherwise, handle it ourself...
else
{
rcDSM = DSM_Status(pAppId,_MSG,(TW_STATUS*)_pData);
}
break;
case DAT_CALLBACK:
// DAT_CALLBACK can be either from an Application registering its Callback,
// or from a DS Invoking a request to send a message to the Application
rcDSM = DSM_Callback(_pOrigin,_pDest,_MSG,(TW_CALLBACK*)_pData);
break;
case DAT_CALLBACK2:
// DAT_CALLBACK2 can be either from an Application registering its Callback,
// or from a DS Invoking a request to send a message to the Application
rcDSM = DSM_Callback2(_pOrigin,_pDest,_MSG,(TW_CALLBACK2*)_pData);
break;
case DAT_NULL:
// Note how the origin and destination are switched for this
// call (and only this call). Because, of course, this
// message is being send from the driver to the application...
rcDSM = DSM_Null(pAppId,pDSId,_MSG);
break;
}
}
// Log how it went...
if (bPrinted)
{
printResults(_DG,_DAT,_MSG,_pData,rcDSM);
}
return rcDSM;
}
/*
* Return the state of the DSM by checking the state of all applications
*/
DSM_State CTwnDsm::DSMGetState()
{
DSM_State CurrentState = pod.m_ptwndsmapps->AppGetState();
return CurrentState;
}
/*
* Handle DAT_STATUS. Just a few things of note, we handle some
* DAT_STATUS stuff in DSM_Entry. And per the spec we have to
* clear the condition code when we are done. I've also put in
* MSG_CHECKSTATUS, because I can't imagine why we have the silly
* thing if it isn't for this function...
*/
TW_INT16 CTwnDsm::DSM_Status(TW_IDENTITY *_pAppId,
TW_UINT16 _MSG,
TW_STATUS *_pStatus)
{
TW_INT16 result = TWRC_SUCCESS;
switch (_MSG)
{
case MSG_GET:
case MSG_CHECKSTATUS:
_pStatus->ConditionCode = pod.m_ptwndsmapps->AppGetConditionCode(_pAppId);
_pStatus->Reserved = 0;
break;
default:
result = TWRC_FAILURE;
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADPROTOCOL);
break;
}
return result;
}
/*
* Handle DAT_PARENT. This is where the DSM is expected to
* do most of its contribution, which is finding drivers for
* the application...
*/
TW_INT16 CTwnDsm::DSM_Parent(TW_IDENTITY *_pAppId,
TW_UINT16 _MSG,
TW_MEMREF _MemRef)
{
TW_UINT16 result;
// Validate...
if (0 == _pAppId)
{
kLOG((kLOGERR,"_pAppId is null"));
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADVALUE);
return TWRC_FAILURE;
}
// Init stuff...
result = TWRC_SUCCESS;
// Process the message...
switch (_MSG)
{
case MSG_OPENDSM:
// Try to add the proposed item...
result = pod.m_ptwndsmapps->AddApp(_pAppId,_MemRef);
break;
case MSG_CLOSEDSM:
// Try to remove the proposed item...
result = pod.m_ptwndsmapps->RemoveApp(_pAppId);
break;
default:
result = TWRC_FAILURE;
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADPROTOCOL);
break;
}
return result;
}
/*
* Handle DAT_IDENTITY. This is where the DSM is expected to
* do most of its contribution, which is finding drivers for
* the application...
*/
TW_INT16 CTwnDsm::DSM_Identity(TW_IDENTITY *_pAppId,
TW_UINT16 _MSG,
TW_IDENTITY *_pDsId)
{
TW_INT16 result;
// Validate...
if (0 == _pAppId || (TWID_T)_pAppId->Id >= pod.m_ptwndsmapps->AppGetNumApp())
{
kLOG((kLOGERR,"_pAppId is null"));
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADVALUE);
return TWRC_FAILURE;
}
// Init stuff...
result = TWRC_SUCCESS;
// Pick the message...
if (dsmState_Open == pod.m_ptwndsmapps->AppGetState(_pAppId))
{
switch (_MSG)
{
case MSG_OPENDS:
result = OpenDS(_pAppId,_pDsId);
break;
case MSG_CLOSEDS:
result = CloseDS(_pAppId,_pDsId);
break;
case MSG_USERSELECT:
result = DSM_SelectDS(_pAppId,_pDsId);
break;
case MSG_GETFIRST:
result = DSM_GetFirst(_pAppId,_pDsId);
break;
case MSG_GETNEXT:
result = DSM_GetNext(_pAppId,_pDsId);
break;
case MSG_GETDEFAULT:
result = GetMatchingDefault(_pAppId,_pDsId);
break;
case MSG_SET:
result = DSM_SetDefaultDS(_pAppId,_pDsId);
break;
default:
result = TWRC_FAILURE;
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADPROTOCOL);
break;
}
}
else
{
result = TWRC_FAILURE;
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_SEQERROR);
}
return result;
}
/*
* Handle DAT_TWUNKIDENTITY. This is here for backwards compatibility.
* DAT_TWUNKIDENTITY is undocumented. It was used by the Twunking
* layer. Some old applications use it to get the path to the DS.
* We need to continue to support it.
*/
TW_INT16 CTwnDsm::DSM_TwunkIdentity(TW_IDENTITY *_pAppId,
TW_UINT16 _MSG,
TW_TWUNKIDENTITY *_pTwunkId)
{
TW_INT16 result = TWRC_SUCCESS;
// Validate...
if (0 == _pAppId || (TWID_T)_pAppId->Id >= pod.m_ptwndsmapps->AppGetNumApp())
{
kLOG((kLOGERR,"_pAppId is null"));
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADVALUE);
return TWRC_FAILURE;
}
else if (dsmState_Open != pod.m_ptwndsmapps->AppGetState(_pAppId))
{
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_SEQERROR);
return TWRC_FAILURE;
}
else if (MSG_GET != _MSG)
{
kLOG((kLOGERR,"protocol error"));
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADPROTOCOL);
return TWRC_FAILURE;
}
else if (0 == _pTwunkId)
{
kLOG((kLOGERR,"_pTwunkId is null"));
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADVALUE);
return TWRC_FAILURE;
}
// Check that the DSID is valid...
else if (!pod.m_ptwndsmapps->AppValidateIds(_pAppId,&_pTwunkId->identity))
{
pod.m_ptwndsmapps->AppSetConditionCode(0,TWCC_BADVALUE);
return TWRC_FAILURE;
}
SSTRCPY((char*)_pTwunkId->dsPath, sizeof(_pTwunkId->dsPath),(char*)pod.m_ptwndsmapps->DsGetPath(_pAppId,(TWID_T)_pTwunkId->identity.Id));
return result;
}
/*
* Handle DAT_ENTRYPOINT. This handles an application asking
* for entry point information. Drivers have this information
* pushed to them in a different part of the code (just before
* DG_CONTORL/DAT_IDENTITY/MSG_OPENDS is received)
*/
TW_INT16 CTwnDsm::DSM_Entrypoint(TW_IDENTITY *_pAppId,
TW_UINT16 _MSG,
TW_ENTRYPOINT *_pEntrypoint)
{
// Validate...
if (0 == _pAppId)
{
kLOG((kLOGERR,"_pAppId is null"));
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADVALUE);
return TWRC_FAILURE;
}
else if (MSG_GET != _MSG)
{
kLOG((kLOGERR,"protocol error"));
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADPROTOCOL);
return TWRC_FAILURE;
}
else if (0 == _pEntrypoint)
{
kLOG((kLOGERR,"_pEntrypoint is null"));
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADVALUE);
return TWRC_FAILURE;
}
else if (0 == _pEntrypoint->Size)
{
kLOG((kLOGERR,"_pEntrypoint is zero, it needs to be set to the size of TW_ENTRYPOINT..."));
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADVALUE);
return TWRC_FAILURE;
}
else if (!(_pAppId->SupportedGroups & DF_APP2))
{
kLOG((kLOGERR,"_pAppId->SupportedGroups must include the DF_APP2 flag to make this call..."));
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADPROTOCOL);
return TWRC_FAILURE;
}
// This is the TWAIN 2.0 minimum size. If we add more values
// in future we should create a new structure (ex: TW_ENTRYPOINT2)
// and then add an if-statement for it...
if (_pEntrypoint->Size < sizeof(TW_ENTRYPOINT))
{
kLOG((kLOGERR,"_pEntrypoint->Size minimum is %ld, we got %ld...",sizeof(TW_ENTRYPOINT),_pEntrypoint->Size));
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADVALUE);
return TWRC_FAILURE;
}
// TWAIN 2.0
// Stock the structure with interesting stuff...
else if (_pEntrypoint->Size == sizeof(TW_ENTRYPOINT))
{
_pEntrypoint->DSM_Entry = ::DSM_Entry;
_pEntrypoint->DSM_MemAllocate = DSM_MemAllocate;
_pEntrypoint->DSM_MemFree = DSM_MemFree;
_pEntrypoint->DSM_MemLock = DSM_MemLock;
_pEntrypoint->DSM_MemUnlock = DSM_MemUnlock;
}
// Uh-oh...
else
{
kLOG((kLOGERR,"_pEntrypoint->Size cannot be larger than %ld, we got %ld...",sizeof(TW_ENTRYPOINT),_pEntrypoint->Size));
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADVALUE);
return TWRC_FAILURE;
}
// All done...
return TWRC_SUCCESS;
}
/*
* We've received a callback. MSG_REGISTER_CALLBACK are from
* the Application and MSG_INVOKE_CALLBACK (Mac OSx only)
* are from the DS.
* If Callbacks have not been registered by the App then when the
* DS Invokes a callback, make a note of it so the next time the
* application hits us with a Windows message for us to process,
* we can send it the callback message...
*/
TW_INT16 CTwnDsm::DSM_Callback(TW_IDENTITY *_pOrigin,
TW_IDENTITY *_pDest,
TW_UINT16 _MSG,
TW_CALLBACK *_pData)
{
TW_INT16 result;
TW_CALLBACK *ptwcallback;
TW_CALLBACK2 *ptwcallback2;
// Init stuff...
result = TWRC_SUCCESS;
// Take action on the message...
switch (_MSG)
{
case MSG_REGISTER_CALLBACK:
{
// Origin is an App
// Check that the ids are valid...
if (!pod.m_ptwndsmapps->AppValidateIds(_pOrigin,_pDest))
{
pod.m_ptwndsmapps->AppSetConditionCode(0,TWCC_BADPROTOCOL);
return TWRC_FAILURE;
}
if(0 == _pData)
{
kLOG((kLOGERR,"Invalid data"));
pod.m_ptwndsmapps->AppSetConditionCode(0,TWCC_BADVALUE);
return TWRC_FAILURE;
}
ptwcallback2 = pod.m_ptwndsmapps->DsCallback2Get(_pOrigin,(TWID_T)_pDest->Id);
ptwcallback2->CallBackProc = ((TW_CALLBACK*)_pData)->CallBackProc;
ptwcallback2->RefCon = (TWID_T)((TW_CALLBACK*)_pData)->RefCon;
ptwcallback2->Message = ((TW_CALLBACK*)_pData)->Message;
pod.m_ptwndsmapps->DsCallbackSetWaiting(_pOrigin,(TWID_T)_pDest->Id,FALSE);
}
break;
case MSG_INVOKE_CALLBACK:
{
// For backwards capability only. MSG_INVOKE_CALLBACK is deprecated - use DAT_NULL
// Origin is a DS
// Check that the ids are valid...
kLOG((kLOGINFO,"MSG_INVOKE_CALLBACK is deprecated - use DAT_NULL"));
if (!pod.m_ptwndsmapps->AppValidateIds(_pDest,_pOrigin))
{
pod.m_ptwndsmapps->AppSetConditionCode(0,TWCC_BADPROTOCOL);
return TWRC_FAILURE;
}
if(0 == _pData)
{
kLOG((kLOGERR,"Invalid data"));
pod.m_ptwndsmapps->AppSetConditionCode(0,TWCC_BADVALUE);
return TWRC_FAILURE;
}
ptwcallback = (TW_CALLBACK*)_pData;
result = DSM_Null(_pDest,_pOrigin,ptwcallback->Message);
}
break;
default:
result = TWRC_FAILURE;
pod.m_ptwndsmapps->AppSetConditionCode(_pOrigin,TWCC_BADPROTOCOL);
break;
}
return result;
}
/*
* We've received a callback. MSG_REGISTER_CALLBACK are from
* the Application and MSG_INVOKE_CALLBACK (Mac OSx only)
* are from the DS.
* If Callbacks have not been registered by the App then when the
* DS Invokes a callback, make a note of it so the next time the
* application hits us with a Windows message for us to process,
* we can send it the callback message...
*/
TW_INT16 CTwnDsm::DSM_Callback2(TW_IDENTITY *_pOrigin,
TW_IDENTITY *_pDest,
TW_UINT16 _MSG,
TW_CALLBACK2 *_pData)
{
TW_INT16 result;
TW_CALLBACK2 *ptwcallback2;
// Init stuff...
result = TWRC_SUCCESS;
// Take action on the message...
switch (_MSG)
{
case MSG_REGISTER_CALLBACK:
{
// Origin is an App
// Check that the ids are valid...
if (!pod.m_ptwndsmapps->AppValidateIds(_pOrigin,_pDest))
{
pod.m_ptwndsmapps->AppSetConditionCode(0,TWCC_BADPROTOCOL);
return TWRC_FAILURE;
}
if(0 == _pData)
{
kLOG((kLOGERR,"Invalid data"));
pod.m_ptwndsmapps->AppSetConditionCode(0,TWCC_BADVALUE);
return TWRC_FAILURE;
}
ptwcallback2 = pod.m_ptwndsmapps->DsCallback2Get(_pOrigin,(TWID_T)_pDest->Id);
memcpy(ptwcallback2,_pData,sizeof(*ptwcallback2));
pod.m_ptwndsmapps->DsCallbackSetWaiting(_pOrigin,(TWID_T)_pDest->Id,FALSE);
}
break;
case MSG_INVOKE_CALLBACK:
{
// For backwards capability only. MSG_INVOKE_CALLBACK is deprecated - use DAT_NULL
// Origin is a DS
// Check that the ids are valid...
kLOG((kLOGINFO,"MSG_INVOKE_CALLBACK is deprecated - use DAT_NULL"));
if (!pod.m_ptwndsmapps->AppValidateIds(_pDest,_pOrigin))
{
pod.m_ptwndsmapps->AppSetConditionCode(0,TWCC_BADPROTOCOL);
return TWRC_FAILURE;
}
if(0 == _pData)
{
kLOG((kLOGERR,"Invalid data"));
pod.m_ptwndsmapps->AppSetConditionCode(0,TWCC_BADVALUE);
return TWRC_FAILURE;
}
ptwcallback2 = (TW_CALLBACK2*)_pData;
result = DSM_Null(_pDest,_pOrigin,ptwcallback2->Message);
}
break;
default:
result = TWRC_FAILURE;
pod.m_ptwndsmapps->AppSetConditionCode(_pOrigin,TWCC_BADPROTOCOL);
break;
}
return result;
}
/*
* Open the specified driver. We're using the application identity
* and the driver identity we picked up during MSG_OPENDSM. The
* application is just telling us which driver to load. As part of
* a successful open we'll remember this driver's full path and file
* name as the new default driver. On Windows this information goes
* into the registry. On Linux we put it under the user's home
* directory...
*/
TW_INT16 CTwnDsm::OpenDS(TW_IDENTITY *_pAppId,
TW_IDENTITY *_pDsId)
{
TW_INT16 result;
TW_ENTRYPOINT twentrypoint;
// Validate...
if (0 == _pAppId)
{
kLOG((kLOGERR,"_pAppId is null"));
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADVALUE);
return TWRC_FAILURE;
}
else if ( ((TWID_T)_pAppId->Id < 1)
|| ((TWID_T)_pAppId->Id >= pod.m_ptwndsmapps->AppGetNumApp()))
{
kLOG((kLOGERR,"id is out of range...%d",(int)(TWID_T)_pAppId->Id));
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_MAXCONNECTIONS);
return TWRC_FAILURE;
}
// Init stuff...
result = TWRC_SUCCESS;
// check that we are in the proper state
if (dsmState_Open != pod.m_ptwndsmapps->AppGetState(_pAppId))
{
kLOG((kLOGERR,"DSM must be open before opening DS"));
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_SEQERROR);
return(TWRC_FAILURE);
}
// check for valid data
if(0 == _pDsId)
{
kLOG((kLOGERR,"_pDsId is null"));
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADDEST);
return TWRC_FAILURE;
}
// Do we need to find a source to open
if (0 == (TWID_T)_pDsId->Id)
{
// Does the app know the name of the source it wants to open
if (0 != _pDsId->ProductName[0])
{
// The application is passing me a TW_IDENTITY structure that contains
// the name of the source to select.
result = GetDSFromProductName(_pAppId,_pDsId);
// was the id found or specified by the app?
if (TWRC_SUCCESS != result)
{
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_NODS);
return result;
}
}
// Does the application want me to choose the default?
// Or no Source located by name
if (0 == _pDsId->ProductName[0])
{
// -if the name of the source is NULL, and the id is 0, the application is
// telling me to select the default source.
result = GetMatchingDefault(_pAppId,_pDsId);
// was the id found or specified by the app?
if (TWRC_SUCCESS != result)
{
return result;
}
}
}
// Load the driver...
result = pod.m_ptwndsmapps->LoadDS(_pAppId,(TWID_T)_pDsId->Id);
if (result != TWRC_SUCCESS)
{
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_NODS);
return TWRC_FAILURE;
}
// open the ds
if (0 != pod.m_ptwndsmapps->DsGetEntryProc(_pAppId,(TWID_T)_pDsId->Id))
{
// If the DS reports support for DF_DS2, then send it our DAT_ENTRYPOINT
// information. Failure to handle this is treated like a failure to open...
result = TWRC_SUCCESS;
// Create a local copy of the AppIdentity
TW_IDENTITY AppId = *pod.m_ptwndsmapps->AppGetIdentity(_pAppId);
if (_pDsId->SupportedGroups & DF_DS2)
{
memset(&twentrypoint,0,sizeof(twentrypoint));
twentrypoint.Size = sizeof(TW_ENTRYPOINT);
twentrypoint.DSM_Entry = ::DSM_Entry;
twentrypoint.DSM_MemAllocate = DSM_MemAllocate;
twentrypoint.DSM_MemFree = DSM_MemFree;
twentrypoint.DSM_MemLock = DSM_MemLock;
twentrypoint.DSM_MemUnlock = DSM_MemUnlock;
result = pod.m_ptwndsmapps->DsGetEntryProc(&AppId,(TWID_T)_pDsId->Id)(
&AppId,
DG_CONTROL,
DAT_ENTRYPOINT,
MSG_SET,
(TW_MEMREF)&twentrypoint);
}
// We have a problem...
if (TWRC_SUCCESS != result)
{
kLOG((kLOGERR,"DAT_ENTRYPOINT failed..."));
pod.m_ptwndsmapps->AppSetConditionCode(&AppId,TWCC_OPERATIONERROR);
}
// Okay, we're good. Either we're a 1.x driver, or we were able to
// push down our entrypoint info, so open the ds...
else
{
result = pod.m_ptwndsmapps->DsGetEntryProc(&AppId,(TWID_T)_pDsId->Id)(
&AppId,
DG_CONTROL,
DAT_IDENTITY,
MSG_OPENDS,
(TW_MEMREF)_pDsId);
// Oh well...
if (TWRC_SUCCESS != result)
{
kLOG((kLOGINFO,"MSG_OPENDS failed..."));
TW_UINT16 rcDSMStatus;
TW_STATUS twstatus = { 0, { 0 } };
// If the call to MSG_OPENDS fails, then we need to get the DAT_STATUS and squirrel
// it away, because we're going to close this data source soon...
rcDSMStatus = (pod.m_ptwndsmapps->DsGetEntryProc(&AppId,(TWID_T)_pDsId->Id))(
&AppId,
DG_CONTROL,
DAT_STATUS,
MSG_GET,
(TW_MEMREF)&twstatus);
if (rcDSMStatus == TWRC_SUCCESS)
{
pod.m_ptwndsmapps->AppSetConditionCode(&AppId,twstatus.ConditionCode);
}
else
{
pod.m_ptwndsmapps->AppSetConditionCode(&AppId,TWCC_NODS);
}
}
}
}
// Remember that we opened this DS...
if (TWRC_SUCCESS == result)
{
// Starting with TWAIN 2.1 the application will use DAT_IDENTITY / MSG_SET
// to set the default DS
if( ( _pAppId->ProtocolMajor == 2
&& _pAppId->ProtocolMinor == 0 )
|| _pAppId->ProtocolMajor < 2 )
{
#if (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP)
// skip...
#elif (TWNDSM_CMP == TWNDSM_CMP_GNUGPP)
int iResult;
FILE *pfile;
char *szHome;
char szFile[FILENAME_MAX];
szHome = getenv("HOME");
if (szHome)
{
SSTRCPY(szFile,sizeof(szFile),szHome);
SSTRCAT(szFile,sizeof(szFile),"/.twndsmrc");
mkdir(szFile,0660);
SSTRCAT(szFile,sizeof(szFile),"/defaultds");
FOPEN(pfile,szFile,"w");
if (pfile)
{
iResult = fwrite
(
pod.m_ptwndsmapps->DsGetPath(_pAppId,(TWID_T)_pDsId->Id),
1,
strlen(pod.m_ptwndsmapps->DsGetPath(_pAppId,(TWID_T)_pDsId->Id)),
pfile
);
if (iResult < (int)strlen(pod.m_ptwndsmapps->DsGetPath(_pAppId,(TWID_T)_pDsId->Id)))
{
kLOG((kLOGERR,"fwrite defaultds failed..."));
}
fclose(pfile);
}
}
#else
#error Sorry, we do not recognize this system...
#endif
}
}
// If we had an error, make sure we unload the ds...
else
{
pod.m_ptwndsmapps->UnloadDS(_pAppId,(TWID_T)_pDsId->Id);
}
// All done...
return result;
}
/*
* Close the specified driver...
*/
TW_INT16 CTwnDsm::CloseDS(TW_IDENTITY *_pAppId,
TW_IDENTITY *_pDsId)
{
TW_INT16 result;
// Validate...
if (0 == _pAppId)
{
kLOG((kLOGERR,"_pAppId is null"));
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADVALUE);
return TWRC_FAILURE;
}
else if ( ((TWID_T)_pAppId->Id < 1)
|| ((TWID_T)_pAppId->Id >= pod.m_ptwndsmapps->AppGetNumApp()))
{
kLOG((kLOGERR,"id out of range...%d",(int)(TWID_T)_pAppId->Id));
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADVALUE);
return TWRC_FAILURE;
}
// Init stuff...
result = TWRC_SUCCESS;
// check that we are in the proper state
if (dsmState_Open != pod.m_ptwndsmapps->AppGetState(_pAppId))
{
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_SEQERROR);
return TWRC_FAILURE;
}
// Check for valid DS
if(0 == _pDsId)
{
kLOG((kLOGERR,"_pDsId is null"));
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADDEST);
return TWRC_FAILURE;
}
// close the ds
if (0 != pod.m_ptwndsmapps->DsGetEntryProc(_pAppId,(TWID_T)_pDsId->Id))
{
// Create a local copy of the AppIdentity
TW_IDENTITY AppId = *pod.m_ptwndsmapps->AppGetIdentity(_pAppId);
result = (pod.m_ptwndsmapps->DsGetEntryProc(&AppId,(TWID_T)_pDsId->Id))(
&AppId,
DG_CONTROL,
DAT_IDENTITY,
MSG_CLOSEDS,
(TW_MEMREF)_pDsId);
if (TWRC_SUCCESS != result)
{
pod.m_ptwndsmapps->AppSetConditionCode(&AppId,TWCC_OPERATIONERROR);
return result;
}
// Cleanup...
pod.m_ptwndsmapps->UnloadDS(&AppId,(TWID_T)_pDsId->Id);
}
// All done...
return result;
}
#if (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP)
/**
* DllMain is only needed for Windows, and it's only needed to collect
* our instance handle, which is also our module handle. Don't ever
* put anything else in here, not even logging messages. It just isn't
* safe...
* @param[in] _hmodule handle to the application that loaded the DSM
* @param[in] _dwReasonCalled why this function is being called
* @return TRUE
*/
BOOL WINAPI DllMain(HINSTANCE _hmodule,
DWORD _dwReasonCalled,
LPVOID)
{
switch (_dwReasonCalled)
{
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_ATTACH:
g_hinstance = _hmodule;
break;
case DLL_PROCESS_DETACH:
if( g_ptwndsm )
{
if( g_ptwndsm->DSMGetState() == dsmState_Open )
{
// This should never happen!
// The Application should always close any open DS, then Close the DSM.
kLOG((kLOGERR,"The DSM was left in an open state when it was unloaded!"));
}
delete g_ptwndsm;
g_ptwndsm = 0;
}
break;
}
return(TRUE);
}
#elif (TWNDSM_CMP == TWNDSM_CMP_GNUGPP)
// Nothing for us to do...
#else
#error Sorry, we do not recognize this system...
#endif
#if (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP)
/**
* We support a selection dialog on Windows. I wish we didn't, it's
* more trouble than it's worth, but it's part of that legacy thing.
* This function is properly constructed for use with DialogBox...
* @param[in] _hWnd Window handle of the dialog
* @param[in] _Message message
* @param[in] _wParam wparam
* @param[in] _lParam lparam
* @return FALSE if we processed the message
*/
BOOL CALLBACK SelectDlgProc(HWND _hWnd,
UINT _Message,
WPARAM _wParam,
LPARAM _lParam)
{
if (g_ptwndsm)
{
return g_ptwndsm->SelectDlgProc(_hWnd,_Message,_wParam,_lParam);
}
else
{
return TRUE;
}
}
#elif (TWNDSM_CMP == TWNDSM_CMP_GNUGPP)
// We don't have one of these...
#else
#error Sorry, we do not recognize this system...
#endif
#if (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP)
/**
* We support a selection dialog on Windows. This function is
* part of our CTwnDsm class, so we don't have to have a lot
* of pointers, and we can keep things private, unlike what we
* would have to do if we put this code into the function we
* actually pass to DialogBox...
* @param[in] hwnd Window handle of the dialog
* @param[in] lParam lparam
* @return TRUE
*/
BOOL CALLBACK EnumChildProc
(
HWND hwnd,
LPARAM lParam
)
{
::SendMessage(hwnd,WM_SETFONT,(WPARAM)lParam,(LPARAM)TRUE);
return TRUE;
}
BOOL CTwnDsm::SelectDlgProc(HWND hWnd,
UINT Message,
WPARAM wParam,
LPARAM /*lParam - unused*/)
{
TW_IDENTITY *pAppId;
int nIndex;
int nSelect;
TW_UINT32 x;
char *szProductName;
HWND hListBox;
RECT rectParent;
RECT rectSelect;
HWND hParent;
LANGID LangId;
wchar_t uzUnicode[128];
HFONT hfont;
LOGFONT lf;
POINT point;
int nWidth;
int nHeight;
// Init stuff...
nSelect = 0;
pAppId = pod.m_pSelectDlgAppId;
// Process the message...
switch (Message)
{
case WM_INITDIALOG:
// If the caller wants us to figure out the language, do this...
if (pAppId->Version.Language == (TW_UINT16)TWLG_USERLOCALE)
{
// Try to find the user's default language...
LangId = ::GetUserDefaultLangID();
for (nIndex = 0;
s_twlocalize[nIndex].Language >= 0;
nIndex++)
{
if ( (s_twlocalize[nIndex].LangId == LangId)
&& s_twlocalize[nIndex].LangId
&& s_twlocalize[nIndex].Title
&& s_twlocalize[nIndex].Title[0]
&& s_twlocalize[nIndex].Sources
&& s_twlocalize[nIndex].Sources[0]
&& s_twlocalize[nIndex].Select
&& s_twlocalize[nIndex].Select[0]
&& s_twlocalize[nIndex].Cancel
&& s_twlocalize[nIndex].Cancel[0])
{
break;
}
}
// If that doesn't work, try for the primary language...
if (s_twlocalize[nIndex].Language < 0)
{
LangId &= 0xFF;
for (nIndex = 0;
s_twlocalize[nIndex].Language >= 0;
nIndex++)
{
if ( ((s_twlocalize[nIndex].LangId & 0xFF) == LangId)
&& s_twlocalize[nIndex].LangId
&& s_twlocalize[nIndex].Title
&& s_twlocalize[nIndex].Title[0]
&& s_twlocalize[nIndex].Sources
&& s_twlocalize[nIndex].Sources[0]
&& s_twlocalize[nIndex].Select
&& s_twlocalize[nIndex].Select[0]
&& s_twlocalize[nIndex].Cancel
&& s_twlocalize[nIndex].Cancel[0])
{
break;
}
}
}
}
// Otherwise, use whatever the caller gave us...
else
{
for (nIndex = 0;
s_twlocalize[nIndex].Language >= 0;
nIndex++)
{
if ( (s_twlocalize[nIndex].Language == pAppId->Version.Language)
&& s_twlocalize[nIndex].LangId
&& s_twlocalize[nIndex].Title
&& s_twlocalize[nIndex].Title[0]
&& s_twlocalize[nIndex].Sources
&& s_twlocalize[nIndex].Sources[0]
&& s_twlocalize[nIndex].Select
&& s_twlocalize[nIndex].Select[0]
&& s_twlocalize[nIndex].Cancel
&& s_twlocalize[nIndex].Cancel[0])
{
break;
}
}
}
// If we didn't find our language, go for English...
if (s_twlocalize[nIndex].Language < 0)
{
for (nIndex = 0;
s_twlocalize[nIndex].Language >= 0;
nIndex++)
{
if ( (s_twlocalize[nIndex].Language == TWLG_ENGLISH)
&& s_twlocalize[nIndex].LangId
&& s_twlocalize[nIndex].Title
&& s_twlocalize[nIndex].Title[0]
&& s_twlocalize[nIndex].Sources
&& s_twlocalize[nIndex].Sources[0]
&& s_twlocalize[nIndex].Select
&& s_twlocalize[nIndex].Select[0]
&& s_twlocalize[nIndex].Cancel
&& s_twlocalize[nIndex].Cancel[0])
{
break;
}
}
}
// If we found something, then use it...
if (s_twlocalize[nIndex].Language >= 0)
{
// Set our font...
memset(&lf,0,sizeof(lf));
lf.lfHeight = 16;
lf.lfCharSet = s_twlocalize[nIndex].CharSet;
hfont = CreateFontIndirect(&lf);
EnumChildWindows(hWnd,EnumChildProc,(LPARAM)hfont);
MultiByteToWideChar(CP_UTF8,0,s_twlocalize[nIndex].Title,-1,uzUnicode,sizeof(uzUnicode)/sizeof(*uzUnicode));
SetWindowTextW(hWnd,uzUnicode);
MultiByteToWideChar(CP_UTF8,0,s_twlocalize[nIndex].Sources,-1,uzUnicode,sizeof(uzUnicode)/sizeof(*uzUnicode));
SetWindowTextW(::GetDlgItem(hWnd,IDC_STATIC),uzUnicode);
MultiByteToWideChar(CP_UTF8,0,s_twlocalize[nIndex].Select,-1,uzUnicode,sizeof(uzUnicode)/sizeof(*uzUnicode));
SetWindowTextW(::GetDlgItem(hWnd,IDOK),uzUnicode);
MultiByteToWideChar(CP_UTF8,0,s_twlocalize[nIndex].Cancel,-1,uzUnicode,sizeof(uzUnicode)/sizeof(*uzUnicode));
SetWindowTextW(::GetDlgItem(hWnd,IDCANCEL),uzUnicode);
}
hListBox = ::GetDlgItem(hWnd,ID_LST_SOURCES);
if (hListBox)
{
SendMessage(hListBox,LB_RESETCONTENT,(WPARAM)NULL,(LPARAM)NULL);
for (x = 1; x < MAX_NUM_DS; ++x)
{
// We expect the list to be contiguous...
szProductName = pod.m_ptwndsmapps->DsGetIdentity(pAppId,x)->ProductName;
if (!szProductName[0])
{
break;
}
// Display the name...
nIndex = (int)SendMessage(hListBox,LB_ADDSTRING,(WPARAM)NULL,(LPARAM)szProductName);
if (LB_ERR == nIndex)
{
break;
}
// Associate the id with the name...
nIndex = (int)SendMessage(hListBox,
LB_SETITEMDATA,
(WPARAM)nIndex,
(LPARAM)pod.m_ptwndsmapps->DsGetIdentity(pAppId,x)->Id);
if (LB_ERR == nIndex)
{
break;
}
// Remember this item if it's the default...
if (!strcmp(pod.m_ptwndsmapps->DsGetPath(pAppId,x),pod.m_DefaultDSPath))
{
nSelect = x;
}
}
// If we have no drivers, then disable the OK button...
if (pod.m_ptwndsmapps->AppGetNumDs(pAppId) < 1)
{
HWND hOK= ::GetDlgItem(hWnd,IDOK);
EnableWindow(hOK, FALSE);
}
// Otherwise select the defaulted item...
else
{
nIndex = (int)SendMessage(hListBox,
LB_FINDSTRINGEXACT,
(WPARAM)-1,
(LPARAM)pod.m_ptwndsmapps->DsGetIdentity(pAppId,nSelect)->ProductName);
if (LB_ERR == nIndex)
{
nIndex = 0;
}
SendMessage(hListBox,LB_SETCURSEL,(WPARAM)nIndex,(LPARAM)NULL);
}
}
// Center our dialog on the window reported to us in MSG_OPENDS...
hParent = (HWND)pod.m_ptwndsmapps->AppHwnd(pAppId);
if (hParent)
{
GetClientRect(hParent,&rectParent);
GetWindowRect(hWnd,&rectSelect);
nWidth = (rectSelect.right - rectSelect.left);
nHeight = (rectSelect.bottom - rectSelect.top);
point.x = (rectParent.right - rectParent.left) / 2;
point.y = (rectParent.bottom - rectParent.top) / 2;
ClientToScreen(hParent,&point);
point.x -= nWidth / 2;
point.y -= nHeight / 2;
// keep the dialog visible on the screen
if(point.x < 0)
{
point.x = 0;
}
if(point.y < 0)
{
point.y = 0;
}
MoveWindow(hWnd,point.x,point.y,nWidth,nHeight,FALSE);
}
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case ID_LST_SOURCES:
if (HIWORD(wParam) != LBN_DBLCLK)
break;
// drop through...
case IDOK:
{
hListBox = ::GetDlgItem(hWnd, ID_LST_SOURCES);
nIndex = 0;
if ( hListBox )
{
nIndex = (int)SendMessage(hListBox,LB_GETCURSEL,(WPARAM)0,(LPARAM)0);
if (LB_ERR == nIndex)
{
// if there is no selection should not have OK available
// to press in the first place.
return TRUE;
}
nIndex = (int)SendMessage(hListBox,LB_GETITEMDATA,(WPARAM)nIndex,(LPARAM)0);
if (LB_ERR != nIndex)
{
pod.m_pSelectDlgDsId = pod.m_ptwndsmapps->DsGetIdentity(pAppId,nIndex);
}
}
EndDialog(hWnd, IDOK);
return TRUE;
}
case IDCANCEL:
EndDialog(hWnd, IDCANCEL);
return TRUE;
}
break;
}
return FALSE;
}
#elif (TWNDSM_CMP == TWNDSM_CMP_GNUGPP)
// We don't have anything to do on Linux...
#else
#error Sorry, we do not recognize this system...
#endif
/*
* Invoke the user selection dialog box. We only support this for
* Windows, for Linux it's a bad protocol, since there is no way
* to query the user (nicely) across all consoles and graphical
* interfaces for all distributions...
*/
TW_INT16 CTwnDsm::DSM_SelectDS(TW_IDENTITY *_pAppId,
TW_IDENTITY *_pDsId)
{
// Validate...
if (0 == _pAppId)
{
kLOG((kLOGERR,"_pAppId is null"));
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADVALUE);
return TWRC_FAILURE;
}
if ( ((TWID_T)_pAppId->Id < 1)
|| ((TWID_T)_pAppId->Id >= pod.m_ptwndsmapps->AppGetNumApp()))
{
kLOG((kLOGERR,"_pAppId.Id is out of range"));
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADVALUE);
return TWRC_FAILURE;
}
else if (0 == _pDsId)
{
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADDEST);
return TWRC_FAILURE;
}
else if (dsmState_Open != pod.m_ptwndsmapps->AppGetState(_pAppId))
{
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_SEQERROR);
return TWRC_FAILURE;
}
/** @todo scanDSDir needs to be done with each MSG_USERSELECT
currently we are only scanDSDir when an App opens the DSM **/
// Make sure the id is 0 before we go into this...
_pDsId->Id = 0;
// Windows...
#if (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP)
HKEY hKey;
long status;
char *szPath;
TW_INT16 result;
// Set the context...
result = TWRC_SUCCESS;
pod.m_pSelectDlgAppId = _pAppId;
// If passed in a DS name we want to select it
if (_pDsId->ProductName[0] != 0)
{
result = GetDSFromProductName(_pAppId,_pDsId);
// If no match continue anyway.
}
// If not passed a DS or the name was not currently found
// then selete the default
_pDsId->Id = 0;
result = GetMatchingDefault(_pAppId,_pDsId);
pod.m_pSelectDlgDsId = _pDsId;
// a.walling - Get the HWND of the parent window, if any, and use it as the dialog's parent
HWND hParent = (HWND)pod.m_ptwndsmapps->AppHwnd(_pAppId);
// create the dialog window
int ret = (int)::DialogBoxW(g_hinstance,
(LPCWSTR)IDD_DLG_SOURCE,
(HWND)hParent,
(DLGPROC)::SelectDlgProc);
// User picked something...
if (ret == IDOK)
{
// Validate the result...
if (!pod.m_pSelectDlgDsId)
{
kLOG((kLOGERR,"We came out of the Select Dialog with a null..."));
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_OPERATIONERROR);
return TWRC_FAILURE;
}
// Copy the data over...
*_pDsId = *pod.m_pSelectDlgDsId;
// save default source to Registry
// sanity check...
if ( (pod.m_pSelectDlgDsId->Id < 1)
|| (pod.m_pSelectDlgDsId->Id >= MAX_NUM_DS))
{
// Failed to save default DS to registry
kLOG((kLOGERR,"Id is out of range 0 - 49..."));
// Nothing preventing us from using the default right now
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BUMMER);
}
else
{
// Get the path we're using...
status = ERROR_SUCCESS;
szPath = pod.m_ptwndsmapps->DsGetPath(pod.m_pSelectDlgAppId,pod.m_pSelectDlgDsId->Id);
// Open the key, creating it if it doesn't exist.
if (RegCreateKeyEx(HKEY_CURRENT_USER,
TWNDSM_DS_REG_LOC,
NULL,
NULL,
NULL,
KEY_READ | KEY_WRITE, NULL,
&hKey,
NULL) == ERROR_SUCCESS)
{
status = RegSetValueEx(hKey,"Default Source",0,REG_SZ,(LPBYTE)szPath,(DWORD)strlen((char*)szPath)+1);
if (status != ERROR_SUCCESS)
{
// Failed to save default DS to registry
kLOG((kLOGERR,"Failed to save default DS to registry"));
// Nothing preventing us from using the default right now
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BUMMER);
}
}
// Close the key.
RegCloseKey(hKey);
}
}
// We're cancelling...
else if (ret == IDCANCEL)
{
result = TWRC_CANCEL;
}
// Something back happened...
else if (ret == -1)
{
::MessageBox(NULL,"Dialog failed!","Error",MB_OK|MB_ICONINFORMATION);
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BUMMER);
result = TWRC_FAILURE;
}
return result;
// We don't support the user selection box on linux...
#elif (TWNDSM_CMP == TWNDSM_CMP_GNUGPP)
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADPROTOCOL);
return TWRC_FAILURE;
// Ruh-roh, Reorge...
#else
#error Sorry, we do not recognize this system...
#endif
}
/*
* Set the datasource as the default
*/
TW_INT16 CTwnDsm::DSM_SetDefaultDS(TW_IDENTITY *_pAppId,
TW_IDENTITY *_pDsId)
{
TW_INT16 result = TWRC_SUCCESS;
// Validate app ...
if (0 == _pAppId)
{
kLOG((kLOGERR,"_pAppId is null"));
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADVALUE);
return TWRC_FAILURE;
}
else if ( (TWID_T)_pAppId->Id < 1
|| (TWID_T)_pAppId->Id >= pod.m_ptwndsmapps->AppGetNumApp() )
{
kLOG((kLOGERR,"_pAppId.Id is out of range...%d",(int)(TWID_T)_pAppId->Id));
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADVALUE);
return TWRC_FAILURE;
}
else if (dsmState_Open != pod.m_ptwndsmapps->AppGetState(_pAppId))
{
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_SEQERROR);
return TWRC_FAILURE;
}
// Validate DS
if(0 == _pDsId)
{
kLOG((kLOGERR,"_pDsId is null"));
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADDEST);
return TWRC_FAILURE;
}
else if ((TWID_T)_pDsId->Id < 1
|| (TWID_T)_pDsId->Id >= MAX_NUM_DS)
{
kLOG((kLOGERR,"Id is out of range 0 - 49..."));
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADVALUE);
return TWRC_FAILURE;
}
char *szPath = pod.m_ptwndsmapps->DsGetPath(_pAppId,(TWID_T)_pDsId->Id); // Get the path we're using...
if(!szPath)
{
kLOG((kLOGERR,"DS is not valid"));
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADVALUE);
return TWRC_FAILURE;
}
// Windows... save default source to Registry
#if (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP)
HKEY hKey;
long status = ERROR_SUCCESS;
// Open the key, creating it if it doesn't exist.
if (RegCreateKeyEx(HKEY_CURRENT_USER,
TWNDSM_DS_REG_LOC,
NULL,
NULL,
NULL,
KEY_READ | KEY_WRITE, NULL,
&hKey,
NULL) == ERROR_SUCCESS)
{
status = RegSetValueEx(hKey,"Default Source",0,REG_SZ,(LPBYTE)szPath,(DWORD)strlen((char*)szPath)+1);
if (status != ERROR_SUCCESS)
{
// Failed to save default DS to registry
kLOG((kLOGERR,"Failed to save default DS to registry"));
// Nothing preventing us from using the default right now
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BUMMER);
result = TWRC_FAILURE;
}
// Close the key.
RegCloseKey(hKey);
}
// Linux looks in the user's directory...
#elif (TWNDSM_CMP == TWNDSM_CMP_GNUGPP)
int iResult;
FILE *pfile;
char *szHome;
char szFile[FILENAME_MAX];
szHome = getenv("HOME");
if (szHome)
{
SSTRCPY(szFile,sizeof(szFile),szHome);
SSTRCAT(szFile,sizeof(szFile),"/.twndsmrc/defaultds");
FOPEN(pfile,szFile,"w");
if (pfile)
{
iResult = fwrite(szPath, 1, strlen(szPath), pfile);
if (iResult < (int)strlen(pod.m_ptwndsmapps->DsGetPath(_pAppId,(TWID_T)_pDsId->Id)))
{
kLOG((kLOGERR,"fwrite defaultds failed..."));
}
fclose(pfile);
}
}
// eek...
#else
#error Sorry, we do not recognize this system...
result = TWRC_FAILURE
#endif
return result;
}
/*
* Invoke the user selection dialog box. We only support this for
* Windows, for Linux it's a bad protocol, since there is no way
* to query the user (nicely) across all consoles and graphical
* interfaces for all distributions...
*/
TW_INT16 CTwnDsm::GetDSFromProductName(TW_IDENTITY *_pAppId,
TW_IDENTITY *_pDsId)
{
TWID_T ii;
// Validate...
if ( !pod.m_ptwndsmapps->AppValidateId(_pAppId)
|| (0 == _pDsId))
{
kLOG((kLOGERR,"bad _pAppId or _pDsId..."));
return TWRC_FAILURE;
}
else if (0 == _pDsId->ProductName[0])
{
return TWRC_FAILURE;
}
// Search for a match on the ProductName...
for (ii = 1; ii < MAX_NUM_DS; ++ii)
{
// Note that TW_STR32 type is NUL-filled, not NUL-terminated...
if (0 == strncmp((char*)_pDsId->ProductName,
(char*)pod.m_ptwndsmapps->DsGetIdentity(_pAppId,ii)->ProductName,
sizeof(TW_STR32)))
{
// match found, set the index
*_pDsId = *pod.m_ptwndsmapps->DsGetIdentity(_pAppId,ii);
return TWRC_SUCCESS;
}
}
// Uh-oh...
return TWRC_FAILURE;
}
/*
* Get the identity for the first driver we found, or TWRC_ENDOFLIST
* if we don't have any...
*/
TW_INT16 CTwnDsm::DSM_GetFirst(TW_IDENTITY *_pAppId,
TW_IDENTITY *_pDsId)
{
// Validate...
if ( !pod.m_ptwndsmapps->AppValidateId(_pAppId)
|| (0 == _pDsId))
{
kLOG((kLOGERR,"bad _pAppId or _pDsId..."));
return TWRC_FAILURE;
}
/** @todo scanDSDir needs to be done with each MSG_GETFIRST
currently we are only scanDSDir when an App opens the DSM **/
// There are no supported drivers...
if (pod.m_ptwndsmapps->AppGetNumDs(_pAppId) < 1)
{
// Make sure we fail of GetNext is called...
pod.m_nextDsId = pod.m_ptwndsmapps->AppGetNumDs(_pAppId) + 1;
return TWRC_ENDOFLIST;
}
// Check for valid DS
if(0 == _pDsId)
{
kLOG((kLOGERR,"_pDsId is null"));
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADDEST);
return TWRC_FAILURE;
}
// Return info on the first driver we found...
pod.m_nextDsId = 1;
*_pDsId = *pod.m_ptwndsmapps->DsGetIdentity(_pAppId,pod.m_nextDsId);
// All done...
return TWRC_SUCCESS;
}
/*
* Get the identity for the next driver we found, or TWRC_ENDOFLIST
* if we've run out...
*/
TW_INT16 CTwnDsm::DSM_GetNext(TW_IDENTITY *_pAppId,
TW_IDENTITY *_pDsId)
{
// Validate...
if ( !pod.m_ptwndsmapps->AppValidateId(_pAppId)
|| (0 == _pDsId))
{
kLOG((kLOGERR,"bad _pAppId or _pDsId..."));
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADDEST);
return TWRC_FAILURE;
}
// Applications must call MSG_GETFIRST before making this call...
if (pod.m_nextDsId == 0)
{
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_SEQERROR);
return TWRC_FAILURE;
}
// Prep for a call to GetNext...
pod.m_nextDsId += 1;
// We're out of items...
if (pod.m_nextDsId > pod.m_ptwndsmapps->AppGetNumDs(_pAppId))
{
pod.m_nextDsId = 0;
return TWRC_ENDOFLIST;
}
// Return info on the this driver...
*_pDsId = *pod.m_ptwndsmapps->DsGetIdentity(_pAppId,pod.m_nextDsId);
// All done...
return TWRC_SUCCESS;
}
/*
* Get the identity of the default source...
*/
TW_INT16 CTwnDsm::GetMatchingDefault(TW_IDENTITY *_pAppId,
TW_IDENTITY *_pDsId)
{
bool bMatchFnd = false;
bool bDefaultFound = false;
TW_UINT32 ii;
// Validate...
if ( !pod.m_ptwndsmapps->AppValidateId(_pAppId)
|| (0 == _pDsId))
{
kLOG((kLOGERR,"bad _pAppId or _pDsId..."));
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADDEST);
return TWRC_FAILURE;
}
// is there something to match to?
if (pod.m_ptwndsmapps->AppGetNumDs(_pAppId) < 1)
{
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_NODS);
return TWRC_FAILURE;
}
// Something very bad may be happening, so don't let the
// application get away with this...
if (0 != (TWID_T)_pDsId->Id)
{
kLOG((kLOGINFO,"Please make sure your TW_IDENTITY.Id for your driver (the destination) is zeroed out before making this call..."));
//pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_OPERATIONERROR);
//return TWRC_FAILURE;
}
// In Windows the default Data Source is stored in the registry
// as the path to that DS. We will need to compare this to the other DS as a match.
// read default source from Registry
memset(pod.m_DefaultDSPath,0,sizeof(pod.m_DefaultDSPath));
// Windows uses the registry...
#if (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP)
HKEY hKey;
if (RegOpenKeyEx(HKEY_CURRENT_USER,
TWNDSM_DS_REG_LOC,
0,
KEY_READ,
&hKey) == ERROR_SUCCESS )
{
// Look for the subkey "Default Source".
DWORD DWtype = REG_SZ;
DWORD DWsize = sizeof(pod.m_DefaultDSPath);
bDefaultFound = ( RegQueryValueEx(hKey,"Default Source",NULL,&DWtype,(LPBYTE)pod.m_DefaultDSPath,&DWsize) == ERROR_SUCCESS);
// Close the registry key handle.
RegCloseKey(hKey);
}
// Linux looks in the user's directory...
#elif (TWNDSM_CMP == TWNDSM_CMP_GNUGPP)
int iResult;
FILE *pfile;
char *szHome;
char szFile[FILENAME_MAX];
memset(pod.m_DefaultDSPath,0,sizeof(pod.m_DefaultDSPath));
szHome = getenv("HOME");
if (szHome)
{
SSTRCPY(szFile,sizeof(szFile),szHome);
SSTRCAT(szFile,sizeof(szFile),"/.twndsmrc/defaultds");
FOPEN(pfile,szFile,"r");
if (pfile)
{
iResult = fread(pod.m_DefaultDSPath,1,sizeof(pod.m_DefaultDSPath)-1,pfile);
if (iResult <= 0)
{
kLOG((kLOGINFO,"The defaultds file is empty, this is okay..."));
pod.m_DefaultDSPath[0] = 0;
}
bDefaultFound = true;
fclose(pfile);
}
}
// eek...
#else
#error Sorry, we do not recognize this system...
#endif
// If current default source is not a match find a new default source
// that will match this app
for (ii = 1; ii < MAX_NUM_DS; ++ii)
{
// Mark the first match to use as default, if we don't
// find a match, this will be the one we go with...
if (!bMatchFnd)
{
*_pDsId = *pod.m_ptwndsmapps->DsGetIdentity(_pAppId,ii);
bMatchFnd = true;
//If no default was saved no need to go checking for a match
if(!bDefaultFound)
{
break;
}
}
// If the system default is a match we will use it and stop looking.
if (0 == STRNICMP(pod.m_DefaultDSPath,
pod.m_ptwndsmapps->DsGetPath(_pAppId,ii),
sizeof(pod.m_DefaultDSPath)))
{
*_pDsId = *pod.m_ptwndsmapps->DsGetIdentity(_pAppId,ii);
bMatchFnd = true;
break;
}
}
if (!bMatchFnd)
{
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_NODS);
return TWRC_FAILURE;
}
return TWRC_SUCCESS;
}
/*
* Log the triplets that the application sends to us...
*/
bool CTwnDsm::printTripletsInfo(const TW_IDENTITY *_pOrigin,
const TW_IDENTITY *_pDest,
const TW_UINT32 _DG,
const TW_UINT16 _DAT,
const TW_UINT16 _MSG,
const TW_MEMREF _pData)
{
char szDg[64];
char szDat[64];
char szMsg[64];
char szData[128];
TW_CAPABILITY *_pCap;
// Don't spend time processing the triplet if we are not logging.
if( !g_ptwndsmlog )
{
return false;
}
// too many of these messages to log...
if ( (DG_CONTROL == _DG)
&& (DAT_EVENT == _DAT))
{
return false;
}
// Convert them...
StringFromDg(szDg,NCHARS(szDg),_DG);
StringFromDat(szDat,NCHARS(szDat),_DAT);
StringFromMsg(szMsg,NCHARS(szMsg),_MSG);
memset(szData, 0, sizeof(szData));
// If we have data do some extra work to see what it might be
if(NULL != _pData)
{
// If we're a capability, try to tell them what cap it is...
if ( (DG_CONTROL == _DG)
&& (DAT_CAPABILITY == _DAT) )
{
_pCap = (TW_CAPABILITY*)_pData;
StringFromCap(szData,NCHARS(szData),_pCap->Cap);
// If sending a container, try to tell them what...
if( MSG_SET == _MSG )
{
char szType[32];
StringFromConType(szType,NCHARS(szType),_pCap->ConType);
SSTRCAT(szData,NCHARS(szData),szType);
}
}
}
// Print out the orgin and Destination
kLOG((kLOGINFO,"%.32s -> %.32s",_pOrigin? (char*)_pOrigin->ProductName:"DSM", _pDest? (char*)_pDest->ProductName:"DSM"));
// Print them
if(strlen(szData))
{
kLOG((kLOGINFO,"%s/%s/%s/%s",szDg,szDat,szMsg,szData));
}
else
{
kLOG((kLOGINFO,"%s/%s/%s",szDg,szDat,szMsg));
}
g_ptwndsmlog->Indent(1);
// All done...
return true;
}
/*
* Log the results after processing the Triplet
*/
void CTwnDsm::printResults(const TW_UINT32 _DG,
const TW_UINT16 _DAT,
const TW_UINT16 _MSG,
const TW_MEMREF _pData,
const TW_UINT16 _RC)
{
char szRc[64];
StringFromRC(szRc,NCHARS(szRc),_RC);
// If we have data do some extra work to see what it might be
if( NULL != _pData && TWRC_FAILURE != _RC)
{
if( DG_CONTROL == _DG
&& DAT_CAPABILITY == _DAT
&& ( MSG_GET == _MSG || MSG_GETCURRENT == _MSG || MSG_GETDEFAULT == _MSG || MSG_RESET == _MSG ) )
{
TW_CAPABILITY *_pCap = (TW_CAPABILITY*)_pData;
char szType[32];
StringFromConType(szType, NCHARS(szType), _pCap->ConType);
SSTRCAT(szRc, NCHARS(szRc), szType);
}
else if( DG_CONTROL == _DG
&& DAT_PENDINGXFERS == _DAT )
{
TW_PENDINGXFERS *pXfer = (TW_PENDINGXFERS*)_pData;
char szValue[32];
SSNPRINTF(szValue, NCHARS(szValue), NCHARS(szValue), " Count = %d", pXfer->Count==0xFFFF?-1:pXfer->Count);
SSTRCAT(szRc, NCHARS(szRc), szValue);
}
else if( DG_CONTROL == _DG
&& DAT_STATUS == _DAT )
{
TW_STATUS *pStatus = (TW_STATUS*)_pData;
char szStatus[32];
StringFromConditionCode(szStatus, NCHARS(szStatus), pStatus->ConditionCode);
SSTRCAT(szRc, NCHARS(szRc), szStatus);
}
}
// ... and add a blank line
SSTRCAT(szRc,NCHARS(szRc),"\n");
g_ptwndsmlog->Indent(-1);
kLOG((kLOGINFO,szRc));
}
/*
* DAT_NULL is used by a driver to send certain messages back to the
* application, like MSG_XFERREADY...
*/
TW_INT16 CTwnDsm::DSM_Null(TW_IDENTITY *_pAppId,
TW_IDENTITY *_pDsId,
TW_UINT16 _MSG)
{
TW_CALLBACK2 *ptwcallback2 = 0;
TW_INT16 result = TWRC_SUCCESS;
TW_MEMREF MemRef = 0;
bool bPrinted = false;
// Validate...
if ( !pod.m_ptwndsmapps->AppValidateIds(_pAppId,_pDsId) )
{
kLOG((kLOGERR,"bad _pAppId or _pDsId..."));
return TWRC_FAILURE;
}
// Invoke the application's callback to send this message along.
if ( (MSG_DEVICEEVENT != _MSG)
&& (MSG_CLOSEDSOK != _MSG)
&& (MSG_CLOSEDSREQ != _MSG)
&& (MSG_XFERREADY != _MSG))
{
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADPROTOCOL);
return TWRC_FAILURE;
}
// Get the current callback...
ptwcallback2 = pod.m_ptwndsmapps->DsCallback2Get(_pAppId,(TWID_T)_pDsId->Id);
// We have something to call...
if ( (0 != ptwcallback2)
&& (ptwcallback2->CallBackProc))
{
// RefCon is returned back to the calling application in pData
// Unfortunately RefCon is defined as TW_INT32
// Application writers that want to store a pointer in RefCon
// on 64bit will need to store an index to local storage.
MemRef = (TW_MEMREF)ptwcallback2->RefCon;
// Set flag to prevent Application from sending a new message
// before returning back from recieving this callback.
pod.m_ptwndsmapps->DsSetAppProcessingCallback(_pAppId,(TWID_T)_pDsId->Id,TRUE);
// We should have a try/catch around this...
// Send a message from DS to the Application.
// Rare case where the origin is the DS and dest is the App
try
{
// Create a local copy of the AppIdentity
TW_IDENTITY AppId = *pod.m_ptwndsmapps->AppGetIdentity(_pAppId);
// Print the triplets to stdout for information purposes
bPrinted = printTripletsInfo(NULL,&AppId,DG_CONTROL,DAT_NULL,_MSG,MemRef);
// Send a pointer to the data...
result = ((DSMENTRYPROC)(ptwcallback2->CallBackProc))(
pod.m_ptwndsmapps->DsGetIdentity(&AppId,(TWID_T)_pDsId->Id),
&AppId,
DG_CONTROL,
DAT_NULL,
_MSG,
MemRef);
}
catch(...)
{
pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BUMMER);
kLOG((kLOGERR,"Exception caught while App was processing message. Returning Failure."));
result = TWRC_FAILURE;
}
pod.m_ptwndsmapps->DsSetAppProcessingCallback(_pAppId,(TWID_T)_pDsId->Id,FALSE);
}
// Application has not registered a callback. As a result, the msg will
// be sent to the app the next time it forwards an event.
// Each App's DS has a callback structure. This way multiple DS's can make
// a callback to a single app, and we are not going to lose MSG's
else
{
if (ptwcallback2)
{
if (ptwcallback2->Message != 0)
{
char szMsg[64];
StringFromMsg(szMsg, NCHARS(szMsg), ptwcallback2->Message);
kLOG((kLOGERR, "%.32s NEVER retrieved DAT_EVENT / %s\n", _pAppId->ProductName, szMsg));
}
ptwcallback2->Message = _MSG;
}
pod.m_ptwndsmapps->DsCallbackSetWaiting(_pAppId,(TWID_T)_pDsId->Id,TRUE);
pod.m_ptwndsmapps->AppWakeup(_pAppId);
}
// Log how it went...
if (bPrinted)
{
printResults(DG_CONTROL,DAT_NULL,_MSG,MemRef,result);
}
return result;
}
/*
* Convert a DG_ data group numerical value to a string...
*/
void CTwnDsm::StringFromDg(char *_szDg,
const int _nChars,
const TW_UINT32 _DG)
{
switch(_DG)
{
default:
SSNPRINTF(_szDg,_nChars,_nChars,"DG_0x%04lx",_DG);
break;
case DG_CONTROL:
SSTRCPY(_szDg,_nChars,"DG_CONTROL");
break;
case DG_IMAGE:
SSTRCPY(_szDg,_nChars,"DG_IMAGE");
break;
case DG_AUDIO:
SSTRCPY(_szDg,_nChars,"DG_AUDIO");
break;
}
}
/*
* Convert a DAT_ data argument type numerical value to a string...
*/
void CTwnDsm::StringFromDat(char *_szDat,
const int _nChars,
const TW_UINT16 _DAT)
{
switch(_DAT)
{
default:
SSNPRINTF(_szDat,_nChars,_nChars,"DAT_0x%04x",_DAT);
case DAT_NULL:
SSTRCPY(_szDat,_nChars,"DAT_NULL");
break;
case DAT_CUSTOMBASE:
SSTRCPY(_szDat,_nChars,"DAT_CUSTOMBASE");
break;
case DAT_CAPABILITY:
SSTRCPY(_szDat,_nChars,"DAT_CAPABILITY");
break;
case DAT_EVENT:
SSTRCPY(_szDat,_nChars,"DAT_EVENT");
break;
case DAT_IDENTITY:
SSTRCPY(_szDat,_nChars,"DAT_IDENTITY");
break;
case DAT_PARENT:
SSTRCPY(_szDat,_nChars,"DAT_PARENT");
break;
case DAT_PENDINGXFERS:
SSTRCPY(_szDat,_nChars,"DAT_PENDINGXFERS");
break;
case DAT_SETUPMEMXFER:
SSTRCPY(_szDat,_nChars,"DAT_SETUPMEMXFER");
break;
case DAT_SETUPFILEXFER:
SSTRCPY(_szDat,_nChars,"DAT_SETUPFILEXFER");
break;
case DAT_STATUS:
SSTRCPY(_szDat,_nChars,"DAT_STATUS");
break;
case DAT_USERINTERFACE:
SSTRCPY(_szDat,_nChars,"DAT_USERINTERFACE");
break;
case DAT_XFERGROUP:
SSTRCPY(_szDat,_nChars,"DAT_XFERGROUP");
break;
case DAT_TWUNKIDENTITY:
SSTRCPY(_szDat,_nChars,"DAT_TWUNKIDENTITY");
break;
case DAT_CUSTOMDSDATA:
SSTRCPY(_szDat,_nChars,"DAT_CUSTOMDSDATA");
break;
case DAT_DEVICEEVENT:
SSTRCPY(_szDat,_nChars,"DAT_DEVICEEVENT");
break;
case DAT_FILESYSTEM:
SSTRCPY(_szDat,_nChars,"DAT_FILESYSTEM");
break;
case DAT_PASSTHRU:
SSTRCPY(_szDat,_nChars,"DAT_PASSTHRU");
break;
case DAT_CALLBACK:
SSTRCPY(_szDat,_nChars,"DAT_CALLBACK");
break;
case DAT_STATUSUTF8:
SSTRCPY(_szDat,_nChars,"DAT_STATUSUTF8");
break;
case DAT_IMAGEINFO:
SSTRCPY(_szDat,_nChars,"DAT_IMAGEINFO");
break;
case DAT_IMAGELAYOUT:
SSTRCPY(_szDat,_nChars,"DAT_IMAGELAYOUT");
break;
case DAT_IMAGEMEMXFER:
SSTRCPY(_szDat,_nChars,"DAT_IMAGEMEMXFER");
break;
case DAT_IMAGENATIVEXFER:
SSTRCPY(_szDat,_nChars,"DAT_IMAGENATIVEXFER");
break;
case DAT_IMAGEFILEXFER:
SSTRCPY(_szDat,_nChars,"DAT_IMAGEFILEXFER");
break;
case DAT_CIECOLOR:
SSTRCPY(_szDat,_nChars,"DAT_CIECOLOR");
break;
case DAT_GRAYRESPONSE:
SSTRCPY(_szDat,_nChars,"DAT_GRAYRESPONSE");
break;
case DAT_RGBRESPONSE:
SSTRCPY(_szDat,_nChars,"DAT_RGBRESPONSE");
break;
case DAT_JPEGCOMPRESSION:
SSTRCPY(_szDat,_nChars,"DAT_JPEGCOMPRESSION");
break;
case DAT_PALETTE8:
SSTRCPY(_szDat,_nChars,"DAT_PALETTE8");
break;
case DAT_EXTIMAGEINFO:
SSTRCPY(_szDat,_nChars,"DAT_EXTIMAGEINFO");
break;
case DAT_AUDIOFILEXFER:
SSTRCPY(_szDat,_nChars,"DAT_AUDIOFILEXFER");
break;
case DAT_AUDIOINFO:
SSTRCPY(_szDat,_nChars,"DAT_AUDIOINFO");
break;
case DAT_AUDIONATIVEXFER:
SSTRCPY(_szDat,_nChars,"DAT_AUDIONATIVEXFER");
break;
case DAT_ICCPROFILE:
SSTRCPY(_szDat,_nChars,"DAT_ICCPROFILE");
break;
case DAT_IMAGEMEMFILEXFER:
SSTRCPY(_szDat,_nChars,"DAT_IMAGEMEMFILEXFER");
break;
case DAT_ENTRYPOINT:
SSTRCPY(_szDat,_nChars,"DAT_ENTRYPOINT");
break;
}
}
/*
* Convert a MSG_ message numerical value to a string...
*/
void CTwnDsm::StringFromMsg(char *_szMsg,
const int _nChars,
const TW_UINT16 _MSG)
{
switch (_MSG)
{
default:
SSNPRINTF(_szMsg,_nChars,_nChars,"MSG_0x%04x",_MSG);
break;
case MSG_NULL:
SSTRCPY(_szMsg,_nChars,"MSG_NULL");
break;
case MSG_CUSTOMBASE:
SSTRCPY(_szMsg,_nChars,"MSG_CUSTOMBASE");
break;
case MSG_GET:
SSTRCPY(_szMsg,_nChars,"MSG_GET");
break;
case MSG_GETCURRENT:
SSTRCPY(_szMsg,_nChars,"MSG_GETCURRENT");
break;
case MSG_GETDEFAULT:
SSTRCPY(_szMsg,_nChars,"MSG_GETDEFAULT");
break;
case MSG_GETFIRST:
SSTRCPY(_szMsg,_nChars,"MSG_GETFIRST");
break;
case MSG_GETNEXT:
SSTRCPY(_szMsg,_nChars,"MSG_GETNEXT");
break;
case MSG_SET:
SSTRCPY(_szMsg,_nChars,"MSG_SET");
break;
case MSG_RESET:
SSTRCPY(_szMsg,_nChars,"MSG_RESET");
break;
case MSG_QUERYSUPPORT:
SSTRCPY(_szMsg,_nChars,"MSG_QUERYSUPPORT");
break;
case MSG_GETHELP:
SSTRCPY(_szMsg,_nChars,"MSG_GETHELP");
break;
case MSG_GETLABEL:
SSTRCPY(_szMsg,_nChars,"MSG_GETLABEL");
break;
case MSG_GETLABELENUM:
SSTRCPY(_szMsg,_nChars,"MSG_GETLABELENUM");
break;
case MSG_XFERREADY:
SSTRCPY(_szMsg,_nChars,"MSG_XFERREADY");
break;
case MSG_CLOSEDSREQ:
SSTRCPY(_szMsg,_nChars,"MSG_CLOSEDSREQ");
break;
case MSG_CLOSEDSOK:
SSTRCPY(_szMsg,_nChars,"MSG_CLOSEDSOK");
break;
case MSG_DEVICEEVENT:
SSTRCPY(_szMsg,_nChars,"MSG_DEVICEEVENT");
break;
case MSG_CHECKSTATUS:
SSTRCPY(_szMsg,_nChars,"MSG_CHECKSTATUS");
break;
case MSG_OPENDSM:
SSTRCPY(_szMsg,_nChars,"MSG_OPENDSM");
break;
case MSG_CLOSEDSM:
SSTRCPY(_szMsg,_nChars,"MSG_CLOSEDSM");
break;
case MSG_OPENDS:
SSTRCPY(_szMsg,_nChars,"MSG_OPENDS");
break;
case MSG_CLOSEDS:
SSTRCPY(_szMsg,_nChars,"MSG_CLOSEDS");
break;
case MSG_USERSELECT:
SSTRCPY(_szMsg,_nChars,"MSG_USERSELECT");
break;
case MSG_DISABLEDS:
SSTRCPY(_szMsg,_nChars,"MSG_DISABLEDS");
break;
case MSG_ENABLEDS:
SSTRCPY(_szMsg,_nChars,"MSG_ENABLEDS");
break;
case MSG_ENABLEDSUIONLY:
SSTRCPY(_szMsg,_nChars,"MSG_ENABLEDSUIONLY");
break;
case MSG_PROCESSEVENT:
SSTRCPY(_szMsg,_nChars,"MSG_PROCESSEVENT");
break;
case MSG_ENDXFER:
SSTRCPY(_szMsg,_nChars,"MSG_ENDXFER");
break;
case MSG_CHANGEDIRECTORY:
SSTRCPY(_szMsg,_nChars,"MSG_CHANGEDIRECTORY");
break;
case MSG_CREATEDIRECTORY:
SSTRCPY(_szMsg,_nChars,"MSG_CREATEDIRECTORY");
break;
case MSG_DELETE:
SSTRCPY(_szMsg,_nChars,"MSG_DELETE");
break;
case MSG_FORMATMEDIA:
SSTRCPY(_szMsg,_nChars,"MSG_FORMATMEDIA");
break;
case MSG_GETCLOSE:
SSTRCPY(_szMsg,_nChars,"MSG_GETCLOSE");
break;
case MSG_GETFIRSTFILE:
SSTRCPY(_szMsg,_nChars,"MSG_GETFIRSTFILE");
break;
case MSG_GETINFO:
SSTRCPY(_szMsg,_nChars,"MSG_GETINFO");
break;
case MSG_GETNEXTFILE:
SSTRCPY(_szMsg,_nChars,"MSG_GETNEXTFILE");
break;
case MSG_RENAME:
SSTRCPY(_szMsg,_nChars,"MSG_RENAME");
break;
case MSG_PASSTHRU:
SSTRCPY(_szMsg,_nChars,"MSG_PASSTHRU");
break;
case MSG_REGISTER_CALLBACK:
SSTRCPY(_szMsg,_nChars,"MSG_REGISTER_CALLBACK");
break;
case MSG_RESETALL:
SSTRCPY(_szMsg,_nChars,"MSG_RESETALL");
break;
}
}
/*
* Convert a CAP_ or ICAP_ capability numerical value to a string...
*/
void CTwnDsm::StringFromCap(char *_szCap,
const int _nChars,
const TW_UINT16 _Cap)
{
switch (_Cap)
{
default:
SSNPRINTF(_szCap,_nChars,_nChars,"CAP_0x%04x",_Cap);
break;
case CAP_CUSTOMBASE:
SSTRCPY(_szCap,_nChars,"CAP_CUSTOMBASE");
break;
case CAP_XFERCOUNT:
SSTRCPY(_szCap,_nChars,"CAP_XFERCOUNT");
break;
case ICAP_COMPRESSION:
SSTRCPY(_szCap,_nChars,"ICAP_COMPRESSION");
break;
case ICAP_PIXELTYPE:
SSTRCPY(_szCap,_nChars,"ICAP_PIXELTYPE");
break;
case ICAP_UNITS:
SSTRCPY(_szCap,_nChars,"ICAP_UNITS");
break;
case ICAP_XFERMECH:
SSTRCPY(_szCap,_nChars,"ICAP_XFERMECH");
break;
case CAP_AUTHOR:
SSTRCPY(_szCap,_nChars,"CAP_AUTHOR");
break;
case CAP_CAPTION:
SSTRCPY(_szCap,_nChars,"CAP_CAPTION");
break;
case CAP_FEEDERENABLED:
SSTRCPY(_szCap,_nChars,"CAP_FEEDERENABLED");
break;
case CAP_FEEDERLOADED:
SSTRCPY(_szCap,_nChars,"CAP_FEEDERLOADED");
break;
case CAP_TIMEDATE:
SSTRCPY(_szCap,_nChars,"CAP_TIMEDATE");
break;
case CAP_SUPPORTEDCAPS:
SSTRCPY(_szCap,_nChars,"CAP_SUPPORTEDCAPS");
break;
case CAP_EXTENDEDCAPS:
SSTRCPY(_szCap,_nChars,"CAP_EXTENDEDCAPS");
break;
case CAP_AUTOFEED:
SSTRCPY(_szCap,_nChars,"CAP_AUTOFEED");
break;
case CAP_CLEARPAGE:
SSTRCPY(_szCap,_nChars,"CAP_CLEARPAGE");
break;
case CAP_FEEDPAGE:
SSTRCPY(_szCap,_nChars,"CAP_FEEDPAGE");
break;
case CAP_REWINDPAGE:
SSTRCPY(_szCap,_nChars,"CAP_REWINDPAGE");
break;
case CAP_INDICATORS:
SSTRCPY(_szCap,_nChars,"CAP_INDICATORS");
break;
case CAP_SUPPORTEDCAPSEXT:
SSTRCPY(_szCap,_nChars,"CAP_SUPPORTEDCAPSEXT");
break;
case CAP_PAPERDETECTABLE:
SSTRCPY(_szCap,_nChars,"CAP_PAPERDETECTABLE");
break;
case CAP_UICONTROLLABLE:
SSTRCPY(_szCap,_nChars,"CAP_UICONTROLLABLE");
break;
case CAP_DEVICEONLINE:
SSTRCPY(_szCap,_nChars,"CAP_DEVICEONLINE");
break;
case CAP_AUTOSCAN:
SSTRCPY(_szCap,_nChars,"CAP_AUTOSCAN");
break;
case CAP_THUMBNAILSENABLED:
SSTRCPY(_szCap,_nChars,"CAP_THUMBNAILSENABLED");
break;
case CAP_DUPLEX:
SSTRCPY(_szCap,_nChars,"CAP_DUPLEX");
break;
case CAP_DUPLEXENABLED:
SSTRCPY(_szCap,_nChars,"CAP_DUPLEXENABLED");
break;
case CAP_ENABLEDSUIONLY:
SSTRCPY(_szCap,_nChars,"CAP_ENABLEDSUIONLY");
break;
case CAP_CUSTOMDSDATA:
SSTRCPY(_szCap,_nChars,"CAP_CUSTOMDSDATA");
break;
case CAP_ENDORSER:
SSTRCPY(_szCap,_nChars,"CAP_ENDORSER");
break;
case CAP_JOBCONTROL:
SSTRCPY(_szCap,_nChars,"CAP_JOBCONTROL");
break;
case CAP_ALARMS:
SSTRCPY(_szCap,_nChars,"CAP_ALARMS");
break;
case CAP_ALARMVOLUME:
SSTRCPY(_szCap,_nChars,"CAP_ALARMVOLUME");
break;
case CAP_AUTOMATICCAPTURE:
SSTRCPY(_szCap,_nChars,"CAP_AUTOMATICCAPTURE");
break;
case CAP_TIMEBEFOREFIRSTCAPTURE:
SSTRCPY(_szCap,_nChars,"CAP_TIMEBEFOREFIRSTCAPTURE");
break;
case CAP_TIMEBETWEENCAPTURES:
SSTRCPY(_szCap,_nChars,"CAP_TIMEBETWEENCAPTURES");
break;
case CAP_CLEARBUFFERS:
SSTRCPY(_szCap,_nChars,"CAP_CLEARBUFFERS");
break;
case CAP_MAXBATCHBUFFERS:
SSTRCPY(_szCap,_nChars,"CAP_MAXBATCHBUFFERS");
break;
case CAP_DEVICETIMEDATE:
SSTRCPY(_szCap,_nChars,"CAP_DEVICETIMEDATE");
break;
case CAP_POWERSUPPLY:
SSTRCPY(_szCap,_nChars,"CAP_POWERSUPPLY");
break;
case CAP_CAMERAPREVIEWUI:
SSTRCPY(_szCap,_nChars,"CAP_CAMERAPREVIEWUI");
break;
case CAP_DEVICEEVENT:
SSTRCPY(_szCap,_nChars,"CAP_DEVICEEVENT");
break;
case CAP_SERIALNUMBER:
SSTRCPY(_szCap,_nChars,"CAP_SERIALNUMBER");
break;
case CAP_PRINTER:
SSTRCPY(_szCap,_nChars,"CAP_PRINTER");
break;
case CAP_PRINTERENABLED:
SSTRCPY(_szCap,_nChars,"CAP_PRINTERENABLED");
break;
case CAP_PRINTERINDEX:
SSTRCPY(_szCap,_nChars,"CAP_PRINTERINDEX");
break;
case CAP_PRINTERMODE:
SSTRCPY(_szCap,_nChars,"CAP_PRINTERMODE");
break;
case CAP_PRINTERSTRING:
SSTRCPY(_szCap,_nChars,"CAP_PRINTERSTRING");
break;
case CAP_PRINTERSUFFIX:
SSTRCPY(_szCap,_nChars,"CAP_PRINTERSUFFIX");
break;
case CAP_LANGUAGE:
SSTRCPY(_szCap,_nChars,"CAP_LANGUAGE");
break;
case CAP_FEEDERALIGNMENT:
SSTRCPY(_szCap,_nChars,"CAP_FEEDERALIGNMENT");
break;
case CAP_FEEDERORDER:
SSTRCPY(_szCap,_nChars,"CAP_FEEDERORDER");
break;
case CAP_REACQUIREALLOWED:
SSTRCPY(_szCap,_nChars,"CAP_REACQUIREALLOWED");
break;
case CAP_BATTERYMINUTES:
SSTRCPY(_szCap,_nChars,"CAP_BATTERYMINUTES");
break;
case CAP_BATTERYPERCENTAGE:
SSTRCPY(_szCap,_nChars,"CAP_BATTERYPERCENTAGE");
break;
case CAP_CAMERASIDE:
SSTRCPY(_szCap,_nChars,"CAP_CAMERASIDE");
break;
case CAP_SEGMENTED:
SSTRCPY(_szCap,_nChars,"CAP_SEGMENTED");
break;
case CAP_CAMERAENABLED:
SSTRCPY(_szCap,_nChars,"CAP_CAMERAENABLED");
break;
case CAP_CAMERAORDER:
SSTRCPY(_szCap,_nChars,"CAP_CAMERAORDER");
break;
case CAP_MICRENABLED:
SSTRCPY(_szCap,_nChars,"CAP_MICRENABLED");
break;
case CAP_FEEDERPREP:
SSTRCPY(_szCap,_nChars,"CAP_FEEDERPREP");
break;
case CAP_FEEDERPOCKET:
SSTRCPY(_szCap,_nChars,"CAP_FEEDERPOCKET");
break;
case CAP_AUTOMATICSENSEMEDIUM:
SSTRCPY(_szCap,_nChars,"CAP_AUTOMATICSENSEMEDIUM");
break;
case CAP_CUSTOMINTERFACEGUID:
SSTRCPY(_szCap,_nChars,"CAP_CUSTOMINTERFACEGUID");
break;
case ICAP_AUTOBRIGHT:
SSTRCPY(_szCap,_nChars,"ICAP_AUTOBRIGHT");
break;
case ICAP_BRIGHTNESS:
SSTRCPY(_szCap,_nChars,"ICAP_BRIGHTNESS");
break;
case ICAP_CONTRAST:
SSTRCPY(_szCap,_nChars,"ICAP_CONTRAST");
break;
case ICAP_CUSTHALFTONE:
SSTRCPY(_szCap,_nChars,"ICAP_CUSTHALFTONE");
break;
case ICAP_EXPOSURETIME:
SSTRCPY(_szCap,_nChars,"ICAP_EXPOSURETIME");
break;
case ICAP_FILTER:
SSTRCPY(_szCap,_nChars,"ICAP_FILTER");
break;
case ICAP_FLASHUSED:
SSTRCPY(_szCap,_nChars,"ICAP_FLASHUSED");
break;
case ICAP_GAMMA:
SSTRCPY(_szCap,_nChars,"ICAP_GAMMA");
break;
case ICAP_HALFTONES:
SSTRCPY(_szCap,_nChars,"ICAP_HALFTONES");
break;
case ICAP_HIGHLIGHT:
SSTRCPY(_szCap,_nChars,"ICAP_HIGHLIGHT");
break;
case ICAP_IMAGEFILEFORMAT:
SSTRCPY(_szCap,_nChars,"ICAP_IMAGEFILEFORMAT");
break;
case ICAP_LAMPSTATE:
SSTRCPY(_szCap,_nChars,"ICAP_LAMPSTATE");
break;
case ICAP_LIGHTSOURCE:
SSTRCPY(_szCap,_nChars,"ICAP_LIGHTSOURCE");
break;
case ICAP_ORIENTATION:
SSTRCPY(_szCap,_nChars,"ICAP_ORIENTATION");
break;
case ICAP_PHYSICALWIDTH:
SSTRCPY(_szCap,_nChars,"ICAP_PHYSICALWIDTH");
break;
case ICAP_PHYSICALHEIGHT:
SSTRCPY(_szCap,_nChars,"ICAP_PHYSICALHEIGHT");
break;
case ICAP_SHADOW:
SSTRCPY(_szCap,_nChars,"ICAP_SHADOW");
break;
case ICAP_FRAMES:
SSTRCPY(_szCap,_nChars,"ICAP_FRAMES");
break;
case ICAP_XNATIVERESOLUTION:
SSTRCPY(_szCap,_nChars,"ICAP_XNATIVERESOLUTION");
break;
case ICAP_YNATIVERESOLUTION:
SSTRCPY(_szCap,_nChars,"ICAP_YNATIVERESOLUTION");
break;
case ICAP_XRESOLUTION:
SSTRCPY(_szCap,_nChars,"ICAP_XRESOLUTION");
break;
case ICAP_YRESOLUTION:
SSTRCPY(_szCap,_nChars,"ICAP_YRESOLUTION");
break;
case ICAP_MAXFRAMES:
SSTRCPY(_szCap,_nChars,"ICAP_MAXFRAMES");
break;
case ICAP_TILES:
SSTRCPY(_szCap,_nChars,"ICAP_TILES");
break;
case ICAP_BITORDER:
SSTRCPY(_szCap,_nChars,"ICAP_BITORDER");
break;
case ICAP_CCITTKFACTOR:
SSTRCPY(_szCap,_nChars,"ICAP_CCITTKFACTOR");
break;
case ICAP_LIGHTPATH:
SSTRCPY(_szCap,_nChars,"ICAP_LIGHTPATH");
break;
case ICAP_PIXELFLAVOR:
SSTRCPY(_szCap,_nChars,"ICAP_PIXELFLAVOR");
break;
case ICAP_PLANARCHUNKY:
SSTRCPY(_szCap,_nChars,"ICAP_PLANARCHUNKY");
break;
case ICAP_ROTATION:
SSTRCPY(_szCap,_nChars,"ICAP_ROTATION");
break;
case ICAP_SUPPORTEDSIZES:
SSTRCPY(_szCap,_nChars,"ICAP_SUPPORTEDSIZES");
break;
case ICAP_THRESHOLD:
SSTRCPY(_szCap,_nChars,"ICAP_THRESHOLD");
break;
case ICAP_XSCALING:
SSTRCPY(_szCap,_nChars,"ICAP_XSCALING");
break;
case ICAP_YSCALING:
SSTRCPY(_szCap,_nChars,"ICAP_YSCALING");
break;
case ICAP_BITORDERCODES:
SSTRCPY(_szCap,_nChars,"ICAP_BITORDERCODES");
break;
case ICAP_PIXELFLAVORCODES:
SSTRCPY(_szCap,_nChars,"ICAP_PIXELFLAVORCODES");
break;
case ICAP_JPEGPIXELTYPE:
SSTRCPY(_szCap,_nChars,"ICAP_JPEGPIXELTYPE");
break;
case ICAP_TIMEFILL:
SSTRCPY(_szCap,_nChars,"ICAP_TIMEFILL");
break;
case ICAP_BITDEPTH:
SSTRCPY(_szCap,_nChars,"ICAP_BITDEPTH");
break;
case ICAP_BITDEPTHREDUCTION:
SSTRCPY(_szCap,_nChars,"ICAP_BITDEPTHREDUCTION");
break;
case ICAP_UNDEFINEDIMAGESIZE:
SSTRCPY(_szCap,_nChars,"ICAP_UNDEFINEDIMAGESIZE");
break;
case ICAP_IMAGEDATASET:
SSTRCPY(_szCap,_nChars,"ICAP_IMAGEDATASET");
break;
case ICAP_EXTIMAGEINFO:
SSTRCPY(_szCap,_nChars,"ICAP_EXTIMAGEINFO");
break;
case ICAP_MINIMUMHEIGHT:
SSTRCPY(_szCap,_nChars,"ICAP_MINIMUMHEIGHT");
break;
case ICAP_MINIMUMWIDTH:
SSTRCPY(_szCap,_nChars,"ICAP_MINIMUMWIDTH");
break;
case ICAP_AUTODISCARDBLANKPAGES:
SSTRCPY(_szCap,_nChars,"ICAP_AUTODISCARDBLANKPAGES");
break;
case ICAP_FLIPROTATION:
SSTRCPY(_szCap,_nChars,"ICAP_FLIPROTATION");
break;
case ICAP_BARCODEDETECTIONENABLED:
SSTRCPY(_szCap,_nChars,"ICAP_BARCODEDETECTIONENABLED");
break;
case ICAP_SUPPORTEDBARCODETYPES:
SSTRCPY(_szCap,_nChars,"ICAP_SUPPORTEDBARCODETYPES");
break;
case ICAP_BARCODEMAXSEARCHPRIORITIES:
SSTRCPY(_szCap,_nChars,"ICAP_BARCODEMAXSEARCHPRIORITIES");
break;
case ICAP_BARCODESEARCHPRIORITIES:
SSTRCPY(_szCap,_nChars,"ICAP_BARCODESEARCHPRIORITIES");
break;
case ICAP_BARCODESEARCHMODE:
SSTRCPY(_szCap,_nChars,"ICAP_BARCODESEARCHMODE");
break;
case ICAP_BARCODEMAXRETRIES:
SSTRCPY(_szCap,_nChars,"ICAP_BARCODEMAXRETRIES");
break;
case ICAP_BARCODETIMEOUT:
SSTRCPY(_szCap,_nChars,"ICAP_BARCODETIMEOUT");
break;
case ICAP_ZOOMFACTOR:
SSTRCPY(_szCap,_nChars,"ICAP_ZOOMFACTOR");
break;
case ICAP_PATCHCODEDETECTIONENABLED:
SSTRCPY(_szCap,_nChars,"ICAP_PATCHCODEDETECTIONENABLED");
break;
case ICAP_SUPPORTEDPATCHCODETYPES:
SSTRCPY(_szCap,_nChars,"ICAP_SUPPORTEDPATCHCODETYPES");
break;
case ICAP_PATCHCODEMAXSEARCHPRIORITIES:
SSTRCPY(_szCap,_nChars,"ICAP_PATCHCODEMAXSEARCHPRIORITIES");
break;
case ICAP_PATCHCODESEARCHPRIORITIES:
SSTRCPY(_szCap,_nChars,"ICAP_PATCHCODESEARCHPRIORITIES");
break;
case ICAP_PATCHCODESEARCHMODE:
SSTRCPY(_szCap,_nChars,"ICAP_PATCHCODESEARCHMODE");
break;
case ICAP_PATCHCODEMAXRETRIES:
SSTRCPY(_szCap,_nChars,"ICAP_PATCHCODEMAXRETRIES");
break;
case ICAP_PATCHCODETIMEOUT:
SSTRCPY(_szCap,_nChars,"ICAP_PATCHCODETIMEOUT");
break;
case ICAP_FLASHUSED2:
SSTRCPY(_szCap,_nChars,"ICAP_FLASHUSED2");
break;
case ICAP_IMAGEFILTER:
SSTRCPY(_szCap,_nChars,"ICAP_IMAGEFILTER");
break;
case ICAP_NOISEFILTER:
SSTRCPY(_szCap,_nChars,"ICAP_NOISEFILTER");
break;
case ICAP_OVERSCAN:
SSTRCPY(_szCap,_nChars,"ICAP_OVERSCAN");
break;
case ICAP_AUTOMATICBORDERDETECTION:
SSTRCPY(_szCap,_nChars,"ICAP_AUTOMATICBORDERDETECTION");
break;
case ICAP_AUTOMATICDESKEW:
SSTRCPY(_szCap,_nChars,"ICAP_AUTOMATICDESKEW");
break;
case ICAP_AUTOMATICROTATE:
SSTRCPY(_szCap,_nChars,"ICAP_AUTOMATICROTATE");
break;
case ICAP_JPEGQUALITY:
SSTRCPY(_szCap,_nChars,"ICAP_JPEGQUALITY");
break;
case ICAP_FEEDERTYPE:
SSTRCPY(_szCap,_nChars,"ICAP_FEEDERTYPE");
break;
case ICAP_ICCPROFILE:
SSTRCPY(_szCap,_nChars,"ICAP_ICCPROFILE");
break;
case ICAP_AUTOSIZE:
SSTRCPY(_szCap,_nChars,"ICAP_AUTOSIZE");
break;
case ICAP_AUTOMATICCROPUSESFRAME:
SSTRCPY(_szCap,_nChars,"ICAP_AUTOMATICCROPUSESFRAME");
break;
case ICAP_AUTOMATICLENGTHDETECTION:
SSTRCPY(_szCap,_nChars,"ICAP_AUTOMATICLENGTHDETECTION");
break;
case ICAP_AUTOMATICCOLORENABLED:
SSTRCPY(_szCap,_nChars,"ICAP_AUTOMATICCOLORENABLED");
break;
case ICAP_AUTOMATICCOLORNONCOLORPIXELTYPE:
SSTRCPY(_szCap,_nChars,"ICAP_AUTOMATICCOLORNONCOLORPIXELTYPE");
break;
case ICAP_COLORMANAGEMENTENABLED:
SSTRCPY(_szCap,_nChars,"ICAP_COLORMANAGEMENTENABLED");
break;
case ICAP_IMAGEMERGE:
SSTRCPY(_szCap,_nChars,"ICAP_IMAGEMERGE");
break;
case ICAP_IMAGEMERGEHEIGHTTHRESHOLD:
SSTRCPY(_szCap,_nChars,"ICAP_IMAGEMERGEHEIGHTTHRESHOLD");
break;
case ICAP_SUPPORTEDEXTIMAGEINFO:
SSTRCPY(_szCap,_nChars,"ICAP_SUPPORTEDEXTIMAGEINFO");
break;
case ACAP_AUDIOFILEFORMAT:
SSTRCPY(_szCap,_nChars,"ACAP_AUDIOFILEFORMAT");
break;
case ACAP_XFERMECH:
SSTRCPY(_szCap,_nChars,"ACAP_XFERMECH");
break;
}
}
/*
* Convert a TWRC_ return code numerical value to a string...
*/
void CTwnDsm::StringFromRC(char *_szRc,
const int _nChars,
const TW_UINT16 _rc)
{
switch (_rc)
{
default:
SSNPRINTF(_szRc,_nChars,_nChars,"TWRC_0x%04x",_rc);
break;
case TWRC_SUCCESS:
SSTRCPY(_szRc,_nChars,"TWRC_SUCCESS");
break;
case TWRC_FAILURE:
SSTRCPY(_szRc,_nChars,"TWRC_FAILURE");
break;
case TWRC_CHECKSTATUS:
SSTRCPY(_szRc,_nChars,"TWRC_CHECKSTATUS");
break;
case TWRC_CANCEL:
SSTRCPY(_szRc,_nChars,"TWRC_CANCEL");
break;
case TWRC_DSEVENT:
SSTRCPY(_szRc,_nChars,"TWRC_DSEVENT");
break;
case TWRC_NOTDSEVENT:
SSTRCPY(_szRc,_nChars,"TWRC_NOTDSEVENT");
break;
case TWRC_XFERDONE:
SSTRCPY(_szRc,_nChars,"TWRC_XFERDONE");
break;
case TWRC_ENDOFLIST:
SSTRCPY(_szRc,_nChars,"TWRC_ENDOFLIST");
break;
case TWRC_INFONOTSUPPORTED:
SSTRCPY(_szRc,_nChars,"TWRC_INFONOTSUPPORTED");
break;
case TWRC_DATANOTAVAILABLE:
SSTRCPY(_szRc,_nChars,"TWRC_DATANOTAVAILABLE");
break;
}
}
/*
* Convert a Container type to a string...
*/
void CTwnDsm::StringFromConType(char *_szData,
const int _nChars,
const TW_UINT16 _ConType)
{
switch (_ConType)
{
default:
SSNPRINTF(_szData,_nChars,_nChars," TWON_0x%04x",_ConType);
break;
case TWON_DONTCARE16:
SSTRCPY(_szData,_nChars," TWON_DONTCARE16");
break;
case TWON_ARRAY:
SSTRCPY(_szData,_nChars," TWON_ARRAY");
break;
case TWON_ENUMERATION:
SSTRCPY(_szData,_nChars," TWON_ENUMERATION");
break;
case TWON_ONEVALUE:
SSTRCPY(_szData,_nChars," TWON_ONEVALUE ");
break;
case TWON_RANGE:
SSTRCPY(_szData,_nChars," TWON_RANGE");
break;
}
}
/*
* Convert a Condition Code to a string...
*/
void CTwnDsm::StringFromConditionCode(char *_szData,
const int _nChars,
const TW_UINT16 _ConCode)
{
switch (_ConCode)
{
default:
SSNPRINTF(_szData,_nChars,_nChars," TWCC_0x%04x",_ConCode);
break;
case TWCC_SUCCESS:
SSTRCPY(_szData,_nChars," TWCC_SUCCESS");
break;
case TWCC_BUMMER:
SSTRCPY(_szData,_nChars," TWCC_BUMMER");
break;
case TWCC_LOWMEMORY:
SSTRCPY(_szData,_nChars," TWCC_LOWMEMORY");
break;
case TWCC_NODS:
SSTRCPY(_szData,_nChars," TWCC_NODS");
break;
case TWCC_MAXCONNECTIONS:
SSTRCPY(_szData,_nChars," TWCC_MAXCONNECTIONS");
break;
case TWCC_OPERATIONERROR:
SSTRCPY(_szData,_nChars," TWCC_OPERATIONERROR");
break;
case TWCC_BADCAP:
SSTRCPY(_szData,_nChars," TWCC_BADCAP");
break;
case TWCC_BADPROTOCOL:
SSTRCPY(_szData,_nChars," TWCC_BADPROTOCOL");
break;
case TWCC_BADVALUE:
SSTRCPY(_szData,_nChars," TWCC_BADVALUE");
break;
case TWCC_SEQERROR:
SSTRCPY(_szData,_nChars," TWCC_SEQERROR");
break;
case TWCC_BADDEST:
SSTRCPY(_szData,_nChars," TWCC_BADDEST");
break;
case TWCC_CAPUNSUPPORTED:
SSTRCPY(_szData,_nChars," TWCC_CAPUNSUPPORTED");
break;
case TWCC_CAPBADOPERATION:
SSTRCPY(_szData,_nChars," TWCC_CAPBADOPERATION");
break;
case TWCC_CAPSEQERROR:
SSTRCPY(_szData,_nChars," TWCC_CAPSEQERROR");
break;
case TWCC_DENIED:
SSTRCPY(_szData,_nChars," TWCC_DENIED");
break;
case TWCC_FILEEXISTS:
SSTRCPY(_szData,_nChars," TWCC_FILEEXISTS");
break;
case TWCC_FILENOTFOUND:
SSTRCPY(_szData,_nChars," TWCC_FILENOTFOUND");
break;
case TWCC_NOTEMPTY:
SSTRCPY(_szData,_nChars," TWCC_NOTEMPTY");
break;
case TWCC_PAPERJAM:
SSTRCPY(_szData,_nChars," TWCC_PAPERJAM");
break;
case TWCC_PAPERDOUBLEFEED:
SSTRCPY(_szData,_nChars," TWCC_PAPERDOUBLEFEED");
break;
case TWCC_FILEWRITEERROR:
SSTRCPY(_szData,_nChars," TWCC_FILEWRITEERROR");
break;
case TWCC_CHECKDEVICEONLINE:
SSTRCPY(_szData,_nChars," TWCC_CHECKDEVICEONLINE");
break;
case TWCC_INTERLOCK:
SSTRCPY(_szData,_nChars," TWCC_INTERLOCK");
break;
case TWCC_DAMAGEDCORNER:
SSTRCPY(_szData,_nChars," TWCC_DAMAGEDCORNER");
break;
case TWCC_FOCUSERROR:
SSTRCPY(_szData,_nChars," TWCC_FOCUSERROR");
break;
case TWCC_DOCTOOLIGHT:
SSTRCPY(_szData,_nChars," TWCC_DOCTOOLIGHT");
break;
case TWCC_DOCTOODARK:
SSTRCPY(_szData,_nChars," TWCC_DOCTOODARK");
break;
case TWCC_NOMEDIA:
SSTRCPY(_szData,_nChars," TWCC_NOMEDIA");
break;
}
}
/*
* Allocate memory on behalf of the caller (could be the application
* or the driver)...
*/
TW_HANDLE PASCAL DSM_MemAllocate (TW_UINT32 _bytes)
{
TW_HANDLE handle;
// Validate...
if (0 == _bytes)
{
kLOG((kLOGERR,"_bytes is zero..."));
return (TW_HANDLE)NULL;
}
// Windows...
#if (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP)
handle = (TW_HANDLE)::GlobalAlloc(GPTR,_bytes);
if (0 == handle)
{
kLOG((kLOGERR,"DSM_MemAllocate failed to allocate %ld bytes...",_bytes));
return (TW_HANDLE)NULL;
}
return handle;
// MacOS
#elif (TWNDSM_OS == TWNDSM_OS_MACOSX)
handle = (TW_HANDLE)NewHandleClear(_bytes);
if (0 == handle)
{
kLOG((kLOGERR,"DSM_MemAllocate failed to allocate %ld bytes...",_bytes));
return (TW_HANDLE)NULL;
}
return handle;
// Linux
#elif (TWNDSM_CMP == TWNDSM_CMP_GNUGPP)
handle = (TW_HANDLE)calloc(_bytes,1);
if (0 == handle)
{
kLOG((kLOGERR,"DSM_MemAllocate failed to allocate %ld bytes...",_bytes));
return (TW_HANDLE)NULL;
}
return handle;
// Oops...
#else
#error Sorry, we do not recognize this system...
#endif
}
/*
* Free memory on behalf of the caller (could be the application
* or the driver)...
*/
void PASCAL DSM_MemFree (TW_HANDLE _handle)
{
// Validate...
if (0 == _handle)
{
kLOG((kLOGERR,"ignoring attempt to free null handle..."));
return;
}
// Windows...
#if (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP)
::GlobalFree(_handle);
// MacOS
#elif (TWNDSM_OS == TWNDSM_OS_MACOSX)
DisposeHandle((Handle)_handle);
// Linux...
#elif (TWNDSM_CMP == TWNDSM_CMP_GNUGPP)
free(_handle);
// Oops...
#else
#error Sorry, we do not recognize this system...
#endif
}
/*
* Lock memory on behalf of the caller...
*/
TW_MEMREF PASCAL DSM_MemLock (TW_HANDLE _handle)
{
// Validate...
if (0 == _handle)
{
kLOG((kLOGERR,"attempting to lock null handle..."));
return (TW_MEMREF)NULL;
}
// Windows...technically we shouldn't have to do the
// lock, since we allocated with GPTR, but I'm nervous
// that we might get a GHND sent to us. And since
// this is a no-op for a GPTR, what they hey...
#if (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP)
return (TW_MEMREF)::GlobalLock(_handle);
// MacOS
#elif (TWNDSM_OS == TWNDSM_OS_MACOSX)
return _handle ? *_handle : 0;
// Linux...
#elif (TWNDSM_CMP == TWNDSM_CMP_GNUGPP)
return (TW_MEMREF)_handle;
// Oops...
#else
#error Sorry, we do not recognize this system...
#endif
}
/*
* Unlock memory on behalf of the caller, if needed. This function
* is a placeholder at the moment. It'll get more interesting if it
* has to do locking on Mac OS/X...
*/
void PASCAL DSM_MemUnlock (TW_HANDLE _handle)
{
// Validate...
if (0 == _handle)
{
kLOG((kLOGERR,"attempting to unlock null handle..."));
return;
}
// Windows...
#if (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP)
::GlobalUnlock(_handle);
// Linux...
#elif (TWNDSM_CMP == TWNDSM_CMP_GNUGPP)
// Oops...
#else
#error Sorry, we do not recognize this system...
#endif
}
/*
* This function wraps the function loading calls. Linux has a
* special way to check dlsym failures.
*/
void* DSM_LoadFunction(void* _pHandle, const char* _pszSymbol)
{
void* pRet = 0;
#if (TWNDSM_OS == TWNDSM_OS_MACOSX)
pRet = CFBundleGetFunctionPointerForName((CFBundleRef)_pHandle,
CFStringCreateWithCStringNoCopy(0, _pszSymbol, kCFStringEncodingUTF8, 0));
#else
#if (TWNDSM_CMP == TWNDSM_CMP_GNUGPP)
dlerror(); /* Clear any existing error */
#endif
// Try to get the entry point...
pRet = LOADFUNCTION(_pHandle, _pszSymbol);
#if (TWNDSM_CMP == TWNDSM_CMP_GNUGPP)
char* psz_error = 0;
if((psz_error = dlerror()) != NULL)
{
kLOG((kLOGERR,"dlsym error: %s",psz_error));
pRet = 0;
}
#endif
#endif
return pRet;
}