49 char szPath[FILENAME_MAX];
70 TW_UINT16 ProtocolMajor;
71 TW_UINT16 ProtocolMinor;
73 TW_STR32 Manufacturer;
74 TW_STR32 ProductFamily;
162 kLOG((
kLOGERR,
"realloc of m_pList failed AppId = %d",AppId));
181 if((AppId==0) || (AppId>=
m_count))
189 for(TWID_T i=
m_count-1; i>0;i--)
200 kLOG((
kLOGERR,
"realloc of m_pList failed AppId = %d",AppId));
290 TW_UINT16 _ConditionCode);
319 kLOG((
kLOGERR,
"new of CTwnDsmAppsImpl failed..."));
341 kLOG((
kLOGINFO,
"The Application, \"%0.32s\", has left the DSM in an open state when it was unloaded!",
368 char szDsm[FILENAME_MAX];
371 if (_pAppId->ProductName[0] == 0)
380 memset(szDsm,0,
sizeof(szDsm));
383 kLOG((
kLOGINFO,
"Application: \"%0.32s\"", _pAppId->Manufacturer));
385 kLOG((
kLOGINFO,
" \"%0.32s\" version: %u.%u", _pAppId->ProductName, _pAppId->Version.MajorNum, _pAppId->Version.MinorNum));
386 kLOG((
kLOGINFO,
" TWAIN %u.%u", _pAppId->ProtocolMajor, _pAppId->ProtocolMinor));
397 kLOG((
kLOGERR,
"A successful MSG_OPENDSM was already done for %s...",_pAppId->ProductName));
414 _pAppId->Id = (TWIDDEST_T)ii;
415 _pAppId->SupportedGroups |= DF_DSM2;
421 kLOG((
kLOGERR,
"calloc failed for %s...",_pAppId->ProductName));
427 #if (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP)
428 (void)::GetWindowsDirectory(szDsm,
sizeof(szDsm));
429 SSTRCAT(szDsm,
sizeof(szDsm),
"\\");
431 #elif (TWNDSM_CMP == TWNDSM_CMP_GNUGPP)
434 #error Sorry, we do not recognize this system...
450 if (_pAppId->SupportedGroups & DF_APP2)
452 _pAppId->SupportedGroups |= DF_DSM2;
473 if ( ((TWID_T)_pAppId->Id ==0)
476 kLOG((
kLOGERR,
"_id is out of range...%d",(
int)(TWID_T)_pAppId->Id));
489 kLOG((
kLOGINFO,
"%0.32s not open.",(
char*)_pAppId->ProductName));
508 kLOG((
kLOGERR,
"MSG_CLOSEDSM called with drivers still open."));
509 kLOG((
kLOGINFO,
"The application should not be doing this."));
510 kLOG((
kLOGINFO,
"The DSM is going to try to gracefully shutdown the drivers..."));
512 memset(&twpendingxfers,0,
sizeof(twpendingxfers));
513 memset(&twuserinterface,0,
sizeof(twuserinterface));
515 pDSInfo->
DS_Entry(_pAppId,DG_CONTROL,DAT_PENDINGXFERS,MSG_ENDXFER,(TW_MEMREF)&twpendingxfers);
516 pDSInfo->
DS_Entry(_pAppId,DG_CONTROL,DAT_PENDINGXFERS,MSG_RESET,(TW_MEMREF)&twpendingxfers);
517 pDSInfo->
DS_Entry(_pAppId,DG_CONTROL,DAT_USERINTERFACE,MSG_DISABLEDS,(TW_MEMREF)&twuserinterface);
518 pDSInfo->
DS_Entry(_pAppId,DG_CONTROL,DAT_IDENTITY,MSG_CLOSEDS,(TW_MEMREF)&pDSInfo->
Identity);
550 kLOG((
kLOGERR,
"invalid App ID...%d",(
int)(TWID_T)_pAppId->Id));
576 kLOG((
kLOGERR,
"invalid DS ID...%d",(
int)(TWID_T)_pDSId->Id));
621 TW_UINT16 conditioncode;
629 return conditioncode;
636 return conditioncode;
648 TW_UINT16 _ConditionCode)
661 TW_UINT16 _ConditionCode)
665 || (0 == (TWID_T)_pAppId->Id)
666 || (0 ==
m_AppInfo[(TWID_T)_pAppId->Id].identity.Id))
674 m_AppInfo[(TWID_T)_pAppId->Id].ConditionCode = _ConditionCode;
678 if (_ConditionCode != TWCC_SUCCESS)
798 kLOG((
kLOGERR,
"Returning NULL from DsGetIdentity..."));
822 kLOG((
kLOGERR,
"Returning NULL from DsGetEntryProc..."));
847 kLOG((
kLOGERR,
"Returning NULL from DsGetPath..."));
873 kLOG((
kLOGERR,
"Returning NULL from DsCallbackGet..."));
898 kLOG((
kLOGERR,
"Returning FALSE from DsCallbackIsWaiting..."));
923 kLOG((
kLOGERR,
"Unable to properly handle DsCallbackSetWaiting..."));
947 kLOG((
kLOGERR,
"Returning FALSE from DsIsProcessingMessage..."));
972 kLOG((
kLOGERR,
"Unable to properly handle DsSetProcessingMessage..."));
995 kLOG((
kLOGERR,
"Returning FALSE from DsIsAppProcessingCallback..."));
1007 TW_BOOL _Processing)
1019 kLOG((
kLOGERR,
"Unable to properly handle DsSetAppProcessingCallback..."));
1032 return "TWRC_SUCCESS";
1036 return "Failure due to unknown causes";
1039 case TWCC_LOWMEMORY:
1040 return "Not enough memory to perform operation";
1044 return "No Data Source";
1047 case TWCC_MAXCONNECTIONS:
1048 return "DS is connected to max possible applications";
1051 case TWCC_OPERATIONERROR:
1052 return "DS or DSM reported error, application shouldn't display an error";
1056 return "Unknown capability";
1059 case TWCC_BADPROTOCOL:
1060 return "Unrecognized MSG DG DAT combination";
1064 return "Data parameter out of range";
1068 return "DG DAT MSG out of expected sequence";
1072 return "Unknown destination Application/Source in DSM_Entry";
1075 case TWCC_CAPUNSUPPORTED:
1076 return "Capability not supported by source";
1079 case TWCC_CAPBADOPERATION:
1080 return "Operation not supported by capability";
1083 case TWCC_CAPSEQERROR:
1084 return "Capability has dependancy on other capability";
1088 return "File System operation is denied (file is protected)";
1091 case TWCC_FILEEXISTS:
1092 return "Operation failed because file already exists.";
1095 case TWCC_FILENOTFOUND:
1096 return "File not found";
1100 return "Operation failed because directory is not empty";
1104 return "The feeder is jammed";
1107 case TWCC_PAPERDOUBLEFEED:
1108 return "The feeder detected multiple pages";
1111 case TWCC_FILEWRITEERROR:
1112 return "Error writing the file (meant for things like disk full conditions)";
1115 case TWCC_CHECKDEVICEONLINE:
1116 return "The device went offline prior to or during this operation";
1120 static TW_STR32 hex;
1121 SSNPRINTF((
char*)hex,
NCHARS(hex), 32,
"TWCC 0x%04x", cc);
1144 return EXIT_FAILURE;
1150 #if (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP)
1151 WIN32_FIND_DATA FileData;
1153 char szABSFilename[FILENAME_MAX];
1154 BOOL bFinished = FALSE;
1155 char szPrevWorkDir[FILENAME_MAX];
1160 hSearch = FindFirstFile(szABSFilename,&FileData);
1163 if (hSearch != INVALID_HANDLE_VALUE)
1166 char *szResult = _getcwd( szPrevWorkDir,
sizeof(szPrevWorkDir) );
1167 if (szResult == (
char*)NULL)
1169 return EXIT_FAILURE;
1171 int iResult = _chdir(_szAbsPath);
1174 return EXIT_FAILURE;
1179 if (SSNPRINTF(szABSFilename,
NCHARS(szABSFilename), FILENAME_MAX,
"%s\\%s", _szAbsPath, FileData.cFileName) > 0)
1181 if (TWRC_SUCCESS ==
LoadDS(_pAppId,
1183 m_AppInfo[(TWID_T)_pAppId->Id].pDSList->NumFiles+1,
1186 m_AppInfo[(TWID_T)_pAppId->Id].pDSList->NumFiles++;
1190 if (!FindNextFile(hSearch, &FileData))
1196 if (!FindClose (hSearch))
1198 (void)_chdir( szPrevWorkDir );
1199 return EXIT_FAILURE;
1206 hSearch = FindFirstFile(szABSFilename, &FileData);
1208 if (hSearch == INVALID_HANDLE_VALUE)
1210 (void)_chdir( szPrevWorkDir );
1211 return EXIT_FAILURE;
1215 if ( (strcmp(
".", FileData.cFileName) != 0)
1216 && (strcmp(
"..", FileData.cFileName) != 0)
1217 && (FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
1219 if (SSNPRINTF(szABSFilename,
NCHARS(szABSFilename), FILENAME_MAX,
"%s\\%s", _szAbsPath, FileData.cFileName) > 0)
1225 if (!FindNextFile(hSearch, &FileData))
1231 (void)_chdir( szPrevWorkDir );
1233 if (!FindClose (hSearch))
1235 return EXIT_FAILURE;
1238 return EXIT_SUCCESS;
1245 #elif (TWNDSM_CMP == TWNDSM_CMP_GNUGPP)
1246 #if (TWNDSM_OS == TWNDSM_OS_MACOSX)
1248 char szABSFilename[FILENAME_MAX];
1253 memset(szABSFilename,0,
sizeof(szABSFilename));
1256 if ((pdir=opendir(_szAbsPath)) == 0)
1259 return EXIT_FAILURE;
1262 struct dirent *pfile;
1263 while(errno=0, ((pfile=readdir(pdir)) != 0))
1265 if ( (strcmp(
".", pfile->d_name) == 0)
1266 || (strcmp(
"..", pfile->d_name) == 0) )
1271 if (
SNPRINTF(szABSFilename,FILENAME_MAX,
"%s/%s",_szAbsPath,pfile->d_name) < 0)
1277 if (lstat(szABSFilename, &st) < 0)
1283 if (S_ISDIR(st.st_mode) && (0 != strstr(pfile->d_name,
".ds")))
1285 if (TWRC_SUCCESS ==
LoadDS(_pAppId,
1287 m_AppInfo[(TWID_T)_pAppId->Id].pDSList->NumFiles+1,
1290 m_AppInfo[(TWID_T)_pAppId->Id].pDSList->NumFiles++;
1301 return EXIT_SUCCESS;
1305 char szABSFilename[FILENAME_MAX];
1310 memset(szABSFilename,0,
sizeof(szABSFilename));
1313 if ((pdir=opendir(_szAbsPath)) == 0)
1316 return EXIT_FAILURE;
1319 struct dirent *pfile;
1320 while(errno=0, ((pfile=readdir(pdir)) != 0))
1322 if ( (strcmp(
".", pfile->d_name) == 0)
1323 || (strcmp(
"..", pfile->d_name) == 0) )
1328 if (
SNPRINTF(szABSFilename,FILENAME_MAX,
"%s/%s",_szAbsPath,pfile->d_name) < 0)
1334 if (lstat(szABSFilename, &st) < 0)
1340 if (S_ISDIR(st.st_mode))
1344 else if (S_ISREG(st.st_mode) && (0 != strstr(pfile->d_name,
".ds")))
1346 if (TWRC_SUCCESS ==
LoadDS(_pAppId,
1348 m_AppInfo[(TWID_T)_pAppId->Id].pDSList->NumFiles+1,
1351 m_AppInfo[(TWID_T)_pAppId->Id].pDSList->NumFiles++;
1362 return EXIT_SUCCESS;
1370 #error Sorry, we do not recognize this system...
1388 #if (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP)
1392 char szPrevWorkDir[FILENAME_MAX];
1393 char szWorkDir[FILENAME_MAX];
1397 size_t x = strlen(szWorkDir);
1408 memset( szPrevWorkDir, 0,
NCHARS(szPrevWorkDir) );
1409 szResult = _getcwd( szPrevWorkDir,
NCHARS(szPrevWorkDir) );
1414 (void)_chdir( szWorkDir );
1421 #if (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP)
1422 if(0!=strlen(szPrevWorkDir))
1424 (void)_chdir( szPrevWorkDir );
1432 kLOG((
kLOGERR,
"Returning TWRC_FAILURE from LoadDS..."));
1433 return TWRC_FAILURE;
1451 TW_INT16 result = TWRC_SUCCESS;
1463 return TWRC_FAILURE;
1470 return TWRC_FAILURE;
1477 #if (TWNDSM_OS == TWNDSM_OS_LINUX)
1478 bool blSuccess =
false;
1479 char szData[2048] = { 0 };
1480 snprintf(szData,
sizeof(szData),
"file \"%s\"", _pPath);
1481 FILE *pf = popen(szData,
"r");
1485 size_t sizet = fread(szData, 1,
sizeof(szData), pf);
1487 #if (TWNDSM_OS_64BIT == 1)
1488 blSuccess = (strstr(szData,
"x86-64") != 0);
1490 blSuccess = (strstr(szData,
"Intel 80386") != 0);
1497 kLOG((
kLOGINFO,
"driver doesn't support architecture: %s", _pPath));
1499 return TWRC_FAILURE;
1507 #if (TWNDSM_OS == TWNDSM_OS_MACOSX)
1508 bool blSuccess =
false;
1509 char szData[2048] = { 0 };
1510 snprintf(szData,
sizeof(szData),
"file \"%s/Contents/MacOS/$(/usr/libexec/PlistBuddy -c 'Print CFBundleExecutable' '%s/Contents/Info.plist')\"", _pPath, _pPath);
1511 FILE *pf = popen(szData,
"r");
1515 size_t sizet = fread(szData, 1,
sizeof(szData), pf);
1517 #if (TWNDSM_OS_64BIT == 1)
1518 blSuccess = (strstr(szData,
"x86_64") != 0);
1520 blSuccess = (strstr(szData,
"i386") != 0);
1527 kLOG((
kLOGINFO,
"driver doesn't support architecture: %s", _pPath));
1529 return TWRC_FAILURE;
1534 pDSInfo = &
m_AppInfo[(TWID_T)_pAppId->Id].pDSList->DSInfo[_DsId];
1548 hook = _boolKeepOpen && !(pDSInfo->
Identity.SupportedGroups & DF_DS2);
1553 #if (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP)
1556 kLOG((
kLOGERR,
"Could not load library: %s",_pPath));
1558 return TWRC_FAILURE;
1560 #elif (TWNDSM_CMP == TWNDSM_CMP_GNUGPP)
1567 fprintf(stderr,
">>> error loading <%s>\r\n",_pPath);
1568 fprintf(stderr,
">>> %s\r\n",dlerror());
1569 fprintf(stderr,
">>> please contact your scanner or driver vendor for more\r\n");
1570 fprintf(stderr,
">>> help, if that doesn't help then check out the FAQ at\r\n");
1571 fprintf(stderr,
">>> http://www.twain.org\r\n");
1572 kLOG((
kLOGERR,
"Could not load library: %s",_pPath));
1575 return TWRC_FAILURE;
1578 #error Sorry, we do not recognize this system...
1586 #if (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP)
1588 if (0 != strstr(_pPath,
"wiatwain.ds"))
1590 kLOG((
kLOGERR,
"We're deliberately skipping this file: %s", _pPath));
1594 pDSInfo->
DS_Entry = (DSENTRYPROC)GetProcAddress((HMODULE)pDSInfo->
pHandle, MAKEINTRESOURCE(1));
1598 kLOG((
kLOGINFO,
"Could not find Entry 1 in DS: %s", _pPath));
1602 kLOG((
kLOGERR,
"Could not find DS_Entry function in DS: %s", _pPath));
1609 return TWRC_FAILURE;
1625 memset(&szUseAppid, 0,
sizeof(szUseAppid));
1626 SGETENV(szUseAppid,
NCHARS(szUseAppid),
"TWAINDSM_USEAPPID");
1628 if (szUseAppid[0] != 0)
1630 #if (TWNDSM_OS == TWNDSM_OS_WINDOWS)
1631 szUseAppid[0] =
'0';
1632 #elif (TWNDSM_OS == TWNDSM_OS_LINUX)
1633 szUseAppid[0] =
'1';
1634 #elif (TWNDSM_OS == TWNDSM_OS_MACOSX)
1635 szUseAppid[0] =
'1';
1641 else if (szUseAppid[0] !=
'0')
1643 szUseAppid[0] =
'1';
1647 kLOG((
kLOGINFO,
"Loaded library: %s (TWAINDSM_USEAPPID:%c)", _pPath, szUseAppid[0]));
1648 pDSInfo->
Identity.Id = (TWIDDEST_T)_DsId;
1660 memset(&twidentitylinux64safe, 0,
sizeof(twidentitylinux64safe));
1661 twidentitylinux64safe.twidentity.Id = (TWIDDEST_T)_DsId;
1662 if (szUseAppid[0] ==
'1')
1665 result = pDSInfo->
DS_Entry(_pAppId, DG_CONTROL, DAT_IDENTITY, MSG_GET, (TW_MEMREF)&twidentitylinux64safe);
1670 result = pDSInfo->
DS_Entry(NULL, DG_CONTROL, DAT_IDENTITY, MSG_GET, (TW_MEMREF)&twidentitylinux64safe);
1672 if (result != TWRC_SUCCESS)
1677 kLOG((
kLOGINFO,
"DG_CONTROL,DAT_IDENTITY,MSG_GET failed"));
1679 return TWRC_FAILURE;
1697 #if (TWNDSM_OS == TWNDSM_OS_LINUX) && (TWNDSM_OS_64BIT == 1)
1698 if ( ((twidentitylinux64safe.twidentity.SupportedGroups & (DG_CONTROL | DG_IMAGE)) == (DG_CONTROL | DG_IMAGE))
1699 && (((twidentitylinux64safe.twidentity.ProtocolMajor >= 3) && (twidentitylinux64safe.twidentity.ProtocolMinor <= 9))
1700 || ((twidentitylinux64safe.twidentity.ProtocolMajor == 2) && (twidentitylinux64safe.twidentity.ProtocolMinor >= 4) && (twidentitylinux64safe.twidentity.ProtocolMinor <= 9))
1701 || ((twidentitylinux64safe.twidentity.ProtocolMajor == 1) && (twidentitylinux64safe.twidentity.ProtocolMinor == 5))
1702 || ((twidentitylinux64safe.twidentity.ProtocolMajor == 1) && (twidentitylinux64safe.twidentity.ProtocolMinor == 6))
1703 || ((twidentitylinux64safe.twidentity.ProtocolMajor == 1) && (twidentitylinux64safe.twidentity.ProtocolMinor == 7))
1704 || ((twidentitylinux64safe.twidentity.ProtocolMajor == 1) && (twidentitylinux64safe.twidentity.ProtocolMinor == 8))
1705 || ((twidentitylinux64safe.twidentity.ProtocolMajor == 1) && (twidentitylinux64safe.twidentity.ProtocolMinor == 9))
1706 || ((twidentitylinux64safe.twidentity.ProtocolMajor == 1) && (twidentitylinux64safe.twidentity.ProtocolMinor == 91))
1707 || ((twidentitylinux64safe.twidentity.ProtocolMajor == 2) && (twidentitylinux64safe.twidentity.ProtocolMinor == 0))
1708 || ((twidentitylinux64safe.twidentity.ProtocolMajor == 2) && (twidentitylinux64safe.twidentity.ProtocolMinor == 1))
1709 || ((twidentitylinux64safe.twidentity.ProtocolMajor == 2) && (twidentitylinux64safe.twidentity.ProtocolMinor == 2))
1710 || ((twidentitylinux64safe.twidentity.ProtocolMajor == 2) && (twidentitylinux64safe.twidentity.ProtocolMinor == 3))))
1719 kLOG((
kLOGINFO,
"DG_CONTROL,DAT_IDENTITY,MSG_GET failed (rejected as old 64-bit TW_INT32/TW_UINT32)"));
1721 return TWRC_FAILURE;
1727 memcpy(&pDSInfo->
Identity, &twidentitylinux64safe.twidentity,
sizeof(pDSInfo->
Identity));
1732 if ( !( (_pAppId->SupportedGroups & DG_MASK & ~DG_CONTROL)
1733 & (pDSInfo->
Identity.SupportedGroups & DG_MASK & ~DG_CONTROL) ) )
1740 return TWRC_FAILURE;
1746 pDSInfo->
Identity.Id = (TWIDDEST_T)_DsId;
1747 if (pDSInfo->
szPath != _pPath)
1778 if (_boolKeepOpen ==
true)
1781 #if (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP)
1784 kLOG((
kLOGERR,
"Could not load library: %s",_pPath));
1786 return TWRC_FAILURE;
1788 #elif (TWNDSM_CMP == TWNDSM_CMP_GNUGPP)
1795 fprintf(stderr,
">>> error loading <%s>\r\n",_pPath);
1796 fprintf(stderr,
">>> %s\r\n",dlerror());
1797 fprintf(stderr,
">>> please contact your scanner or driver vendor for more\r\n");
1798 fprintf(stderr,
">>> help, if that doesn't help then check out the FAQ at\r\n");
1799 fprintf(stderr,
">>> http://www.twain.org\r\n");
1800 kLOG((
kLOGERR,
"Could not load library: %s",_pPath));
1803 return TWRC_FAILURE;
1806 #error Sorry, we do not recognize this system...
1813 #if (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP)
1815 if(0 != strstr(_pPath,
"wiatwain.ds"))
1817 kLOG((
kLOGERR,
"We're deliberately skipping this file: %s",_pPath));
1821 pDSInfo->
DS_Entry = (DSENTRYPROC)GetProcAddress((HMODULE)pDSInfo->
pHandle, MAKEINTRESOURCE(1));
1825 kLOG((
kLOGINFO,
"Could not find Entry 1 in DS: %s",_pPath));
1829 kLOG((
kLOGERR,
"Could not find DS_Entry function in DS: %s",_pPath));
1836 return TWRC_FAILURE;
1868 #if (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP)
1895 #if (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP)
1908 #elif (TWNDSM_CMP == TWNDSM_CMP_GNUGPP)
1909 kLOG((
kLOGERR,
"We shouldn't be here in AppWakeup..."));
1913 void *unused = _pAppId;
1916 #error Sorry, we do not recognize this system...