#include "pch.h" #include "load_sane.h" #include #include // 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; } };