|  | /* | 
|  | * WINE ct-api wrapper | 
|  | * | 
|  | * Copyright 2007 Christian Eggers | 
|  | * | 
|  | * This library is free software; you can redistribute it and/or | 
|  | * modify it under the terms of the GNU Lesser General Public | 
|  | * License as published by the Free Software Foundation; either | 
|  | * version 2.1 of the License, or (at your option) any later version. | 
|  | * | 
|  | * This library is distributed in the hope that it will be useful, | 
|  | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|  | * Lesser General Public License for more details. | 
|  | * | 
|  | * You should have received a copy of the GNU Lesser General Public | 
|  | * License along with this library; if not, write to the Free Software | 
|  | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA | 
|  | */ | 
|  |  | 
|  | #include "config.h" | 
|  | #include "wine/port.h" | 
|  | #include <string.h> | 
|  | #include "wine/library.h" | 
|  | #include "wine/debug.h" | 
|  | #include "windef.h" | 
|  | #include "winreg.h" | 
|  | #include "winnls.h" | 
|  | #include "ctapi.h" | 
|  |  | 
|  | WINE_DEFAULT_DEBUG_CHANNEL(ctapi32); | 
|  |  | 
|  | #define FALLBACK_LIBCTAPI "libctapi.so" | 
|  | static const WCHAR value_name[] = {'l','i','b','r','a','r','y',0}; | 
|  |  | 
|  |  | 
|  | static IS8 (*pCT_init)(IU16 ctn, IU16 pn) = NULL; | 
|  | static IS8 (*pCT_data)(IU16 ctn, IU8 *dad, IU8 *sad, IU16 lenc, IU8 *command, | 
|  | IU16 *lenr, IU8 *response) = NULL; | 
|  | static IS8 (*pCT_close)(IU16 ctn) = NULL; | 
|  |  | 
|  | static void *ctapi_handle = NULL; | 
|  |  | 
|  |  | 
|  | static int load_functions(void) { | 
|  | char soname[MAX_PATH] = FALLBACK_LIBCTAPI, buffer[MAX_PATH]; | 
|  | LONG result; | 
|  | HKEY key_handle; | 
|  |  | 
|  | if (pCT_init) /* loaded already */ | 
|  | return 0; | 
|  |  | 
|  | /* Try to get name of low level library from registry */ | 
|  | /* @@ Wine registry key: HKCU\Software\Wine\ctapi32 */ | 
|  | result = RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Wine\\ctapi32", 0, KEY_READ, &key_handle); | 
|  | if (result == ERROR_SUCCESS) { | 
|  | DWORD type, size; | 
|  | WCHAR buffer_w[MAX_PATH]; | 
|  |  | 
|  | size = sizeof(buffer_w) - sizeof(WCHAR);  /* Leave space for null termination */ | 
|  | result = RegQueryValueExW(key_handle, value_name, NULL, &type, (LPBYTE)buffer_w, &size); | 
|  | if ((result == ERROR_SUCCESS) && (type == REG_SZ)) { | 
|  | int len; | 
|  |  | 
|  | /* Null termination */ | 
|  | buffer_w[size / sizeof(WCHAR)] = '\0'; | 
|  | len = WideCharToMultiByte(CP_UNIXCP, 0, buffer_w, -1, buffer, sizeof(buffer), NULL, NULL); | 
|  | if (len) | 
|  | memcpy(soname, buffer, len); | 
|  | } | 
|  | RegCloseKey(key_handle); | 
|  | } | 
|  |  | 
|  | TRACE("Loading library '%s'\n", soname); | 
|  | ctapi_handle = wine_dlopen(soname, RTLD_NOW, NULL, 0); | 
|  | if (ctapi_handle) { | 
|  | TRACE("Successfully loaded '%s'\n", soname); | 
|  | } | 
|  | else { | 
|  | MESSAGE("Wine cannot find any usable hardware library, ctapi32.dll not working.\n"); | 
|  | MESSAGE("Please create the key \"HKEY_CURRENT_USER\\Software\\Wine\\ctapi32\" in your registry\n"); | 
|  | MESSAGE("and set the value \"library\" to your library name (e.g. \"libctapi-cyberjack.so.1\" or \"/usr/lib/readers/libctapi.so\").\n"); | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | #define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(ctapi_handle, #f, NULL, 0)) == NULL){WARN("Can't find symbol %s\n", #f); return 1;} | 
|  | LOAD_FUNCPTR(CT_init); | 
|  | LOAD_FUNCPTR(CT_data); | 
|  | LOAD_FUNCPTR(CT_close); | 
|  | #undef LOAD_FUNCPTR | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static void unload_functions(void) | 
|  | { | 
|  | pCT_close = NULL; | 
|  | pCT_data = NULL; | 
|  | pCT_init = NULL; | 
|  | if (ctapi_handle) | 
|  | wine_dlclose(ctapi_handle, NULL, 0); | 
|  | } | 
|  |  | 
|  |  | 
|  | /* | 
|  | *  ct-API specific functions | 
|  | */ | 
|  |  | 
|  | IS8 WINAPI WIN_CT_init(IU16 ctn, IU16 pn) | 
|  | { | 
|  | if (!pCT_init) | 
|  | return ERR_HOST; | 
|  | return pCT_init(ctn, pn); | 
|  | } | 
|  |  | 
|  | IS8 WINAPI WIN_CT_data(IU16 ctn, IU8 *dad, IU8 *sad, IU16 lenc, IU8 *command, IU16 *lenr, IU8 *response) | 
|  | { | 
|  | if (!pCT_data) | 
|  | return ERR_HOST; | 
|  | return pCT_data(ctn, dad, sad, lenc, command, lenr, response); | 
|  | } | 
|  |  | 
|  | IS8 WINAPI WIN_CT_close(IU16 ctn) | 
|  | { | 
|  | if (!pCT_close) | 
|  | return ERR_HOST; | 
|  | return pCT_close(ctn); | 
|  | } | 
|  |  | 
|  | /* | 
|  | *  Dll Main function | 
|  | */ | 
|  | BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) | 
|  | { | 
|  | TRACE("%p,%x,%p\n", hinstDLL, fdwReason, lpvReserved); | 
|  |  | 
|  | switch (fdwReason) | 
|  | { | 
|  | case DLL_PROCESS_ATTACH: | 
|  | { | 
|  | DisableThreadLibraryCalls(hinstDLL); | 
|  | /* Try to load low-level library */ | 
|  | if (load_functions() != 0) | 
|  | return FALSE;  /* error */ | 
|  | break; | 
|  | } | 
|  | case DLL_PROCESS_DETACH: | 
|  | { | 
|  | unload_functions(); | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | return TRUE; | 
|  | } |