247 lines
6.0 KiB
C++
247 lines
6.0 KiB
C++
#include "pch.h"
|
|
#include "load_sane.h"
|
|
#include <string>
|
|
#include <shellapi.h> // for SHFileOperationW
|
|
#include "../../sdk/include/huagao/brand.h"
|
|
|
|
#pragma comment(lib, "shell32.lib")
|
|
|
|
namespace load_sane_util
|
|
{
|
|
static std::wstring sane_path(L"");
|
|
static HMODULE sane_module(NULL);
|
|
static int (__stdcall* sane_inst)(SCANNERID, ISaneInvoker**) = NULL;
|
|
static int(__stdcall* is_on)(SCANNERID) = NULL;
|
|
static int(__stdcall* init)(void*) = NULL;
|
|
static int(__stdcall* uninit)(void*) = NULL;
|
|
static void(__stdcall* log)(const wchar_t*, int) = NULL;
|
|
|
|
static std::string u2m(const wchar_t* u, int page)
|
|
{
|
|
char* ansi = NULL;
|
|
int len = 0;
|
|
std::string mb("");
|
|
|
|
len = WideCharToMultiByte(page, 0, u, lstrlenW(u), NULL, 0, NULL, NULL);
|
|
ansi = new char[len + 2];
|
|
len = WideCharToMultiByte(page, 0, u, lstrlenW(u), ansi, len, NULL, NULL);
|
|
ansi[len--] = 0;
|
|
mb = ansi;
|
|
delete[] ansi;
|
|
|
|
return mb;
|
|
}
|
|
static std::wstring m2u(const char* m, int page)
|
|
{
|
|
wchar_t* unic = NULL;
|
|
int len = 0;
|
|
std::wstring u(L"");
|
|
|
|
len = MultiByteToWideChar(page, 0, m, lstrlenA(m), NULL, 0);
|
|
unic = new wchar_t[len + 2];
|
|
len = MultiByteToWideChar(page, 0, m, lstrlenA(m), unic, len);
|
|
unic[len--] = 0;
|
|
u = unic;
|
|
delete[] unic;
|
|
|
|
return u;
|
|
}
|
|
static std::wstring reg_read(HKEY root, const wchar_t* path, const wchar_t* name)
|
|
{
|
|
HKEY key = NULL;
|
|
|
|
RegOpenKeyW(root, path, &key);
|
|
if (!key)
|
|
return L"";
|
|
|
|
wchar_t* buf = NULL;
|
|
DWORD len = 0;
|
|
DWORD type = REG_SZ;
|
|
std::wstring ret(L"");
|
|
|
|
RegQueryValueExW(key, name, NULL, &type, (LPBYTE)buf, &len);
|
|
if (len)
|
|
{
|
|
buf = new wchar_t[len + 4];
|
|
memset(buf, 0, (len + 4) * sizeof(*buf));
|
|
RegQueryValueExW(key, name, NULL, &type, (LPBYTE)buf, &len);
|
|
ret = buf;
|
|
delete[] buf;
|
|
}
|
|
RegCloseKey(key);
|
|
|
|
return ret;
|
|
}
|
|
static std::wstring reg_get_app_installing_path(std::wstring* rp = NULL)
|
|
{
|
|
std::wstring path(m2u(PRODUCT_VENDOR, CP_ACP)), key(L"DriverPath");
|
|
|
|
path.insert(0, L"Software\\");
|
|
path += L"Scan";
|
|
|
|
if (sizeof(void*) != 4)
|
|
key += L"64";
|
|
|
|
if (rp)
|
|
*rp = path + L"\\" + key;
|
|
|
|
return reg_read(HKEY_LOCAL_MACHINE, path.c_str(), key.c_str());
|
|
}
|
|
static int load_dll(const wchar_t* path_dll, HMODULE* dll)
|
|
{
|
|
HMODULE h = LoadLibraryW(path_dll);
|
|
int ret = GetLastError();
|
|
wchar_t info[128] = { 0 };
|
|
|
|
swprintf_s(info, _countof(info) - 1, L" = %d\r\n", ret);
|
|
OutputDebugStringW((L"[TWAIN]Load: " + std::wstring(path_dll) + info).c_str());
|
|
if (!h && (ret == ERROR_MOD_NOT_FOUND || ret == ERROR_BAD_EXE_FORMAT))
|
|
{
|
|
std::wstring dir(path_dll);
|
|
size_t pos = dir.rfind(L'\\');
|
|
wchar_t path[MAX_PATH] = { 0 };
|
|
|
|
GetDllDirectoryW(_countof(path) - 1, path);
|
|
if (pos != std::wstring::npos)
|
|
dir.erase(pos);
|
|
OutputDebugStringW((L"[TWAIN]Load: try change directory to " + dir + L"\r\n").c_str());
|
|
SetDllDirectoryW(dir.c_str());
|
|
h = LoadLibraryW(path_dll);
|
|
// h = LoadLibraryExW(path_dll, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
|
|
ret = GetLastError();
|
|
swprintf_s(info, _countof(info) - 1, L" = %d\r\n", ret);
|
|
OutputDebugStringW((L"[TWAIN]Load: " + std::wstring(path_dll) + info).c_str());
|
|
OutputDebugStringW((L"[TWAIN]Load: restore directory to " + std::wstring(path) + L"\r\n").c_str());
|
|
SetDllDirectoryW(path);
|
|
}
|
|
|
|
if (dll)
|
|
*dll = h;
|
|
|
|
return ret;
|
|
}
|
|
|
|
bool initialize(HMODULE me)
|
|
{
|
|
std::wstring reg_path(L"");
|
|
bool ret = false;
|
|
sane_path = reg_get_app_installing_path(®_path);
|
|
if (!sane_path.empty())
|
|
{
|
|
sane_path += L"\\sane.dll";
|
|
load_dll(sane_path.c_str(), &sane_module);
|
|
if (sane_module)
|
|
{
|
|
*((FARPROC*)&init) = GetProcAddress(sane_module, "initialize");
|
|
*((FARPROC*)&sane_inst) = GetProcAddress(sane_module, "open_scanner");
|
|
*((FARPROC*)&is_on) = GetProcAddress(sane_module, "is_scanner_online");
|
|
*((FARPROC*)&uninit) = GetProcAddress(sane_module, "uninitialize");
|
|
*((FARPROC*)&log) = GetProcAddress(sane_module, "log_info");
|
|
ret = is_ok();
|
|
if (ret)
|
|
ret = init(NULL) == 0;
|
|
}
|
|
}
|
|
|
|
if (!ret)
|
|
MessageBoxW(NULL, (reg_path + L": " + sane_path).c_str(), L"Load scanner driver failed:", MB_OK);
|
|
|
|
return ret;
|
|
}
|
|
bool is_ok(void)
|
|
{
|
|
wchar_t info[128] = { 0 };
|
|
swprintf_s(info, _countof(info) - 1, L"[TWAIN]Load: sane_inst: %s, is_on: %s, init: %s, uninit: %s\r\n"
|
|
, sane_inst != NULL ? "ok" : "not found"
|
|
, is_on != NULL ? "ok" : "not found"
|
|
, init != NULL ? "ok" : "not found"
|
|
, uninit != NULL ? "ok" : "not found");
|
|
|
|
return sane_inst != NULL && is_on != NULL && init != NULL && uninit != NULL;
|
|
}
|
|
bool is_online(SCANNERID guid)
|
|
{
|
|
if (is_on)
|
|
return is_on(guid);
|
|
else
|
|
return false;
|
|
}
|
|
ISaneInvoker* open(SCANNERID guid, int* err)
|
|
{
|
|
ISaneInvoker* ret = NULL;
|
|
int code = 0;
|
|
|
|
if (!err)
|
|
err = &code;
|
|
|
|
if (sane_inst)
|
|
*err = sane_inst(guid, &ret);
|
|
|
|
return ret;
|
|
}
|
|
void uninitialize(void)
|
|
{
|
|
sane_inst = NULL;
|
|
is_on = NULL;
|
|
init = NULL;
|
|
log = NULL;
|
|
|
|
if (uninit)
|
|
uninit(NULL);
|
|
uninit = NULL;
|
|
|
|
if (sane_module)
|
|
{
|
|
FreeLibrary(sane_module);
|
|
sane_module = NULL;
|
|
}
|
|
sane_path = L"";
|
|
sane_inst = NULL;
|
|
}
|
|
void log_info(const wchar_t* info, int level)
|
|
{
|
|
if (log)
|
|
log(info, level);
|
|
}
|
|
|
|
std::string utf82ansi(const char* utf8)
|
|
{
|
|
return u2m(m2u(utf8, CP_UTF8).c_str(), CP_ACP);
|
|
}
|
|
std::string ansi2utf8(const char* ansi)
|
|
{
|
|
return u2m(m2u(ansi, CP_ACP).c_str(), CP_UTF8);
|
|
}
|
|
std::wstring ansi2unic(const char* ansi)
|
|
{
|
|
return m2u(ansi, CP_ACP);
|
|
}
|
|
|
|
int move_file(const char* from, const char* to)
|
|
{
|
|
return move_file(ansi2unic(from).c_str(), ansi2unic(to).c_str());
|
|
}
|
|
int move_file(const wchar_t* from, const wchar_t* to)
|
|
{
|
|
SHFILEOPSTRUCTW fo = { 0 };
|
|
int ret = 0;
|
|
std::wstring _from(from), _to(to ? to : L"");
|
|
|
|
if (wcsicmp(from, to) == 0)
|
|
return 0;
|
|
|
|
_from += std::wstring((wchar_t*)&ret, 2); // ended with double '\0'
|
|
fo.pFrom = &_from[0];
|
|
_to += std::wstring((wchar_t*)&ret, 2); // ended with double '\0'
|
|
fo.pTo = &_to[0];
|
|
fo.fFlags = FOF_NO_UI | FOF_NO_CONNECTED_ELEMENTS; // 614 | 2000
|
|
fo.wFunc = FO_MOVE;
|
|
|
|
ret = SHFileOperationW(&fo);
|
|
if (ret == /*DE_SAMEFILE*/0x71)
|
|
ret = 0;
|
|
|
|
return ret;
|
|
}
|
|
};
|