Twain_DSM  1.0
dsm.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * TWAIN Data Source Manager version 2.1
3  * Manages image acquisition data sources used by a machine.
4  * Copyright © 2007 TWAIN Working Group:
5  * Adobe Systems Incorporated,AnyDoc Software Inc., Eastman Kodak Company,
6  * Fujitsu Computer Products of America, JFL Peripheral Solutions Inc.,
7  * Ricoh Corporation, and Xerox Corporation.
8  * All rights reserved.
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23  *
24  * Contact the TWAIN Working Group by emailing the Technical Subcommittee at
25  * twainwg@twain.org or mailing us at 13090 Hwy 9, Suite 3, Boulder Creek, CA 95006.
26  *
27  ***************************************************************************/
28 
61 #include "dsm.h"
62 
63 
64 
65 /*
66 * These are all the globals we should ever have in this project...
67 */
68 HINSTANCE g_hinstance = 0;
85 /*
86 * we need this because xcode insists on complaining about content
87 * inside of visual studio's code block
88 */
89 #if (TWNDSM_OS == TWNDSM_OS_MACOSX)
90 #pragma clang diagnostic push
91 #pragma clang diagnostic ignored "-Wall"
92 #endif
93 #if (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP)
94 typedef struct
95 {
96  TW_INT16 Language;
97  BYTE CharSet;
98  LANGID LangId;
99  char *Title;
100  char *Sources;
101  char *Select;
102  char *Cancel;
103 } TwLocalize;
104 
109 {
110  {TWLG_AFRIKAANS, ANSI_CHARSET, MAKELANGID(LANG_AFRIKAANS,SUBLANG_NEUTRAL), "Select Source","Sources:","Select","\x4b\x61\x6e\x73\x65\x6c\x6c\x65\x65\x72"},
111  {TWLG_ALBANIA, EASTEUROPE_CHARSET, MAKELANGID(LANG_ALBANIAN,SUBLANG_NEUTRAL), "","","",""},
112  {TWLG_ARABIC, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_NEUTRAL), "","","",""},
113  {TWLG_ARABIC_ALGERIA, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_ALGERIA), "","","",""},
114  {TWLG_ARABIC_BAHRAIN, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_BAHRAIN), "","","",""},
115  {TWLG_ARABIC_EGYPT, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_EGYPT), "","","",""},
116  {TWLG_ARABIC_IRAQ, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_IRAQ), "","","",""},
117  {TWLG_ARABIC_JORDAN, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_JORDAN), "","","",""},
118  {TWLG_ARABIC_KUWAIT, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_KUWAIT), "","","",""},
119  {TWLG_ARABIC_LEBANON, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_LEBANON), "","","",""},
120  {TWLG_ARABIC_LIBYA, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_LIBYA), "","","",""},
121  {TWLG_ARABIC_MOROCCO, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_MOROCCO), "","","",""},
122  {TWLG_ARABIC_OMAN, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_OMAN), "","","",""},
123  {TWLG_ARABIC_QATAR, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_QATAR), "","","",""},
124  {TWLG_ARABIC_SAUDIARABIA, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_SAUDI_ARABIA), "","","",""},
125  {TWLG_ARABIC_SYRIA, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_SYRIA), "","","",""},
126  {TWLG_ARABIC_TUNISIA, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_TUNISIA), "","","",""},
127  {TWLG_ARABIC_UAE, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_UAE), "","","",""},
128  {TWLG_ARABIC_YEMEN, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_YEMEN), "","","",""},
129  {TWLG_ASSAMESE, ANSI_CHARSET, MAKELANGID(LANG_ASSAMESE,SUBLANG_NEUTRAL), "","","",""},
130  {TWLG_BASQUE, ANSI_CHARSET, MAKELANGID(LANG_BASQUE,SUBLANG_NEUTRAL), "Select Source","Sources:","Select","\x55\x74\x7a\x69"},
131  {TWLG_BENGALI, ANSI_CHARSET, MAKELANGID(LANG_BENGALI,SUBLANG_NEUTRAL), "","","",""},
132  {TWLG_BIHARI, 0, 0, "","","",""},
133  {TWLG_BODO, 0, 0, "","","",""},
134  {TWLG_BULGARIAN, RUSSIAN_CHARSET, MAKELANGID(LANG_BULGARIAN,SUBLANG_NEUTRAL), "","","",""},
135  {TWLG_BYELORUSSIAN, RUSSIAN_CHARSET, MAKELANGID(LANG_BELARUSIAN,SUBLANG_NEUTRAL), "","","",""},
136  {TWLG_CATALAN, ANSI_CHARSET, MAKELANGID(LANG_CATALAN,SUBLANG_NEUTRAL), "Select Source","Sources:","Select","\x43\x61\x6e\x63\x65\x6c\xc2\xb7\x6c\x61"},
137  {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"},
138  {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"},
139  {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"},
140  {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"},
141  {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"},
142  {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"},
143  {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"},
144  {TWLG_CROATIA, EASTEUROPE_CHARSET, MAKELANGID(LANG_CROATIAN,SUBLANG_NEUTRAL), "Select Source","Sources:","Select","\x4f\x64\x75\x73\x74\x61\x6e\x69"},
145  {TWLG_CZECH, EASTEUROPE_CHARSET, MAKELANGID(LANG_CZECH,SUBLANG_DEFAULT), "Select Source","Sources:","Select","\x53\x74\x6f\x72\x6e\x6f"},
146  {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"},
147  {TWLG_DOGRI, 0, 0, "","","",""},
148  {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"},
149  {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"},
150  {TWLG_ENGLISH, ANSI_CHARSET, MAKELANGID(LANG_ENGLISH,SUBLANG_NEUTRAL), "Select Source","Sources:","Select","Cancel"},
151  {TWLG_ENGLISH_AUSTRALIAN, ANSI_CHARSET, MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_AUS), "Select Source","Sources:","Select","Cancel"},
152  {TWLG_ENGLISH_CANADIAN, ANSI_CHARSET, MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_CAN), "Select Source","Sources:","Select","Cancel"},
153  {TWLG_ENGLISH_IRELAND, ANSI_CHARSET, MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_EIRE), "Select Source","Sources:","Select","Cancel"},
154  {TWLG_ENGLISH_NEWZEALAND, ANSI_CHARSET, MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_NZ), "Select Source","Sources:","Select","Cancel"},
155  {TWLG_ENGLISH_SOUTHAFRICA,ANSI_CHARSET, MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_SOUTH_AFRICA), "Select Source","Sources:","Select","Cancel"},
156  {TWLG_ENGLISH_UK, ANSI_CHARSET, MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_UK), "Select Source","Sources:","Select","Cancel"},
157  {TWLG_ENGLISH_USA, ANSI_CHARSET, MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US), "Select Source","Sources:","Select","Cancel"},
158  {TWLG_ESTONIAN, BALTIC_CHARSET, MAKELANGID(LANG_ESTONIAN,SUBLANG_NEUTRAL), "Select Source","Sources:","Select","\x4b\x75\x73\x74\x75\x74\x61"},
159  {TWLG_FAEROESE, EASTEUROPE_CHARSET, MAKELANGID(LANG_FAEROESE,SUBLANG_NEUTRAL), "","","",""},
160  {TWLG_FARSI, ARABIC_CHARSET, MAKELANGID(LANG_FARSI,SUBLANG_NEUTRAL), "","","",""},
161  {TWLG_FINNISH, ANSI_CHARSET, MAKELANGID(LANG_FINNISH,SUBLANG_NEUTRAL), "Select Source","Sources:","Select","\x50\x65\x72\x75\x75\x74\x61"},
162  {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"},
163  {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"},
164  {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"},
165  {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"},
166  {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"},
167  {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"},
168  {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"},
169  {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"},
170  {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"},
171  {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"},
172  {TWLG_GREEK, GREEK_CHARSET, MAKELANGID(LANG_GREEK,SUBLANG_DEFAULT), "","","",""},
173  {TWLG_GUJARATI, GREEK_CHARSET, MAKELANGID(LANG_GUJARATI,SUBLANG_DEFAULT), "","","",""},
174  {TWLG_HARYANVI, 0, 0, "","","",""},
175  {TWLG_HEBREW, HEBREW_CHARSET, MAKELANGID(LANG_HEBREW,SUBLANG_NEUTRAL), "","","",""},
176  {TWLG_HINDI, HEBREW_CHARSET, MAKELANGID(LANG_HINDI,SUBLANG_NEUTRAL), "","","",""},
177  {TWLG_HUNGARIAN, EASTEUROPE_CHARSET, MAKELANGID(LANG_HUNGARIAN,SUBLANG_NEUTRAL), "Select Source","Sources:","Select","\x4d\xc3\xa9\x67\x73\x65"},
178  {TWLG_ICELANDIC, ANSI_CHARSET, MAKELANGID(LANG_ICELANDIC,SUBLANG_NEUTRAL), "","","",""},
179  {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"},
180  {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"},
181  {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"},
182  {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"},
183  {TWLG_KANNADA, ANSI_CHARSET, MAKELANGID(LANG_KANNADA,SUBLANG_NEUTRAL), "","","",""},
184  {TWLG_KASHMIRI, ANSI_CHARSET, MAKELANGID(LANG_KASHMIRI,SUBLANG_NEUTRAL), "","","",""},
185  {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"},
186  {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"},
187  {TWLG_LATVIAN, BALTIC_CHARSET, MAKELANGID(LANG_LATVIAN,SUBLANG_NEUTRAL), "","","",""},
188  {TWLG_LITHUANIAN, BALTIC_CHARSET, MAKELANGID(LANG_LITHUANIAN,SUBLANG_NEUTRAL), "","","",""},
189  {TWLG_MALAYALAM, BALTIC_CHARSET, MAKELANGID(LANG_MALAYALAM,SUBLANG_NEUTRAL), "","","",""},
190  {TWLG_MARATHI, ANSI_CHARSET, MAKELANGID(LANG_MARATHI,SUBLANG_NEUTRAL), "","","",""},
191  {TWLG_MARWARI, 0, 0, "","","",""},
192  {TWLG_MEGHALAYAN, 0, 0, "","","",""},
193  {TWLG_MIZO, 0, 0, "","","",""},
194  {TWLG_NAGA, 0, 0, "","","",""},
195  {TWLG_NORWEGIAN, ANSI_CHARSET, MAKELANGID(LANG_NORWEGIAN,SUBLANG_NEUTRAL), "","","",""},
196  {TWLG_NORWEGIAN_BOKMAL, ANSI_CHARSET, MAKELANGID(LANG_NORWEGIAN,SUBLANG_NORWEGIAN_BOKMAL), "","","",""},
197  {TWLG_NORWEGIAN_NYNORSK, ANSI_CHARSET, MAKELANGID(LANG_NORWEGIAN,SUBLANG_NORWEGIAN_NYNORSK), "","","",""},
198  {TWLG_ORISSI, 0, 0, "","","",""},
199  {TWLG_POLISH, EASTEUROPE_CHARSET, MAKELANGID(LANG_POLISH,SUBLANG_NEUTRAL), "Select Source","Sources:","Select","\x41\x6e\x75\x6c\x75\x6a"},
200  {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"},
201  {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"},
202  {TWLG_PUNJABI, ANSI_CHARSET, MAKELANGID(LANG_PUNJABI,SUBLANG_NEUTRAL), "","","",""},
203  {TWLG_PUSHTU, 0, 0, "","","",""},
204  {TWLG_ROMANIAN, EASTEUROPE_CHARSET, MAKELANGID(LANG_ROMANIAN,SUBLANG_NEUTRAL), "","","",""},
205  {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"},
206  {TWLG_SERBIAN_CYRILLIC, ANSI_CHARSET, MAKELANGID(LANG_SERBIAN,SUBLANG_SERBIAN_CYRILLIC), "","","",""},
207  {TWLG_SERBIAN_LATIN, EASTEUROPE_CHARSET, MAKELANGID(LANG_SERBIAN,SUBLANG_SERBIAN_LATIN), "","","",""},
208  {TWLG_SIKKIMI, 0, 0, "","","",""},
209  {TWLG_SLOVAK, EASTEUROPE_CHARSET, MAKELANGID(LANG_SLOVAK,SUBLANG_NEUTRAL), "","","",""},
210  {TWLG_SLOVENIAN, EASTEUROPE_CHARSET, MAKELANGID(LANG_SLOVENIAN,SUBLANG_NEUTRAL), "Select Source","Sources:","Select","\x50\x72\x65\x6b\x69\x6e\x69"},
211  {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"},
212  {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"},
213  {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"},
214  {TWLG_SWEDISH, ANSI_CHARSET, MAKELANGID(LANG_SWEDISH,SUBLANG_SWEDISH), "Select Source","Sources:","Select","\x41\x76\x62\x72\x79\x74"},
215  {TWLG_SWEDISH_FINLAND, ANSI_CHARSET, MAKELANGID(LANG_SWEDISH,SUBLANG_SWEDISH_FINLAND), "Select Source","Sources:","Select","\x41\x76\x62\x72\x79\x74"},
216  {TWLG_TAMIL, ANSI_CHARSET, MAKELANGID(LANG_TAMIL,SUBLANG_NEUTRAL), "","","",""},
217  {TWLG_TELUGU, ANSI_CHARSET, MAKELANGID(LANG_TELUGU,SUBLANG_NEUTRAL), "","","",""},
218  {TWLG_THAI, THAI_CHARSET, MAKELANGID(LANG_THAI,SUBLANG_NEUTRAL), "","","",""},
219  {TWLG_TRIPURI, 0, 0, "","","",""},
220  {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"},
221  {TWLG_UKRANIAN, RUSSIAN_CHARSET, MAKELANGID(LANG_UKRAINIAN,SUBLANG_NEUTRAL), "","","",""},
222  {TWLG_URDU, ANSI_CHARSET, MAKELANGID(LANG_URDU,SUBLANG_NEUTRAL), "","","",""},
223  {TWLG_VIETNAMESE, VIETNAMESE_CHARSET, MAKELANGID(LANG_VIETNAMESE,SUBLANG_NEUTRAL), "","","",""},
224  {-1, 0, 0, 0, 0, 0, 0} // must be last...
225 };
226 #elif (TWNDSM_CMP == TWNDSM_CMP_GNUGPP)
227  // We don't have anything for here...
228 #else
229  #error Sorry, we do not recognize this system...
230 #endif
231 #if (TWNDSM_OS == TWNDSM_OS_MACOSX)
232 #pragma clang diagnostic pop
233 #endif
234 
235 #if TWNDSM_OS_64BIT
236  #define TWNDSM_DS_REG_LOC "Software\\Microsoft\\Windows NT\\CurrentVersion\\TWAIN64"
237 #else
238  #define TWNDSM_DS_REG_LOC "Software\\Microsoft\\Windows NT\\CurrentVersion\\TWAIN"
239 #endif
240 
241 
247 #if 0
248 
253 static TW_HANDLE PASCAL DSM_MemAllocate(TW_UINT32 _size);
254 
259 static void PASCAL DSM_MemFree(TW_HANDLE _handle);
260 
266 static TW_MEMREF PASCAL DSM_MemLock(TW_HANDLE _handle);
267 
272 static void PASCAL DSM_MemUnlock(TW_HANDLE _handle);
273 // @}
274 #endif
275 
315  TW_IDENTITY *_pDest,
316  TW_UINT32 _DG,
317  TW_UINT16 _DAT,
318  TW_UINT16 _MSG,
319  TW_MEMREF _pData)
320 {
321  TW_UINT16 rcDSM;
322 
323  // Validate...
324  if (0 == _pOrigin)
325  {
326  return TWRC_FAILURE;
327  }
328 
329  // If we're processing DG_CONTROL/DAT_PARENT/MSG_OPENDSM then see
330  // if we need to create our CTwnDsm object. We don't want to
331  // allocate any resources prior to new CTwnDsm!!!
332  if ( (_MSG == MSG_OPENDSM)
333  && (_DAT == DAT_PARENT)
334  && (_DG == DG_CONTROL)
335  && (0 == g_ptwndsm))
336  {
337  g_ptwndsm = new CTwnDsm;
338  if (0 == g_ptwndsm)
339  {
340  kPANIC("Failed to new CTwnDsm!!!");
341  return TWRC_FAILURE;
342  }
343  }
344 
345  // If we have no CTwnDsm object, then we're in trouble, but
346  // try to handle DAT_STATUS in case it gets called before
347  // MSG_OPENDSM or after MSG_CLOSEDSM...
348  if (0 == g_ptwndsm)
349  {
350  if ( ( (_MSG == MSG_GET) || (_MSG == MSG_CHECKSTATUS) )
351  && (_DAT == DAT_STATUS)
352  && (_DG == DG_CONTROL)
353  && (0 != _pData)
354  )
355  {
356  ((TW_STATUS*)_pData)->ConditionCode = TWCC_BUMMER;
357  return (TWRC_SUCCESS);
358  }
359  else
360  {
361  //kLOG((kLOGERR,"DAT_STATUS called before MSG_OPENDSM or after MSG_CLOSEDSM..."));
362  return (TWRC_FAILURE);
363  }
364  }
365 
366  // Transfer control over to our dsm object, otherwise we'll
367  // be doing g_ptwndsm all over the place...
368  rcDSM = g_ptwndsm->DSM_Entry(_pOrigin,_pDest,_DG,_DAT,_MSG,_pData);
369 
370  // If we successfully processed DG_CONTROL/DAT_PARENT/MSG_CLOSEDSM,
371  // and don't have any other applications with it open,
372  // then destroy our object. We don't want to have any resources
373  // lingering around after we destroy our CTwnDsm object!!!
374  if ( (TWRC_SUCCESS == rcDSM)
375  && (_MSG == MSG_CLOSEDSM)
376  && (_DAT == DAT_PARENT)
377  && (_DG == DG_CONTROL)
379  {
380  delete g_ptwndsm;
381  g_ptwndsm = 0;
382  }
383 
384  // All done...
385  return rcDSM;
386 }
387 
388 
389 
390 /*
391 * Our constructor...
392 * Clean out the pod and set stuff. Get logging set up so we
393 * can have a clue what's going on...
394 */
396 {
397  // Zero out the pod...
398  memset(&pod,0,sizeof(pod));
399 
400  // Get our logging object...
401  g_ptwndsmlog = new CTwnDsmLog;
402  if (!g_ptwndsmlog)
403  {
404  kPANIC("Failed to new CTwnDsmLog!!!");
405  }
406 
407  // If logging is on, then this is a good chance to dump information
408  // about ourselves...
409  kLOG((kLOGINFO,"************************************************"));
410  kLOG((kLOGINFO,"%s",TWNDSM_ORGANIZATION));
411  kLOG((kLOGINFO,"%s",TWNDSM_DESCRIPTION));
412  kLOG((kLOGINFO,"version: %s",TWNDSM_VERSION_STR));
413 
414  // Get our application object...
415  pod.m_ptwndsmapps = new CTwnDsmApps();
416  if (!pod.m_ptwndsmapps)
417  {
418  kPANIC("Failed to new CTwnDsmApps!!!");
419  }
420 }
421 
422 
423 
424 /*
425 * Our destructor...
426 * Free any resources we might have...
427 */
429 {
430  if (pod.m_ptwndsmapps)
431  {
432  delete pod.m_ptwndsmapps;
433  }
434  if (g_ptwndsmlog)
435  {
436  delete g_ptwndsmlog;
437  }
438  memset(&pod,0,sizeof(pod));
439 }
440 
441 
442 
443 /*
444 * This is where we finish up the DSM_Entry duties inside of the
445 * context of the class...
446 */
447 TW_UINT16 CTwnDsm::DSM_Entry(TW_IDENTITY *_pOrigin,
448  TW_IDENTITY *_pDest,
449  TW_UINT32 _DG,
450  TW_UINT16 _DAT,
451  TW_UINT16 _MSG,
452  TW_MEMREF _pData)
453 {
454  TW_UINT16 rcDSM = TWRC_SUCCESS;
455  bool bPrinted;
456  TW_CALLBACK2 *ptwcallback2;
457  TW_IDENTITY *pAppId = _pOrigin;
458  TW_IDENTITY *pDSId = _pDest;
459 
460  // Do a test to see if pOrigin is a DS instead of App, if so then switch pAppId and pDSId
461  // MSG_INVOKE_CALLBACK was only used on the Mac and is now deprecated (ver 2.1)
462  // it is here for backwords capabiltiy
463  if ( (_DAT == DAT_NULL /*&& _DG == DG_CONTROL */)
464  || (_DAT == DAT_CALLBACK && _MSG == MSG_INVOKE_CALLBACK /*&& _DG == DG_CONTROL */) )
465  {
466  pAppId = _pDest;
467  pDSId = _pOrigin;
468  }
469 
470  // Print the triplets to stdout for information purposes
471  bPrinted = printTripletsInfo(_pOrigin,_pDest,_DG,_DAT,_MSG,_pData);
472 
473  // Sniff for the application forwarding an event to the
474  // DS. It may be possible that the app has a message waiting for
475  // it because it didn't register a callback.
476  if ( (DAT_EVENT == _DAT)
477  && (MSG_PROCESSEVENT == _MSG))
478  {
479  // Check that the AppID and DSID are valid...
480  if (!pod.m_ptwndsmapps->AppValidateIds(pAppId,pDSId))
481  {
482  kLOG((kLOGINFO,"Bad TW_IDENTITY"));
483  pod.m_ptwndsmapps->AppSetConditionCode(0,TWCC_BADPROTOCOL);
484  rcDSM = TWRC_FAILURE;
485  }
486  else if (pod.m_ptwndsmapps->DsCallbackIsWaiting(pAppId,(TWID_T)pDSId->Id))
487  {
488  ptwcallback2 = pod.m_ptwndsmapps->DsCallback2Get(pAppId,(TWID_T)pDSId->Id);
489  ((TW_EVENT*)(_pData))->TWMessage = ptwcallback2->Message;
490  if( g_ptwndsmlog )
491  {
492  char szMsg[64];
493  StringFromMsg(szMsg,NCHARS(szMsg),ptwcallback2->Message);
494  kLOG((kLOGINFO,"%.32s retrieving DAT_EVENT / %s\n", pAppId->ProductName, szMsg));
495  }
496  ptwcallback2->Message = 0;
497  pod.m_ptwndsmapps->DsCallbackSetWaiting(pAppId,(TWID_T)pDSId->Id,FALSE);
498  rcDSM = TWRC_DSEVENT;
499  }
500  // No callback, so fall on through...
501  }
502 
503  // Is this msg for us?
504  if( TWRC_SUCCESS == rcDSM )
505  {
506  switch (_DAT)
507  {
508  case DAT_IDENTITY:
509  // If the pDSId is 0 then the message is intended for us. We're
510  // going to force the matter if _MSG is MSG_CLOSEDS, otherwise
511  // we send the MSG_CLOSEDS to the driver, but never process it
512  // ourselves, which seems like a terrible idea...
513  if ((pDSId == 0) || (_MSG == MSG_CLOSEDS))
514  {
515  rcDSM = DSM_Identity(pAppId,_MSG,(TW_IDENTITY*)_pData);
516  break;
517  }
518  // else we fall thru to send the message onto the DS
519 
520  default:
521  // check if the application is open or not. If it isn't, we have a bad sequence
522  if (dsmState_Open == pod.m_ptwndsmapps->AppGetState(pAppId))
523  {
524  // Check that the AppID and DSID are valid...
525  if (!pod.m_ptwndsmapps->AppValidateIds(pAppId,pDSId))
526  {
527  kLOG((kLOGINFO,"Bad TW_IDENTITY"));
528  pod.m_ptwndsmapps->AppSetConditionCode(0,TWCC_BADPROTOCOL);
529  rcDSM = TWRC_FAILURE;
530  }
531 
532  // Issue the command...
533  else if (0 != pod.m_ptwndsmapps->DsGetEntryProc(pAppId,(TWID_T)pDSId->Id))
534  {
535  // Don't send a new message if the DS is still processing a previous message
536  // or if the application has not returned back from recieving callback.
537  // Place a Try | Catch around the function so we can maintain correct state
538  // in the case of an exception
539  //
540  // We are only enforcing this new behavior for TWAIN 2.2 applications and
541  // and higher. Older apps can still use the 'wrong' behavior. We need this
542  // to preserve backwards compability, and to give ourselves a chance to
543  // inform developers of the new requirement...
544  //
545  if(((((pAppId->ProtocolMajor*10) + (pAppId->ProtocolMinor)) <= 201) ||
546  !pod.m_ptwndsmapps->DsIsProcessingMessage(pAppId,(TWID_T)pDSId->Id) ) &&
547  ((((pAppId->ProtocolMajor*10) + (pAppId->ProtocolMinor)) <= 202) ||
548  !pod.m_ptwndsmapps->DsIsAppProcessingCallback(pAppId,(TWID_T)pDSId->Id) ) )
549  {
550  pod.m_ptwndsmapps->DsSetProcessingMessage(pAppId,(TWID_T)pDSId->Id,TRUE);
551  try
552  {
553  // Create a local copy of the AppIdentity
554  TW_IDENTITY AppId = *pod.m_ptwndsmapps->AppGetIdentity(pAppId);
555 
556  rcDSM = (pod.m_ptwndsmapps->DsGetEntryProc(&AppId,(TWID_T)pDSId->Id))(
557  &AppId,
558  _DG,
559  _DAT,
560  _MSG,
561  _pData);
562  }
563  catch(...)
564  {
565  rcDSM = TWRC_FAILURE;
566  pod.m_ptwndsmapps->AppSetConditionCode(pAppId,TWCC_BUMMER);
567  kLOG((kLOGERR,"Exception caught while DS was processing message. Returning Failure."));
568  }
569  pod.m_ptwndsmapps->DsSetProcessingMessage(pAppId,(TWID_T)pDSId->Id,FALSE);
570  }
571  else
572  {
573  if( _DAT == DAT_EVENT && _MSG == MSG_PROCESSEVENT)
574  {
575  kLOG((kLOGINFO,"Nested DAT_EVENT / MSG_PROCESSEVENT Ignored"));
576  rcDSM = TWRC_NOTDSEVENT;
577  ((TW_EVENT*)(_pData))->TWMessage = MSG_NULL;
578  }
579  else
580  {
581  kLOG((kLOGERR,"Nested calls back to the DS. Returning Failure."));
582  pod.m_ptwndsmapps->AppSetConditionCode(pAppId,TWCC_SEQERROR);
583  rcDSM = TWRC_FAILURE;
584  }
585  }
586  }
587 
588  // For some reason we have no pointer to the dsentry function...
589  else
590  {
591  kLOG((kLOGERR,"Unable to find driver, check your AppId and DsId values..."));
592  pod.m_ptwndsmapps->AppSetConditionCode(pAppId,TWCC_OPERATIONERROR);
593  kLOG((kLOGERR,"DS_Entry is null...%ld",(TWID_T)pAppId->Id));
594  rcDSM = TWRC_FAILURE;
595  }
596  }
597  else
598  {
599  kLOG((kLOGINFO,"DS is not open"));
600  pod.m_ptwndsmapps->AppSetConditionCode(pAppId,TWCC_SEQERROR);
601  rcDSM = TWRC_FAILURE;
602  }
603  break;
604 
605  case DAT_PARENT:
606  rcDSM = DSM_Parent(pAppId,_MSG,_pData);
607  break;
608 
609  case DAT_TWUNKIDENTITY:
610  rcDSM = DSM_TwunkIdentity(pAppId,_MSG,(TW_TWUNKIDENTITY*)_pData);
611  break;
612 
613  case DAT_ENTRYPOINT:
614  rcDSM = DSM_Entrypoint(pAppId,_MSG,(TW_ENTRYPOINT*)_pData);
615  break;
616 
617  case DAT_STATUS:
618  if( _MSG == MSG_CHECKSTATUS )
619  {
620  _MSG = MSG_GET;
621  kLOG((kLOGINFO, "MSG_CHECKSTATUS is Depreciated using MSG_GET"));
622  }
623 
624  // If we get a DSId then it is intended to be passed along to the driver.
625  // If the DSId is null then the request is handled by the DSM
626  // If we're talking to a driver (state 4 or higher), then we
627  // will pass the DAT_STATUS request down to it...
628  if ( 0 != pDSId
629  && (dsmState_Open == pod.m_ptwndsmapps->AppGetState(pAppId))
630  && pod.m_ptwndsmapps->AppValidateIds(pAppId,pDSId)
631  && (0 != pod.m_ptwndsmapps->DsGetEntryProc(pAppId,(TWID_T)pDSId->Id)))
632  {
633  // Create a local copy of the AppIdentity
634  TW_IDENTITY AppId = *pod.m_ptwndsmapps->AppGetIdentity(pAppId);
635 
636  rcDSM = (pod.m_ptwndsmapps->DsGetEntryProc(&AppId,(TWID_T)pDSId->Id))(
637  &AppId,
638  _DG,
639  _DAT,
640  _MSG,
641  _pData);
642  }
643  // Otherwise, handle it ourself...
644  else
645  {
646  rcDSM = DSM_Status(pAppId,_MSG,(TW_STATUS*)_pData);
647  }
648  break;
649 
650  case DAT_CALLBACK:
651  // DAT_CALLBACK can be either from an Application registering its Callback,
652  // or from a DS Invoking a request to send a message to the Application
653  rcDSM = DSM_Callback(_pOrigin,_pDest,_MSG,(TW_CALLBACK*)_pData);
654  break;
655 
656  case DAT_CALLBACK2:
657  // DAT_CALLBACK2 can be either from an Application registering its Callback,
658  // or from a DS Invoking a request to send a message to the Application
659  rcDSM = DSM_Callback2(_pOrigin,_pDest,_MSG,(TW_CALLBACK2*)_pData);
660  break;
661 
662  case DAT_NULL:
663  // Note how the origin and destination are switched for this
664  // call (and only this call). Because, of course, this
665  // message is being send from the driver to the application...
666  rcDSM = DSM_Null(pAppId,pDSId,_MSG);
667  break;
668  }
669  }
670 
671  // Log how it went...
672  if (bPrinted)
673  {
674  printResults(_DG,_DAT,_MSG,_pData,rcDSM);
675  }
676 
677  return rcDSM;
678 }
679 
680 /*
681 * Return the state of the DSM by checking the state of all applications
682 */
684 {
685  DSM_State CurrentState = pod.m_ptwndsmapps->AppGetState();
686  return CurrentState;
687 }
688 
689 /*
690 * Handle DAT_STATUS. Just a few things of note, we handle some
691 * DAT_STATUS stuff in DSM_Entry. And per the spec we have to
692 * clear the condition code when we are done. I've also put in
693 * MSG_CHECKSTATUS, because I can't imagine why we have the silly
694 * thing if it isn't for this function...
695 */
697  TW_UINT16 _MSG,
698  TW_STATUS *_pStatus)
699 {
700  TW_INT16 result = TWRC_SUCCESS;
701 
702  switch (_MSG)
703  {
704  case MSG_GET:
705  case MSG_CHECKSTATUS:
706  _pStatus->ConditionCode = pod.m_ptwndsmapps->AppGetConditionCode(_pAppId);
707  _pStatus->Reserved = 0;
708  break;
709 
710  default:
711  result = TWRC_FAILURE;
712  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADPROTOCOL);
713  break;
714  }
715 
716  return result;
717 }
718 
719 
720 
721 /*
722 * Handle DAT_PARENT. This is where the DSM is expected to
723 * do most of its contribution, which is finding drivers for
724 * the application...
725 */
727  TW_UINT16 _MSG,
728  TW_MEMREF _MemRef)
729 {
730  TW_UINT16 result;
731 
732  // Validate...
733  if (0 == _pAppId)
734  {
735  kLOG((kLOGERR,"_pAppId is null"));
736  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADVALUE);
737  return TWRC_FAILURE;
738  }
739 
740  // Init stuff...
741  result = TWRC_SUCCESS;
742 
743  // Process the message...
744  switch (_MSG)
745  {
746  case MSG_OPENDSM:
747  // Try to add the proposed item...
748  result = pod.m_ptwndsmapps->AddApp(_pAppId,_MemRef);
749  break;
750 
751  case MSG_CLOSEDSM:
752  // Try to remove the proposed item...
753  result = pod.m_ptwndsmapps->RemoveApp(_pAppId);
754  break;
755 
756  default:
757  result = TWRC_FAILURE;
758  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADPROTOCOL);
759  break;
760  }
761 
762  return result;
763 }
764 
765 
766 
767 /*
768 * Handle DAT_IDENTITY. This is where the DSM is expected to
769 * do most of its contribution, which is finding drivers for
770 * the application...
771 */
773  TW_UINT16 _MSG,
774  TW_IDENTITY *_pDsId)
775 {
776  TW_INT16 result;
777 
778  // Validate...
779  if (0 == _pAppId || (TWID_T)_pAppId->Id >= pod.m_ptwndsmapps->AppGetNumApp())
780  {
781  kLOG((kLOGERR,"_pAppId is null"));
782  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADVALUE);
783  return TWRC_FAILURE;
784  }
785 
786  // Init stuff...
787  result = TWRC_SUCCESS;
788 
789  // Pick the message...
790  if (dsmState_Open == pod.m_ptwndsmapps->AppGetState(_pAppId))
791  {
792  switch (_MSG)
793  {
794  case MSG_OPENDS:
795  result = OpenDS(_pAppId,_pDsId);
796  break;
797 
798  case MSG_CLOSEDS:
799  result = CloseDS(_pAppId,_pDsId);
800  break;
801 
802  case MSG_USERSELECT:
803  result = DSM_SelectDS(_pAppId,_pDsId);
804  break;
805 
806  case MSG_GETFIRST:
807  result = DSM_GetFirst(_pAppId,_pDsId);
808  break;
809 
810  case MSG_GETNEXT:
811  result = DSM_GetNext(_pAppId,_pDsId);
812  break;
813 
814  case MSG_GETDEFAULT:
815  result = GetMatchingDefault(_pAppId,_pDsId);
816  break;
817 
818  case MSG_SET:
819  result = DSM_SetDefaultDS(_pAppId,_pDsId);
820  break;
821 
822  default:
823  result = TWRC_FAILURE;
824  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADPROTOCOL);
825  break;
826  }
827  }
828  else
829  {
830  result = TWRC_FAILURE;
831  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_SEQERROR);
832  }
833 
834  return result;
835 }
836 
837 /*
838 * Handle DAT_TWUNKIDENTITY. This is here for backwards compatibility.
839 * DAT_TWUNKIDENTITY is undocumented. It was used by the Twunking
840 * layer. Some old applications use it to get the path to the DS.
841 * We need to continue to support it.
842 */
844  TW_UINT16 _MSG,
845  TW_TWUNKIDENTITY *_pTwunkId)
846 {
847  TW_INT16 result = TWRC_SUCCESS;
848 
849  // Validate...
850  if (0 == _pAppId || (TWID_T)_pAppId->Id >= pod.m_ptwndsmapps->AppGetNumApp())
851  {
852  kLOG((kLOGERR,"_pAppId is null"));
853  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADVALUE);
854  return TWRC_FAILURE;
855  }
856  else if (dsmState_Open != pod.m_ptwndsmapps->AppGetState(_pAppId))
857  {
858  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_SEQERROR);
859  return TWRC_FAILURE;
860  }
861  else if (MSG_GET != _MSG)
862  {
863  kLOG((kLOGERR,"protocol error"));
864  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADPROTOCOL);
865  return TWRC_FAILURE;
866  }
867  else if (0 == _pTwunkId)
868  {
869  kLOG((kLOGERR,"_pTwunkId is null"));
870  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADVALUE);
871  return TWRC_FAILURE;
872  }
873  // Check that the DSID is valid...
874  else if (!pod.m_ptwndsmapps->AppValidateIds(_pAppId,&_pTwunkId->identity))
875  {
876  pod.m_ptwndsmapps->AppSetConditionCode(0,TWCC_BADVALUE);
877  return TWRC_FAILURE;
878  }
879 
880  SSTRCPY((char*)_pTwunkId->dsPath, sizeof(_pTwunkId->dsPath),(char*)pod.m_ptwndsmapps->DsGetPath(_pAppId,(TWID_T)_pTwunkId->identity.Id));
881 
882  return result;
883 }
884 
885 
886 
887 /*
888 * Handle DAT_ENTRYPOINT. This handles an application asking
889 * for entry point information. Drivers have this information
890 * pushed to them in a different part of the code (just before
891 * DG_CONTORL/DAT_IDENTITY/MSG_OPENDS is received)
892 */
894  TW_UINT16 _MSG,
895  TW_ENTRYPOINT *_pEntrypoint)
896 {
897  // Validate...
898  if (0 == _pAppId)
899  {
900  kLOG((kLOGERR,"_pAppId is null"));
901  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADVALUE);
902  return TWRC_FAILURE;
903  }
904  else if (MSG_GET != _MSG)
905  {
906  kLOG((kLOGERR,"protocol error"));
907  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADPROTOCOL);
908  return TWRC_FAILURE;
909  }
910  else if (0 == _pEntrypoint)
911  {
912  kLOG((kLOGERR,"_pEntrypoint is null"));
913  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADVALUE);
914  return TWRC_FAILURE;
915  }
916  else if (0 == _pEntrypoint->Size)
917  {
918  kLOG((kLOGERR,"_pEntrypoint is zero, it needs to be set to the size of TW_ENTRYPOINT..."));
919  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADVALUE);
920  return TWRC_FAILURE;
921  }
922  else if (!(_pAppId->SupportedGroups & DF_APP2))
923  {
924  kLOG((kLOGERR,"_pAppId->SupportedGroups must include the DF_APP2 flag to make this call..."));
925  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADPROTOCOL);
926  return TWRC_FAILURE;
927  }
928 
929  // This is the TWAIN 2.0 minimum size. If we add more values
930  // in future we should create a new structure (ex: TW_ENTRYPOINT2)
931  // and then add an if-statement for it...
932  if (_pEntrypoint->Size < sizeof(TW_ENTRYPOINT))
933  {
934  kLOG((kLOGERR,"_pEntrypoint->Size minimum is %ld, we got %ld...",sizeof(TW_ENTRYPOINT),_pEntrypoint->Size));
935  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADVALUE);
936  return TWRC_FAILURE;
937  }
938 
939  // TWAIN 2.0
940  // Stock the structure with interesting stuff...
941  else if (_pEntrypoint->Size == sizeof(TW_ENTRYPOINT))
942  {
943  _pEntrypoint->DSM_Entry = ::DSM_Entry;
944  _pEntrypoint->DSM_MemAllocate = DSM_MemAllocate;
945  _pEntrypoint->DSM_MemFree = DSM_MemFree;
946  _pEntrypoint->DSM_MemLock = DSM_MemLock;
947  _pEntrypoint->DSM_MemUnlock = DSM_MemUnlock;
948  }
949 
950  // Uh-oh...
951  else
952  {
953  kLOG((kLOGERR,"_pEntrypoint->Size cannot be larger than %ld, we got %ld...",sizeof(TW_ENTRYPOINT),_pEntrypoint->Size));
954  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADVALUE);
955  return TWRC_FAILURE;
956  }
957 
958  // All done...
959  return TWRC_SUCCESS;
960 }
961 
962 
963 
964 /*
965 * We've received a callback. MSG_REGISTER_CALLBACK are from
966 * the Application and MSG_INVOKE_CALLBACK (Mac OSx only)
967 * are from the DS.
968 * If Callbacks have not been registered by the App then when the
969 * DS Invokes a callback, make a note of it so the next time the
970 * application hits us with a Windows message for us to process,
971 * we can send it the callback message...
972 */
974  TW_IDENTITY *_pDest,
975  TW_UINT16 _MSG,
976  TW_CALLBACK *_pData)
977 {
978  TW_INT16 result;
979  TW_CALLBACK *ptwcallback;
980  TW_CALLBACK2 *ptwcallback2;
981 
982  // Init stuff...
983  result = TWRC_SUCCESS;
984 
985  // Take action on the message...
986  switch (_MSG)
987  {
988  case MSG_REGISTER_CALLBACK:
989  {
990  // Origin is an App
991  // Check that the ids are valid...
992  if (!pod.m_ptwndsmapps->AppValidateIds(_pOrigin,_pDest))
993  {
994  pod.m_ptwndsmapps->AppSetConditionCode(0,TWCC_BADPROTOCOL);
995  return TWRC_FAILURE;
996  }
997  if(0 == _pData)
998  {
999  kLOG((kLOGERR,"Invalid data"));
1000  pod.m_ptwndsmapps->AppSetConditionCode(0,TWCC_BADVALUE);
1001  return TWRC_FAILURE;
1002  }
1003 
1004  ptwcallback2 = pod.m_ptwndsmapps->DsCallback2Get(_pOrigin,(TWID_T)_pDest->Id);
1005  ptwcallback2->CallBackProc = ((TW_CALLBACK*)_pData)->CallBackProc;
1006  ptwcallback2->RefCon = (TWID_T)((TW_CALLBACK*)_pData)->RefCon;
1007  ptwcallback2->Message = ((TW_CALLBACK*)_pData)->Message;
1008  pod.m_ptwndsmapps->DsCallbackSetWaiting(_pOrigin,(TWID_T)_pDest->Id,FALSE);
1009  }
1010  break;
1011 
1012  case MSG_INVOKE_CALLBACK:
1013  {
1014  // For backwards capability only. MSG_INVOKE_CALLBACK is deprecated - use DAT_NULL
1015  // Origin is a DS
1016  // Check that the ids are valid...
1017  kLOG((kLOGINFO,"MSG_INVOKE_CALLBACK is deprecated - use DAT_NULL"));
1018  if (!pod.m_ptwndsmapps->AppValidateIds(_pDest,_pOrigin))
1019  {
1020  pod.m_ptwndsmapps->AppSetConditionCode(0,TWCC_BADPROTOCOL);
1021  return TWRC_FAILURE;
1022  }
1023  if(0 == _pData)
1024  {
1025  kLOG((kLOGERR,"Invalid data"));
1026  pod.m_ptwndsmapps->AppSetConditionCode(0,TWCC_BADVALUE);
1027  return TWRC_FAILURE;
1028  }
1029 
1030  ptwcallback = (TW_CALLBACK*)_pData;
1031  result = DSM_Null(_pDest,_pOrigin,ptwcallback->Message);
1032  }
1033  break;
1034 
1035  default:
1036  result = TWRC_FAILURE;
1037  pod.m_ptwndsmapps->AppSetConditionCode(_pOrigin,TWCC_BADPROTOCOL);
1038  break;
1039  }
1040 
1041  return result;
1042 }
1043 
1044 
1045 
1046 /*
1047 * We've received a callback. MSG_REGISTER_CALLBACK are from
1048 * the Application and MSG_INVOKE_CALLBACK (Mac OSx only)
1049 * are from the DS.
1050 * If Callbacks have not been registered by the App then when the
1051 * DS Invokes a callback, make a note of it so the next time the
1052 * application hits us with a Windows message for us to process,
1053 * we can send it the callback message...
1054 */
1056  TW_IDENTITY *_pDest,
1057  TW_UINT16 _MSG,
1058  TW_CALLBACK2 *_pData)
1059 {
1060  TW_INT16 result;
1061  TW_CALLBACK2 *ptwcallback2;
1062 
1063  // Init stuff...
1064  result = TWRC_SUCCESS;
1065 
1066  // Take action on the message...
1067  switch (_MSG)
1068  {
1069  case MSG_REGISTER_CALLBACK:
1070  {
1071  // Origin is an App
1072  // Check that the ids are valid...
1073  if (!pod.m_ptwndsmapps->AppValidateIds(_pOrigin,_pDest))
1074  {
1075  pod.m_ptwndsmapps->AppSetConditionCode(0,TWCC_BADPROTOCOL);
1076  return TWRC_FAILURE;
1077  }
1078  if(0 == _pData)
1079  {
1080  kLOG((kLOGERR,"Invalid data"));
1081  pod.m_ptwndsmapps->AppSetConditionCode(0,TWCC_BADVALUE);
1082  return TWRC_FAILURE;
1083  }
1084 
1085  ptwcallback2 = pod.m_ptwndsmapps->DsCallback2Get(_pOrigin,(TWID_T)_pDest->Id);
1086  memcpy(ptwcallback2,_pData,sizeof(*ptwcallback2));
1087  pod.m_ptwndsmapps->DsCallbackSetWaiting(_pOrigin,(TWID_T)_pDest->Id,FALSE);
1088  }
1089  break;
1090 
1091  case MSG_INVOKE_CALLBACK:
1092  {
1093  // For backwards capability only. MSG_INVOKE_CALLBACK is deprecated - use DAT_NULL
1094  // Origin is a DS
1095  // Check that the ids are valid...
1096  kLOG((kLOGINFO,"MSG_INVOKE_CALLBACK is deprecated - use DAT_NULL"));
1097  if (!pod.m_ptwndsmapps->AppValidateIds(_pDest,_pOrigin))
1098  {
1099  pod.m_ptwndsmapps->AppSetConditionCode(0,TWCC_BADPROTOCOL);
1100  return TWRC_FAILURE;
1101  }
1102  if(0 == _pData)
1103  {
1104  kLOG((kLOGERR,"Invalid data"));
1105  pod.m_ptwndsmapps->AppSetConditionCode(0,TWCC_BADVALUE);
1106  return TWRC_FAILURE;
1107  }
1108 
1109  ptwcallback2 = (TW_CALLBACK2*)_pData;
1110  result = DSM_Null(_pDest,_pOrigin,ptwcallback2->Message);
1111  }
1112  break;
1113 
1114  default:
1115  result = TWRC_FAILURE;
1116  pod.m_ptwndsmapps->AppSetConditionCode(_pOrigin,TWCC_BADPROTOCOL);
1117  break;
1118  }
1119 
1120  return result;
1121 }
1122 
1123 
1124 
1125 /*
1126 * Open the specified driver. We're using the application identity
1127 * and the driver identity we picked up during MSG_OPENDSM. The
1128 * application is just telling us which driver to load. As part of
1129 * a successful open we'll remember this driver's full path and file
1130 * name as the new default driver. On Windows this information goes
1131 * into the registry. On Linux we put it under the user's home
1132 * directory...
1133 */
1134 TW_INT16 CTwnDsm::OpenDS(TW_IDENTITY *_pAppId,
1135  TW_IDENTITY *_pDsId)
1136 {
1137  TW_INT16 result;
1138  TW_ENTRYPOINT twentrypoint;
1139 
1140  // Validate...
1141  if (0 == _pAppId)
1142  {
1143  kLOG((kLOGERR,"_pAppId is null"));
1144  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADVALUE);
1145  return TWRC_FAILURE;
1146  }
1147  else if ( ((TWID_T)_pAppId->Id < 1)
1148  || ((TWID_T)_pAppId->Id >= pod.m_ptwndsmapps->AppGetNumApp()))
1149  {
1150  kLOG((kLOGERR,"id is out of range...%d",(int)(TWID_T)_pAppId->Id));
1151  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_MAXCONNECTIONS);
1152  return TWRC_FAILURE;
1153  }
1154 
1155  // Init stuff...
1156  result = TWRC_SUCCESS;
1157 
1158  // check that we are in the proper state
1159  if (dsmState_Open != pod.m_ptwndsmapps->AppGetState(_pAppId))
1160  {
1161  kLOG((kLOGERR,"DSM must be open before opening DS"));
1162  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_SEQERROR);
1163  return(TWRC_FAILURE);
1164  }
1165 
1166  // check for valid data
1167  if(0 == _pDsId)
1168  {
1169  kLOG((kLOGERR,"_pDsId is null"));
1170  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADDEST);
1171  return TWRC_FAILURE;
1172  }
1173 
1174  // Do we need to find a source to open
1175  if (0 == (TWID_T)_pDsId->Id)
1176  {
1177  // Does the app know the name of the source it wants to open
1178  if (0 != _pDsId->ProductName[0])
1179  {
1180  // The application is passing me a TW_IDENTITY structure that contains
1181  // the name of the source to select.
1182  result = GetDSFromProductName(_pAppId,_pDsId);
1183 
1184  // was the id found or specified by the app?
1185  if (TWRC_SUCCESS != result)
1186  {
1187  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_NODS);
1188  return result;
1189  }
1190  }
1191 
1192  // Does the application want me to choose the default?
1193  // Or no Source located by name
1194  if (0 == _pDsId->ProductName[0])
1195  {
1196  // -if the name of the source is NULL, and the id is 0, the application is
1197  // telling me to select the default source.
1198  result = GetMatchingDefault(_pAppId,_pDsId);
1199 
1200  // was the id found or specified by the app?
1201  if (TWRC_SUCCESS != result)
1202  {
1203  return result;
1204  }
1205  }
1206  }
1207 
1208  // Load the driver...
1209  result = pod.m_ptwndsmapps->LoadDS(_pAppId,(TWID_T)_pDsId->Id);
1210  if (result != TWRC_SUCCESS)
1211  {
1212  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_NODS);
1213  return TWRC_FAILURE;
1214  }
1215 
1216  // open the ds
1217  if (0 != pod.m_ptwndsmapps->DsGetEntryProc(_pAppId,(TWID_T)_pDsId->Id))
1218  {
1219  // If the DS reports support for DF_DS2, then send it our DAT_ENTRYPOINT
1220  // information. Failure to handle this is treated like a failure to open...
1221  result = TWRC_SUCCESS;
1222 
1223  // Create a local copy of the AppIdentity
1224  TW_IDENTITY AppId = *pod.m_ptwndsmapps->AppGetIdentity(_pAppId);
1225 
1226  if (_pDsId->SupportedGroups & DF_DS2)
1227  {
1228  memset(&twentrypoint,0,sizeof(twentrypoint));
1229  twentrypoint.Size = sizeof(TW_ENTRYPOINT);
1230  twentrypoint.DSM_Entry = ::DSM_Entry;
1231  twentrypoint.DSM_MemAllocate = DSM_MemAllocate;
1232  twentrypoint.DSM_MemFree = DSM_MemFree;
1233  twentrypoint.DSM_MemLock = DSM_MemLock;
1234  twentrypoint.DSM_MemUnlock = DSM_MemUnlock;
1235  result = pod.m_ptwndsmapps->DsGetEntryProc(&AppId,(TWID_T)_pDsId->Id)(
1236  &AppId,
1237  DG_CONTROL,
1238  DAT_ENTRYPOINT,
1239  MSG_SET,
1240  (TW_MEMREF)&twentrypoint);
1241  }
1242 
1243  // We have a problem...
1244  if (TWRC_SUCCESS != result)
1245  {
1246  kLOG((kLOGERR,"DAT_ENTRYPOINT failed..."));
1247  pod.m_ptwndsmapps->AppSetConditionCode(&AppId,TWCC_OPERATIONERROR);
1248  }
1249 
1250  // Okay, we're good. Either we're a 1.x driver, or we were able to
1251  // push down our entrypoint info, so open the ds...
1252  else
1253  {
1254  result = pod.m_ptwndsmapps->DsGetEntryProc(&AppId,(TWID_T)_pDsId->Id)(
1255  &AppId,
1256  DG_CONTROL,
1257  DAT_IDENTITY,
1258  MSG_OPENDS,
1259  (TW_MEMREF)_pDsId);
1260 
1261  // Oh well...
1262  if (TWRC_SUCCESS != result)
1263  {
1264  kLOG((kLOGINFO,"MSG_OPENDS failed..."));
1265  TW_UINT16 rcDSMStatus;
1266  TW_STATUS twstatus = { 0, { 0 } };
1267  // If the call to MSG_OPENDS fails, then we need to get the DAT_STATUS and squirrel
1268  // it away, because we're going to close this data source soon...
1269  rcDSMStatus = (pod.m_ptwndsmapps->DsGetEntryProc(&AppId,(TWID_T)_pDsId->Id))(
1270  &AppId,
1271  DG_CONTROL,
1272  DAT_STATUS,
1273  MSG_GET,
1274  (TW_MEMREF)&twstatus);
1275  if (rcDSMStatus == TWRC_SUCCESS)
1276  {
1277  pod.m_ptwndsmapps->AppSetConditionCode(&AppId,twstatus.ConditionCode);
1278  }
1279  else
1280  {
1281  pod.m_ptwndsmapps->AppSetConditionCode(&AppId,TWCC_NODS);
1282  }
1283  }
1284  }
1285  }
1286 
1287  // Remember that we opened this DS...
1288  if (TWRC_SUCCESS == result)
1289  {
1290  // Starting with TWAIN 2.1 the application will use DAT_IDENTITY / MSG_SET
1291  // to set the default DS
1292  if( ( _pAppId->ProtocolMajor == 2
1293  && _pAppId->ProtocolMinor == 0 )
1294  || _pAppId->ProtocolMajor < 2 )
1295  {
1296  #if (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP)
1297  // skip...
1298  #elif (TWNDSM_CMP == TWNDSM_CMP_GNUGPP)
1299  int iResult;
1300  FILE *pfile;
1301  char *szHome;
1302  char szFile[FILENAME_MAX];
1303  szHome = getenv("HOME");
1304  if (szHome)
1305  {
1306  SSTRCPY(szFile,sizeof(szFile),szHome);
1307  SSTRCAT(szFile,sizeof(szFile),"/.twndsmrc");
1308  mkdir(szFile,0660);
1309  SSTRCAT(szFile,sizeof(szFile),"/defaultds");
1310  FOPEN(pfile,szFile,"w");
1311  if (pfile)
1312  {
1313  iResult = fwrite
1314  (
1315  pod.m_ptwndsmapps->DsGetPath(_pAppId,(TWID_T)_pDsId->Id),
1316  1,
1317  strlen(pod.m_ptwndsmapps->DsGetPath(_pAppId,(TWID_T)_pDsId->Id)),
1318  pfile
1319  );
1320  if (iResult < (int)strlen(pod.m_ptwndsmapps->DsGetPath(_pAppId,(TWID_T)_pDsId->Id)))
1321  {
1322  kLOG((kLOGERR,"fwrite defaultds failed..."));
1323  }
1324  fclose(pfile);
1325  }
1326  }
1327  #else
1328  #error Sorry, we do not recognize this system...
1329  #endif
1330  }
1331  }
1332 
1333  // If we had an error, make sure we unload the ds...
1334  else
1335  {
1336  pod.m_ptwndsmapps->UnloadDS(_pAppId,(TWID_T)_pDsId->Id);
1337  }
1338 
1339  // All done...
1340  return result;
1341 }
1342 
1343 
1344 
1345 /*
1346 * Close the specified driver...
1347 */
1348 TW_INT16 CTwnDsm::CloseDS(TW_IDENTITY *_pAppId,
1349  TW_IDENTITY *_pDsId)
1350 {
1351  TW_INT16 result;
1352 
1353  // Validate...
1354  if (0 == _pAppId)
1355  {
1356  kLOG((kLOGERR,"_pAppId is null"));
1357  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADVALUE);
1358  return TWRC_FAILURE;
1359  }
1360  else if ( ((TWID_T)_pAppId->Id < 1)
1361  || ((TWID_T)_pAppId->Id >= pod.m_ptwndsmapps->AppGetNumApp()))
1362  {
1363  kLOG((kLOGERR,"id out of range...%d",(int)(TWID_T)_pAppId->Id));
1364  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADVALUE);
1365  return TWRC_FAILURE;
1366  }
1367 
1368  // Init stuff...
1369  result = TWRC_SUCCESS;
1370 
1371  // check that we are in the proper state
1372  if (dsmState_Open != pod.m_ptwndsmapps->AppGetState(_pAppId))
1373  {
1374  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_SEQERROR);
1375  return TWRC_FAILURE;
1376  }
1377 
1378  // Check for valid DS
1379  if(0 == _pDsId)
1380  {
1381  kLOG((kLOGERR,"_pDsId is null"));
1382  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADDEST);
1383  return TWRC_FAILURE;
1384  }
1385 
1386  // close the ds
1387  if (0 != pod.m_ptwndsmapps->DsGetEntryProc(_pAppId,(TWID_T)_pDsId->Id))
1388  {
1389  // Create a local copy of the AppIdentity
1390  TW_IDENTITY AppId = *pod.m_ptwndsmapps->AppGetIdentity(_pAppId);
1391 
1392  result = (pod.m_ptwndsmapps->DsGetEntryProc(&AppId,(TWID_T)_pDsId->Id))(
1393  &AppId,
1394  DG_CONTROL,
1395  DAT_IDENTITY,
1396  MSG_CLOSEDS,
1397  (TW_MEMREF)_pDsId);
1398 
1399  if (TWRC_SUCCESS != result)
1400  {
1401  pod.m_ptwndsmapps->AppSetConditionCode(&AppId,TWCC_OPERATIONERROR);
1402  return result;
1403  }
1404 
1405  // Cleanup...
1406  pod.m_ptwndsmapps->UnloadDS(&AppId,(TWID_T)_pDsId->Id);
1407  }
1408 
1409  // All done...
1410  return result;
1411 }
1412 
1413 
1414 
1415 #if (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP)
1416 
1425 BOOL WINAPI DllMain(HINSTANCE _hmodule,
1426  DWORD _dwReasonCalled,
1427  LPVOID)
1428 {
1429  switch (_dwReasonCalled)
1430  {
1431  case DLL_THREAD_ATTACH:
1432  case DLL_THREAD_DETACH:
1433  break;
1434  case DLL_PROCESS_ATTACH:
1435  g_hinstance = _hmodule;
1436  break;
1437  case DLL_PROCESS_DETACH:
1438  if( g_ptwndsm )
1439  {
1440  if( g_ptwndsm->DSMGetState() == dsmState_Open )
1441  {
1442  // This should never happen!
1443  // The Application should always close any open DS, then Close the DSM.
1444  kLOG((kLOGERR,"The DSM was left in an open state when it was unloaded!"));
1445  }
1446  delete g_ptwndsm;
1447  g_ptwndsm = 0;
1448  }
1449  break;
1450  }
1451  return(TRUE);
1452 }
1453 #elif (TWNDSM_CMP == TWNDSM_CMP_GNUGPP)
1454  // Nothing for us to do...
1455 #else
1456  #error Sorry, we do not recognize this system...
1457 #endif
1458 
1459 
1460 
1461 #if (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP)
1462 
1472 BOOL CALLBACK SelectDlgProc(HWND _hWnd,
1473  UINT _Message,
1474  WPARAM _wParam,
1475  LPARAM _lParam)
1476 {
1477  if (g_ptwndsm)
1478  {
1479  return g_ptwndsm->SelectDlgProc(_hWnd,_Message,_wParam,_lParam);
1480  }
1481  else
1482  {
1483  return TRUE;
1484  }
1485 }
1486 #elif (TWNDSM_CMP == TWNDSM_CMP_GNUGPP)
1487  // We don't have one of these...
1488 #else
1489  #error Sorry, we do not recognize this system...
1490 #endif
1491 
1492 
1493 
1494 #if (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP)
1495 
1505 BOOL CALLBACK EnumChildProc
1506 (
1507  HWND hwnd,
1508  LPARAM lParam
1509 )
1510 {
1511  ::SendMessage(hwnd,WM_SETFONT,(WPARAM)lParam,(LPARAM)TRUE);
1512  return TRUE;
1513 }
1514 
1515 
1516 
1517 BOOL CTwnDsm::SelectDlgProc(HWND hWnd,
1518  UINT Message,
1519  WPARAM wParam,
1520  LPARAM /*lParam - unused*/)
1521 {
1522  TW_IDENTITY *pAppId;
1523  int nIndex;
1524  int nSelect;
1525  TW_UINT32 x;
1526  char *szProductName;
1527  HWND hListBox;
1528  RECT rectParent;
1529  RECT rectSelect;
1530  HWND hParent;
1531  LANGID LangId;
1532  wchar_t uzUnicode[128];
1533  HFONT hfont;
1534  LOGFONT lf;
1535  POINT point;
1536  int nWidth;
1537  int nHeight;
1538 
1539  // Init stuff...
1540  nSelect = 0;
1541  pAppId = pod.m_pSelectDlgAppId;
1542 
1543  // Process the message...
1544  switch (Message)
1545  {
1546  case WM_INITDIALOG:
1547 
1548  // If the caller wants us to figure out the language, do this...
1549  if (pAppId->Version.Language == (TW_UINT16)TWLG_USERLOCALE)
1550  {
1551  // Try to find the user's default language...
1552  LangId = ::GetUserDefaultLangID();
1553  for (nIndex = 0;
1554  s_twlocalize[nIndex].Language >= 0;
1555  nIndex++)
1556  {
1557  if ( (s_twlocalize[nIndex].LangId == LangId)
1558  && s_twlocalize[nIndex].LangId
1559  && s_twlocalize[nIndex].Title
1560  && s_twlocalize[nIndex].Title[0]
1561  && s_twlocalize[nIndex].Sources
1562  && s_twlocalize[nIndex].Sources[0]
1563  && s_twlocalize[nIndex].Select
1564  && s_twlocalize[nIndex].Select[0]
1565  && s_twlocalize[nIndex].Cancel
1566  && s_twlocalize[nIndex].Cancel[0])
1567  {
1568  break;
1569  }
1570  }
1571 
1572  // If that doesn't work, try for the primary language...
1573  if (s_twlocalize[nIndex].Language < 0)
1574  {
1575  LangId &= 0xFF;
1576  for (nIndex = 0;
1577  s_twlocalize[nIndex].Language >= 0;
1578  nIndex++)
1579  {
1580  if ( ((s_twlocalize[nIndex].LangId & 0xFF) == LangId)
1581  && s_twlocalize[nIndex].LangId
1582  && s_twlocalize[nIndex].Title
1583  && s_twlocalize[nIndex].Title[0]
1584  && s_twlocalize[nIndex].Sources
1585  && s_twlocalize[nIndex].Sources[0]
1586  && s_twlocalize[nIndex].Select
1587  && s_twlocalize[nIndex].Select[0]
1588  && s_twlocalize[nIndex].Cancel
1589  && s_twlocalize[nIndex].Cancel[0])
1590  {
1591  break;
1592  }
1593  }
1594  }
1595  }
1596 
1597  // Otherwise, use whatever the caller gave us...
1598  else
1599  {
1600  for (nIndex = 0;
1601  s_twlocalize[nIndex].Language >= 0;
1602  nIndex++)
1603  {
1604  if ( (s_twlocalize[nIndex].Language == pAppId->Version.Language)
1605  && s_twlocalize[nIndex].LangId
1606  && s_twlocalize[nIndex].Title
1607  && s_twlocalize[nIndex].Title[0]
1608  && s_twlocalize[nIndex].Sources
1609  && s_twlocalize[nIndex].Sources[0]
1610  && s_twlocalize[nIndex].Select
1611  && s_twlocalize[nIndex].Select[0]
1612  && s_twlocalize[nIndex].Cancel
1613  && s_twlocalize[nIndex].Cancel[0])
1614  {
1615  break;
1616  }
1617  }
1618  }
1619 
1620  // If we didn't find our language, go for English...
1621  if (s_twlocalize[nIndex].Language < 0)
1622  {
1623  for (nIndex = 0;
1624  s_twlocalize[nIndex].Language >= 0;
1625  nIndex++)
1626  {
1627  if ( (s_twlocalize[nIndex].Language == TWLG_ENGLISH)
1628  && s_twlocalize[nIndex].LangId
1629  && s_twlocalize[nIndex].Title
1630  && s_twlocalize[nIndex].Title[0]
1631  && s_twlocalize[nIndex].Sources
1632  && s_twlocalize[nIndex].Sources[0]
1633  && s_twlocalize[nIndex].Select
1634  && s_twlocalize[nIndex].Select[0]
1635  && s_twlocalize[nIndex].Cancel
1636  && s_twlocalize[nIndex].Cancel[0])
1637  {
1638  break;
1639  }
1640  }
1641  }
1642 
1643  // If we found something, then use it...
1644  if (s_twlocalize[nIndex].Language >= 0)
1645  {
1646  // Set our font...
1647  memset(&lf,0,sizeof(lf));
1648  lf.lfHeight = 16;
1649  lf.lfCharSet = s_twlocalize[nIndex].CharSet;
1650  hfont = CreateFontIndirect(&lf);
1651  EnumChildWindows(hWnd,EnumChildProc,(LPARAM)hfont);
1652 
1653  MultiByteToWideChar(CP_UTF8,0,s_twlocalize[nIndex].Title,-1,uzUnicode,sizeof(uzUnicode)/sizeof(*uzUnicode));
1654  SetWindowTextW(hWnd,uzUnicode);
1655 
1656  MultiByteToWideChar(CP_UTF8,0,s_twlocalize[nIndex].Sources,-1,uzUnicode,sizeof(uzUnicode)/sizeof(*uzUnicode));
1657  SetWindowTextW(::GetDlgItem(hWnd,IDC_STATIC),uzUnicode);
1658 
1659  MultiByteToWideChar(CP_UTF8,0,s_twlocalize[nIndex].Select,-1,uzUnicode,sizeof(uzUnicode)/sizeof(*uzUnicode));
1660  SetWindowTextW(::GetDlgItem(hWnd,IDOK),uzUnicode);
1661 
1662  MultiByteToWideChar(CP_UTF8,0,s_twlocalize[nIndex].Cancel,-1,uzUnicode,sizeof(uzUnicode)/sizeof(*uzUnicode));
1663  SetWindowTextW(::GetDlgItem(hWnd,IDCANCEL),uzUnicode);
1664  }
1665 
1666  hListBox = ::GetDlgItem(hWnd,ID_LST_SOURCES);
1667  if (hListBox)
1668  {
1669  SendMessage(hListBox,LB_RESETCONTENT,(WPARAM)NULL,(LPARAM)NULL);
1670 
1671  for (x = 1; x < MAX_NUM_DS; ++x)
1672  {
1673  // We expect the list to be contiguous...
1674  szProductName = pod.m_ptwndsmapps->DsGetIdentity(pAppId,x)->ProductName;
1675  if (!szProductName[0])
1676  {
1677  break;
1678  }
1679  // Display the name...
1680  nIndex = (int)SendMessage(hListBox,LB_ADDSTRING,(WPARAM)NULL,(LPARAM)szProductName);
1681  if (LB_ERR == nIndex)
1682  {
1683  break;
1684  }
1685  // Associate the id with the name...
1686  nIndex = (int)SendMessage(hListBox,
1687  LB_SETITEMDATA,
1688  (WPARAM)nIndex,
1689  (LPARAM)pod.m_ptwndsmapps->DsGetIdentity(pAppId,x)->Id);
1690  if (LB_ERR == nIndex)
1691  {
1692  break;
1693  }
1694  // Remember this item if it's the default...
1695  if (!strcmp(pod.m_ptwndsmapps->DsGetPath(pAppId,x),pod.m_DefaultDSPath))
1696  {
1697  nSelect = x;
1698  }
1699  }
1700  // If we have no drivers, then disable the OK button...
1701  if (pod.m_ptwndsmapps->AppGetNumDs(pAppId) < 1)
1702  {
1703  HWND hOK= ::GetDlgItem(hWnd,IDOK);
1704  EnableWindow(hOK, FALSE);
1705  }
1706  // Otherwise select the defaulted item...
1707  else
1708  {
1709  nIndex = (int)SendMessage(hListBox,
1710  LB_FINDSTRINGEXACT,
1711  (WPARAM)-1,
1712  (LPARAM)pod.m_ptwndsmapps->DsGetIdentity(pAppId,nSelect)->ProductName);
1713  if (LB_ERR == nIndex)
1714  {
1715  nIndex = 0;
1716  }
1717  SendMessage(hListBox,LB_SETCURSEL,(WPARAM)nIndex,(LPARAM)NULL);
1718  }
1719  }
1720 
1721  // Center our dialog on the window reported to us in MSG_OPENDS...
1722  hParent = (HWND)pod.m_ptwndsmapps->AppHwnd(pAppId);
1723  if (hParent)
1724  {
1725  GetClientRect(hParent,&rectParent);
1726  GetWindowRect(hWnd,&rectSelect);
1727  nWidth = (rectSelect.right - rectSelect.left);
1728  nHeight = (rectSelect.bottom - rectSelect.top);
1729  point.x = (rectParent.right - rectParent.left) / 2;
1730  point.y = (rectParent.bottom - rectParent.top) / 2;
1731  ClientToScreen(hParent,&point);
1732  point.x -= nWidth / 2;
1733  point.y -= nHeight / 2;
1734  // keep the dialog visible on the screen
1735  if(point.x < 0)
1736  {
1737  point.x = 0;
1738  }
1739  if(point.y < 0)
1740  {
1741  point.y = 0;
1742  }
1743  MoveWindow(hWnd,point.x,point.y,nWidth,nHeight,FALSE);
1744  }
1745 
1746  return TRUE;
1747 
1748  case WM_COMMAND:
1749  switch (LOWORD(wParam))
1750  {
1751  case ID_LST_SOURCES:
1752  if (HIWORD(wParam) != LBN_DBLCLK)
1753  break;
1754  // drop through...
1755 
1756  case IDOK:
1757  {
1758  hListBox = ::GetDlgItem(hWnd, ID_LST_SOURCES);
1759  nIndex = 0;
1760  if ( hListBox )
1761  {
1762  nIndex = (int)SendMessage(hListBox,LB_GETCURSEL,(WPARAM)0,(LPARAM)0);
1763  if (LB_ERR == nIndex)
1764  {
1765  // if there is no selection should not have OK available
1766  // to press in the first place.
1767  return TRUE;
1768  }
1769  nIndex = (int)SendMessage(hListBox,LB_GETITEMDATA,(WPARAM)nIndex,(LPARAM)0);
1770  if (LB_ERR != nIndex)
1771  {
1773  }
1774  }
1775  EndDialog(hWnd, IDOK);
1776  return TRUE;
1777  }
1778  case IDCANCEL:
1779  EndDialog(hWnd, IDCANCEL);
1780  return TRUE;
1781  }
1782  break;
1783  }
1784  return FALSE;
1785 }
1786 #elif (TWNDSM_CMP == TWNDSM_CMP_GNUGPP)
1787  // We don't have anything to do on Linux...
1788 #else
1789  #error Sorry, we do not recognize this system...
1790 #endif
1791 
1792 
1793 
1794 /*
1795 * Invoke the user selection dialog box. We only support this for
1796 * Windows, for Linux it's a bad protocol, since there is no way
1797 * to query the user (nicely) across all consoles and graphical
1798 * interfaces for all distributions...
1799 */
1801  TW_IDENTITY *_pDsId)
1802 {
1803  // Validate...
1804  if (0 == _pAppId)
1805  {
1806  kLOG((kLOGERR,"_pAppId is null"));
1807  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADVALUE);
1808  return TWRC_FAILURE;
1809  }
1810  if ( ((TWID_T)_pAppId->Id < 1)
1811  || ((TWID_T)_pAppId->Id >= pod.m_ptwndsmapps->AppGetNumApp()))
1812  {
1813  kLOG((kLOGERR,"_pAppId.Id is out of range"));
1814  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADVALUE);
1815  return TWRC_FAILURE;
1816  }
1817  else if (0 == _pDsId)
1818  {
1819  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADDEST);
1820  return TWRC_FAILURE;
1821  }
1822  else if (dsmState_Open != pod.m_ptwndsmapps->AppGetState(_pAppId))
1823  {
1824  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_SEQERROR);
1825  return TWRC_FAILURE;
1826  }
1827 
1831  // Make sure the id is 0 before we go into this...
1832  _pDsId->Id = 0;
1833 
1834  // Windows...
1835  #if (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP)
1836 
1837  HKEY hKey;
1838  long status;
1839  char *szPath;
1840  TW_INT16 result;
1841 
1842  // Set the context...
1843  result = TWRC_SUCCESS;
1844  pod.m_pSelectDlgAppId = _pAppId;
1845 
1846  // If passed in a DS name we want to select it
1847  if (_pDsId->ProductName[0] != 0)
1848  {
1849  result = GetDSFromProductName(_pAppId,_pDsId);
1850  // If no match continue anyway.
1851  }
1852 
1853  // If not passed a DS or the name was not currently found
1854  // then selete the default
1855  _pDsId->Id = 0;
1856  result = GetMatchingDefault(_pAppId,_pDsId);
1857  pod.m_pSelectDlgDsId = _pDsId;
1858 
1859  // a.walling - Get the HWND of the parent window, if any, and use it as the dialog's parent
1860  HWND hParent = (HWND)pod.m_ptwndsmapps->AppHwnd(_pAppId);
1861 
1862  // create the dialog window
1863  int ret = (int)::DialogBoxW(g_hinstance,
1864  (LPCWSTR)IDD_DLG_SOURCE,
1865  (HWND)hParent,
1866  (DLGPROC)::SelectDlgProc);
1867 
1868  // User picked something...
1869  if (ret == IDOK)
1870  {
1871  // Validate the result...
1872  if (!pod.m_pSelectDlgDsId)
1873  {
1874  kLOG((kLOGERR,"We came out of the Select Dialog with a null..."));
1875  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_OPERATIONERROR);
1876  return TWRC_FAILURE;
1877  }
1878 
1879  // Copy the data over...
1880  *_pDsId = *pod.m_pSelectDlgDsId;
1881 
1882  // save default source to Registry
1883  // sanity check...
1884  if ( (pod.m_pSelectDlgDsId->Id < 1)
1885  || (pod.m_pSelectDlgDsId->Id >= MAX_NUM_DS))
1886  {
1887  // Failed to save default DS to registry
1888  kLOG((kLOGERR,"Id is out of range 0 - 49..."));
1889  // Nothing preventing us from using the default right now
1890  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BUMMER);
1891  }
1892 
1893  else
1894  {
1895  // Get the path we're using...
1896  status = ERROR_SUCCESS;
1898 
1899  // Open the key, creating it if it doesn't exist.
1900  if (RegCreateKeyEx(HKEY_CURRENT_USER,
1901  TWNDSM_DS_REG_LOC,
1902  NULL,
1903  NULL,
1904  NULL,
1905  KEY_READ | KEY_WRITE, NULL,
1906  &hKey,
1907  NULL) == ERROR_SUCCESS)
1908  {
1909  status = RegSetValueEx(hKey,"Default Source",0,REG_SZ,(LPBYTE)szPath,(DWORD)strlen((char*)szPath)+1);
1910  if (status != ERROR_SUCCESS)
1911  {
1912  // Failed to save default DS to registry
1913  kLOG((kLOGERR,"Failed to save default DS to registry"));
1914  // Nothing preventing us from using the default right now
1915  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BUMMER);
1916  }
1917  }
1918  // Close the key.
1919  RegCloseKey(hKey);
1920  }
1921  }
1922 
1923  // We're cancelling...
1924  else if (ret == IDCANCEL)
1925  {
1926  result = TWRC_CANCEL;
1927  }
1928 
1929  // Something back happened...
1930  else if (ret == -1)
1931  {
1932  ::MessageBox(NULL,"Dialog failed!","Error",MB_OK|MB_ICONINFORMATION);
1933  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BUMMER);
1934  result = TWRC_FAILURE;
1935  }
1936 
1937  return result;
1938 
1939  // We don't support the user selection box on linux...
1940  #elif (TWNDSM_CMP == TWNDSM_CMP_GNUGPP)
1941 
1942  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADPROTOCOL);
1943  return TWRC_FAILURE;
1944 
1945  // Ruh-roh, Reorge...
1946  #else
1947  #error Sorry, we do not recognize this system...
1948  #endif
1949 }
1950 
1951 
1952 /*
1953 * Set the datasource as the default
1954 */
1956  TW_IDENTITY *_pDsId)
1957 {
1958  TW_INT16 result = TWRC_SUCCESS;
1959 
1960  // Validate app ...
1961  if (0 == _pAppId)
1962  {
1963  kLOG((kLOGERR,"_pAppId is null"));
1964  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADVALUE);
1965  return TWRC_FAILURE;
1966  }
1967  else if ( (TWID_T)_pAppId->Id < 1
1968  || (TWID_T)_pAppId->Id >= pod.m_ptwndsmapps->AppGetNumApp() )
1969  {
1970  kLOG((kLOGERR,"_pAppId.Id is out of range...%d",(int)(TWID_T)_pAppId->Id));
1971  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADVALUE);
1972  return TWRC_FAILURE;
1973  }
1974  else if (dsmState_Open != pod.m_ptwndsmapps->AppGetState(_pAppId))
1975  {
1976  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_SEQERROR);
1977  return TWRC_FAILURE;
1978  }
1979 
1980  // Validate DS
1981  if(0 == _pDsId)
1982  {
1983  kLOG((kLOGERR,"_pDsId is null"));
1984  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADDEST);
1985  return TWRC_FAILURE;
1986  }
1987  else if ((TWID_T)_pDsId->Id < 1
1988  || (TWID_T)_pDsId->Id >= MAX_NUM_DS)
1989  {
1990  kLOG((kLOGERR,"Id is out of range 0 - 49..."));
1991  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADVALUE);
1992  return TWRC_FAILURE;
1993  }
1994 
1995  char *szPath = pod.m_ptwndsmapps->DsGetPath(_pAppId,(TWID_T)_pDsId->Id); // Get the path we're using...
1996 
1997  if(!szPath)
1998  {
1999  kLOG((kLOGERR,"DS is not valid"));
2000  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADVALUE);
2001  return TWRC_FAILURE;
2002  }
2003 
2004  // Windows... save default source to Registry
2005  #if (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP)
2006  HKEY hKey;
2007  long status = ERROR_SUCCESS;
2008 
2009  // Open the key, creating it if it doesn't exist.
2010  if (RegCreateKeyEx(HKEY_CURRENT_USER,
2011  TWNDSM_DS_REG_LOC,
2012  NULL,
2013  NULL,
2014  NULL,
2015  KEY_READ | KEY_WRITE, NULL,
2016  &hKey,
2017  NULL) == ERROR_SUCCESS)
2018  {
2019  status = RegSetValueEx(hKey,"Default Source",0,REG_SZ,(LPBYTE)szPath,(DWORD)strlen((char*)szPath)+1);
2020  if (status != ERROR_SUCCESS)
2021  {
2022  // Failed to save default DS to registry
2023  kLOG((kLOGERR,"Failed to save default DS to registry"));
2024  // Nothing preventing us from using the default right now
2025  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BUMMER);
2026  result = TWRC_FAILURE;
2027  }
2028 
2029  // Close the key.
2030  RegCloseKey(hKey);
2031  }
2032 
2033  // Linux looks in the user's directory...
2034  #elif (TWNDSM_CMP == TWNDSM_CMP_GNUGPP)
2035  int iResult;
2036  FILE *pfile;
2037  char *szHome;
2038  char szFile[FILENAME_MAX];
2039  szHome = getenv("HOME");
2040  if (szHome)
2041  {
2042  SSTRCPY(szFile,sizeof(szFile),szHome);
2043  SSTRCAT(szFile,sizeof(szFile),"/.twndsmrc/defaultds");
2044  FOPEN(pfile,szFile,"w");
2045  if (pfile)
2046  {
2047  iResult = fwrite(szPath, 1, strlen(szPath), pfile);
2048  if (iResult < (int)strlen(pod.m_ptwndsmapps->DsGetPath(_pAppId,(TWID_T)_pDsId->Id)))
2049  {
2050  kLOG((kLOGERR,"fwrite defaultds failed..."));
2051  }
2052  fclose(pfile);
2053  }
2054  }
2055 
2056  // eek...
2057  #else
2058  #error Sorry, we do not recognize this system...
2059  result = TWRC_FAILURE
2060  #endif
2061 
2062  return result;
2063 }
2064 
2065 
2066 /*
2067 * Invoke the user selection dialog box. We only support this for
2068 * Windows, for Linux it's a bad protocol, since there is no way
2069 * to query the user (nicely) across all consoles and graphical
2070 * interfaces for all distributions...
2071 */
2073  TW_IDENTITY *_pDsId)
2074 {
2075  TWID_T ii;
2076 
2077  // Validate...
2078  if ( !pod.m_ptwndsmapps->AppValidateId(_pAppId)
2079  || (0 == _pDsId))
2080  {
2081  kLOG((kLOGERR,"bad _pAppId or _pDsId..."));
2082  return TWRC_FAILURE;
2083  }
2084  else if (0 == _pDsId->ProductName[0])
2085  {
2086  return TWRC_FAILURE;
2087  }
2088 
2089  // Search for a match on the ProductName...
2090  for (ii = 1; ii < MAX_NUM_DS; ++ii)
2091  {
2092  // Note that TW_STR32 type is NUL-filled, not NUL-terminated...
2093  if (0 == strncmp((char*)_pDsId->ProductName,
2094  (char*)pod.m_ptwndsmapps->DsGetIdentity(_pAppId,ii)->ProductName,
2095  sizeof(TW_STR32)))
2096  {
2097  // match found, set the index
2098  *_pDsId = *pod.m_ptwndsmapps->DsGetIdentity(_pAppId,ii);
2099  return TWRC_SUCCESS;
2100  }
2101  }
2102 
2103  // Uh-oh...
2104  return TWRC_FAILURE;
2105 }
2106 
2107 
2108 
2109 /*
2110 * Get the identity for the first driver we found, or TWRC_ENDOFLIST
2111 * if we don't have any...
2112 */
2114  TW_IDENTITY *_pDsId)
2115 {
2116  // Validate...
2117  if ( !pod.m_ptwndsmapps->AppValidateId(_pAppId)
2118  || (0 == _pDsId))
2119  {
2120  kLOG((kLOGERR,"bad _pAppId or _pDsId..."));
2121  return TWRC_FAILURE;
2122  }
2123 
2127  // There are no supported drivers...
2128  if (pod.m_ptwndsmapps->AppGetNumDs(_pAppId) < 1)
2129  {
2130  // Make sure we fail of GetNext is called...
2131  pod.m_nextDsId = pod.m_ptwndsmapps->AppGetNumDs(_pAppId) + 1;
2132  return TWRC_ENDOFLIST;
2133  }
2134 
2135  // Check for valid DS
2136  if(0 == _pDsId)
2137  {
2138  kLOG((kLOGERR,"_pDsId is null"));
2139  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADDEST);
2140  return TWRC_FAILURE;
2141  }
2142 
2143 
2144  // Return info on the first driver we found...
2145  pod.m_nextDsId = 1;
2146  *_pDsId = *pod.m_ptwndsmapps->DsGetIdentity(_pAppId,pod.m_nextDsId);
2147 
2148  // All done...
2149  return TWRC_SUCCESS;
2150 }
2151 
2152 
2153 
2154 /*
2155 * Get the identity for the next driver we found, or TWRC_ENDOFLIST
2156 * if we've run out...
2157 */
2159  TW_IDENTITY *_pDsId)
2160 {
2161  // Validate...
2162  if ( !pod.m_ptwndsmapps->AppValidateId(_pAppId)
2163  || (0 == _pDsId))
2164  {
2165  kLOG((kLOGERR,"bad _pAppId or _pDsId..."));
2166  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADDEST);
2167  return TWRC_FAILURE;
2168  }
2169 
2170  // Applications must call MSG_GETFIRST before making this call...
2171  if (pod.m_nextDsId == 0)
2172  {
2173  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_SEQERROR);
2174  return TWRC_FAILURE;
2175  }
2176 
2177  // Prep for a call to GetNext...
2178  pod.m_nextDsId += 1;
2179 
2180  // We're out of items...
2181  if (pod.m_nextDsId > pod.m_ptwndsmapps->AppGetNumDs(_pAppId))
2182  {
2183  pod.m_nextDsId = 0;
2184  return TWRC_ENDOFLIST;
2185  }
2186 
2187  // Return info on the this driver...
2188  *_pDsId = *pod.m_ptwndsmapps->DsGetIdentity(_pAppId,pod.m_nextDsId);
2189 
2190  // All done...
2191  return TWRC_SUCCESS;
2192 }
2193 
2194 
2195 
2196 /*
2197 * Get the identity of the default source...
2198 */
2200  TW_IDENTITY *_pDsId)
2201 {
2202  bool bMatchFnd = false;
2203  bool bDefaultFound = false;
2204  TW_UINT32 ii;
2205 
2206  // Validate...
2207  if ( !pod.m_ptwndsmapps->AppValidateId(_pAppId)
2208  || (0 == _pDsId))
2209  {
2210  kLOG((kLOGERR,"bad _pAppId or _pDsId..."));
2211  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADDEST);
2212  return TWRC_FAILURE;
2213  }
2214 
2215  // is there something to match to?
2216  if (pod.m_ptwndsmapps->AppGetNumDs(_pAppId) < 1)
2217  {
2218  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_NODS);
2219  return TWRC_FAILURE;
2220  }
2221 
2222  // Something very bad may be happening, so don't let the
2223  // application get away with this...
2224  if (0 != (TWID_T)_pDsId->Id)
2225  {
2226  kLOG((kLOGINFO,"Please make sure your TW_IDENTITY.Id for your driver (the destination) is zeroed out before making this call..."));
2227  //pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_OPERATIONERROR);
2228  //return TWRC_FAILURE;
2229  }
2230 
2231  // In Windows the default Data Source is stored in the registry
2232  // as the path to that DS. We will need to compare this to the other DS as a match.
2233  // read default source from Registry
2234  memset(pod.m_DefaultDSPath,0,sizeof(pod.m_DefaultDSPath));
2235 
2236  // Windows uses the registry...
2237  #if (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP)
2238  HKEY hKey;
2239  if (RegOpenKeyEx(HKEY_CURRENT_USER,
2240  TWNDSM_DS_REG_LOC,
2241  0,
2242  KEY_READ,
2243  &hKey) == ERROR_SUCCESS )
2244  {
2245  // Look for the subkey "Default Source".
2246  DWORD DWtype = REG_SZ;
2247  DWORD DWsize = sizeof(pod.m_DefaultDSPath);
2248  bDefaultFound = ( RegQueryValueEx(hKey,"Default Source",NULL,&DWtype,(LPBYTE)pod.m_DefaultDSPath,&DWsize) == ERROR_SUCCESS);
2249 
2250  // Close the registry key handle.
2251  RegCloseKey(hKey);
2252  }
2253 
2254  // Linux looks in the user's directory...
2255  #elif (TWNDSM_CMP == TWNDSM_CMP_GNUGPP)
2256  int iResult;
2257  FILE *pfile;
2258  char *szHome;
2259  char szFile[FILENAME_MAX];
2260  memset(pod.m_DefaultDSPath,0,sizeof(pod.m_DefaultDSPath));
2261  szHome = getenv("HOME");
2262  if (szHome)
2263  {
2264  SSTRCPY(szFile,sizeof(szFile),szHome);
2265  SSTRCAT(szFile,sizeof(szFile),"/.twndsmrc/defaultds");
2266  FOPEN(pfile,szFile,"r");
2267  if (pfile)
2268  {
2269  iResult = fread(pod.m_DefaultDSPath,1,sizeof(pod.m_DefaultDSPath)-1,pfile);
2270  if (iResult <= 0)
2271  {
2272  kLOG((kLOGINFO,"The defaultds file is empty, this is okay..."));
2273  pod.m_DefaultDSPath[0] = 0;
2274  }
2275  bDefaultFound = true;
2276  fclose(pfile);
2277  }
2278  }
2279 
2280  // eek...
2281  #else
2282  #error Sorry, we do not recognize this system...
2283  #endif
2284 
2285 
2286  // If current default source is not a match find a new default source
2287  // that will match this app
2288  for (ii = 1; ii < MAX_NUM_DS; ++ii)
2289  {
2290  // Mark the first match to use as default, if we don't
2291  // find a match, this will be the one we go with...
2292  if (!bMatchFnd)
2293  {
2294  *_pDsId = *pod.m_ptwndsmapps->DsGetIdentity(_pAppId,ii);
2295  bMatchFnd = true;
2296 
2297  //If no default was saved no need to go checking for a match
2298  if(!bDefaultFound)
2299  {
2300  break;
2301  }
2302  }
2303 
2304  // If the system default is a match we will use it and stop looking.
2305  if (0 == STRNICMP(pod.m_DefaultDSPath,
2306  pod.m_ptwndsmapps->DsGetPath(_pAppId,ii),
2307  sizeof(pod.m_DefaultDSPath)))
2308  {
2309  *_pDsId = *pod.m_ptwndsmapps->DsGetIdentity(_pAppId,ii);
2310  bMatchFnd = true;
2311  break;
2312  }
2313  }
2314 
2315  if (!bMatchFnd)
2316  {
2317  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_NODS);
2318  return TWRC_FAILURE;
2319  }
2320 
2321  return TWRC_SUCCESS;
2322 }
2323 
2324 
2325 /*
2326 * Log the triplets that the application sends to us...
2327 */
2329  const TW_IDENTITY *_pDest,
2330  const TW_UINT32 _DG,
2331  const TW_UINT16 _DAT,
2332  const TW_UINT16 _MSG,
2333  const TW_MEMREF _pData)
2334 {
2335  char szDg[64];
2336  char szDat[64];
2337  char szMsg[64];
2338  char szData[128];
2339  TW_CAPABILITY *_pCap;
2340 
2341  // Don't spend time processing the triplet if we are not logging.
2342  if( !g_ptwndsmlog )
2343  {
2344  return false;
2345  }
2346 
2347  // too many of these messages to log...
2348  if ( (DG_CONTROL == _DG)
2349  && (DAT_EVENT == _DAT))
2350  {
2351  return false;
2352  }
2353 
2354  // Convert them...
2355  StringFromDg(szDg,NCHARS(szDg),_DG);
2356  StringFromDat(szDat,NCHARS(szDat),_DAT);
2357  StringFromMsg(szMsg,NCHARS(szMsg),_MSG);
2358 
2359  memset(szData, 0, sizeof(szData));
2360 
2361  // If we have data do some extra work to see what it might be
2362  if(NULL != _pData)
2363  {
2364  // If we're a capability, try to tell them what cap it is...
2365  if ( (DG_CONTROL == _DG)
2366  && (DAT_CAPABILITY == _DAT) )
2367  {
2368  _pCap = (TW_CAPABILITY*)_pData;
2369  StringFromCap(szData,NCHARS(szData),_pCap->Cap);
2370 
2371  // If sending a container, try to tell them what...
2372  if( MSG_SET == _MSG )
2373  {
2374  char szType[32];
2375  StringFromConType(szType,NCHARS(szType),_pCap->ConType);
2376  SSTRCAT(szData,NCHARS(szData),szType);
2377  }
2378  }
2379  }
2380 
2381  // Print out the orgin and Destination
2382  kLOG((kLOGINFO,"%.32s -> %.32s",_pOrigin? (char*)_pOrigin->ProductName:"DSM", _pDest? (char*)_pDest->ProductName:"DSM"));
2383 
2384  // Print them
2385  if(strlen(szData))
2386  {
2387  kLOG((kLOGINFO,"%s/%s/%s/%s",szDg,szDat,szMsg,szData));
2388  }
2389  else
2390  {
2391  kLOG((kLOGINFO,"%s/%s/%s",szDg,szDat,szMsg));
2392  }
2393  g_ptwndsmlog->Indent(1);
2394 
2395  // All done...
2396  return true;
2397 }
2398 
2399 /*
2400 * Log the results after processing the Triplet
2401 */
2402 void CTwnDsm::printResults(const TW_UINT32 _DG,
2403  const TW_UINT16 _DAT,
2404  const TW_UINT16 _MSG,
2405  const TW_MEMREF _pData,
2406  const TW_UINT16 _RC)
2407 {
2408  char szRc[64];
2409 
2410  StringFromRC(szRc,NCHARS(szRc),_RC);
2411 
2412  // If we have data do some extra work to see what it might be
2413  if( NULL != _pData && TWRC_FAILURE != _RC)
2414  {
2415  if( DG_CONTROL == _DG
2416  && DAT_CAPABILITY == _DAT
2417  && ( MSG_GET == _MSG || MSG_GETCURRENT == _MSG || MSG_GETDEFAULT == _MSG || MSG_RESET == _MSG ) )
2418  {
2419  TW_CAPABILITY *_pCap = (TW_CAPABILITY*)_pData;
2420  char szType[32];
2421  StringFromConType(szType, NCHARS(szType), _pCap->ConType);
2422  SSTRCAT(szRc, NCHARS(szRc), szType);
2423  }
2424  else if( DG_CONTROL == _DG
2425  && DAT_PENDINGXFERS == _DAT )
2426  {
2427  TW_PENDINGXFERS *pXfer = (TW_PENDINGXFERS*)_pData;
2428  char szValue[32];
2429  SSNPRINTF(szValue, NCHARS(szValue), NCHARS(szValue), " Count = %d", pXfer->Count==0xFFFF?-1:pXfer->Count);
2430  SSTRCAT(szRc, NCHARS(szRc), szValue);
2431  }
2432  else if( DG_CONTROL == _DG
2433  && DAT_STATUS == _DAT )
2434  {
2435  TW_STATUS *pStatus = (TW_STATUS*)_pData;
2436  char szStatus[32];
2437  StringFromConditionCode(szStatus, NCHARS(szStatus), pStatus->ConditionCode);
2438  SSTRCAT(szRc, NCHARS(szRc), szStatus);
2439  }
2440  }
2441 
2442  // ... and add a blank line
2443  SSTRCAT(szRc,NCHARS(szRc),"\n");
2444 
2445  g_ptwndsmlog->Indent(-1);
2446  kLOG((kLOGINFO,szRc));
2447 }
2448 
2449 /*
2450 * DAT_NULL is used by a driver to send certain messages back to the
2451 * application, like MSG_XFERREADY...
2452 */
2453 TW_INT16 CTwnDsm::DSM_Null(TW_IDENTITY *_pAppId,
2454  TW_IDENTITY *_pDsId,
2455  TW_UINT16 _MSG)
2456 {
2457  TW_CALLBACK2 *ptwcallback2 = 0;
2458  TW_INT16 result = TWRC_SUCCESS;
2459  TW_MEMREF MemRef;
2460  bool bPrinted = false;
2461 
2462  // Validate...
2463  if ( !pod.m_ptwndsmapps->AppValidateIds(_pAppId,_pDsId) )
2464  {
2465  kLOG((kLOGERR,"bad _pAppId or _pDsId..."));
2466  return TWRC_FAILURE;
2467  }
2468 
2469  // Invoke the application's callback to send this message along.
2470  if ( (MSG_DEVICEEVENT != _MSG)
2471  && (MSG_CLOSEDSOK != _MSG)
2472  && (MSG_CLOSEDSREQ != _MSG)
2473  && (MSG_XFERREADY != _MSG))
2474  {
2475  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BADPROTOCOL);
2476  return TWRC_FAILURE;
2477  }
2478 
2479  // Get the current callback...
2480  ptwcallback2 = pod.m_ptwndsmapps->DsCallback2Get(_pAppId,(TWID_T)_pDsId->Id);
2481 
2482  // We have something to call...
2483  if ( (0 != ptwcallback2)
2484  && (ptwcallback2->CallBackProc))
2485  {
2486  // RefCon is returned back to the calling application in pData
2487  // Unfortunately RefCon is defined as TW_INT32
2488  // Application writers that want to store a pointer in RefCon
2489  // on 64bit will need to store an index to local storage.
2490  MemRef = (TW_MEMREF)ptwcallback2->RefCon;
2491 
2492  // Set flag to prevent Application from sending a new message
2493  // before returning back from recieving this callback.
2494  pod.m_ptwndsmapps->DsSetAppProcessingCallback(_pAppId,(TWID_T)_pDsId->Id,TRUE);
2495 
2496  // We should have a try/catch around this...
2497  // Send a message from DS to the Application.
2498  // Rare case where the origin is the DS and dest is the App
2499  try
2500  {
2501  // Create a local copy of the AppIdentity
2502  TW_IDENTITY AppId = *pod.m_ptwndsmapps->AppGetIdentity(_pAppId);
2503 
2504  // Print the triplets to stdout for information purposes
2505  bPrinted = printTripletsInfo(NULL,&AppId,DG_CONTROL,DAT_NULL,_MSG,MemRef);
2506 
2507  // Send a pointer to the data...
2508  result = ((DSMENTRYPROC)(ptwcallback2->CallBackProc))(
2509  pod.m_ptwndsmapps->DsGetIdentity(&AppId,(TWID_T)_pDsId->Id),
2510  &AppId,
2511  DG_CONTROL,
2512  DAT_NULL,
2513  _MSG,
2514  MemRef);
2515  }
2516  catch(...)
2517  {
2518  pod.m_ptwndsmapps->AppSetConditionCode(_pAppId,TWCC_BUMMER);
2519  kLOG((kLOGERR,"Exception caught while App was processing message. Returning Failure."));
2520  result = TWRC_FAILURE;
2521  }
2522 
2523  pod.m_ptwndsmapps->DsSetAppProcessingCallback(_pAppId,(TWID_T)_pDsId->Id,FALSE);
2524  }
2525 
2526  // Application has not registered a callback. As a result, the msg will
2527  // be sent to the app the next time it forwards an event.
2528  // Each App's DS has a callback structure. This way multiple DS's can make
2529  // a callback to a single app, and we are not going to lose MSG's
2530  else
2531  {
2532  if (ptwcallback2)
2533  {
2534  if (ptwcallback2->Message != 0)
2535  {
2536  char szMsg[64];
2537  StringFromMsg(szMsg, NCHARS(szMsg), ptwcallback2->Message);
2538  kLOG((kLOGERR, "%.32s NEVER retrieved DAT_EVENT / %s\n", _pAppId->ProductName, szMsg));
2539  }
2540  ptwcallback2->Message = _MSG;
2541  }
2542  pod.m_ptwndsmapps->DsCallbackSetWaiting(_pAppId,(TWID_T)_pDsId->Id,TRUE);
2543  pod.m_ptwndsmapps->AppWakeup(_pAppId);
2544  }
2545 
2546  // Log how it went...
2547  if (bPrinted)
2548  {
2549  printResults(DG_CONTROL,DAT_NULL,_MSG,MemRef,result);
2550  }
2551 
2552  return result;
2553 }
2554 
2555 
2556 
2557 /*
2558 * Convert a DG_ data group numerical value to a string...
2559 */
2560 void CTwnDsm::StringFromDg(char *_szDg,
2561  const int _nChars,
2562  const TW_UINT32 _DG)
2563 {
2564  switch(_DG)
2565  {
2566  default:
2567  SSNPRINTF(_szDg,_nChars,_nChars,"DG_0x%04lx",_DG);
2568  break;
2569 
2570  case DG_CONTROL:
2571  SSTRCPY(_szDg,_nChars,"DG_CONTROL");
2572  break;
2573 
2574  case DG_IMAGE:
2575  SSTRCPY(_szDg,_nChars,"DG_IMAGE");
2576  break;
2577 
2578  case DG_AUDIO:
2579  SSTRCPY(_szDg,_nChars,"DG_AUDIO");
2580  break;
2581  }
2582 }
2583 
2584 
2585 
2586 /*
2587 * Convert a DAT_ data argument type numerical value to a string...
2588 */
2589 void CTwnDsm::StringFromDat(char *_szDat,
2590  const int _nChars,
2591  const TW_UINT16 _DAT)
2592 {
2593  switch(_DAT)
2594  {
2595  default:
2596  SSNPRINTF(_szDat,_nChars,_nChars,"DAT_0x%04x",_DAT);
2597 
2598  case DAT_NULL:
2599  SSTRCPY(_szDat,_nChars,"DAT_NULL");
2600  break;
2601 
2602  case DAT_CUSTOMBASE:
2603  SSTRCPY(_szDat,_nChars,"DAT_CUSTOMBASE");
2604  break;
2605 
2606  case DAT_CAPABILITY:
2607  SSTRCPY(_szDat,_nChars,"DAT_CAPABILITY");
2608  break;
2609 
2610  case DAT_EVENT:
2611  SSTRCPY(_szDat,_nChars,"DAT_EVENT");
2612  break;
2613 
2614  case DAT_IDENTITY:
2615  SSTRCPY(_szDat,_nChars,"DAT_IDENTITY");
2616  break;
2617 
2618  case DAT_PARENT:
2619  SSTRCPY(_szDat,_nChars,"DAT_PARENT");
2620  break;
2621 
2622  case DAT_PENDINGXFERS:
2623  SSTRCPY(_szDat,_nChars,"DAT_PENDINGXFERS");
2624  break;
2625 
2626  case DAT_SETUPMEMXFER:
2627  SSTRCPY(_szDat,_nChars,"DAT_SETUPMEMXFER");
2628  break;
2629 
2630  case DAT_SETUPFILEXFER:
2631  SSTRCPY(_szDat,_nChars,"DAT_SETUPFILEXFER");
2632  break;
2633 
2634  case DAT_STATUS:
2635  SSTRCPY(_szDat,_nChars,"DAT_STATUS");
2636  break;
2637 
2638  case DAT_USERINTERFACE:
2639  SSTRCPY(_szDat,_nChars,"DAT_USERINTERFACE");
2640  break;
2641 
2642  case DAT_XFERGROUP:
2643  SSTRCPY(_szDat,_nChars,"DAT_XFERGROUP");
2644  break;
2645 
2646  case DAT_TWUNKIDENTITY:
2647  SSTRCPY(_szDat,_nChars,"DAT_TWUNKIDENTITY");
2648  break;
2649 
2650  case DAT_CUSTOMDSDATA:
2651  SSTRCPY(_szDat,_nChars,"DAT_CUSTOMDSDATA");
2652  break;
2653 
2654  case DAT_DEVICEEVENT:
2655  SSTRCPY(_szDat,_nChars,"DAT_DEVICEEVENT");
2656  break;
2657 
2658  case DAT_FILESYSTEM:
2659  SSTRCPY(_szDat,_nChars,"DAT_FILESYSTEM");
2660  break;
2661 
2662  case DAT_PASSTHRU:
2663  SSTRCPY(_szDat,_nChars,"DAT_PASSTHRU");
2664  break;
2665 
2666  case DAT_CALLBACK:
2667  SSTRCPY(_szDat,_nChars,"DAT_CALLBACK");
2668  break;
2669 
2670  case DAT_STATUSUTF8:
2671  SSTRCPY(_szDat,_nChars,"DAT_STATUSUTF8");
2672  break;
2673 
2674  case DAT_IMAGEINFO:
2675  SSTRCPY(_szDat,_nChars,"DAT_IMAGEINFO");
2676  break;
2677 
2678  case DAT_IMAGELAYOUT:
2679  SSTRCPY(_szDat,_nChars,"DAT_IMAGELAYOUT");
2680  break;
2681 
2682  case DAT_IMAGEMEMXFER:
2683  SSTRCPY(_szDat,_nChars,"DAT_IMAGEMEMXFER");
2684  break;
2685 
2686  case DAT_IMAGENATIVEXFER:
2687  SSTRCPY(_szDat,_nChars,"DAT_IMAGENATIVEXFER");
2688  break;
2689 
2690  case DAT_IMAGEFILEXFER:
2691  SSTRCPY(_szDat,_nChars,"DAT_IMAGEFILEXFER");
2692  break;
2693 
2694  case DAT_CIECOLOR:
2695  SSTRCPY(_szDat,_nChars,"DAT_CIECOLOR");
2696  break;
2697 
2698  case DAT_GRAYRESPONSE:
2699  SSTRCPY(_szDat,_nChars,"DAT_GRAYRESPONSE");
2700  break;
2701 
2702  case DAT_RGBRESPONSE:
2703  SSTRCPY(_szDat,_nChars,"DAT_RGBRESPONSE");
2704  break;
2705 
2706  case DAT_JPEGCOMPRESSION:
2707  SSTRCPY(_szDat,_nChars,"DAT_JPEGCOMPRESSION");
2708  break;
2709 
2710  case DAT_PALETTE8:
2711  SSTRCPY(_szDat,_nChars,"DAT_PALETTE8");
2712  break;
2713 
2714  case DAT_EXTIMAGEINFO:
2715  SSTRCPY(_szDat,_nChars,"DAT_EXTIMAGEINFO");
2716  break;
2717 
2718  case DAT_AUDIOFILEXFER:
2719  SSTRCPY(_szDat,_nChars,"DAT_AUDIOFILEXFER");
2720  break;
2721 
2722  case DAT_AUDIOINFO:
2723  SSTRCPY(_szDat,_nChars,"DAT_AUDIOINFO");
2724  break;
2725 
2726  case DAT_AUDIONATIVEXFER:
2727  SSTRCPY(_szDat,_nChars,"DAT_AUDIONATIVEXFER");
2728  break;
2729 
2730  case DAT_ICCPROFILE:
2731  SSTRCPY(_szDat,_nChars,"DAT_ICCPROFILE");
2732  break;
2733 
2734  case DAT_IMAGEMEMFILEXFER:
2735  SSTRCPY(_szDat,_nChars,"DAT_IMAGEMEMFILEXFER");
2736  break;
2737 
2738  case DAT_ENTRYPOINT:
2739  SSTRCPY(_szDat,_nChars,"DAT_ENTRYPOINT");
2740  break;
2741  }
2742 }
2743 
2744 
2745 
2746 /*
2747 * Convert a MSG_ message numerical value to a string...
2748 */
2749 void CTwnDsm::StringFromMsg(char *_szMsg,
2750  const int _nChars,
2751  const TW_UINT16 _MSG)
2752 {
2753  switch (_MSG)
2754  {
2755  default:
2756  SSNPRINTF(_szMsg,_nChars,_nChars,"MSG_0x%04x",_MSG);
2757  break;
2758 
2759  case MSG_NULL:
2760  SSTRCPY(_szMsg,_nChars,"MSG_NULL");
2761  break;
2762 
2763  case MSG_CUSTOMBASE:
2764  SSTRCPY(_szMsg,_nChars,"MSG_CUSTOMBASE");
2765  break;
2766 
2767  case MSG_GET:
2768  SSTRCPY(_szMsg,_nChars,"MSG_GET");
2769  break;
2770 
2771  case MSG_GETCURRENT:
2772  SSTRCPY(_szMsg,_nChars,"MSG_GETCURRENT");
2773  break;
2774 
2775  case MSG_GETDEFAULT:
2776  SSTRCPY(_szMsg,_nChars,"MSG_GETDEFAULT");
2777  break;
2778 
2779  case MSG_GETFIRST:
2780  SSTRCPY(_szMsg,_nChars,"MSG_GETFIRST");
2781  break;
2782 
2783  case MSG_GETNEXT:
2784  SSTRCPY(_szMsg,_nChars,"MSG_GETNEXT");
2785  break;
2786 
2787  case MSG_SET:
2788  SSTRCPY(_szMsg,_nChars,"MSG_SET");
2789  break;
2790 
2791  case MSG_RESET:
2792  SSTRCPY(_szMsg,_nChars,"MSG_RESET");
2793  break;
2794 
2795  case MSG_QUERYSUPPORT:
2796  SSTRCPY(_szMsg,_nChars,"MSG_QUERYSUPPORT");
2797  break;
2798 
2799  case MSG_GETHELP:
2800  SSTRCPY(_szMsg,_nChars,"MSG_GETHELP");
2801  break;
2802 
2803  case MSG_GETLABEL:
2804  SSTRCPY(_szMsg,_nChars,"MSG_GETLABEL");
2805  break;
2806 
2807  case MSG_GETLABELENUM:
2808  SSTRCPY(_szMsg,_nChars,"MSG_GETLABELENUM");
2809  break;
2810 
2811  case MSG_XFERREADY:
2812  SSTRCPY(_szMsg,_nChars,"MSG_XFERREADY");
2813  break;
2814 
2815  case MSG_CLOSEDSREQ:
2816  SSTRCPY(_szMsg,_nChars,"MSG_CLOSEDSREQ");
2817  break;
2818 
2819  case MSG_CLOSEDSOK:
2820  SSTRCPY(_szMsg,_nChars,"MSG_CLOSEDSOK");
2821  break;
2822 
2823  case MSG_DEVICEEVENT:
2824  SSTRCPY(_szMsg,_nChars,"MSG_DEVICEEVENT");
2825  break;
2826  case MSG_CHECKSTATUS:
2827  SSTRCPY(_szMsg,_nChars,"MSG_CHECKSTATUS");
2828  break;
2829  case MSG_OPENDSM:
2830  SSTRCPY(_szMsg,_nChars,"MSG_OPENDSM");
2831  break;
2832 
2833  case MSG_CLOSEDSM:
2834  SSTRCPY(_szMsg,_nChars,"MSG_CLOSEDSM");
2835  break;
2836 
2837  case MSG_OPENDS:
2838  SSTRCPY(_szMsg,_nChars,"MSG_OPENDS");
2839  break;
2840 
2841  case MSG_CLOSEDS:
2842  SSTRCPY(_szMsg,_nChars,"MSG_CLOSEDS");
2843  break;
2844 
2845  case MSG_USERSELECT:
2846  SSTRCPY(_szMsg,_nChars,"MSG_USERSELECT");
2847  break;
2848 
2849  case MSG_DISABLEDS:
2850  SSTRCPY(_szMsg,_nChars,"MSG_DISABLEDS");
2851  break;
2852 
2853  case MSG_ENABLEDS:
2854  SSTRCPY(_szMsg,_nChars,"MSG_ENABLEDS");
2855  break;
2856 
2857  case MSG_ENABLEDSUIONLY:
2858  SSTRCPY(_szMsg,_nChars,"MSG_ENABLEDSUIONLY");
2859  break;
2860 
2861  case MSG_PROCESSEVENT:
2862  SSTRCPY(_szMsg,_nChars,"MSG_PROCESSEVENT");
2863  break;
2864 
2865  case MSG_ENDXFER:
2866  SSTRCPY(_szMsg,_nChars,"MSG_ENDXFER");
2867  break;
2868 
2869  case MSG_CHANGEDIRECTORY:
2870  SSTRCPY(_szMsg,_nChars,"MSG_CHANGEDIRECTORY");
2871  break;
2872 
2873  case MSG_CREATEDIRECTORY:
2874  SSTRCPY(_szMsg,_nChars,"MSG_CREATEDIRECTORY");
2875  break;
2876 
2877  case MSG_DELETE:
2878  SSTRCPY(_szMsg,_nChars,"MSG_DELETE");
2879  break;
2880 
2881  case MSG_FORMATMEDIA:
2882  SSTRCPY(_szMsg,_nChars,"MSG_FORMATMEDIA");
2883  break;
2884 
2885  case MSG_GETCLOSE:
2886  SSTRCPY(_szMsg,_nChars,"MSG_GETCLOSE");
2887  break;
2888 
2889  case MSG_GETFIRSTFILE:
2890  SSTRCPY(_szMsg,_nChars,"MSG_GETFIRSTFILE");
2891  break;
2892 
2893  case MSG_GETINFO:
2894  SSTRCPY(_szMsg,_nChars,"MSG_GETINFO");
2895  break;
2896 
2897  case MSG_GETNEXTFILE:
2898  SSTRCPY(_szMsg,_nChars,"MSG_GETNEXTFILE");
2899  break;
2900 
2901  case MSG_RENAME:
2902  SSTRCPY(_szMsg,_nChars,"MSG_RENAME");
2903  break;
2904 
2905  case MSG_PASSTHRU:
2906  SSTRCPY(_szMsg,_nChars,"MSG_PASSTHRU");
2907  break;
2908 
2909  case MSG_REGISTER_CALLBACK:
2910  SSTRCPY(_szMsg,_nChars,"MSG_REGISTER_CALLBACK");
2911  break;
2912 
2913  case MSG_RESETALL:
2914  SSTRCPY(_szMsg,_nChars,"MSG_RESETALL");
2915  break;
2916  }
2917 }
2918 
2919 
2920 
2921 /*
2922 * Convert a CAP_ or ICAP_ capability numerical value to a string...
2923 */
2924 void CTwnDsm::StringFromCap(char *_szCap,
2925  const int _nChars,
2926  const TW_UINT16 _Cap)
2927 {
2928  switch (_Cap)
2929  {
2930  default:
2931  SSNPRINTF(_szCap,_nChars,_nChars,"CAP_0x%04x",_Cap);
2932  break;
2933 
2934  case CAP_CUSTOMBASE:
2935  SSTRCPY(_szCap,_nChars,"CAP_CUSTOMBASE");
2936  break;
2937 
2938  case CAP_XFERCOUNT:
2939  SSTRCPY(_szCap,_nChars,"CAP_XFERCOUNT");
2940  break;
2941 
2942  case ICAP_COMPRESSION:
2943  SSTRCPY(_szCap,_nChars,"ICAP_COMPRESSION");
2944  break;
2945 
2946  case ICAP_PIXELTYPE:
2947  SSTRCPY(_szCap,_nChars,"ICAP_PIXELTYPE");
2948  break;
2949 
2950  case ICAP_UNITS:
2951  SSTRCPY(_szCap,_nChars,"ICAP_UNITS");
2952  break;
2953 
2954  case ICAP_XFERMECH:
2955  SSTRCPY(_szCap,_nChars,"ICAP_XFERMECH");
2956  break;
2957 
2958  case CAP_AUTHOR:
2959  SSTRCPY(_szCap,_nChars,"CAP_AUTHOR");
2960  break;
2961 
2962  case CAP_CAPTION:
2963  SSTRCPY(_szCap,_nChars,"CAP_CAPTION");
2964  break;
2965 
2966  case CAP_FEEDERENABLED:
2967  SSTRCPY(_szCap,_nChars,"CAP_FEEDERENABLED");
2968  break;
2969 
2970  case CAP_FEEDERLOADED:
2971  SSTRCPY(_szCap,_nChars,"CAP_FEEDERLOADED");
2972  break;
2973 
2974  case CAP_TIMEDATE:
2975  SSTRCPY(_szCap,_nChars,"CAP_TIMEDATE");
2976  break;
2977 
2978  case CAP_SUPPORTEDCAPS:
2979  SSTRCPY(_szCap,_nChars,"CAP_SUPPORTEDCAPS");
2980  break;
2981 
2982  case CAP_EXTENDEDCAPS:
2983  SSTRCPY(_szCap,_nChars,"CAP_EXTENDEDCAPS");
2984  break;
2985 
2986  case CAP_AUTOFEED:
2987  SSTRCPY(_szCap,_nChars,"CAP_AUTOFEED");
2988  break;
2989 
2990  case CAP_CLEARPAGE:
2991  SSTRCPY(_szCap,_nChars,"CAP_CLEARPAGE");
2992  break;
2993 
2994  case CAP_FEEDPAGE:
2995  SSTRCPY(_szCap,_nChars,"CAP_FEEDPAGE");
2996  break;
2997 
2998  case CAP_REWINDPAGE:
2999  SSTRCPY(_szCap,_nChars,"CAP_REWINDPAGE");
3000  break;
3001 
3002  case CAP_INDICATORS:
3003  SSTRCPY(_szCap,_nChars,"CAP_INDICATORS");
3004  break;
3005 
3006  case CAP_SUPPORTEDCAPSEXT:
3007  SSTRCPY(_szCap,_nChars,"CAP_SUPPORTEDCAPSEXT");
3008  break;
3009 
3010  case CAP_PAPERDETECTABLE:
3011  SSTRCPY(_szCap,_nChars,"CAP_PAPERDETECTABLE");
3012  break;
3013 
3014  case CAP_UICONTROLLABLE:
3015  SSTRCPY(_szCap,_nChars,"CAP_UICONTROLLABLE");
3016  break;
3017 
3018  case CAP_DEVICEONLINE:
3019  SSTRCPY(_szCap,_nChars,"CAP_DEVICEONLINE");
3020  break;
3021 
3022  case CAP_AUTOSCAN:
3023  SSTRCPY(_szCap,_nChars,"CAP_AUTOSCAN");
3024  break;
3025 
3026  case CAP_THUMBNAILSENABLED:
3027  SSTRCPY(_szCap,_nChars,"CAP_THUMBNAILSENABLED");
3028  break;
3029 
3030  case CAP_DUPLEX:
3031  SSTRCPY(_szCap,_nChars,"CAP_DUPLEX");
3032  break;
3033 
3034  case CAP_DUPLEXENABLED:
3035  SSTRCPY(_szCap,_nChars,"CAP_DUPLEXENABLED");
3036  break;
3037 
3038  case CAP_ENABLEDSUIONLY:
3039  SSTRCPY(_szCap,_nChars,"CAP_ENABLEDSUIONLY");
3040  break;
3041 
3042  case CAP_CUSTOMDSDATA:
3043  SSTRCPY(_szCap,_nChars,"CAP_CUSTOMDSDATA");
3044  break;
3045 
3046  case CAP_ENDORSER:
3047  SSTRCPY(_szCap,_nChars,"CAP_ENDORSER");
3048  break;
3049 
3050  case CAP_JOBCONTROL:
3051  SSTRCPY(_szCap,_nChars,"CAP_JOBCONTROL");
3052  break;
3053 
3054  case CAP_ALARMS:
3055  SSTRCPY(_szCap,_nChars,"CAP_ALARMS");
3056  break;
3057 
3058  case CAP_ALARMVOLUME:
3059  SSTRCPY(_szCap,_nChars,"CAP_ALARMVOLUME");
3060  break;
3061 
3062  case CAP_AUTOMATICCAPTURE:
3063  SSTRCPY(_szCap,_nChars,"CAP_AUTOMATICCAPTURE");
3064  break;
3065 
3066  case CAP_TIMEBEFOREFIRSTCAPTURE:
3067  SSTRCPY(_szCap,_nChars,"CAP_TIMEBEFOREFIRSTCAPTURE");
3068  break;
3069 
3070  case CAP_TIMEBETWEENCAPTURES:
3071  SSTRCPY(_szCap,_nChars,"CAP_TIMEBETWEENCAPTURES");
3072  break;
3073 
3074  case CAP_CLEARBUFFERS:
3075  SSTRCPY(_szCap,_nChars,"CAP_CLEARBUFFERS");
3076  break;
3077 
3078  case CAP_MAXBATCHBUFFERS:
3079  SSTRCPY(_szCap,_nChars,"CAP_MAXBATCHBUFFERS");
3080  break;
3081 
3082  case CAP_DEVICETIMEDATE:
3083  SSTRCPY(_szCap,_nChars,"CAP_DEVICETIMEDATE");
3084  break;
3085 
3086  case CAP_POWERSUPPLY:
3087  SSTRCPY(_szCap,_nChars,"CAP_POWERSUPPLY");
3088  break;
3089 
3090  case CAP_CAMERAPREVIEWUI:
3091  SSTRCPY(_szCap,_nChars,"CAP_CAMERAPREVIEWUI");
3092  break;
3093 
3094  case CAP_DEVICEEVENT:
3095  SSTRCPY(_szCap,_nChars,"CAP_DEVICEEVENT");
3096  break;
3097 
3098  case CAP_SERIALNUMBER:
3099  SSTRCPY(_szCap,_nChars,"CAP_SERIALNUMBER");
3100  break;
3101 
3102  case CAP_PRINTER:
3103  SSTRCPY(_szCap,_nChars,"CAP_PRINTER");
3104  break;
3105 
3106  case CAP_PRINTERENABLED:
3107  SSTRCPY(_szCap,_nChars,"CAP_PRINTERENABLED");
3108  break;
3109 
3110  case CAP_PRINTERINDEX:
3111  SSTRCPY(_szCap,_nChars,"CAP_PRINTERINDEX");
3112  break;
3113 
3114  case CAP_PRINTERMODE:
3115  SSTRCPY(_szCap,_nChars,"CAP_PRINTERMODE");
3116  break;
3117 
3118  case CAP_PRINTERSTRING:
3119  SSTRCPY(_szCap,_nChars,"CAP_PRINTERSTRING");
3120  break;
3121 
3122  case CAP_PRINTERSUFFIX:
3123  SSTRCPY(_szCap,_nChars,"CAP_PRINTERSUFFIX");
3124  break;
3125 
3126  case CAP_LANGUAGE:
3127  SSTRCPY(_szCap,_nChars,"CAP_LANGUAGE");
3128  break;
3129 
3130  case CAP_FEEDERALIGNMENT:
3131  SSTRCPY(_szCap,_nChars,"CAP_FEEDERALIGNMENT");
3132  break;
3133 
3134  case CAP_FEEDERORDER:
3135  SSTRCPY(_szCap,_nChars,"CAP_FEEDERORDER");
3136  break;
3137 
3138  case CAP_REACQUIREALLOWED:
3139  SSTRCPY(_szCap,_nChars,"CAP_REACQUIREALLOWED");
3140  break;
3141 
3142  case CAP_BATTERYMINUTES:
3143  SSTRCPY(_szCap,_nChars,"CAP_BATTERYMINUTES");
3144  break;
3145 
3146  case CAP_BATTERYPERCENTAGE:
3147  SSTRCPY(_szCap,_nChars,"CAP_BATTERYPERCENTAGE");
3148  break;
3149 
3150  case CAP_CAMERASIDE:
3151  SSTRCPY(_szCap,_nChars,"CAP_CAMERASIDE");
3152  break;
3153 
3154  case CAP_SEGMENTED:
3155  SSTRCPY(_szCap,_nChars,"CAP_SEGMENTED");
3156  break;
3157 
3158  case CAP_CAMERAENABLED:
3159  SSTRCPY(_szCap,_nChars,"CAP_CAMERAENABLED");
3160  break;
3161 
3162  case CAP_CAMERAORDER:
3163  SSTRCPY(_szCap,_nChars,"CAP_CAMERAORDER");
3164  break;
3165 
3166  case CAP_MICRENABLED:
3167  SSTRCPY(_szCap,_nChars,"CAP_MICRENABLED");
3168  break;
3169 
3170  case CAP_FEEDERPREP:
3171  SSTRCPY(_szCap,_nChars,"CAP_FEEDERPREP");
3172  break;
3173 
3174  case CAP_FEEDERPOCKET:
3175  SSTRCPY(_szCap,_nChars,"CAP_FEEDERPOCKET");
3176  break;
3177 
3178  case CAP_AUTOMATICSENSEMEDIUM:
3179  SSTRCPY(_szCap,_nChars,"CAP_AUTOMATICSENSEMEDIUM");
3180  break;
3181 
3182  case CAP_CUSTOMINTERFACEGUID:
3183  SSTRCPY(_szCap,_nChars,"CAP_CUSTOMINTERFACEGUID");
3184  break;
3185 
3186  case ICAP_AUTOBRIGHT:
3187  SSTRCPY(_szCap,_nChars,"ICAP_AUTOBRIGHT");
3188  break;
3189 
3190  case ICAP_BRIGHTNESS:
3191  SSTRCPY(_szCap,_nChars,"ICAP_BRIGHTNESS");
3192  break;
3193 
3194  case ICAP_CONTRAST:
3195  SSTRCPY(_szCap,_nChars,"ICAP_CONTRAST");
3196  break;
3197 
3198  case ICAP_CUSTHALFTONE:
3199  SSTRCPY(_szCap,_nChars,"ICAP_CUSTHALFTONE");
3200  break;
3201 
3202  case ICAP_EXPOSURETIME:
3203  SSTRCPY(_szCap,_nChars,"ICAP_EXPOSURETIME");
3204  break;
3205 
3206  case ICAP_FILTER:
3207  SSTRCPY(_szCap,_nChars,"ICAP_FILTER");
3208  break;
3209 
3210  case ICAP_FLASHUSED:
3211  SSTRCPY(_szCap,_nChars,"ICAP_FLASHUSED");
3212  break;
3213 
3214  case ICAP_GAMMA:
3215  SSTRCPY(_szCap,_nChars,"ICAP_GAMMA");
3216  break;
3217 
3218  case ICAP_HALFTONES:
3219  SSTRCPY(_szCap,_nChars,"ICAP_HALFTONES");
3220  break;
3221 
3222  case ICAP_HIGHLIGHT:
3223  SSTRCPY(_szCap,_nChars,"ICAP_HIGHLIGHT");
3224  break;
3225 
3226  case ICAP_IMAGEFILEFORMAT:
3227  SSTRCPY(_szCap,_nChars,"ICAP_IMAGEFILEFORMAT");
3228  break;
3229 
3230  case ICAP_LAMPSTATE:
3231  SSTRCPY(_szCap,_nChars,"ICAP_LAMPSTATE");
3232  break;
3233 
3234  case ICAP_LIGHTSOURCE:
3235  SSTRCPY(_szCap,_nChars,"ICAP_LIGHTSOURCE");
3236  break;
3237 
3238  case ICAP_ORIENTATION:
3239  SSTRCPY(_szCap,_nChars,"ICAP_ORIENTATION");
3240  break;
3241 
3242  case ICAP_PHYSICALWIDTH:
3243  SSTRCPY(_szCap,_nChars,"ICAP_PHYSICALWIDTH");
3244  break;
3245 
3246  case ICAP_PHYSICALHEIGHT:
3247  SSTRCPY(_szCap,_nChars,"ICAP_PHYSICALHEIGHT");
3248  break;
3249 
3250  case ICAP_SHADOW:
3251  SSTRCPY(_szCap,_nChars,"ICAP_SHADOW");
3252  break;
3253 
3254  case ICAP_FRAMES:
3255  SSTRCPY(_szCap,_nChars,"ICAP_FRAMES");
3256  break;
3257 
3258  case ICAP_XNATIVERESOLUTION:
3259  SSTRCPY(_szCap,_nChars,"ICAP_XNATIVERESOLUTION");
3260  break;
3261 
3262  case ICAP_YNATIVERESOLUTION:
3263  SSTRCPY(_szCap,_nChars,"ICAP_YNATIVERESOLUTION");
3264  break;
3265 
3266  case ICAP_XRESOLUTION:
3267  SSTRCPY(_szCap,_nChars,"ICAP_XRESOLUTION");
3268  break;
3269 
3270  case ICAP_YRESOLUTION:
3271  SSTRCPY(_szCap,_nChars,"ICAP_YRESOLUTION");
3272  break;
3273 
3274  case ICAP_MAXFRAMES:
3275  SSTRCPY(_szCap,_nChars,"ICAP_MAXFRAMES");
3276  break;
3277 
3278  case ICAP_TILES:
3279  SSTRCPY(_szCap,_nChars,"ICAP_TILES");
3280  break;
3281 
3282  case ICAP_BITORDER:
3283  SSTRCPY(_szCap,_nChars,"ICAP_BITORDER");
3284  break;
3285 
3286  case ICAP_CCITTKFACTOR:
3287  SSTRCPY(_szCap,_nChars,"ICAP_CCITTKFACTOR");
3288  break;
3289 
3290  case ICAP_LIGHTPATH:
3291  SSTRCPY(_szCap,_nChars,"ICAP_LIGHTPATH");
3292  break;
3293 
3294  case ICAP_PIXELFLAVOR:
3295  SSTRCPY(_szCap,_nChars,"ICAP_PIXELFLAVOR");
3296  break;
3297 
3298  case ICAP_PLANARCHUNKY:
3299  SSTRCPY(_szCap,_nChars,"ICAP_PLANARCHUNKY");
3300  break;
3301 
3302  case ICAP_ROTATION:
3303  SSTRCPY(_szCap,_nChars,"ICAP_ROTATION");
3304  break;
3305 
3306  case ICAP_SUPPORTEDSIZES:
3307  SSTRCPY(_szCap,_nChars,"ICAP_SUPPORTEDSIZES");
3308  break;
3309 
3310  case ICAP_THRESHOLD:
3311  SSTRCPY(_szCap,_nChars,"ICAP_THRESHOLD");
3312  break;
3313 
3314  case ICAP_XSCALING:
3315  SSTRCPY(_szCap,_nChars,"ICAP_XSCALING");
3316  break;
3317 
3318  case ICAP_YSCALING:
3319  SSTRCPY(_szCap,_nChars,"ICAP_YSCALING");
3320  break;
3321 
3322  case ICAP_BITORDERCODES:
3323  SSTRCPY(_szCap,_nChars,"ICAP_BITORDERCODES");
3324  break;
3325 
3326  case ICAP_PIXELFLAVORCODES:
3327  SSTRCPY(_szCap,_nChars,"ICAP_PIXELFLAVORCODES");
3328  break;
3329 
3330  case ICAP_JPEGPIXELTYPE:
3331  SSTRCPY(_szCap,_nChars,"ICAP_JPEGPIXELTYPE");
3332  break;
3333 
3334  case ICAP_TIMEFILL:
3335  SSTRCPY(_szCap,_nChars,"ICAP_TIMEFILL");
3336  break;
3337 
3338  case ICAP_BITDEPTH:
3339  SSTRCPY(_szCap,_nChars,"ICAP_BITDEPTH");
3340  break;
3341 
3342  case ICAP_BITDEPTHREDUCTION:
3343  SSTRCPY(_szCap,_nChars,"ICAP_BITDEPTHREDUCTION");
3344  break;
3345 
3346  case ICAP_UNDEFINEDIMAGESIZE:
3347  SSTRCPY(_szCap,_nChars,"ICAP_UNDEFINEDIMAGESIZE");
3348  break;
3349 
3350  case ICAP_IMAGEDATASET:
3351  SSTRCPY(_szCap,_nChars,"ICAP_IMAGEDATASET");
3352  break;
3353 
3354  case ICAP_EXTIMAGEINFO:
3355  SSTRCPY(_szCap,_nChars,"ICAP_EXTIMAGEINFO");
3356  break;
3357 
3358  case ICAP_MINIMUMHEIGHT:
3359  SSTRCPY(_szCap,_nChars,"ICAP_MINIMUMHEIGHT");
3360  break;
3361 
3362  case ICAP_MINIMUMWIDTH:
3363  SSTRCPY(_szCap,_nChars,"ICAP_MINIMUMWIDTH");
3364  break;
3365 
3366  case ICAP_AUTODISCARDBLANKPAGES:
3367  SSTRCPY(_szCap,_nChars,"ICAP_AUTODISCARDBLANKPAGES");
3368  break;
3369 
3370  case ICAP_FLIPROTATION:
3371  SSTRCPY(_szCap,_nChars,"ICAP_FLIPROTATION");
3372  break;
3373 
3374  case ICAP_BARCODEDETECTIONENABLED:
3375  SSTRCPY(_szCap,_nChars,"ICAP_BARCODEDETECTIONENABLED");
3376  break;
3377 
3378  case ICAP_SUPPORTEDBARCODETYPES:
3379  SSTRCPY(_szCap,_nChars,"ICAP_SUPPORTEDBARCODETYPES");
3380  break;
3381 
3382  case ICAP_BARCODEMAXSEARCHPRIORITIES:
3383  SSTRCPY(_szCap,_nChars,"ICAP_BARCODEMAXSEARCHPRIORITIES");
3384  break;
3385 
3386  case ICAP_BARCODESEARCHPRIORITIES:
3387  SSTRCPY(_szCap,_nChars,"ICAP_BARCODESEARCHPRIORITIES");
3388  break;
3389 
3390  case ICAP_BARCODESEARCHMODE:
3391  SSTRCPY(_szCap,_nChars,"ICAP_BARCODESEARCHMODE");
3392  break;
3393 
3394  case ICAP_BARCODEMAXRETRIES:
3395  SSTRCPY(_szCap,_nChars,"ICAP_BARCODEMAXRETRIES");
3396  break;
3397 
3398  case ICAP_BARCODETIMEOUT:
3399  SSTRCPY(_szCap,_nChars,"ICAP_BARCODETIMEOUT");
3400  break;
3401 
3402  case ICAP_ZOOMFACTOR:
3403  SSTRCPY(_szCap,_nChars,"ICAP_ZOOMFACTOR");
3404  break;
3405 
3406  case ICAP_PATCHCODEDETECTIONENABLED:
3407  SSTRCPY(_szCap,_nChars,"ICAP_PATCHCODEDETECTIONENABLED");
3408  break;
3409 
3410  case ICAP_SUPPORTEDPATCHCODETYPES:
3411  SSTRCPY(_szCap,_nChars,"ICAP_SUPPORTEDPATCHCODETYPES");
3412  break;
3413 
3414  case ICAP_PATCHCODEMAXSEARCHPRIORITIES:
3415  SSTRCPY(_szCap,_nChars,"ICAP_PATCHCODEMAXSEARCHPRIORITIES");
3416  break;
3417 
3418  case ICAP_PATCHCODESEARCHPRIORITIES:
3419  SSTRCPY(_szCap,_nChars,"ICAP_PATCHCODESEARCHPRIORITIES");
3420  break;
3421 
3422  case ICAP_PATCHCODESEARCHMODE:
3423  SSTRCPY(_szCap,_nChars,"ICAP_PATCHCODESEARCHMODE");
3424  break;
3425 
3426  case ICAP_PATCHCODEMAXRETRIES:
3427  SSTRCPY(_szCap,_nChars,"ICAP_PATCHCODEMAXRETRIES");
3428  break;
3429 
3430  case ICAP_PATCHCODETIMEOUT:
3431  SSTRCPY(_szCap,_nChars,"ICAP_PATCHCODETIMEOUT");
3432  break;
3433 
3434  case ICAP_FLASHUSED2:
3435  SSTRCPY(_szCap,_nChars,"ICAP_FLASHUSED2");
3436  break;
3437 
3438  case ICAP_IMAGEFILTER:
3439  SSTRCPY(_szCap,_nChars,"ICAP_IMAGEFILTER");
3440  break;
3441 
3442  case ICAP_NOISEFILTER:
3443  SSTRCPY(_szCap,_nChars,"ICAP_NOISEFILTER");
3444  break;
3445 
3446  case ICAP_OVERSCAN:
3447  SSTRCPY(_szCap,_nChars,"ICAP_OVERSCAN");
3448  break;
3449 
3450  case ICAP_AUTOMATICBORDERDETECTION:
3451  SSTRCPY(_szCap,_nChars,"ICAP_AUTOMATICBORDERDETECTION");
3452  break;
3453 
3454  case ICAP_AUTOMATICDESKEW:
3455  SSTRCPY(_szCap,_nChars,"ICAP_AUTOMATICDESKEW");
3456  break;
3457 
3458  case ICAP_AUTOMATICROTATE:
3459  SSTRCPY(_szCap,_nChars,"ICAP_AUTOMATICROTATE");
3460  break;
3461 
3462  case ICAP_JPEGQUALITY:
3463  SSTRCPY(_szCap,_nChars,"ICAP_JPEGQUALITY");
3464  break;
3465 
3466  case ICAP_FEEDERTYPE:
3467  SSTRCPY(_szCap,_nChars,"ICAP_FEEDERTYPE");
3468  break;
3469 
3470  case ICAP_ICCPROFILE:
3471  SSTRCPY(_szCap,_nChars,"ICAP_ICCPROFILE");
3472  break;
3473 
3474  case ICAP_AUTOSIZE:
3475  SSTRCPY(_szCap,_nChars,"ICAP_AUTOSIZE");
3476  break;
3477 
3478  case ICAP_AUTOMATICCROPUSESFRAME:
3479  SSTRCPY(_szCap,_nChars,"ICAP_AUTOMATICCROPUSESFRAME");
3480  break;
3481 
3482  case ICAP_AUTOMATICLENGTHDETECTION:
3483  SSTRCPY(_szCap,_nChars,"ICAP_AUTOMATICLENGTHDETECTION");
3484  break;
3485 
3486  case ICAP_AUTOMATICCOLORENABLED:
3487  SSTRCPY(_szCap,_nChars,"ICAP_AUTOMATICCOLORENABLED");
3488  break;
3489 
3490  case ICAP_AUTOMATICCOLORNONCOLORPIXELTYPE:
3491  SSTRCPY(_szCap,_nChars,"ICAP_AUTOMATICCOLORNONCOLORPIXELTYPE");
3492  break;
3493 
3494  case ICAP_COLORMANAGEMENTENABLED:
3495  SSTRCPY(_szCap,_nChars,"ICAP_COLORMANAGEMENTENABLED");
3496  break;
3497 
3498  case ICAP_IMAGEMERGE:
3499  SSTRCPY(_szCap,_nChars,"ICAP_IMAGEMERGE");
3500  break;
3501 
3502  case ICAP_IMAGEMERGEHEIGHTTHRESHOLD:
3503  SSTRCPY(_szCap,_nChars,"ICAP_IMAGEMERGEHEIGHTTHRESHOLD");
3504  break;
3505 
3506  case ICAP_SUPPORTEDEXTIMAGEINFO:
3507  SSTRCPY(_szCap,_nChars,"ICAP_SUPPORTEDEXTIMAGEINFO");
3508  break;
3509 
3510  case ACAP_AUDIOFILEFORMAT:
3511  SSTRCPY(_szCap,_nChars,"ACAP_AUDIOFILEFORMAT");
3512  break;
3513 
3514  case ACAP_XFERMECH:
3515  SSTRCPY(_szCap,_nChars,"ACAP_XFERMECH");
3516  break;
3517  }
3518 }
3519 
3520 
3521 
3522 /*
3523 * Convert a TWRC_ return code numerical value to a string...
3524 */
3525 void CTwnDsm::StringFromRC(char *_szRc,
3526  const int _nChars,
3527  const TW_UINT16 _rc)
3528 {
3529  switch (_rc)
3530  {
3531  default:
3532  SSNPRINTF(_szRc,_nChars,_nChars,"TWRC_0x%04x",_rc);
3533  break;
3534 
3535  case TWRC_SUCCESS:
3536  SSTRCPY(_szRc,_nChars,"TWRC_SUCCESS");
3537  break;
3538 
3539  case TWRC_FAILURE:
3540  SSTRCPY(_szRc,_nChars,"TWRC_FAILURE");
3541  break;
3542 
3543  case TWRC_CHECKSTATUS:
3544  SSTRCPY(_szRc,_nChars,"TWRC_CHECKSTATUS");
3545  break;
3546 
3547  case TWRC_CANCEL:
3548  SSTRCPY(_szRc,_nChars,"TWRC_CANCEL");
3549  break;
3550 
3551  case TWRC_DSEVENT:
3552  SSTRCPY(_szRc,_nChars,"TWRC_DSEVENT");
3553  break;
3554 
3555  case TWRC_NOTDSEVENT:
3556  SSTRCPY(_szRc,_nChars,"TWRC_NOTDSEVENT");
3557  break;
3558 
3559  case TWRC_XFERDONE:
3560  SSTRCPY(_szRc,_nChars,"TWRC_XFERDONE");
3561  break;
3562 
3563  case TWRC_ENDOFLIST:
3564  SSTRCPY(_szRc,_nChars,"TWRC_ENDOFLIST");
3565  break;
3566 
3567  case TWRC_INFONOTSUPPORTED:
3568  SSTRCPY(_szRc,_nChars,"TWRC_INFONOTSUPPORTED");
3569  break;
3570 
3571  case TWRC_DATANOTAVAILABLE:
3572  SSTRCPY(_szRc,_nChars,"TWRC_DATANOTAVAILABLE");
3573  break;
3574  }
3575 }
3576 
3577 /*
3578 * Convert a Container type to a string...
3579 */
3580 void CTwnDsm::StringFromConType(char *_szData,
3581  const int _nChars,
3582  const TW_UINT16 _ConType)
3583 {
3584  switch (_ConType)
3585  {
3586  default:
3587  SSNPRINTF(_szData,_nChars,_nChars," TWON_0x%04x",_ConType);
3588  break;
3589 
3590  case TWON_DONTCARE16:
3591  SSTRCPY(_szData,_nChars," TWON_DONTCARE16");
3592  break;
3593 
3594  case TWON_ARRAY:
3595  SSTRCPY(_szData,_nChars," TWON_ARRAY");
3596  break;
3597 
3598  case TWON_ENUMERATION:
3599  SSTRCPY(_szData,_nChars," TWON_ENUMERATION");
3600  break;
3601 
3602  case TWON_ONEVALUE:
3603  SSTRCPY(_szData,_nChars," TWON_ONEVALUE ");
3604  break;
3605 
3606  case TWON_RANGE:
3607  SSTRCPY(_szData,_nChars," TWON_RANGE");
3608  break;
3609  }
3610 }
3611 
3612 /*
3613 * Convert a Condition Code to a string...
3614 */
3616  const int _nChars,
3617  const TW_UINT16 _ConCode)
3618 {
3619  switch (_ConCode)
3620  {
3621  default:
3622  SSNPRINTF(_szData,_nChars,_nChars," TWCC_0x%04x",_ConCode);
3623  break;
3624 
3625  case TWCC_SUCCESS:
3626  SSTRCPY(_szData,_nChars," TWCC_SUCCESS");
3627  break;
3628 
3629  case TWCC_BUMMER:
3630  SSTRCPY(_szData,_nChars," TWCC_BUMMER");
3631  break;
3632 
3633  case TWCC_LOWMEMORY:
3634  SSTRCPY(_szData,_nChars," TWCC_LOWMEMORY");
3635  break;
3636 
3637  case TWCC_NODS:
3638  SSTRCPY(_szData,_nChars," TWCC_NODS");
3639  break;
3640 
3641  case TWCC_MAXCONNECTIONS:
3642  SSTRCPY(_szData,_nChars," TWCC_MAXCONNECTIONS");
3643  break;
3644 
3645  case TWCC_OPERATIONERROR:
3646  SSTRCPY(_szData,_nChars," TWCC_OPERATIONERROR");
3647  break;
3648 
3649  case TWCC_BADCAP:
3650  SSTRCPY(_szData,_nChars," TWCC_BADCAP");
3651  break;
3652 
3653  case TWCC_BADPROTOCOL:
3654  SSTRCPY(_szData,_nChars," TWCC_BADPROTOCOL");
3655  break;
3656 
3657  case TWCC_BADVALUE:
3658  SSTRCPY(_szData,_nChars," TWCC_BADVALUE");
3659  break;
3660 
3661  case TWCC_SEQERROR:
3662  SSTRCPY(_szData,_nChars," TWCC_SEQERROR");
3663  break;
3664 
3665  case TWCC_BADDEST:
3666  SSTRCPY(_szData,_nChars," TWCC_BADDEST");
3667  break;
3668 
3669  case TWCC_CAPUNSUPPORTED:
3670  SSTRCPY(_szData,_nChars," TWCC_CAPUNSUPPORTED");
3671  break;
3672 
3673  case TWCC_CAPBADOPERATION:
3674  SSTRCPY(_szData,_nChars," TWCC_CAPBADOPERATION");
3675  break;
3676 
3677  case TWCC_CAPSEQERROR:
3678  SSTRCPY(_szData,_nChars," TWCC_CAPSEQERROR");
3679  break;
3680 
3681  case TWCC_DENIED:
3682  SSTRCPY(_szData,_nChars," TWCC_DENIED");
3683  break;
3684 
3685  case TWCC_FILEEXISTS:
3686  SSTRCPY(_szData,_nChars," TWCC_FILEEXISTS");
3687  break;
3688 
3689  case TWCC_FILENOTFOUND:
3690  SSTRCPY(_szData,_nChars," TWCC_FILENOTFOUND");
3691  break;
3692 
3693  case TWCC_NOTEMPTY:
3694  SSTRCPY(_szData,_nChars," TWCC_NOTEMPTY");
3695  break;
3696 
3697  case TWCC_PAPERJAM:
3698  SSTRCPY(_szData,_nChars," TWCC_PAPERJAM");
3699  break;
3700 
3701  case TWCC_PAPERDOUBLEFEED:
3702  SSTRCPY(_szData,_nChars," TWCC_PAPERDOUBLEFEED");
3703  break;
3704 
3705  case TWCC_FILEWRITEERROR:
3706  SSTRCPY(_szData,_nChars," TWCC_FILEWRITEERROR");
3707  break;
3708 
3709  case TWCC_CHECKDEVICEONLINE:
3710  SSTRCPY(_szData,_nChars," TWCC_CHECKDEVICEONLINE");
3711  break;
3712 
3713  case TWCC_INTERLOCK:
3714  SSTRCPY(_szData,_nChars," TWCC_INTERLOCK");
3715  break;
3716 
3717  case TWCC_DAMAGEDCORNER:
3718  SSTRCPY(_szData,_nChars," TWCC_DAMAGEDCORNER");
3719  break;
3720 
3721  case TWCC_FOCUSERROR:
3722  SSTRCPY(_szData,_nChars," TWCC_FOCUSERROR");
3723  break;
3724 
3725  case TWCC_DOCTOOLIGHT:
3726  SSTRCPY(_szData,_nChars," TWCC_DOCTOOLIGHT");
3727  break;
3728 
3729  case TWCC_DOCTOODARK:
3730  SSTRCPY(_szData,_nChars," TWCC_DOCTOODARK");
3731  break;
3732 
3733  case TWCC_NOMEDIA:
3734  SSTRCPY(_szData,_nChars," TWCC_NOMEDIA");
3735  break;
3736  }
3737 }
3738 
3739 
3740 /*
3741 * Allocate memory on behalf of the caller (could be the application
3742 * or the driver)...
3743 */
3744 TW_HANDLE PASCAL DSM_MemAllocate (TW_UINT32 _bytes)
3745 {
3746  TW_HANDLE handle;
3747 
3748  // Validate...
3749  if (0 == _bytes)
3750  {
3751  kLOG((kLOGERR,"_bytes is zero..."));
3752  return (TW_HANDLE)NULL;
3753  }
3754 
3755  // Windows...
3756  #if (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP)
3757  handle = (TW_HANDLE)::GlobalAlloc(GPTR,_bytes);
3758  if (0 == handle)
3759  {
3760  kLOG((kLOGERR,"DSM_MemAllocate failed to allocate %ld bytes...",_bytes));
3761  return (TW_HANDLE)NULL;
3762  }
3763  return handle;
3764 
3765  // MacOS
3766  #elif (TWNDSM_OS == TWNDSM_OS_MACOSX)
3767  handle = (TW_HANDLE)NewHandleClear(_bytes);
3768  if (0 == handle)
3769  {
3770  kLOG((kLOGERR,"DSM_MemAllocate failed to allocate %ld bytes...",_bytes));
3771  return (TW_HANDLE)NULL;
3772  }
3773  return handle;
3774 
3775  // Linux
3776  #elif (TWNDSM_CMP == TWNDSM_CMP_GNUGPP)
3777  handle = (TW_HANDLE)calloc(_bytes,1);
3778  if (0 == handle)
3779  {
3780  kLOG((kLOGERR,"DSM_MemAllocate failed to allocate %ld bytes...",_bytes));
3781  return (TW_HANDLE)NULL;
3782  }
3783  return handle;
3784 
3785  // Oops...
3786  #else
3787  #error Sorry, we do not recognize this system...
3788  #endif
3789 }
3790 
3791 
3792 
3793 /*
3794 * Free memory on behalf of the caller (could be the application
3795 * or the driver)...
3796 */
3797 void PASCAL DSM_MemFree (TW_HANDLE _handle)
3798 {
3799  // Validate...
3800  if (0 == _handle)
3801  {
3802  kLOG((kLOGERR,"ignoring attempt to free null handle..."));
3803  return;
3804  }
3805 
3806  // Windows...
3807  #if (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP)
3808  ::GlobalFree(_handle);
3809 
3810  // MacOS
3811  #elif (TWNDSM_OS == TWNDSM_OS_MACOSX)
3812  DisposeHandle((Handle)_handle);
3813 
3814  // Linux...
3815  #elif (TWNDSM_CMP == TWNDSM_CMP_GNUGPP)
3816  free(_handle);
3817 
3818  // Oops...
3819  #else
3820  #error Sorry, we do not recognize this system...
3821  #endif
3822 }
3823 
3824 
3825 
3826 /*
3827 * Lock memory on behalf of the caller...
3828 */
3829 TW_MEMREF PASCAL DSM_MemLock (TW_HANDLE _handle)
3830 {
3831  // Validate...
3832  if (0 == _handle)
3833  {
3834  kLOG((kLOGERR,"attempting to lock null handle..."));
3835  return (TW_MEMREF)NULL;
3836  }
3837 
3838  // Windows...technically we shouldn't have to do the
3839  // lock, since we allocated with GPTR, but I'm nervous
3840  // that we might get a GHND sent to us. And since
3841  // this is a no-op for a GPTR, what they hey...
3842  #if (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP)
3843  return (TW_MEMREF)::GlobalLock(_handle);
3844 
3845  // MacOS
3846  #elif (TWNDSM_OS == TWNDSM_OS_MACOSX)
3847  return _handle ? *_handle : 0;
3848 
3849  // Linux...
3850  #elif (TWNDSM_CMP == TWNDSM_CMP_GNUGPP)
3851  return (TW_MEMREF)_handle;
3852 
3853  // Oops...
3854  #else
3855  #error Sorry, we do not recognize this system...
3856  #endif
3857 }
3858 
3859 
3860 
3861 /*
3862 * Unlock memory on behalf of the caller, if needed. This function
3863 * is a placeholder at the moment. It'll get more interesting if it
3864 * has to do locking on Mac OS/X...
3865 */
3866 void PASCAL DSM_MemUnlock (TW_HANDLE _handle)
3867 {
3868  // Validate...
3869  if (0 == _handle)
3870  {
3871  kLOG((kLOGERR,"attempting to unlock null handle..."));
3872  return;
3873  }
3874 
3875  // Windows...
3876  #if (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP)
3877  ::GlobalUnlock(_handle);
3878 
3879  // Linux...
3880  #elif (TWNDSM_CMP == TWNDSM_CMP_GNUGPP)
3881 
3882  // Oops...
3883  #else
3884  #error Sorry, we do not recognize this system...
3885  #endif
3886 }
3887 
3888 /*
3889 * This function wraps the function loading calls. Linux has a
3890 * special way to check dlsym failures.
3891 */
3892 void* DSM_LoadFunction(void* _pHandle, const char* _pszSymbol)
3893 {
3894  void* pRet = 0;
3895 #if (TWNDSM_OS == TWNDSM_OS_MACOSX)
3896  pRet = CFBundleGetFunctionPointerForName((CFBundleRef)_pHandle,
3897  CFStringCreateWithCStringNoCopy(0, _pszSymbol, kCFStringEncodingUTF8, 0));
3898 #else
3899 
3900  #if (TWNDSM_CMP == TWNDSM_CMP_GNUGPP)
3901  dlerror(); /* Clear any existing error */
3902  #endif
3903 
3904  // Try to get the entry point...
3905  pRet = LOADFUNCTION(_pHandle, _pszSymbol);
3906 
3907 #if (TWNDSM_CMP == TWNDSM_CMP_GNUGPP)
3908  char* psz_error = 0;
3909 
3910  if((psz_error = dlerror()) != NULL)
3911  {
3912  kLOG((kLOGERR,"dlsym error: %s",psz_error));
3913  pRet = 0;
3914  }
3915 #endif
3916 #endif
3917  return pRet;
3918 }
dsm.h
Everything we need to make our .cpp files happy.
CTwnDsm::SelectDlgProc
BOOL CALLBACK SelectDlgProc(HWND _hWnd, UINT _Message, WPARAM _wParam, LPARAM _lParam)
Selection dialog, for apps that don't want to do GetFirst GetNext.
Definition: dsm.cpp:1517
TwLocalize::Title
char * Title
the Title string
Definition: dsm.cpp:99
STRNICMP
#define STRNICMP
OS abstraction macro that calls system _strnicmp function.
Definition: dsm.h:297
CTwnDsmApps::AppSetConditionCode
void AppSetConditionCode(TW_IDENTITY *_pAppId, TW_UINT16 _conditioncode)
Set the condition code.
Definition: apps.cpp:647
CTwnDsmLog
Our logging class.
Definition: dsm.h:553
TW_PENDINGXFERS
Definition: twain.h:543
FOPEN
#define FOPEN(pf, name, mode)
Definition: dsm.h:300
kLOGINFO
#define kLOGINFO
write info messages to LogFile.
Definition: dsm.h:485
CTwnDsmApps::DsSetProcessingMessage
void DsSetProcessingMessage(TW_IDENTITY *_pAppId, TWID_T _DsId, TW_BOOL _Processing)
Set the ProcessingMessage flag.
Definition: apps.cpp:958
CTwnDsmApps::DsGetPath
char * DsGetPath(TW_IDENTITY *_pAppId, TWID_T _DsId)
Get a pointer to the driver file path and name, which is guaranteed to be unique, even if the Product...
Definition: apps.cpp:834
CTwnDsmApps::AddApp
TW_UINT16 AddApp(TW_IDENTITY *_pAppId, TW_MEMREF _MemRef)
Add an application.
Definition: apps.cpp:364
CTwnDsmApps::AppValidateId
TW_BOOL AppValidateId(TW_IDENTITY *_pAppId)
Validate that an id is in range...
Definition: apps.cpp:541
TwLocalize::Sources
char * Sources
the Sources string
Definition: dsm.cpp:100
TwLocalize
Localization: we have the selection box on Windows that we have to deal with, so this table gives us ...
Definition: dsm.cpp:95
CTwnDsm::_pod::m_pSelectDlgDsId
TW_IDENTITY * m_pSelectDlgDsId
The DS ID we end up with from SelectDlgProc.
Definition: dsm.h:1259
TW_EVENT
Definition: twain.h:382
CTwnDsm::DSM_Parent
TW_INT16 DSM_Parent(TW_IDENTITY *_pAppId, TW_UINT16 _MSG, TW_MEMREF _MemRef)
Initializes or closes the DSM.
Definition: dsm.cpp:726
CTwnDsmApps::DsGetIdentity
TW_IDENTITY * DsGetIdentity(TW_IDENTITY *_pAppId, TWID_T _DsId)
Get a pointer to the identity of the specified driver...
Definition: apps.cpp:785
CTwnDsm::DSM_Identity
TW_INT16 DSM_Identity(TW_IDENTITY *_pAppId, TW_UINT16 _MSG, TW_IDENTITY *_pDsId)
Source operations.
Definition: dsm.cpp:772
DllMain
BOOL WINAPI DllMain(HINSTANCE _hmodule, DWORD _dwReasonCalled, LPVOID)
DllMain is only needed for Windows, and it's only needed to collect our instance handle,...
Definition: dsm.cpp:1425
CTwnDsm::DSM_Status
TW_INT16 DSM_Status(TW_IDENTITY *_pAppId, TW_UINT16 _MSG, TW_STATUS *_pStatus)
Returns the current DSM status.
Definition: dsm.cpp:696
CTwnDsm::printTripletsInfo
bool 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)
prints to stdout information about the triplets.
Definition: dsm.cpp:2328
CTwnDsm::_pod::m_nextDsId
TWID_T m_nextDsId
The next id to test for GetFirst/GetNext...
Definition: dsm.h:1253
kLOGERR
#define kLOGERR
write error messages to LogFile.
Definition: dsm.h:490
CTwnDsmApps::DsCallbackSetWaiting
void DsCallbackSetWaiting(TW_IDENTITY *_pAppId, TWID_T _DsId, TW_BOOL _Waiting)
Set the callback flag for the driver to TRUE if the callback needs to have its callback called,...
Definition: apps.cpp:909
TW_TWUNKIDENTITY
Definition: twain.h:2094
CTwnDsm::_pod::m_DefaultDSPath
char m_DefaultDSPath[FILENAME_MAX]
The path to the default DS.
Definition: dsm.h:1248
g_ptwndsmlog
CTwnDsmLog * g_ptwndsmlog
The logging object, only access through macros.
Definition: dsm.cpp:70
CTwnDsmApps::RemoveApp
TW_UINT16 RemoveApp(TW_IDENTITY *_pAppId)
Remove an application.
Definition: apps.cpp:465
CTwnDsm::StringFromDg
void StringFromDg(char *_szDg, const int _nChars, const TW_UINT32 _DG)
Translates the _DG passed in into a string and returns it.
Definition: dsm.cpp:2560
CTwnDsm::_pod::m_pSelectDlgAppId
TW_IDENTITY * m_pSelectDlgAppId
The Application ID we're using inside of SelectDlgProc.
Definition: dsm.h:1265
TW_IDENTITY
Definition: twain.h:443
TW_ENTRYPOINT
Definition: twain.h:2221
LOADFUNCTION
#define LOADFUNCTION(lib, func)
Call system GetProcAddress function.
Definition: dsm.h:288
CTwnDsm::StringFromConditionCode
void StringFromConditionCode(char *_szCondCode, const int _nChars, const TW_UINT16 _cc)
Translates the Condition Code passed in into a string and returns it.
Definition: dsm.cpp:3615
TW_CALLBACK
Definition: twain.h:297
EnumChildProc
BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lParam)
We support a selection dialog on Windows.
Definition: dsm.cpp:1506
CTwnDsmApps::DsCallbackIsWaiting
TW_BOOL DsCallbackIsWaiting(TW_IDENTITY *_pAppId, TWID_T _DsId)
Test if the driver has a callback pending for attention...
Definition: apps.cpp:885
kLOG
#define kLOG(a)
Define to write messages to LogFile.
Definition: dsm.h:496
CTwnDsm::~CTwnDsm
~CTwnDsm()
Our CTwnDsm destructor...
Definition: dsm.cpp:428
TW_CALLBACK2
Definition: twain.h:308
DSMENTRY
#define DSMENTRY
the DSM entry point type
Definition: dsm.h:298
CTwnDsm::DSM_Callback2
TW_INT16 DSM_Callback2(TW_IDENTITY *_pAppId, TW_IDENTITY *_pDsId, TW_UINT16 _MSG, TW_CALLBACK2 *_pData)
Register application's callback.
Definition: dsm.cpp:1055
CTwnDsm::DSM_SetDefaultDS
TW_INT16 DSM_SetDefaultDS(TW_IDENTITY *_pAppId, TW_IDENTITY *_pDsId)
Set the default source.
Definition: dsm.cpp:1955
CTwnDsm::CTwnDsm
CTwnDsm()
Our CTwnDsm constructor...
Definition: dsm.cpp:395
CTwnDsmApps::DsIsProcessingMessage
TW_BOOL DsIsProcessingMessage(TW_IDENTITY *_pAppId, TWID_T _DsId)
Check if the DS is still processing last message.
Definition: apps.cpp:934
CTwnDsmApps::AppValidateIds
TW_BOOL AppValidateIds(TW_IDENTITY *_pAppId, TW_IDENTITY *_pDSId)
Validate that the App ID and DS ID are in range...
Definition: apps.cpp:561
CTwnDsmApps::AppGetConditionCode
TW_UINT16 AppGetConditionCode(TW_IDENTITY *_pAppId)
Get the condition code, then reset it internally to TWCC_SUCCESS, so you can only get it once,...
Definition: apps.cpp:619
DSM_Entry
DSMENTRY DSM_Entry(TW_IDENTITY *_pOrigin, TW_IDENTITY *_pDest, TW_UINT32 _DG, TW_UINT16 _DAT, TW_UINT16 _MSG, TW_MEMREF _pData)
Data Source Manager Entry Point.
Definition: dsm.cpp:314
CTwnDsmApps::DsIsAppProcessingCallback
TW_BOOL DsIsAppProcessingCallback(TW_IDENTITY *_pAppId, TWID_T _DsId)
Check if the App is still processing last callback.
Definition: apps.cpp:982
CTwnDsm::DSM_Entrypoint
TW_INT16 DSM_Entrypoint(TW_IDENTITY *_pAppId, TW_UINT16 _MSG, TW_ENTRYPOINT *_pEntrypoint)
Gets entry points.
Definition: dsm.cpp:893
CTwnDsmApps::LoadDS
TW_INT16 LoadDS(TW_IDENTITY *_pAppId, TWID_T _DsId)
Loads a DS from disk and adds it to a global list of DS's.
Definition: apps.cpp:1380
SSTRCAT
#define SSTRCAT(d, z, s)
Secure String catinate.
Definition: dsm.h:402
CTwnDsm::printResults
void printResults(const TW_UINT32 _DG, const TW_UINT16 _DAT, const TW_UINT16 _MSG, const TW_MEMREF _pData, const TW_UINT16 _RC)
prints to stdout information about result of processing the triplets.
Definition: dsm.cpp:2402
CTwnDsm::StringFromRC
void StringFromRC(char *_szRc, const int _nChars, const TW_UINT16 _rc)
Translates the rc passed in into a string and returns it.
Definition: dsm.cpp:3525
CTwnDsm::DSM_Null
TW_INT16 DSM_Null(TW_IDENTITY *_pAppId, TW_IDENTITY *_pDsId, TW_UINT16 _MSG)
Handles DAT_NULL calls from DS for Application.
Definition: dsm.cpp:2453
dsmState_Open
@ dsmState_Open
Source Manager is open.
Definition: dsm.h:534
CTwnDsmApps::AppGetNumDs
TWID_T AppGetNumDs(TW_IDENTITY *_pAppId)
Get the number of drivers we found as the result of a successful call to LoadDS with _boolKeepOpen se...
Definition: apps.cpp:762
SSTRCPY
#define SSTRCPY(d, z, s)
Secure String copy.
Definition: dsm.h:401
CTwnDsm::DSM_GetFirst
TW_INT16 DSM_GetFirst(TW_IDENTITY *_pAppId, TW_IDENTITY *_pDsId)
Copies the applications first available source into _pDsId.
Definition: dsm.cpp:2113
g_hinstance
HINSTANCE g_hinstance
Windows Instance handle for the DSM DLL...
Definition: dsm.cpp:68
CTwnDsm::OpenDS
TW_INT16 OpenDS(TW_IDENTITY *_pAppId, TW_IDENTITY *_pDsId)
Opens the Data Source specified by pDSIdentity.
Definition: dsm.cpp:1134
CTwnDsmApps::DsGetEntryProc
DSENTRYPROC DsGetEntryProc(TW_IDENTITY *_pAppId, TWID_T _DsId)
Get a pointer to the DS_Entry function of the specified driver...
Definition: apps.cpp:809
CTwnDsmApps::DsCallback2Get
TW_CALLBACK2 * DsCallback2Get(TW_IDENTITY *_pAppId, TWID_T _DsId)
Get a pointer to TW_CALLBACK structure for the specified driver...
Definition: apps.cpp:860
TwLocalize::Select
char * Select
the Select string
Definition: dsm.cpp:101
CTwnDsm::StringFromMsg
void StringFromMsg(char *_szMsg, const int _nChars, const TW_UINT16 _MSG)
Translates the _MSG passed in into a string and returns it.
Definition: dsm.cpp:2749
kPANIC
#define kPANIC(msg)
Display message to user.
Definition: dsm.h:508
SelectDlgProc
BOOL CALLBACK SelectDlgProc(HWND _hWnd, UINT _Message, WPARAM _wParam, LPARAM _lParam)
We support a selection dialog on Windows.
Definition: dsm.cpp:1472
g_ptwndsm
CTwnDsm * g_ptwndsm
The main DSM object.
Definition: dsm.cpp:69
CTwnDsm::DSM_GetNext
TW_INT16 DSM_GetNext(TW_IDENTITY *_pAppId, TW_IDENTITY *_pDsId)
Copies the applications next available source into _pDsId.
Definition: dsm.cpp:2158
CTwnDsmApps::UnloadDS
void UnloadDS(TW_IDENTITY *_pAppId, TWID_T _DsId)
Unloads a DS and frees all its resources...
Definition: apps.cpp:1853
CTwnDsmApps::DsSetAppProcessingCallback
void DsSetAppProcessingCallback(TW_IDENTITY *_pAppId, TWID_T _DsId, TW_BOOL _Processing)
Set the AppProcessingCallback flag.
Definition: apps.cpp:1005
CTwnDsm::CloseDS
TW_INT16 CloseDS(TW_IDENTITY *_pAppId, TW_IDENTITY *_pDsId)
Closes the Data Source specified by pDSIdentity.
Definition: dsm.cpp:1348
TW_CAPABILITY
Definition: twain.h:315
CTwnDsm::DSM_Callback
TW_INT16 DSM_Callback(TW_IDENTITY *_pAppId, TW_IDENTITY *_pDsId, TW_UINT16 _MSG, TW_CALLBACK *_pData)
Register application's callback.
Definition: dsm.cpp:973
CTwnDsm::DSMGetState
DSM_State DSMGetState()
Get the state of the DSM by checking the state of all applications.
Definition: dsm.cpp:683
CTwnDsmApps::AppHwnd
void * AppHwnd(TW_IDENTITY *_pAppId)
Get the hwnd sent in with the call to MSG_OPENDSM.
Definition: apps.cpp:740
CTwnDsm::GetMatchingDefault
TW_INT16 GetMatchingDefault(TW_IDENTITY *_pAppId, TW_IDENTITY *_pDsId)
This routine will check if the current default source matches the applications supported groups.
Definition: dsm.cpp:2199
CTwnDsm::StringFromConType
void StringFromConType(char *_szConType, const int _nChars, const TW_UINT16 _ConType)
Translates the _ConType and _hContainer passed in into a string and returns it.
Definition: dsm.cpp:3580
CTwnDsm::DSM_Entry
TW_UINT16 DSM_Entry(TW_IDENTITY *_pOrigin, TW_IDENTITY *_pDest, TW_UINT32 _DG, TW_UINT16 _DAT, TW_UINT16 _MSG, TW_MEMREF _pData)
The guts of the DSM_Entry, the resource management portion resides in a our DSM_Entry entry point,...
Definition: dsm.cpp:447
CTwnDsmApps::AppGetNumApp
TWID_T AppGetNumApp()
Get number of allocated App slots (Last valid App ID +1)
Definition: apps.cpp:729
CTwnDsmApps::AppWakeup
void AppWakeup(TW_IDENTITY *_pAppId)
Poke the application to wake it up when sending a DAT_NULL message to it...
Definition: apps.cpp:1893
CTwnDsm::_pod::m_ptwndsmapps
CTwnDsmApps * m_ptwndsmapps
The class takes care of our list of applications and drivers.
Definition: dsm.h:1241
CTwnDsmLog::Indent
void Indent(int nChange)
Indent the logging to help with seeing recursive calls param[in] nChange Either +1 or -1.
Definition: log.cpp:302
TwLocalize::CharSet
BYTE CharSet
Character Set.
Definition: dsm.cpp:97
CTwnDsmApps::AppGetState
DSM_State AppGetState()
Get the state of the DSM for all applications.
Definition: apps.cpp:688
s_twlocalize
static TwLocalize s_twlocalize[]
Localized strings for the select dialog.
Definition: dsm.cpp:108
CTwnDsm::GetDSFromProductName
TW_INT16 GetDSFromProductName(TW_IDENTITY *_pAppId, TW_IDENTITY *_pDsId)
Goes through the applications supported data sources looking for one that has the exact same name as ...
Definition: dsm.cpp:2072
TwLocalize::LangId
LANGID LangId
Language Id.
Definition: dsm.cpp:98
CTwnDsm::StringFromDat
void StringFromDat(char *_szDat, const int _nChars, const TW_UINT16 _DAT)
Translates the _DAT passed in into a string and returns it.
Definition: dsm.cpp:2589
TW_STATUS
Definition: twain.h:587
CTwnDsm::DSM_SelectDS
TW_INT16 DSM_SelectDS(TW_IDENTITY *_pAppId, TW_IDENTITY *_pDsId)
Displays the source select dialog and sets the default source.
Definition: dsm.cpp:1800
CTwnDsm::StringFromCap
void StringFromCap(char *_szCap, const int _nChars, const TW_UINT16 _Cap)
Translates the _Cap passed in into a string and returns it.
Definition: dsm.cpp:2924
DSM_State
DSM_State
Possible States of the DSM.
Definition: dsm.h:531
CTwnDsm::DSM_TwunkIdentity
TW_INT16 DSM_TwunkIdentity(TW_IDENTITY *_pAppId, TW_UINT16 _MSG, TW_TWUNKIDENTITY *_pTwunkId)
This routine will return the path to a DS.
Definition: dsm.cpp:843
DSM_LoadFunction
void * DSM_LoadFunction(void *_pHandle, const char *_pszSymbol)
This function wraps the function loading calls.
Definition: dsm.cpp:3892
CTwnDsm
This is the main class for the Data Source Manager.
Definition: dsm.h:861
TwLocalize::Language
TW_INT16 Language
Language.
Definition: dsm.cpp:96
TwLocalize::Cancel
char * Cancel
the Cancel string
Definition: dsm.cpp:102
NCHARS
#define NCHARS(s)
The number of characters in a charter array.
Definition: dsm.h:285
CTwnDsm::pod
struct CTwnDsm::_pod pod
Pieces of Data for the DSM class.
CTwnDsmApps::AppGetIdentity
TW_IDENTITY * AppGetIdentity(TW_IDENTITY *_pAppId)
Return a pointer to the application's identity.
Definition: apps.cpp:598
MAX_NUM_DS
#define MAX_NUM_DS
Maximum number of Data Sources that can be opened under one application.
Definition: dsm.h:521
CTwnDsmApps
Class to hold list of connected applications.
Definition: dsm.h:610