aboutsummaryrefslogtreecommitdiffstats
path: root/src/init.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/init.c')
-rw-r--r--src/init.c256
1 files changed, 203 insertions, 53 deletions
diff --git a/src/init.c b/src/init.c
index 60c60b7..c9e0047 100644
--- a/src/init.c
+++ b/src/init.c
@@ -35,13 +35,25 @@
/* Locale directory support. */
#if HAVE_W32_SYSTEM
-/* The implementation follows below. */
+/* The TLS space definition. */
+struct tls_space_s
+{
+ /* 119 bytes for an error message should be enough. With this size
+ we can assume that the allocation does not take up more than 128
+ bytes per thread. */
+ char strerror_buffer[120];
+};
+static int tls_index; /* Index for the TLS functions. */
+
static char *get_locale_dir (void);
static void drop_locale_dir (char *locale_dir);
-#else
+
+#else /*!HAVE_W32_SYSTEM*/
+
#define get_locale_dir() LOCALEDIR
#define drop_locale_dir(dir)
-#endif
+
+#endif /*!HAVE_W32_SYSTEM*/
/* Initialize the library. This function should be run early. */
@@ -121,62 +133,72 @@ read_w32_registry_string( const char *root, const char *dir, const char *name )
}
nbytes = 1;
- if( RegQueryValueEx( key_handle, name, 0, NULL, NULL, &nbytes ) ) {
- if (root)
- goto leave;
- /* Try to fallback to HKLM also vor a missing value. */
- RegCloseKey (key_handle);
- if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle) )
- return NULL; /* Nope. */
- if (RegQueryValueEx( key_handle, name, 0, NULL, NULL, &nbytes))
- goto leave;
- }
- result = malloc( (n1=nbytes+1) );
+ if( RegQueryValueEx( key_handle, name, 0, NULL, NULL, &nbytes ) )
+ {
+ if (root)
+ goto leave;
+ /* Try to fallback to HKLM also vor a missing value. */
+ RegCloseKey (key_handle);
+ if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle) )
+ return NULL; /* Nope. */
+ if (RegQueryValueEx( key_handle, name, 0, NULL, NULL, &nbytes))
+ goto leave;
+ }
+ result = malloc ( (n1=nbytes+1) );
if( !result )
goto leave;
- if( RegQueryValueEx( key_handle, name, 0, &type, result, &n1 ) ) {
- free(result); result = NULL;
- goto leave;
- }
+ if( RegQueryValueEx( key_handle, name, 0, &type, result, &n1 ) )
+ {
+ free(result); result = NULL;
+ goto leave;
+ }
result[nbytes] = 0; /* make sure it is really a string */
- if (type == REG_EXPAND_SZ && strchr (result, '%')) {
- char *tmp;
- n1 += 1000;
- tmp = malloc (n1+1);
- if (!tmp)
- goto leave;
- nbytes = ExpandEnvironmentStrings (result, tmp, n1);
- if (nbytes && nbytes > n1) {
- free (tmp);
- n1 = nbytes;
- tmp = malloc (n1 + 1);
+#ifndef HAVE_W32CE_SYSTEM /* W32CE has no environment variables. */
+ if (type == REG_EXPAND_SZ && strchr (result, '%'))
+ {
+ char *tmp;
+
+ n1 += 1000;
+ tmp = malloc (n1+1);
if (!tmp)
- goto leave;
+ goto leave;
nbytes = ExpandEnvironmentStrings (result, tmp, n1);
- if (nbytes && nbytes > n1) {
- free (tmp); /* oops - truncated, better don't expand at all */
- goto leave;
- }
- tmp[nbytes] = 0;
- free (result);
- result = tmp;
+ if (nbytes && nbytes > n1)
+ {
+ free (tmp);
+ n1 = nbytes;
+ tmp = malloc (n1 + 1);
+ if (!tmp)
+ goto leave;
+ nbytes = ExpandEnvironmentStrings (result, tmp, n1);
+ if (nbytes && nbytes > n1)
+ {
+ free (tmp); /* oops - truncated, better don't expand at all */
+ goto leave;
+ }
+ tmp[nbytes] = 0;
+ free (result);
+ result = tmp;
+ }
+ else if (nbytes) /* okay, reduce the length */
+ {
+ tmp[nbytes] = 0;
+ free (result);
+ result = malloc (strlen (tmp)+1);
+ if (!result)
+ result = tmp;
+ else {
+ strcpy (result, tmp);
+ free (tmp);
+ }
+ }
+ else /* error - don't expand */
+ {
+ free (tmp);
+ }
}
- else if (nbytes) { /* okay, reduce the length */
- tmp[nbytes] = 0;
- free (result);
- result = malloc (strlen (tmp)+1);
- if (!result)
- result = tmp;
- else {
- strcpy (result, tmp);
- free (tmp);
- }
- }
- else { /* error - don't expand */
- free (tmp);
- }
- }
+#endif /*HAVE_W32CE_SYSTEM*/
leave:
RegCloseKey( key_handle );
@@ -223,4 +245,132 @@ drop_locale_dir (char *locale_dir)
free (locale_dir);
}
-#endif /* HAVE_W32_SYSTEM */
+
+/* Return the tls object. This function is guaranteed to return a
+ valid non-NULL object. */
+#ifdef HAVE_W32CE_SYSTEM
+static struct tls_space_s *
+get_tls (void)
+{
+ struct tls_space_s *tls;
+
+ tls = TlsGetValue (tls_index);
+ if (!tls)
+ {
+ /* Called by a thread which existed before this DLL was loaded.
+ Allocate the space. */
+ tls = LocalAlloc (LPTR, sizeof *tls);
+ if (!tls)
+ {
+ /* No way to continue - commit suicide. */
+ abort ();
+ }
+ TlsSetValue (tls_index, tls);
+ }
+
+ return tls;
+}
+#endif /*HAVE_W32CE_SYSTEM*/
+
+/* Return the value of the ERRNO variable. This needs to be a
+ function so that we can have a per-thread ERRNO. This is used only
+ on WindowsCE because that OS misses an errno. */
+#ifdef HAVE_W32CE_SYSTEM
+int
+_gpg_w32ce_get_errno (void)
+{
+ int err;
+
+ err = GetLastError ();
+ /* FIXME: Should we fold some W32 error codes into the same errno
+ value? */
+ return err;
+}
+#endif /*HAVE_W32CE_SYSTEM*/
+
+
+/* Replacement strerror function for WindowsCE. */
+#ifdef HAVE_W32CE_SYSTEM
+char *
+_gpg_w32ce_strerror (int err)
+{
+ struct tls_space_s *tls = get_tls ();
+
+ if (err == -1)
+ err = _gpg_w32ce_get_errno ();
+ if (!FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, err,
+ MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
+ tls->strerror_buffer, sizeof tls->strerror_buffer -1,
+ NULL))
+ snprintf (tls->strerror_buffer, sizeof tls->strerror_buffer -1,
+ "[w32err=%d]", err);
+ return tls->strerror_buffer;
+}
+#endif /*HAVE_W32CE_SYSTEM*/
+
+
+void
+gpg_err_set_errno (int err)
+{
+#ifdef HAVE_W32CE_SYSTEM
+ SetLastError (err);
+#else /*!HAVE_W32CE_SYSTEM*/
+ errno = err;
+#endif /*!HAVE_W32CE_SYSTEM*/
+}
+
+
+/* Entry point called by the DLL loader. This is only used by
+ WindowsCE for now; we might eventually use TLS to implement a
+ thread safe strerror. */
+#ifdef HAVE_W32CE_SYSTEM
+int WINAPI
+DllMain (HINSTANCE hinst, DWORD reason, LPVOID reserved)
+{
+ struct tls_space_s *tls;
+ (void)reserved;
+
+ switch (reason)
+ {
+ case DLL_PROCESS_ATTACH:
+ tls_index = TlsAlloc ();
+ if (tls_index == TLS_OUT_OF_INDEXES)
+ return FALSE;
+ /* falltru. */
+ case DLL_THREAD_ATTACH:
+ tls = LocalAlloc (LPTR, sizeof *tls);
+ if (!tls)
+ return FALSE;
+ TlsSetValue (tls_index, tls);
+ break;
+
+ case DLL_THREAD_DETACH:
+ tls = TlsGetValue (tls_index);
+ if (tls)
+ LocalFree (tls);
+ break;
+
+ case DLL_PROCESS_DETACH:
+ tls = TlsGetValue (tls_index);
+ if (tls)
+ LocalFree (tls);
+ TlsFree (tls_index);
+ break;
+
+ default:
+ break;
+ }
+
+ return TRUE;
+}
+#endif /*HAVE_W32CE_SYSTEM*/
+
+#else /*!HAVE_W32_SYSTEM*/
+
+void
+gpg_err_set_errno (int err)
+{
+ errno = err;
+}
+
+#endif /*!HAVE_W32_SYSTEM*/