code_device/twain/dsm/dsm.cpp

3919 lines
127 KiB
C++
Raw Normal View History

/***************************************************************************
* 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;
}