diff options
author | Werner Koch <[email protected]> | 2007-06-06 18:12:30 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2007-06-06 18:12:30 +0000 |
commit | 2c9791db555cc571eaedfa71444da05454bd052a (patch) | |
tree | 9566d22f85e562e0c7b35dacc1697c9a58fcff1a /jnlib | |
parent | Print passphrase encoding info only in PEM mode. (diff) | |
download | gnupg-2c9791db555cc571eaedfa71444da05454bd052a.tar.gz gnupg-2c9791db555cc571eaedfa71444da05454bd052a.zip |
First steps towards supporting W32.
This is mainly source code reorganization.
Update gnulib.
g10/ does currently not build.
Diffstat (limited to 'jnlib')
-rw-r--r-- | jnlib/ChangeLog | 22 | ||||
-rw-r--r-- | jnlib/Makefile.am | 9 | ||||
-rw-r--r-- | jnlib/dotlock.c | 1 | ||||
-rw-r--r-- | jnlib/dynload.h | 73 | ||||
-rw-r--r-- | jnlib/libjnlib-config.h | 13 | ||||
-rw-r--r-- | jnlib/stringhelp.c | 2 | ||||
-rw-r--r-- | jnlib/utf8conv.c | 57 | ||||
-rw-r--r-- | jnlib/w32-gettext.c | 556 | ||||
-rw-r--r-- | jnlib/w32-pth.c | 1500 | ||||
-rw-r--r-- | jnlib/w32-pth.h | 245 | ||||
-rw-r--r-- | jnlib/w32-reg.c | 184 | ||||
-rw-r--r-- | jnlib/w32help.h | 41 |
12 files changed, 949 insertions, 1754 deletions
diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index 0db89e3c4..bb2d06574 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -1,3 +1,25 @@ +2007-06-06 Werner Koch <[email protected]> + + * w32help.h: New. + * w32-gettext.c: New. Taken from gnupg 1.4, added ngettext, + changed to use jnlib malloc functions and put under the LGPL. + * w32-reg.c: New. Taken from../common/w32reg.c and changed to + LGPL. Changed API to use the jnlib malloc functions. + * Makefile.am (libjnlib_a_SOURCES) [!W32]: Do not build the w32 + specific modules. + + * dotlock.c: Include stringhelp.h for stpcpy prototype. + +2007-06-04 Werner Koch <[email protected]> + + * dynload.h: New. Taken from ../common and changed to LGPL. + + * utf8conv.c (load_libiconv): New. Taken from GnuPG 1.4 + +2007-05-30 Werner Koch <[email protected]> + + * w32-pth.h, w32-pth.c: Remove. + 2007-04-25 Werner Koch <[email protected]> * argparse.c (long_opt_strlen): Fixed for utf-8. diff --git a/jnlib/Makefile.am b/jnlib/Makefile.am index 951c562f2..0f593bb3f 100644 --- a/jnlib/Makefile.am +++ b/jnlib/Makefile.am @@ -41,9 +41,12 @@ libjnlib_a_SOURCES = \ argparse.c argparse.h \ logging.c logging.h \ dotlock.c dotlock.h \ - types.h mischelp.c mischelp.h \ - w32-pth.c w32-pth.h \ - w32-afunix.c w32-afunix.h + types.h mischelp.c mischelp.h dynload.h w32help.h + +if HAVE_W32_SYSTEM +libjnlib_a_SOURCES += w32-reg.c w32-afunix.c w32-afunix.h w32-gettext.c +endif + # For GnuPG we don't need the xmalloc stuff. # xmalloc.c xmalloc.h diff --git a/jnlib/dotlock.c b/jnlib/dotlock.c index ba89bcea6..53fb52655 100644 --- a/jnlib/dotlock.c +++ b/jnlib/dotlock.c @@ -37,6 +37,7 @@ #include <signal.h> #include "libjnlib-config.h" +#include "stringhelp.h" #include "dotlock.h" #if !defined(DIRSEP_C) && !defined(EXTSEP_C) \ diff --git a/jnlib/dynload.h b/jnlib/dynload.h new file mode 100644 index 000000000..e365d4f0d --- /dev/null +++ b/jnlib/dynload.h @@ -0,0 +1,73 @@ +/* dynload.h - Wrapper functions for run-time dynamic loading + * Copyright (C) 2003 Free Software Foundation, Inc. + * + * This file is part of JNLIB. + * + * JNLIB 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. + * + * JNLIB 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 program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifndef LIBJNLIB_DYNLOAD_H +#define LIBJNLIB_DYNLOAD_H + +#ifndef __MINGW32__ +# include <dlfcn.h> +#else +# include <windows.h> + +# define RTLD_LAZY 0 + +static inline void * +dlopen (const char * name, int flag) +{ + void * hd = LoadLibrary (name); + return hd; +} + +static inline void * +dlsym (void *hd, const char *sym) +{ + if (hd && sym) + { + void * fnc = GetProcAddress (hd, sym); + if (!fnc) + return NULL; + return fnc; + } + return NULL; +} + + +static inline const char * +dlerror (void) +{ + static char buf[32]; + sprintf (buf, "ec=%lu", GetLastError ()); + return buf; +} + + +static inline int +dlclose (void * hd) +{ + if (hd) + { + CloseHandle (hd); + return 0; + } + return -1; +} +# endif /*__MINGW32__*/ +#endif /*LIBJNLIB_DYNLOAD_H*/ diff --git a/jnlib/libjnlib-config.h b/jnlib/libjnlib-config.h index 4554b9d1a..6c9408fdb 100644 --- a/jnlib/libjnlib-config.h +++ b/jnlib/libjnlib-config.h @@ -34,11 +34,14 @@ #define JNLIB_NEED_UTF8CONV 1 + +#if !defined(JNLIB_NEED_UTF8CONV) && defined(HAVE_W32_SYSTEM) +#define JNLIB_NEED_UTF8CONV 1 +#endif + /* Gettext stuff */ #ifdef USE_SIMPLE_GETTEXT - int set_gettext_file( const char *filename ); - const char *gettext( const char *msgid ); - +# include "w32help.h" # define _(a) gettext (a) # define N_(a) (a) @@ -61,7 +64,9 @@ #endif #endif /* !USE_SIMPLE_GETTEXT */ -/* Malloc functions to be jused by jnlib. */ +/* Malloc functions to be used by jnlib. */ +#define jnlib_malloc(a) gcry_malloc( (a) ) +#define jnlib_calloc(a,b) gcry_calloc( (a), (b) ) #define jnlib_xmalloc(a) gcry_xmalloc( (a) ) #define jnlib_xcalloc(a,b) gcry_xcalloc( (a), (b) ) #define jnlib_xrealloc(a,n) gcry_xrealloc( (a), (n) ) diff --git a/jnlib/stringhelp.c b/jnlib/stringhelp.c index b74f84a9c..b7f8b28db 100644 --- a/jnlib/stringhelp.c +++ b/jnlib/stringhelp.c @@ -821,7 +821,7 @@ memrchr (const void *buffer, int c, size_t n) for (p += n; n ; n--) if (*--p == c) - return p; + return (void *)p; return NULL; } #endif /*HAVE_MEMRCHR*/ diff --git a/jnlib/utf8conv.c b/jnlib/utf8conv.c index d7c0d44ba..90a319984 100644 --- a/jnlib/utf8conv.c +++ b/jnlib/utf8conv.c @@ -29,10 +29,13 @@ #include <langinfo.h> #endif #include <errno.h> -#include <iconv.h> +#ifndef HAVE_W32_SYSTEM +# include <iconv.h> +#endif #include "libjnlib-config.h" #include "stringhelp.h" +#include "dynload.h" #include "utf8conv.h" #ifndef MB_LEN_MAX @@ -45,6 +48,58 @@ static int no_translation; /* Set to true if we let simply pass through. */ static int use_iconv; /* iconv comversion fucntions required. */ +/* Under W32 we dlopen the iconv dll and don't require any iconv + related headers at all. However we need to define some stuff. */ +#ifdef HAVE_W32_SYSTEM +typedef void *iconv_t; +#ifndef ICONV_CONST +#define ICONV_CONST const +#endif +static iconv_t (* __stdcall iconv_open) (const char *tocode, + const char *fromcode); +static size_t (* __stdcall iconv) (iconv_t cd, + const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft); +static int (* __stdcall iconv_close) (iconv_t cd); + +static int +load_libiconv (void) +{ + static int done; + + if (!done) + { + void *handle; + + done = 1; /* Do it right now because we might get called recursivly + through gettext. */ + + handle = dlopen ("iconv.dll", RTLD_LAZY); + if (handle) + { + iconv_open = dlsym (handle, "libiconv_open"); + if (iconv_open) + iconv = dlsym (handle, "libiconv"); + if (iconv) + iconv_close = dlsym (handle, "libiconv_close"); + } + if (!handle || !iconv_close) + { + log_info (_("error loading `%s': %s\n"), + "iconv.dll", dlerror ()); + log_info (_("please see http://www.gnupg.org/download/iconv.html " + "for more information\n")); + iconv_open = NULL; + iconv = NULL; + iconv_close = NULL; + if (handle) + dlclose (handle); + } + } + return iconv_open? 0: -1; +} +#endif /*HAVE_W32_SYSTEM*/ + /* Error handler for iconv failures. This is needed to not clutter the output with repeated diagnostics about a missing conversion. */ diff --git a/jnlib/w32-gettext.c b/jnlib/w32-gettext.c new file mode 100644 index 000000000..eca1ee324 --- /dev/null +++ b/jnlib/w32-gettext.c @@ -0,0 +1,556 @@ +/* w32-gettext.c - A simplified version of gettext for use under W32. + * Copyright (C) 1995, 1996, 1997, 1999, + * 2005, 2007 Free Software Foundation, Inc. + * + * This file is part of JNLIB. + * + * JNLIB 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. + * + * JNLIB 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 program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/* + This is a simplified version of gettext written by Ulrich Drepper. + It is used for the Win32 version of GnuPG becaise all the overhead + of gettext is not needed and we have to do some special Win32 + stuff. I decided that this is far easier than to tweak gettext for + the special cases (I tried it but it is a lot of code). wk 15.09.99 + */ + +#include <config.h> +#ifdef USE_SIMPLE_GETTEXT +#if !defined (_WIN32) && !defined (__CYGWIN32__) +#error This module may only be build for Windows or Cygwin32 +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include "libjnlib-config.h" +#include "types.h" +#include "stringhelp.h" +#include "utf8conv.h" +#include "w32help.h" + +#include "windows.h" /* For GetModuleFileName. */ + +/* The magic number of the GNU message catalog format. */ +#define MAGIC 0x950412de +#define MAGIC_SWAPPED 0xde120495 + +/* Revision number of the currently used .mo (binary) file format. */ +#define MO_REVISION_NUMBER 0 + + +/* Header for binary .mo file format. */ +struct mo_file_header +{ + /* The magic number. */ + u32 magic; + /* The revision number of the file format. */ + u32 revision; + /* The number of strings pairs. */ + u32 nstrings; + /* Offset of table with start offsets of original strings. */ + u32 orig_tab_offset; + /* Offset of table with start offsets of translation strings. */ + u32 trans_tab_offset; + /* Size of hashing table. */ + u32 hash_tab_size; + /* Offset of first hashing entry. */ + u32 hash_tab_offset; +}; + +struct string_desc +{ + /* Length of addressed string. */ + u32 length; + /* Offset of string in file. */ + u32 offset; +}; + + +struct overflow_space_s +{ + struct overflow_space_s *next; + u32 idx; + char d[1]; +}; + +struct loaded_domain +{ + char *data; + int must_swap; + u32 nstrings; + char *mapped; /* 0 = not yet mapped, 1 = mapped, + 2 = mapped to + overflow space */ + struct overflow_space_s *overflow_space; + struct string_desc *orig_tab; + struct string_desc *trans_tab; + u32 hash_size; + u32 *hash_tab; +}; + + +static struct loaded_domain *the_domain; + +static __inline__ u32 +do_swap_u32( u32 i ) +{ + return (i << 24) | ((i & 0xff00) << 8) | ((i >> 8) & 0xff00) | (i >> 24); +} + +#define SWAPIT(flag, data) ((flag) ? do_swap_u32(data) : (data) ) + + +/* We assume to have `unsigned long int' value with at least 32 bits. */ +#define HASHWORDBITS 32 + +/* The so called `hashpjw' function by P.J. Weinberger + [see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools, + 1986, 1987 Bell Telephone Laboratories, Inc.] */ + +static __inline__ ulong +hash_string (const char *str_param) +{ + unsigned long int hval, g; + const char *str = str_param; + + hval = 0; + while (*str != '\0') + { + hval <<= 4; + hval += (unsigned long int) *str++; + g = hval & ((unsigned long int) 0xf << (HASHWORDBITS - 4)); + if (g != 0) + { + hval ^= g >> (HASHWORDBITS - 8); + hval ^= g; + } + } + return hval; +} + + +static struct loaded_domain * +load_domain (const char *filename) +{ + FILE *fp; + size_t size; + struct stat st; + struct mo_file_header *data = NULL; + struct loaded_domain *domain = NULL; + size_t to_read; + char *read_ptr; + + fp = fopen( filename, "rb" ); + if (!fp) + return NULL; /* Can't open the file. */ + /* We need to know the size of the file. */ + if (fstat( fileno(fp ), &st ) + || (size = (size_t)st.st_size) != st.st_size + || size < sizeof (struct mo_file_header) ) + { + fclose (fp); + return NULL; + } + + data = jnlib_malloc (size); + if (!data) + { + fclose (fp); + return NULL; /* Out of memory. */ + } + + to_read = size; + read_ptr = (char *) data; + do + { + long int nb; + + nb = fread (read_ptr, 1, to_read, fp); + if (nb < to_read ) + { + fclose (fp); + jnlib_free (data); + return NULL; /* Read error. */ + } + read_ptr += nb; + to_read -= nb; + } + while (to_read > 0); + fclose (fp); + + /* Using the magic number we test whether it is really a message + catalog file. */ + if (data->magic != MAGIC && data->magic != MAGIC_SWAPPED) + { + /* The magic number is wrong: not a message catalog file. */ + jnlib_free (data); + return NULL; + } + + domain = jnlib_calloc (1, sizeof *domain); + if (!domain) + { + jnlib_free (data); + return NULL; + } + domain->data = (char *) data; + domain->must_swap = data->magic != MAGIC; + + /* Fill in the information about the available tables. */ + switch (SWAPIT(domain->must_swap, data->revision)) + { + case 0: + domain->nstrings = SWAPIT(domain->must_swap, data->nstrings); + domain->orig_tab = (struct string_desc *) + ((char *) data + SWAPIT(domain->must_swap, data->orig_tab_offset)); + domain->trans_tab = (struct string_desc *) + ((char *) data + SWAPIT(domain->must_swap, data->trans_tab_offset)); + domain->hash_size = SWAPIT(domain->must_swap, data->hash_tab_size); + domain->hash_tab = (u32 *) + ((char *) data + SWAPIT(domain->must_swap, data->hash_tab_offset)); + break; + + default: /* This is an invalid revision. */ + jnlib_free( data ); + jnlib_free( domain ); + return NULL; + } + + /* Allocate an array to keep track of code page mappings. */ + domain->mapped = jnlib_calloc (1, domain->nstrings); + if (!domain->mapped) + { + jnlib_free (data); + jnlib_free (domain); + return NULL; + } + + return domain; +} + + +/* Set the file used for translations. Pass a NULL to disable + translation. A new filename may be set at anytime. WARNING: After + changing the filename you should not access any data retrieved by + gettext(). + + If REGKEY is not NULL, the function tries to selected the language + the registry key "Lang" below that key. If in addition the + environment variable LANGUAGE has been set, that value will + override a value set by the registry key. + */ +int +set_gettext_file ( const char *filename, const char *regkey ) +{ + struct loaded_domain *domain = NULL; + + if ( filename && *filename ) + { + if ( filename[0] == '/' +#ifdef HAVE_DRIVE_LETTERS + || ( isalpha(filename[0]) + && filename[1] == ':' + && (filename[2] == '/' || filename[2] == '\\') ) +#endif + ) + { + /* absolute path - use it as is */ + domain = load_domain( filename ); + } + else if (regkey) /* Standard. */ + { + char *instdir, *langid, *fname; + char *p; + int envvar_mode = 0; + + again: + if (!envvar_mode && (p = getenv ("LANGUAGE")) && *p) + { + envvar_mode = 1; + langid = jnlib_malloc (strlen (p)+1); + if (!langid) + return -1; + strcpy (langid, p); + /* We only make use of the first language given. Strip + the rest. */ + p = strchr (langid, ':'); + if (p) + *p = 0; + + /* In the $LANGUAGE case we do not use the registered + installation directory but the one where the gpg + binary has been found. */ + instdir = jnlib_malloc (MAX_PATH+5); + if ( !instdir || !GetModuleFileName (NULL, instdir, MAX_PATH) ) + { + jnlib_free (langid); + jnlib_free (instdir); + return -1; /* Error getting the process' file name. */ + } + p = strrchr (instdir, DIRSEP_C); + if (!p) + { + jnlib_free (langid); + jnlib_free (instdir); + return -1; /* Invalid file name returned. */ + } + *p = 0; + } + else + { + instdir = read_w32_registry_string ("HKEY_LOCAL_MACHINE", + regkey, + "Install Directory"); + if (!instdir) + return -1; + langid = read_w32_registry_string (NULL, /* HKCU then HKLM */ + regkey, + "Lang"); + if (!langid) + { + jnlib_free (instdir); + return -1; + } + } + + /* Strip stuff after a dot in case the user tried to enter + the entire locale syntacs as usual for POSIX. */ + p = strchr (langid, '.'); + if (p) + *p = 0; + + /* Build the key: "<instdir>/<domain>.nls/<langid>.mo" We + use a directory below the installation directory with the + domain included in case the software has been insalled + with other software altogether at the same place. */ + fname = jnlib_malloc (strlen (instdir) + 1 + strlen (filename) + 5 + + strlen (langid) + 3 + 1); + if (!fname) + { + jnlib_free (instdir); + jnlib_free (langid); + return -1; + } + strcpy (stpcpy (stpcpy (stpcpy (stpcpy ( stpcpy (fname, + instdir),"\\"), filename), ".nls\\"), langid), ".mo"); + jnlib_free (instdir); + jnlib_free (langid); + + /* Better make sure that we don't mix forward and backward + slashes. It seems that some Windoze versions don't + accept this. */ + for (p=fname; *p; p++) + { + if (*p == '/') + *p = '\\'; + } + domain = load_domain (fname); + jnlib_free(fname); + + if (!domain && envvar_mode == 1) + { + /* In case it failed, we try again using the registry + method. */ + envvar_mode++; + goto again; + } + } + + + if (!domain) + return -1; + } + + if ( the_domain ) + { + struct overflow_space_s *os, *os2; + + jnlib_free ( the_domain->data ); + jnlib_free ( the_domain->mapped ); + for (os=the_domain->overflow_space; os; os = os2) + { + os2 = os->next; + jnlib_free (os); + } + jnlib_free ( the_domain ); + the_domain = NULL; + } + the_domain = domain; + return 0; +} + + +static const char* +get_string( struct loaded_domain *domain, u32 idx ) +{ + struct overflow_space_s *os; + char *p; + + p = domain->data + SWAPIT(domain->must_swap, domain->trans_tab[idx].offset); + if (!domain->mapped[idx]) + { + size_t plen, buflen; + char *buf; + + domain->mapped[idx] = 1; + + plen = strlen (p); + buf = utf8_to_native (p, plen, -1); + buflen = strlen (buf); + if (buflen <= plen) + strcpy (p, buf); + else + { + /* There is not enough space for the translation - store it + in the overflow_space else and mark that in the mapped + array. Because we expect that this won't happen too + often, we use a simple linked list. */ + os = jnlib_malloc (sizeof *os + buflen); + if (os) + { + os->idx = idx; + strcpy (os->d, buf); + os->next = domain->overflow_space; + domain->overflow_space = os; + p = os->d; + } + else + p = "ERROR in GETTEXT MALLOC"; + } + jnlib_free (buf); + } + else if (domain->mapped[idx] == 2) + { /* We need to get the string from the overflow_space. */ + for (os=domain->overflow_space; os; os = os->next) + if (os->idx == idx) + return (const char*)os->d; + p = "ERROR in GETTEXT\n"; + } + return (const char*)p; +} + + + +const char * +gettext( const char *msgid ) +{ + struct loaded_domain *domain; + size_t act = 0; + size_t top, bottom; + + if (!(domain = the_domain)) + goto not_found; + + /* Locate the MSGID and its translation. */ + if (domain->hash_size > 2 && domain->hash_tab) + { + /* Use the hashing table. */ + u32 len = strlen (msgid); + u32 hash_val = hash_string (msgid); + u32 idx = hash_val % domain->hash_size; + u32 incr = 1 + (hash_val % (domain->hash_size - 2)); + u32 nstr = SWAPIT (domain->must_swap, domain->hash_tab[idx]); + + if ( !nstr ) /* Hash table entry is empty. */ + goto not_found; + + if (SWAPIT(domain->must_swap, + domain->orig_tab[nstr - 1].length) == len + && !strcmp (msgid, + domain->data + SWAPIT(domain->must_swap, + domain->orig_tab[nstr-1].offset))) + return get_string( domain, nstr - 1 ); + + for (;;) + { + if (idx >= domain->hash_size - incr) + idx -= domain->hash_size - incr; + else + idx += incr; + + nstr = SWAPIT (domain->must_swap, domain->hash_tab[idx]); + if (!nstr) + goto not_found; /* Hash table entry is empty. */ + + if ( SWAPIT(domain->must_swap, + domain->orig_tab[nstr - 1].length) == len + && !strcmp (msgid, + domain->data + + SWAPIT(domain->must_swap, + domain->orig_tab[nstr-1].offset))) + return get_string( domain, nstr-1 ); + } + /*NOTREACHED*/ + } + + /* Now we try the default method: binary search in the sorted array + of messages. */ + bottom = 0; + top = domain->nstrings; + while (bottom < top) + { + int cmp_val; + + act = (bottom + top) / 2; + cmp_val = strcmp(msgid, domain->data + + SWAPIT(domain->must_swap, + domain->orig_tab[act].offset)); + if (cmp_val < 0) + top = act; + else if (cmp_val > 0) + bottom = act + 1; + else + return get_string (domain, act); + } + + not_found: + return msgid; +} + + +const char * +ngettext (const char *msgid1, const char *msgid2, unsigned long int n) +{ + /* We use the simple Germanic plural rule. */ + return gettext (n==1? msgid1 : msgid2); +} + + + +#if 0 + unsigned int cp1, cp2; + + cp1 = GetConsoleCP(); + cp2 = GetConsoleOutputCP(); + + log_info("InputCP=%u OutputCP=%u\n", cp1, cp2 ); + + if( !SetConsoleOutputCP( 1252 ) ) + log_info("SetConsoleOutputCP failed: %s\n", w32_strerror (0)); + + cp1 = GetConsoleCP(); + cp2 = GetConsoleOutputCP(); + log_info("InputCP=%u OutputCP=%u after switch1\n", cp1, cp2 ); +#endif + +#endif /* USE_SIMPLE_GETTEXT */ diff --git a/jnlib/w32-pth.c b/jnlib/w32-pth.c deleted file mode 100644 index 0ef4d9e4e..000000000 --- a/jnlib/w32-pth.c +++ /dev/null @@ -1,1500 +0,0 @@ -/* w32-pth.c - GNU Pth emulation for W32 (MS Windows). - * Copyright (c) 1999-2003 Ralf S. Engelschall <[email protected]> - * Copyright (C) 2004, 2006 g10 Code GmbH - * - * This file is part of JNLIB. - * - * JNLIB 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. - * - * JNLIB 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 program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * ------------------------------------------------------------------ - * This code is based on Ralf Engelschall's GNU Pth, a non-preemptive - * thread scheduling library which can be found at - * http://www.gnu.org/software/pth/. MS Windows (W32) specific code - * written by Timo Schulz, g10 Code. - */ - -#include <config.h> -#ifdef HAVE_W32_SYSTEM -#include <windows.h> -#include <stdio.h> -#include <stdlib.h> -#include <io.h> -#include <signal.h> - -#include "logging.h" /* For log_get_prefix () */ - -/* We don't want to have any Windows specific code in the header, thus - we use a macro which defaults to a compatible type in w32-pth.h. */ -#define W32_PTH_HANDLE_INTERNAL HANDLE -#include "w32-pth.h" - - -#ifndef FALSE -#define FALSE 0 -#endif -#ifndef TRUE -#define TRUE 1 -#endif -#if FALSE != 0 || TRUE != 1 -#error TRUE or FALSE defined to wrong values -#endif - - -/* States whether this module has been initialized. */ -static int pth_initialized; - -/* Keeps the current debug level. Define marcos to test them. */ -static int debug_level; -#define DBG_ERROR (debug_level >= 1) -#define DBG_INFO (debug_level >= 2) -#define DBG_CALLS (debug_level >= 3) - -/* Variables to support event handling. */ -static int pth_signo; -static HANDLE pth_signo_ev; - -/* Mutex to make sure only one thread is running. */ -static CRITICAL_SECTION pth_shd; - -/* Events are store in a double linked event ring. */ -struct pth_event_s -{ - struct pth_event_s * next; - struct pth_event_s * prev; - HANDLE hd; - union - { - struct sigset_s * sig; - int fd; - struct timeval tv; - pth_mutex_t * mx; - } u; - int * val; - int u_type; - int flags; -}; - - -struct pth_attr_s -{ - unsigned int flags; - unsigned int stack_size; - char * name; -}; - - -/* Object to keep information about a thread. This may eventually be - used to implement a scheduler queue. */ -struct thread_info_s -{ - void *(*thread)(void *); /* The actual thread fucntion. */ - void * arg; /* The argument passed to that fucntion. */ - int joinable; /* True if this Thread is joinable. */ - HANDLE th; /* Handle of this thread. Used by non-joinable - threads to close the handle. */ -}; - - -/* Convenience macro to startup the system. */ -#define implicit_init() do { if (!pth_initialized) pth_init(); } while (0) - -/* Prototypes. */ -static pth_event_t do_pth_event (unsigned long spec, ...); -static unsigned int do_pth_waitpid (unsigned pid, int * status, int options); -static int do_pth_wait (pth_event_t ev); -static int do_pth_event_status (pth_event_t ev); -static void *launch_thread (void * ctx); - - - - -int -pth_init (void) -{ - SECURITY_ATTRIBUTES sa; - WSADATA wsadat; - const char *s; - - if (pth_initialized) - return TRUE; - - debug_level = (s=getenv ("DEBUG_PTH"))? atoi (s):0; - if (debug_level) - fprintf (stderr, "%s: pth_init: called.\n", log_get_prefix (NULL)); - - if (WSAStartup (0x202, &wsadat)) - return FALSE; - pth_signo = 0; - InitializeCriticalSection (&pth_shd); - if (pth_signo_ev) - CloseHandle (pth_signo_ev); - memset (&sa, 0, sizeof sa); - sa.bInheritHandle = TRUE; - sa.lpSecurityDescriptor = NULL; - sa.nLength = sizeof sa; - pth_signo_ev = CreateEvent (&sa, TRUE, FALSE, NULL); - if (!pth_signo_ev) - return FALSE; - - pth_initialized = 1; - EnterCriticalSection (&pth_shd); - return TRUE; -} - - -int -pth_kill (void) -{ - pth_signo = 0; - if (pth_signo_ev) - { - CloseHandle (pth_signo_ev); - pth_signo_ev = NULL; - } - if (pth_initialized) - DeleteCriticalSection (&pth_shd); - WSACleanup (); - pth_initialized = 0; - return TRUE; -} - - -static char * -w32_strerror (char *strerr, size_t strerrsize) -{ - if (strerrsize > 1) - FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, (int)GetLastError (), - MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), - strerr, strerrsize, NULL); - return strerr; -} - - -static void -enter_pth (const char *function) -{ - /* Fixme: I am not sure whether the same thread my enter a critical - section twice. */ - if (DBG_CALLS) - fprintf (stderr, "%s: enter_pth (%s)\n", - log_get_prefix (NULL), function? function:""); - LeaveCriticalSection (&pth_shd); -} - - -static void -leave_pth (const char *function) -{ - EnterCriticalSection (&pth_shd); - if (DBG_CALLS) - fprintf (stderr, "%s: leave_pth (%s)\n", - log_get_prefix (NULL), function? function:""); -} - - -long -pth_ctrl (unsigned long query, ...) -{ - implicit_init (); - - switch (query) - { - case PTH_CTRL_GETAVLOAD: - case PTH_CTRL_GETPRIO: - case PTH_CTRL_GETNAME: - case PTH_CTRL_GETTHREADS_NEW: - case PTH_CTRL_GETTHREADS_READY: - case PTH_CTRL_GETTHREADS_RUNNING: - case PTH_CTRL_GETTHREADS_WAITING: - case PTH_CTRL_GETTHREADS_SUSPENDED: - case PTH_CTRL_GETTHREADS_DEAD: - case PTH_CTRL_GETTHREADS: - default: - return -1; - } - return 0; -} - - - -pth_time_t -pth_timeout (long sec, long usec) -{ - pth_time_t tvd; - - tvd.tv_sec = sec; - tvd.tv_usec = usec; - return tvd; -} - - -int -pth_read_ev (int fd, void *buffer, size_t size, pth_event_t ev) -{ - implicit_init (); - return 0; -} - - -int -pth_read (int fd, void * buffer, size_t size) -{ - int n; - - implicit_init (); - enter_pth (__FUNCTION__); - - n = recv (fd, buffer, size, 0); - if (n == -1 && WSAGetLastError () == WSAENOTSOCK) - { - DWORD nread = 0; - n = ReadFile ((HANDLE)fd, buffer, size, &nread, NULL); - if (!n) - { - char strerr[256]; - - if (DBG_ERROR) - fprintf (stderr, "%s: pth_read(%d) failed read from file: %s\n", - log_get_prefix (NULL), fd, - w32_strerror (strerr, sizeof strerr)); - n = -1; - } - else - n = (int)nread; - } - leave_pth (__FUNCTION__); - return n; -} - - -int -pth_write_ev (int fd, const void *buffer, size_t size, pth_event_t ev) -{ - implicit_init (); - return 0; -} - - -int -pth_write (int fd, const void * buffer, size_t size) -{ - int n; - - implicit_init (); - enter_pth (__FUNCTION__); - n = send (fd, buffer, size, 0); - if (n == -1 && WSAGetLastError () == WSAENOTSOCK) - { - DWORD nwrite; - char strerr[256]; - - /* This is no real error because we first need to figure out if - we have a handle or a socket. */ - - n = WriteFile ((HANDLE)fd, buffer, size, &nwrite, NULL); - if (!n) - { - if (DBG_ERROR) - fprintf (stderr, "%s: pth_write(%d) failed in write: %s\n", - log_get_prefix (NULL), fd, - w32_strerror (strerr, sizeof strerr)); - n = -1; - } - else - n = (int)nwrite; - } - leave_pth (__FUNCTION__); - return n; -} - - -int -pth_select (int nfds, fd_set * rfds, fd_set * wfds, fd_set * efds, - const struct timeval * timeout) -{ - int n; - - implicit_init (); - enter_pth (__FUNCTION__); - n = select (nfds, rfds, wfds, efds, timeout); - leave_pth (__FUNCTION__); - return n; -} - - -int -pth_fdmode (int fd, int mode) -{ - unsigned long val; - int ret = PTH_FDMODE_BLOCK; - - implicit_init (); - /* Note: we don't do the eter/leave pth here because this is for one - a fast fucntion and secondly already called from inside such a - block. */ - /* XXX: figure out original fd mode */ - switch (mode) - { - case PTH_FDMODE_NONBLOCK: - val = 1; - if (ioctlsocket (fd, FIONBIO, &val) == SOCKET_ERROR) - ret = PTH_FDMODE_ERROR; - break; - - case PTH_FDMODE_BLOCK: - val = 0; - if (ioctlsocket (fd, FIONBIO, &val) == SOCKET_ERROR) - ret = PTH_FDMODE_ERROR; - break; - } - return ret; -} - - -int -pth_accept (int fd, struct sockaddr *addr, int *addrlen) -{ - int rc; - - implicit_init (); - enter_pth (__FUNCTION__); - rc = accept (fd, addr, addrlen); - leave_pth (__FUNCTION__); - return rc; -} - - -int -pth_accept_ev (int fd, struct sockaddr *addr, int *addrlen, - pth_event_t ev_extra) -{ - pth_key_t ev_key; - pth_event_t ev; - int rv; - int fdmode; - - implicit_init (); - enter_pth (__FUNCTION__); - - fdmode = pth_fdmode (fd, PTH_FDMODE_NONBLOCK); - if (fdmode == PTH_FDMODE_ERROR) - { - leave_pth (__FUNCTION__); - return -1; - } - - ev = NULL; - while ((rv = accept (fd, addr, addrlen)) == -1 && - (WSAGetLastError () == WSAEINPROGRESS || - WSAGetLastError () == WSAEWOULDBLOCK)) - { - if (!ev) - { - ev = do_pth_event (PTH_EVENT_FD|PTH_UNTIL_FD_READABLE| - PTH_MODE_STATIC, &ev_key, fd); - if (!ev) - { - leave_pth (__FUNCTION__); - return -1; - } - if (ev_extra) - pth_event_concat (ev, ev_extra, NULL); - } - /* Wait until accept has a chance. */ - do_pth_wait (ev); - if (ev_extra) - { - pth_event_isolate (ev); - if (do_pth_event_status (ev) != PTH_STATUS_OCCURRED) - { - pth_fdmode (fd, fdmode); - leave_pth (__FUNCTION__); - return -1; - } - } - } - - pth_fdmode (fd, fdmode); - leave_pth (__FUNCTION__); - return rv; -} - - -int -pth_connect (int fd, struct sockaddr *name, int namelen) -{ - int rc; - - implicit_init (); - enter_pth (__FUNCTION__); - rc = connect (fd, name, namelen); - leave_pth (__FUNCTION__); - return rc; -} - - -int -pth_mutex_release (pth_mutex_t *mutex) -{ - int rc; - - implicit_init (); - enter_pth (__FUNCTION__); - - if (!ReleaseMutex (*mutex)) - { - char strerr[256]; - - if (DBG_ERROR) - fprintf (stderr, "%s: pth_release_mutex %p failed: %s\n", - log_get_prefix (NULL), *mutex, - w32_strerror (strerr, sizeof strerr)); - rc = FALSE; - } - else - rc = TRUE; - - leave_pth (__FUNCTION__); - return rc; -} - - -int -pth_mutex_acquire (pth_mutex_t *mutex, int tryonly, pth_event_t ev_extra) -{ - int code; - int rc; - - implicit_init (); - enter_pth (__FUNCTION__); - - /* FIXME: ev_extra is not yet supported. */ - - code = WaitForSingleObject (*mutex, INFINITE); - switch (code) - { - case WAIT_FAILED: - { - char strerr[256]; - - if (DBG_ERROR) - fprintf (stderr, "%s: pth_mutex_acquire for %p failed: %s\n", - log_get_prefix (NULL), *mutex, - w32_strerror (strerr, sizeof strerr)); - } - rc = FALSE; - break; - - case WAIT_OBJECT_0: - rc = TRUE; - break; - - default: - if (DBG_ERROR) - fprintf (stderr, "%s: WaitForSingleObject returned unexpected " - "code %d for mutex %p\n", - log_get_prefix (NULL), code, *mutex); - rc = FALSE; - break; - } - - leave_pth (__FUNCTION__); - return rc; -} - - - -int -pth_mutex_init (pth_mutex_t *mutex) -{ - SECURITY_ATTRIBUTES sa; - - implicit_init (); - enter_pth (__FUNCTION__); - - memset (&sa, 0, sizeof sa); - sa.bInheritHandle = TRUE; - sa.lpSecurityDescriptor = NULL; - sa.nLength = sizeof sa; - *mutex = CreateMutex (&sa, FALSE, NULL); - if (!*mutex) - { - free (*mutex); - *mutex = NULL; - leave_pth (__FUNCTION__); - return FALSE; - } - - leave_pth (__FUNCTION__); - return TRUE; -} - - -pth_attr_t -pth_attr_new (void) -{ - pth_attr_t hd; - - implicit_init (); - hd = calloc (1, sizeof *hd); - return hd; -} - - -int -pth_attr_destroy (pth_attr_t hd) -{ - if (!hd) - return -1; - implicit_init (); - if (hd->name) - free (hd->name); - free (hd); - return TRUE; -} - - -int -pth_attr_set (pth_attr_t hd, int field, ...) -{ - va_list args; - char * str; - int val; - int rc = TRUE; - - implicit_init (); - - va_start (args, field); - switch (field) - { - case PTH_ATTR_JOINABLE: - val = va_arg (args, int); - if (val) - { - hd->flags |= PTH_ATTR_JOINABLE; - if (DBG_INFO) - fprintf (stderr, "%s: pth_attr_set: PTH_ATTR_JOINABLE\n", - log_get_prefix (NULL)); - } - break; - - case PTH_ATTR_STACK_SIZE: - val = va_arg (args, int); - if (val) - { - hd->flags |= PTH_ATTR_STACK_SIZE; - hd->stack_size = val; - if (DBG_INFO) - fprintf (stderr, "%s: pth_attr_set: PTH_ATTR_STACK_SIZE %d\n", - log_get_prefix (NULL), val); - } - break; - - case PTH_ATTR_NAME: - str = va_arg (args, char*); - if (hd->name) - free (hd->name); - if (str) - { - hd->name = strdup (str); - if (!hd->name) - return FALSE; - hd->flags |= PTH_ATTR_NAME; - if (DBG_INFO) - fprintf (stderr, "%s: pth_attr_set: PTH_ATTR_NAME %s\n", - log_get_prefix (NULL), hd->name); - } - break; - - default: - rc = FALSE; - break; - } - va_end (args); - return rc; -} - - -static pth_t -do_pth_spawn (pth_attr_t hd, void *(*func)(void *), void *arg) -{ - SECURITY_ATTRIBUTES sa; - DWORD tid; - HANDLE th; - struct thread_info_s *ctx; - - if (!hd) - return NULL; - - memset (&sa, 0, sizeof sa); - sa.bInheritHandle = TRUE; - sa.lpSecurityDescriptor = NULL; - sa.nLength = sizeof sa; - - ctx = calloc (1, sizeof *ctx); - if (!ctx) - return NULL; - ctx->thread = func; - ctx->arg = arg; - ctx->joinable = (hd->flags & PTH_ATTR_JOINABLE); - - /* XXX: we don't use all thread attributes. */ - - /* Note that we create the thread suspended so that we are able to - store the thread's handle in the context structure. We need to - do this to be able to close the handle from the launch helper. - - FIXME: We should no use th W32's Thread handle directly but keep - our own thread control structure. CTX may be used for that. */ - if (DBG_INFO) - fprintf (stderr, "%s: do_pth_spawn creating thread ...\n", - log_get_prefix (NULL)); - th = CreateThread (&sa, hd->stack_size, - (LPTHREAD_START_ROUTINE)launch_thread, - ctx, CREATE_SUSPENDED, &tid); - ctx->th = th; - if (DBG_INFO) - fprintf (stderr, "%s: do_pth_spawn created thread %p\n", - log_get_prefix (NULL),th); - if (!th) - free (ctx); - else - ResumeThread (th); - - return th; -} - -pth_t -pth_spawn (pth_attr_t hd, void *(*func)(void *), void *arg) -{ - HANDLE th; - - if (!hd) - return NULL; - - implicit_init (); - enter_pth (__FUNCTION__); - th = do_pth_spawn (hd, func, arg); - leave_pth (__FUNCTION__); - return th; -} - - -pth_t -pth_self (void) -{ - return GetCurrentThread (); -} - -int -pth_join (pth_t hd, void **value) -{ - return TRUE; -} - - -/* friendly */ -int -pth_cancel (pth_t hd) -{ - if (!hd) - return -1; - implicit_init (); - enter_pth (__FUNCTION__); - WaitForSingleObject (hd, 1000); - TerminateThread (hd, 0); - leave_pth (__FUNCTION__); - return TRUE; -} - - -/* cruel */ -int -pth_abort (pth_t hd) -{ - if (!hd) - return -1; - implicit_init (); - enter_pth (__FUNCTION__); - TerminateThread (hd, 0); - leave_pth (__FUNCTION__); - return TRUE; -} - - -void -pth_exit (void *value) -{ - implicit_init (); - enter_pth (__FUNCTION__); - pth_kill (); - leave_pth (__FUNCTION__); - exit ((int)(long)value); -} - - -static unsigned int -do_pth_waitpid (unsigned pid, int * status, int options) -{ -#if 0 - pth_event_t ev; - static pth_key_t ev_key = PTH_KEY_INIT; - pid_t pid; - - pth_debug2("pth_waitpid: called from thread \"%s\"", pth_current->name); - - for (;;) - { - /* do a non-blocking poll for the pid */ - while ( (pid = pth_sc(waitpid)(wpid, status, options|WNOHANG)) < 0 - && errno == EINTR) - ; - - /* if pid was found or caller requested a polling return immediately */ - if (pid == -1 || pid > 0 || (pid == 0 && (options & WNOHANG))) - break; - - /* else wait a little bit */ - ev = pth_event(PTH_EVENT_TIME|PTH_MODE_STATIC, &ev_key, - pth_timeout (0,250000)); - pth_wait(ev); - } - - pth_debug2("pth_waitpid: leave to thread \"%s\"", pth_current->name); -#endif - return 0; -} - - -unsigned int -pth_waitpid (unsigned pid, int * status, int options) -{ - unsigned int n; - - implicit_init (); - enter_pth (__FUNCTION__); - n = do_pth_waitpid (pid, status, options); - leave_pth (__FUNCTION__); - return n; -} - - -static BOOL WINAPI -sig_handler (DWORD signo) -{ - switch (signo) - { - case CTRL_C_EVENT: pth_signo = SIGINT; break; - case CTRL_BREAK_EVENT: pth_signo = SIGTERM; break; - } - SetEvent (pth_signo_ev); - if (DBG_INFO) - fprintf (stderr, "%s: sig_handler=%d\n", log_get_prefix (NULL), pth_signo); - return TRUE; -} - - -static pth_event_t -do_pth_event_body (unsigned long spec, va_list arg) -{ - SECURITY_ATTRIBUTES sa; - pth_event_t ev; - int rc; - - if (DBG_INFO) - fprintf (stderr, "%s: pth_event spec=%lu\n", log_get_prefix (NULL), spec); - ev = calloc (1, sizeof *ev); - if (!ev) - return NULL; - if (spec == 0) - ; - else if (spec & PTH_EVENT_SIGS) - { - ev->u.sig = va_arg (arg, struct sigset_s *); - ev->u_type = PTH_EVENT_SIGS; - ev->val = va_arg (arg, int *); - rc = SetConsoleCtrlHandler (sig_handler, TRUE); - if (DBG_INFO) - fprintf (stderr, "%s: pth_event: sigs rc=%d\n", - log_get_prefix (NULL), rc); - } - else if (spec & PTH_EVENT_FD) - { - if (spec & PTH_UNTIL_FD_READABLE) - ev->flags |= PTH_UNTIL_FD_READABLE; - if (spec & PTH_MODE_STATIC) - ev->flags |= PTH_MODE_STATIC; - ev->u_type = PTH_EVENT_FD; - va_arg (arg, pth_key_t); - ev->u.fd = va_arg (arg, int); - if (DBG_INFO) - fprintf (stderr, "%s: pth_event: fd=%d\n", - log_get_prefix (NULL), ev->u.fd); - } - else if (spec & PTH_EVENT_TIME) - { - pth_time_t t; - if (spec & PTH_MODE_STATIC) - ev->flags |= PTH_MODE_STATIC; - va_arg (arg, pth_key_t); - t = va_arg (arg, pth_time_t); - ev->u_type = PTH_EVENT_TIME; - ev->u.tv.tv_sec = t.tv_sec; - ev->u.tv.tv_usec = t.tv_usec; - } - else if (spec & PTH_EVENT_MUTEX) - { - va_arg (arg, pth_key_t); - ev->u_type = PTH_EVENT_MUTEX; - ev->u.mx = va_arg (arg, pth_mutex_t*); - } - - memset (&sa, 0, sizeof sa); - sa.bInheritHandle = TRUE; - sa.lpSecurityDescriptor = NULL; - sa.nLength = sizeof sa; - ev->hd = CreateEvent (&sa, FALSE, FALSE, NULL); - if (!ev->hd) - { - free (ev); - return NULL; - } - ev->next = ev; - ev->prev = ev; - - return ev; -} - -static pth_event_t -do_pth_event (unsigned long spec, ...) -{ - va_list arg; - pth_event_t ev; - - va_start (arg, spec); - ev = do_pth_event_body (spec, arg); - va_end (arg); - - return ev; -} - -pth_event_t -pth_event (unsigned long spec, ...) -{ - va_list arg; - pth_event_t ev; - - implicit_init (); - enter_pth (__FUNCTION__); - - va_start (arg, spec); - ev = do_pth_event_body (spec, arg); - va_end (arg); - - leave_pth (__FUNCTION__); - return ev; -} - - -static void -pth_event_add (pth_event_t root, pth_event_t node) -{ - pth_event_t n; - - for (n=root; n->next; n = n->next) - ; - n->next = node; -} - - -pth_event_t -pth_event_concat (pth_event_t evf, ...) -{ - pth_event_t evn; - va_list ap; - - if (!evf) - return NULL; - - implicit_init (); - - va_start (ap, evf); - while ((evn = va_arg(ap, pth_event_t)) != NULL) - pth_event_add (evf, evn); - va_end (ap); - - return evf; -} - - -static int -wait_for_fd (int fd, int is_read, int nwait) -{ - struct timeval tv; - fd_set r; - fd_set w; - int n; - - FD_ZERO (&r); - FD_ZERO (&w); - FD_SET (fd, is_read ? &r : &w); - - tv.tv_sec = nwait; - tv.tv_usec = 0; - - while (1) - { - n = select (fd+1, &r, &w, NULL, &tv); - if (DBG_INFO) - fprintf (stderr, "%s: wait_for_fd=%d fd %d (ec=%d)\n", - log_get_prefix (NULL), n, fd,(int)WSAGetLastError ()); - if (n == -1) - break; - if (!n) - continue; - if (n == 1) - { - if (is_read && FD_ISSET (fd, &r)) - break; - else if (FD_ISSET (fd, &w)) - break; - } - } - return 0; -} - - -static void * -launch_thread (void *arg) -{ - struct thread_info_s *c = arg; - - if (c) - { - leave_pth (__FUNCTION__); - c->thread (c->arg); - if (!c->joinable && c->th) - { - CloseHandle (c->th); - c->th = NULL; - } - /* FIXME: We would badly fail if someone accesses the now - deallocated handle. Don't use it directly but setup proper - scheduling queues. */ - enter_pth (__FUNCTION__); - free (c); - } - ExitThread (0); - return NULL; -} - -/* void */ -/* sigemptyset (struct sigset_s * ss) */ -/* { */ -/* if (ss) { */ -/* memset (ss->sigs, 0, sizeof ss->sigs); */ -/* ss->idx = 0; */ -/* } */ -/* } */ - - -/* int */ -/* sigaddset (struct sigset_s * ss, int signo) */ -/* { */ -/* if (!ss) */ -/* return -1; */ -/* if (ss->idx + 1 > 64) */ -/* return -1; */ -/* ss->sigs[ss->idx] = signo; */ -/* ss->idx++; */ -/* return 0; */ -/* } */ - - -static int -sigpresent (struct sigset_s * ss, int signo) -{ -/* int i; */ -/* for (i=0; i < ss->idx; i++) { */ -/* if (ss->sigs[i] == signo) */ -/* return 1; */ -/* } */ -/* FIXME: See how to implement it. */ - return 0; -} - - -static int -do_pth_event_occurred (pth_event_t ev) -{ - int ret; - - if (!ev) - return 0; - - ret = 0; - switch (ev->u_type) - { - case 0: - if (WaitForSingleObject (ev->hd, 0) == WAIT_OBJECT_0) - ret = 1; - break; - - case PTH_EVENT_SIGS: - if (sigpresent (ev->u.sig, pth_signo) && - WaitForSingleObject (pth_signo_ev, 0) == WAIT_OBJECT_0) - { - if (DBG_INFO) - fprintf (stderr, "%s: pth_event_occurred: sig signaled.\n", - log_get_prefix (NULL)); - (*ev->val) = pth_signo; - ret = 1; - } - break; - - case PTH_EVENT_FD: - if (WaitForSingleObject (ev->hd, 0) == WAIT_OBJECT_0) - ret = 1; - break; - } - - return ret; -} - - -int -pth_event_occurred (pth_event_t ev) -{ - int ret; - - implicit_init (); - enter_pth (__FUNCTION__); - ret = do_pth_event_occurred (ev); - leave_pth (__FUNCTION__); - return ret; -} - - -static int -do_pth_event_status (pth_event_t ev) -{ - if (!ev) - return 0; - if (do_pth_event_occurred (ev)) - return PTH_STATUS_OCCURRED; - return 0; -} - -int -pth_event_status (pth_event_t ev) -{ - if (!ev) - return 0; - if (pth_event_occurred (ev)) - return PTH_STATUS_OCCURRED; - return 0; -} - - -static int -do_pth_event_free (pth_event_t ev, int mode) -{ - if (!ev) - return FALSE; - - if (mode == PTH_FREE_ALL) - { - pth_event_t cur = ev; - do - { - pth_event_t next = cur->next; - CloseHandle (cur->hd); - cur->hd = NULL; - free (cur); - cur = next; - } - while (cur != ev); - } - else if (mode == PTH_FREE_THIS) - { - ev->prev->next = ev->next; - ev->next->prev = ev->prev; - CloseHandle (ev->hd); - ev->hd = NULL; - free (ev); - } - else - return FALSE; - - return TRUE; -} - -int -pth_event_free (pth_event_t ev, int mode) -{ - int rc; - - implicit_init (); - enter_pth (__FUNCTION__); - rc = do_pth_event_free (ev, mode); - leave_pth (__FUNCTION__); - return rc; -} - - -pth_event_t -pth_event_isolate (pth_event_t ev) -{ - pth_event_t ring; - - if (!ev) - return NULL; - if (ev->next == ev && ev->prev == ev) - return NULL; /* Only one event. */ - - ring = ev->next; - ev->prev->next = ev->next; - ev->next->prev = ev->prev; - ev->prev = ev; - ev->next = ev; - return ring; -} - - -static int -event_count (pth_event_t ev) -{ - pth_event_t r; - int cnt = 0; - - if (ev) - { - r = ev; - do - { - cnt++; - r = r->next; - } - while (r != ev); - } - - return cnt; -} - - - -static pth_t -spawn_helper_thread (void *(*func)(void *), void *arg) -{ - SECURITY_ATTRIBUTES sa; - DWORD tid; - HANDLE th; - - memset (&sa, 0, sizeof sa); - sa.bInheritHandle = TRUE; - sa.lpSecurityDescriptor = NULL; - sa.nLength = sizeof sa; - - if (DBG_INFO) - fprintf (stderr, "%s: spawn_helper_thread creating thread ...\n", - log_get_prefix (NULL)); - th = CreateThread (&sa, 32*1024, - (LPTHREAD_START_ROUTINE)func, - arg, 0, &tid); - if (DBG_INFO) - fprintf (stderr, "%s: spawn_helper_thread created thread %p\n", - log_get_prefix (NULL), th); - - return th; -} - - -static void -free_helper_threads (HANDLE *waitbuf, int *hdidx, int n) -{ - int i; - - for (i=0; i < n; i++) - { - CloseHandle (waitbuf[hdidx[i]]); - waitbuf[hdidx[i]] = NULL; - } -} - - -static void * -wait_fd_thread (void * ctx) -{ - pth_event_t ev = ctx; - - wait_for_fd (ev->u.fd, ev->flags & PTH_UNTIL_FD_READABLE, 3600); - if (DBG_INFO) - fprintf (stderr, "%s: wait_fd_thread: exit.\n", log_get_prefix (NULL)); - SetEvent (ev->hd); - ExitThread (0); - return NULL; -} - - -static void * -wait_timer_thread (void * ctx) -{ - pth_event_t ev = ctx; - int n = ev->u.tv.tv_sec*1000; - Sleep (n); - SetEvent (ev->hd); - if (DBG_INFO) - fprintf (stderr, "%s: wait_timer_thread: exit.\n", log_get_prefix (NULL)); - ExitThread (0); - return NULL; -} - - -static int -do_pth_wait (pth_event_t ev) -{ - HANDLE waitbuf[MAXIMUM_WAIT_OBJECTS/2]; - int hdidx[MAXIMUM_WAIT_OBJECTS/2]; - DWORD n = 0; - int pos=0, i=0; - - if (!ev) - return 0; - - n = event_count (ev); - if (n > MAXIMUM_WAIT_OBJECTS/2) - return -1; - - if (DBG_INFO) - fprintf (stderr, "%s: pth_wait: cnt %lu\n", log_get_prefix (NULL), n); - if (ev) - { - pth_event_t r = ev; - do - { - switch (r->u_type) - { - case 0: - waitbuf[pos++] = r->hd; - break; - - case PTH_EVENT_SIGS: - waitbuf[pos++] = pth_signo_ev; - if (DBG_INFO) - fprintf (stderr, "pth_wait: add signal event.\n"); - break; - - case PTH_EVENT_FD: - if (DBG_INFO) - fprintf (stderr, "pth_wait: spawn event wait thread.\n"); - hdidx[i++] = pos; - waitbuf[pos++] = spawn_helper_thread (wait_fd_thread, r); - break; - - case PTH_EVENT_TIME: - if (DBG_INFO) - fprintf (stderr, "pth_wait: spawn event timer thread.\n"); - hdidx[i++] = pos; - waitbuf[pos++] = spawn_helper_thread (wait_timer_thread, r); - break; - - case PTH_EVENT_MUTEX: - if (DBG_INFO) - fprintf (stderr, "pth_wait: ignoring mutex event.\n"); - break; - } - } - while ( r != ev ); - } - if (DBG_INFO) - fprintf (stderr, "%s: pth_wait: set %d\n", log_get_prefix (NULL), pos); - n = WaitForMultipleObjects (pos, waitbuf, FALSE, INFINITE); - free_helper_threads (waitbuf, hdidx, i); - if (DBG_INFO) - fprintf (stderr, "%s: pth_wait: n %ld\n", log_get_prefix (NULL), n); - - if (n != WAIT_TIMEOUT) - return 1; - - return 0; -} - -int -pth_wait (pth_event_t ev) -{ - int rc; - - implicit_init (); - enter_pth (__FUNCTION__); - rc = do_pth_wait (ev); - leave_pth (__FUNCTION__); - return rc; -} - - -int -pth_sleep (int sec) -{ - static pth_key_t ev_key = PTH_KEY_INIT; - pth_event_t ev; - - implicit_init (); - enter_pth (__FUNCTION__); - - if (sec == 0) - { - leave_pth (__FUNCTION__); - return 0; - } - - ev = do_pth_event (PTH_EVENT_TIME|PTH_MODE_STATIC, &ev_key, - pth_timeout (sec, 0)); - if (ev == NULL) - { - leave_pth (__FUNCTION__); - return -1; - } - do_pth_wait (ev); - do_pth_event_free (ev, PTH_FREE_ALL); - - leave_pth (__FUNCTION__); - return 0; -} - - - - - -/* - Some simple tests. - */ -#ifdef TEST -#include <stdio.h> - -void * thread (void * c) -{ - - Sleep (2000); - SetEvent (((pth_event_t)c)->hd); - fprintf (stderr, "\n\nhallo!.\n"); - pth_exit (NULL); - return NULL; -} - - -int main_1 (int argc, char ** argv) -{ - pth_attr_t t; - pth_t hd; - pth_event_t ev; - - pth_init (); - ev = pth_event (0, NULL); - t = pth_attr_new (); - pth_attr_set (t, PTH_ATTR_JOINABLE, 1); - pth_attr_set (t, PTH_ATTR_STACK_SIZE, 4096); - pth_attr_set (t, PTH_ATTR_NAME, "hello"); - hd = pth_spawn (t, thread, ev); - - pth_wait (ev); - pth_attr_destroy (t); - pth_event_free (ev, 0); - pth_kill (); - - return 0; -} - - -static pth_event_t -setup_signals (struct sigset_s *sigs, int *signo) -{ - pth_event_t ev; - - sigemptyset (sigs); - sigaddset (sigs, SIGINT); - sigaddset (sigs, SIGTERM); - - ev = pth_event (PTH_EVENT_SIGS, sigs, signo); - return ev; -} - -int -main_2 (int argc, char ** argv) -{ - pth_event_t ev; - struct sigset_s sigs; - int signo = 0; - - pth_init (); - ev = setup_signals (&sigs, &signo); - pth_wait (ev); - if (pth_event_occured (ev) && signo) - fprintf (stderr, "signal caught! signo %d\n", signo); - - pth_event_free (ev, PTH_FREE_ALL); - pth_kill (); - return 0; -} - -int -main_3 (int argc, char ** argv) -{ - struct sockaddr_in addr, rem; - int fd, n = 0, infd; - int signo = 0; - struct sigset_s sigs; - pth_event_t ev; - - pth_init (); - fd = socket (AF_INET, SOCK_STREAM, 0); - - memset (&addr, 0, sizeof addr); - addr.sin_addr.s_addr = INADDR_ANY; - addr.sin_port = htons (5050); - addr.sin_family = AF_INET; - bind (fd, (struct sockaddr*)&addr, sizeof addr); - listen (fd, 5); - - ev = setup_signals (&sigs, &signo); - n = sizeof addr; - infd = pth_accept_ev (fd, (struct sockaddr *)&rem, &n, ev); - fprintf (stderr, "infd %d: %s:%d\n", infd, inet_ntoa (rem.sin_addr), - htons (rem.sin_port)); - - closesocket (infd); - pth_event_free (ev, PTH_FREE_ALL); - pth_kill (); - return 0; -} - -int -main (int argc, char ** argv) -{ - pth_event_t ev; - pth_key_t ev_key; - - pth_init (); - /*ev = pth_event (PTH_EVENT_TIME, &ev_key, pth_timeout (5, 0)); - pth_wait (ev); - pth_event_free (ev, PTH_FREE_ALL);*/ - pth_sleep (5); - pth_kill (); - return 0; -} -#endif - -#endif /*HAVE_W32_SYSTEM*/ - diff --git a/jnlib/w32-pth.h b/jnlib/w32-pth.h deleted file mode 100644 index e351a9f0a..000000000 --- a/jnlib/w32-pth.h +++ /dev/null @@ -1,245 +0,0 @@ -/* w32-pth.h - GNU Pth emulation for W32 (MS Windows). - * Copyright (c) 1999-2003 Ralf S. Engelschall <[email protected]> - * Copyright (C) 2004, 2006 g10 Code GmbH - * - * This file is part of JNLIB. - * - * JNLIB 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. - * - * JNLIB 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 program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * ------------------------------------------------------------------ - * This code is based on Ralf Engelschall's GNU Pth, a non-preemptive - * thread scheduling library which can be found at - * http://www.gnu.org/software/pth/. - */ - -/* Note that this header is usually used through a symlinked pth.h - file. This is needed so that we don't have a pth.h file here which - would conflict if a system really has pth available. */ -#ifndef W32_PTH_H -#define W32_PTH_H - -#include <windows.h> /* We need this for sockaddr et al. FIXME: too - heavyweight - may be we should factor such - code out to a second header and adjust all - user files to include it only if required. */ - -#ifndef W32_PTH_HANDLE_INTERNAL -#define W32_PTH_HANDLE_INTERNAL int -#endif - - -/* Filedescriptor blocking modes. */ -enum - { - PTH_FDMODE_ERROR = -1, - PTH_FDMODE_POLL = 0, - PTH_FDMODE_BLOCK, - PTH_FDMODE_NONBLOCK - }; - - -/* Mutex values. */ -#define PTH_MUTEX_INITIALIZED (1<<0) -#define PTH_MUTEX_LOCKED (1<<1) - -/* Note: We can't do static initialization, thus we don't define the - initializer PTH_MUTEX_INIT. */ - - -#define PTH_KEY_INIT (1<<0) - - -/* Event subject classes. */ -#define PTH_EVENT_FD (1<<1) -#define PTH_EVENT_SELECT (1<<2) -#define PTH_EVENT_SIGS (1<<3) -#define PTH_EVENT_TIME (1<<4) -#define PTH_EVENT_MSG (1<<5) -#define PTH_EVENT_MUTEX (1<<6) -#define PTH_EVENT_COND (1<<7) -#define PTH_EVENT_TID (1<<8) -#define PTH_EVENT_FUNC (1<<9) - - - -/* Event occurrence restrictions. */ -#define PTH_UNTIL_OCCURRED (1<<11) -#define PTH_UNTIL_FD_READABLE (1<<12) -#define PTH_UNTIL_FD_WRITEABLE (1<<13) -#define PTH_UNTIL_FD_EXCEPTION (1<<14) -#define PTH_UNTIL_TID_NEW (1<<15) -#define PTH_UNTIL_TID_READY (1<<16) -#define PTH_UNTIL_TID_WAITING (1<<17) -#define PTH_UNTIL_TID_DEAD (1<<18) - - -/* Event structure handling modes. */ -#define PTH_MODE_REUSE (1<<20) -#define PTH_MODE_CHAIN (1<<21) -#define PTH_MODE_STATIC (1<<22) - - -/* Attribute commands for pth_attr_get and pth_attr_set(). */ -enum - { - PTH_ATTR_PRIO, /* RW [int] Priority of thread. */ - PTH_ATTR_NAME, /* RW [char *] Name of thread. */ - PTH_ATTR_JOINABLE, /* RW [int] Thread detachment type. */ - PTH_ATTR_CANCEL_STATE, /* RW [unsigned int] Thread cancellation state.*/ - PTH_ATTR_STACK_SIZE, /* RW [unsigned int] Stack size. */ - PTH_ATTR_STACK_ADDR, /* RW [char *] Stack lower address. */ - PTH_ATTR_DISPATCHES, /* RO [int] Total number of - thread dispatches. */ - PTH_ATTR_TIME_SPAWN, /* RO [pth_time_t] Time thread was spawned. */ - PTH_ATTR_TIME_LAST, /* RO [pth_time_t] Time thread was - last dispatched. */ - PTH_ATTR_TIME_RAN, /* RO [pth_time_t] Time thread was running. */ - PTH_ATTR_START_FUNC, /* RO [void *(*)(void *)] Thread start function.*/ - PTH_ATTR_START_ARG, /* RO [void *] Thread start argument. */ - PTH_ATTR_STATE, /* RO [pth_state_t] Scheduling state. */ - PTH_ATTR_EVENTS, /* RO [pth_event_t] Events the thread - is waiting for. */ - PTH_ATTR_BOUND /* RO [int] Whether object is - bound to thread. */ - }; - - - -/* Queries for pth_ctrl(). */ -#define PTH_CTRL_GETAVLOAD (1<<1) -#define PTH_CTRL_GETPRIO (1<<2) -#define PTH_CTRL_GETNAME (1<<3) -#define PTH_CTRL_GETTHREADS_NEW (1<<4) -#define PTH_CTRL_GETTHREADS_READY (1<<5) -#define PTH_CTRL_GETTHREADS_RUNNING (1<<6) -#define PTH_CTRL_GETTHREADS_WAITING (1<<7) -#define PTH_CTRL_GETTHREADS_SUSPENDED (1<<8) -#define PTH_CTRL_GETTHREADS_DEAD (1<<9) -#define PTH_CTRL_DUMPSTATE (1<<10) - -#define PTH_CTRL_GETTHREADS ( PTH_CTRL_GETTHREADS_NEW \ - | PTH_CTRL_GETTHREADS_READY \ - | PTH_CTRL_GETTHREADS_RUNNING \ - | PTH_CTRL_GETTHREADS_WAITING \ - | PTH_CTRL_GETTHREADS_SUSPENDED \ - | PTH_CTRL_GETTHREADS_DEAD ) - - -/* Event status codes. */ -typedef enum - { - PTH_STATUS_PENDING, - PTH_STATUS_OCCURRED, - PTH_STATUS_FAILED - } -pth_status_t; - - -/* Event deallocation types. */ -enum - { - PTH_FREE_THIS, - PTH_FREE_ALL - }; - - -/* The Pth thread handle object. */ -typedef void *pth_t; - - -/* The Mutex object. */ -typedef W32_PTH_HANDLE_INTERNAL pth_mutex_t; - - -/* The Event object. */ -struct pth_event_s; -typedef struct pth_event_s *pth_event_t; - - -/* The Attribute object. */ -struct pth_attr_s; -typedef struct pth_attr_s *pth_attr_t; - - -/* The Key object. */ -typedef int pth_key_t; - - -/* The Pth time object. */ -typedef struct timeval pth_time_t; - - -/* Function prototypes. */ -int pth_init (void); -int pth_kill (void); -long pth_ctrl (unsigned long query, ...); - -int pth_read_ev (int fd, void *buffer, size_t size, pth_event_t ev); -int pth_read (int fd, void *buffer, size_t size); -int pth_write_ev (int fd, const void *buffer, size_t size, pth_event_t ev); -int pth_write (int fd, const void *buffer, size_t size); - -int pth_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, - const struct timeval *timeout); - -int pth_accept (int fd, struct sockaddr *addr, int *addrlen); -int pth_accept_ev (int fd, struct sockaddr *addr, int *addrlen, - pth_event_t hd); - -int pth_connect (int fd, struct sockaddr *name, int namelen); - - -int pth_mutex_release (pth_mutex_t *hd); -int pth_mutex_acquire(pth_mutex_t *hd, int try_only, pth_event_t ev_extra); -int pth_mutex_init (pth_mutex_t *hd); - - -pth_attr_t pth_attr_new (void); -int pth_attr_destroy (pth_attr_t hd); -int pth_attr_set (pth_attr_t hd, int field, ...); - -pth_t pth_spawn (pth_attr_t hd, void *(*func)(void *), void *arg); -pth_t pth_self (void); -int pth_join (pth_t hd, void **value); -int pth_abort (pth_t hd); -void pth_exit (void *value); - -unsigned int pth_waitpid (unsigned int, int *status, int options); -int pth_wait (pth_event_t hd); - -int pth_sleep (int n); -pth_time_t pth_timeout (long sec, long usec); - - - -pth_event_t pth_event_isolate (pth_event_t hd); -int pth_event_free (pth_event_t hd, int mode); -int pth_event_status (pth_event_t hd); -int pth_event_occurred (pth_event_t hd); -pth_event_t pth_event_concat (pth_event_t ev, ...); -pth_event_t pth_event (unsigned long spec, ...); - - - -/*-- pth_util.c --*/ - -/* void sigemptyset (struct sigset_s * ss); */ - -/* int sigaddset (struct sigset_s * ss, int signo); */ - - - -#endif /*W32_PTH_H*/ diff --git a/jnlib/w32-reg.c b/jnlib/w32-reg.c new file mode 100644 index 000000000..b7a383e3f --- /dev/null +++ b/jnlib/w32-reg.c @@ -0,0 +1,184 @@ +/* w32-reg.c - MS-Windows Registry access + * Copyright (C) 1999, 2002, 2007 Free Software Foundation, Inc. + * + * This file is part of JNLIB. + * + * JNLIB 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. + * + * JNLIB 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 program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include <config.h> +#ifdef HAVE_W32_SYSTEM + /* This module is only used in this environment */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <windows.h> + +#include "libjnlib-config.h" +#include "w32help.h" + +static HKEY +get_root_key(const char *root) +{ + HKEY root_key; + + if (!root) + root_key = HKEY_CURRENT_USER; + else if (!strcmp( root, "HKEY_CLASSES_ROOT" ) ) + root_key = HKEY_CLASSES_ROOT; + else if (!strcmp( root, "HKEY_CURRENT_USER" ) ) + root_key = HKEY_CURRENT_USER; + else if (!strcmp( root, "HKEY_LOCAL_MACHINE" ) ) + root_key = HKEY_LOCAL_MACHINE; + else if (!strcmp( root, "HKEY_USERS" ) ) + root_key = HKEY_USERS; + else if (!strcmp( root, "HKEY_PERFORMANCE_DATA" ) ) + root_key = HKEY_PERFORMANCE_DATA; + else if (!strcmp( root, "HKEY_CURRENT_CONFIG" ) ) + root_key = HKEY_CURRENT_CONFIG; + else + return NULL; + + return root_key; +} + + +/* Return a string from the Win32 Registry or NULL in case of error. + Caller must release the return value. A NULL for root is an alias + for HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE in turn. */ +char * +read_w32_registry_string (const char *root, const char *dir, const char *name) +{ + HKEY root_key, key_handle; + DWORD n1, nbytes, type; + char *result = NULL; + + if ( !(root_key = get_root_key(root) ) ) + return NULL; + + if ( RegOpenKeyEx( root_key, dir, 0, KEY_READ, &key_handle ) ) + { + if (root) + return NULL; /* No need for a RegClose, so return immediately. */ + /* It seems to be common practise to fall back to HKLM. */ + if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle) ) + return NULL; /* Still no need for a RegClose. */ + } + + nbytes = 1; + if (RegQueryValueEx( key_handle, name, 0, NULL, NULL, &nbytes ) ) + goto leave; + result = jnlib_malloc ((n1=nbytes+1)); + if (!result) + goto leave; + if (RegQueryValueEx( key_handle, name, 0, &type, result, &n1 )) + { + jnlib_free (result); + result = NULL; + goto leave; + } + result[nbytes] = 0; /* Make sure it is a string. */ + if (type == REG_EXPAND_SZ && strchr (result, '%')) + { + char *tmp; + + n1 += 1000; + tmp = jnlib_malloc (n1+1); + if (!tmp) + goto leave; + nbytes = ExpandEnvironmentStrings (result, tmp, n1); + if (nbytes && nbytes > n1) + { + jnlib_free (tmp); + n1 = nbytes; + tmp = jnlib_malloc (n1 + 1); + if (!tmp) + goto leave; + nbytes = ExpandEnvironmentStrings (result, tmp, n1); + if (nbytes && nbytes > n1) + { + /* Oops - truncated, better don't expand at all. */ + jnlib_free (tmp); + goto leave; + } + tmp[nbytes] = 0; + jnlib_free (result); + result = tmp; + } + else if (nbytes) + { + /* Okay, reduce the length. */ + tmp[nbytes] = 0; + jnlib_free (result); + result = jnlib_malloc (strlen (tmp)+1); + if (!result) + result = tmp; + else + { + strcpy (result, tmp); + jnlib_free (tmp); + } + } + else + { + /* Error - don't expand. */ + jnlib_free (tmp); + } + } + + leave: + RegCloseKey (key_handle); + return result; +} + + +int +write_w32_registry_string (const char *root, const char *dir, + const char *name, const char *value) +{ + HKEY root_key, reg_key; + + if ( !(root_key = get_root_key(root) ) ) + return -1; + + if ( RegOpenKeyEx( root_key, dir, 0, KEY_WRITE, ®_key ) + != ERROR_SUCCESS ) + return -1; + + if ( RegSetValueEx (reg_key, name, 0, REG_SZ, (BYTE *)value, + strlen( value ) ) != ERROR_SUCCESS ) + { + if ( RegCreateKey( root_key, name, ®_key ) != ERROR_SUCCESS ) + { + RegCloseKey(reg_key); + return -1; + } + if ( RegSetValueEx (reg_key, name, 0, REG_SZ, (BYTE *)value, + strlen( value ) ) != ERROR_SUCCESS ) + { + RegCloseKey(reg_key); + return -1; + } + } + + RegCloseKey (reg_key); + + return 0; +} + +#endif /*HAVE_W32_SYSTEM*/ diff --git a/jnlib/w32help.h b/jnlib/w32help.h new file mode 100644 index 000000000..cb1dafcf5 --- /dev/null +++ b/jnlib/w32help.h @@ -0,0 +1,41 @@ +/* w32help.h - W32 speicif functions + * Copyright (C) 2007 Free Software Foundation, Inc. + * + * This file is part of JNLIB. + * + * JNLIB 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. + * + * JNLIB 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 program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifndef LIBJNLIB_W32HELP_H +#define LIBJNLIB_W32HELP_H +#ifdef HAVE_W32_SYSTEM + +/*-- w32-reg.c --*/ +char *read_w32_registry_string (const char *root, + const char *dir, const char *name ); +int write_w32_registry_string (const char *root, const char *dir, + const char *name, const char *value); + +#ifdef USE_SIMPLE_GETTEXT +int set_gettext_file (const char *filename, const char *regkey); +const char *gettext (const char *msgid ); +const char *ngettext (const char *msgid1, const char *msgid2, + unsigned long int n); +#endif /*USE_SIMPLE_GETTEXT*/ + + +#endif /*HAVE_W32_SYSTEM*/ +#endif /*LIBJNLIB_MISCHELP_H*/ |