windows-nt/Source/XPSP1/NT/base/ntsetup/win95upg/w95upg/common9x/twain.c

351 lines
7.2 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1998 Microsoft Corporation
Module Name:
twain.c
Abstract:
Enumeration routines for TWAIN data sources.
Author:
Jim Schmidt (jimschm) 13-Aug-1998
Revision History:
--*/
#include "pch.h"
VOID
pSplitDataIntoWords (
IN PCTSTR Data,
OUT PWORD LeftWord,
OUT PWORD RightWord
)
{
INT a, b;
PCTSTR p;
a = _ttoi (Data);
p = _tcschr (Data, TEXT('.'));
if (!p) {
b = 0;
} else {
b = _ttoi (p + 1);
}
*LeftWord = (WORD) a;
*RightWord = (WORD) b;
}
BOOL
pGetDsInfo16 (
IN PCTSTR DsPath,
OUT TW_IDENTITY *Id
)
{
CHAR CmdLine[MAX_CMDLINE];
STARTUPINFO si;
PROCESS_INFORMATION pi;
BOOL ProcessResult;
DWORD rc;
PSTR Data;
Data = CmdLine;
//
// Launch TWID.EXE
//
wsprintf (CmdLine, TEXT("\"%s\\TWID.EXE\" %s"), g_UpgradeSources, DsPath);
ZeroMemory (&si, sizeof (si));
si.cb = sizeof (si);
si.dwFlags = STARTF_FORCEOFFFEEDBACK;
ProcessResult = CreateProcessA (
NULL,
CmdLine,
NULL,
NULL,
FALSE,
CREATE_DEFAULT_ERROR_MODE,
NULL,
g_WinDir,
&si,
&pi
);
if (ProcessResult) {
CloseHandle (pi.hThread);
} else {
LOG ((LOG_ERROR, "Cannot start %s", CmdLine));
return FALSE;
}
rc = WaitForSingleObject (pi.hProcess, 10000);
if (rc != WAIT_OBJECT_0) {
TerminateProcess (pi.hProcess, 0);
}
CloseHandle (pi.hProcess);
//
// If process terminated, look for win.ini section
//
if (rc == WAIT_OBJECT_0) {
ZeroMemory (Id, sizeof (TW_IDENTITY));
GetProfileString (
TEXT("$TWAINDSINFO$"),
TEXT("Version"),
TEXT("1.0"),
Data,
32
);
pSplitDataIntoWords (Data, &Id->Version.MajorNum, &Id->Version.MinorNum);
GetProfileString (
TEXT("$TWAINDSINFO$"),
TEXT("Locale"),
TEXT(""),
Data,
32
);
pSplitDataIntoWords (Data, &Id->Version.Language, &Id->Version.Country);
GetProfileString (
TEXT("$TWAINDSINFO$"),
TEXT("VersionInfo"),
TEXT(""),
Id->Version.Info,
sizeof (Id->Version.Info)
);
GetProfileString (
TEXT("$TWAINDSINFO$"),
TEXT("Mfg"),
TEXT(""),
Id->Manufacturer,
sizeof (Id->Manufacturer)
);
GetProfileString (
TEXT("$TWAINDSINFO$"),
TEXT("Family"),
TEXT(""),
Id->ProductFamily,
sizeof (Id->ProductFamily)
);
GetProfileString (
TEXT("$TWAINDSINFO$"),
TEXT("Name"),
TEXT(""),
Id->ProductName,
sizeof (Id->ProductName)
);
//
// Delete the INI data
//
WriteProfileString (
TEXT("$TWAINDSINFO$"),
NULL,
NULL
);
return *(Id->ProductName) != 0;
}
return FALSE;
}
DWORD g_OrgEsp;
DWORD g_OrgEbp;
#if _MSC_FULL_VER >= 13008827 && defined(_M_IX86)
#pragma warning(push)
#pragma warning(disable:4731) // EBP modified with inline asm
#endif
BOOL
pGetDsInfo32 (
IN PCTSTR DsPath,
OUT TW_IDENTITY *Id
)
{
HINSTANCE DsLib = NULL;
DSENTRYPROC DsEntry;
TW_UINT16 TwainRc;
__try {
//
// Open the DS as a 32-bit library
//
DsLib = LoadLibrary (DsPath);
if (!DsLib) {
return FALSE;
}
//
// Get the DS entry point
//
DsEntry = (DSENTRYPROC) GetProcAddress (DsLib, "DS_Entry");
if (!DsEntry) {
FreeLibrary (DsLib);
return FALSE;
}
//
// Get the TW_IDENTITY struct, and preserve the stack for poorly
// written DSes.
//
__asm {
mov eax, esp
mov [g_OrgEsp], eax
mov [g_OrgEbp], ebp
}
TwainRc = DsEntry (NULL, DG_CONTROL, DAT_IDENTITY, MSG_GET, Id);
__asm {
mov eax, [g_OrgEsp]
mov esp, eax
mov ebp, [g_OrgEbp]
}
}
__except (TRUE) {
TwainRc = ERROR_NOACCESS;
}
if (DsLib) {
FreeLibrary (DsLib);
}
return TwainRc == ERROR_SUCCESS;
}
#if _MSC_FULL_VER >= 13008827
#pragma warning(pop)
#endif
BOOL
EnumFirstTwainDataSource (
OUT PTWAINDATASOURCE_ENUM EnumPtr
)
{
ZeroMemory (EnumPtr, sizeof (EnumPtr));
EnumPtr->State = TE_INIT;
return EnumNextTwainDataSource (EnumPtr);
}
BOOL
EnumNextTwainDataSource (
IN OUT PTWAINDATASOURCE_ENUM EnumPtr
)
{
TCHAR Path[MAX_TCHAR_PATH];
TW_IDENTITY Id;
while (EnumPtr->State != TE_DONE) {
switch (EnumPtr->State) {
case TE_INIT:
EnumPtr->State = TE_BEGIN_ENUM;
EnumPtr->Dir = TEXT("TWAIN\0TWAIN_32\0TWAIN32\0");
break;
case TE_BEGIN_ENUM:
wsprintf (Path, TEXT("%s\\%s"), g_WinDir, EnumPtr->Dir);
if (!EnumFirstFileInTree (&EnumPtr->Enum, Path, TEXT("*.DS"), TRUE)) {
EnumPtr->State = TE_END_ENUM;
} else {
EnumPtr->State = TE_EVALUATE;
}
break;
case TE_EVALUATE:
if (EnumPtr->Enum.Directory) {
EnumPtr->State = TE_NEXT;
} else if (pGetDsInfo16 (EnumPtr->Enum.FullPath, &Id)) {
EnumPtr->State = TE_RETURN;
} else if (pGetDsInfo32 (EnumPtr->Enum.FullPath, &Id)) {
EnumPtr->State = TE_RETURN;
} else {
EnumPtr->State = TE_NEXT;
}
break;
case TE_RETURN:
EnumPtr->State = TE_NEXT;
__try {
StackStringCopy (EnumPtr->Manufacturer, Id.Manufacturer);
StackStringCopy (EnumPtr->ProductFamily, Id.ProductFamily);
StackStringCopy (EnumPtr->DisplayName, Id.ProductName);
StackStringCopy (EnumPtr->DataSourceModule, EnumPtr->Enum.FullPath);
}
__except (TRUE) {
break;
}
return TRUE;
case TE_NEXT:
if (!EnumNextFileInTree (&EnumPtr->Enum)) {
EnumPtr->State = TE_END_ENUM;
} else {
EnumPtr->State = TE_EVALUATE;
}
break;
case TE_END_ENUM:
EnumPtr->Dir = GetEndOfString (EnumPtr->Dir) + 1;
if (*EnumPtr->Dir) {
EnumPtr->State = TE_BEGIN_ENUM;
} else {
EnumPtr->State = TE_DONE;
}
break;
}
}
return FALSE;
}
VOID
AbortTwainDataSourceEnum (
IN OUT PTWAINDATASOURCE_ENUM EnumPtr
)
{
if (EnumPtr->State != TE_DONE) {
AbortEnumFileInTree (&EnumPtr->Enum);
EnumPtr->State = TE_DONE;
}
}