Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F18824743
w32-util.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
14 KB
Subscribers
None
w32-util.c
View Options
/* w32-util.c - Utility functions for the W32 API
Copyright (C) 1999 Free Software Foundation, Inc
Copyright (C) 2001 Werner Koch (dd9jn)
Copyright (C) 2001, 2002, 2003, 2004, 2007 g10 Code GmbH
This file is part of GPGME.
GPGME 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.
GPGME 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., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
#ifdef HAVE_CONFIG_H
#include
<config.h>
#endif
#include
<stdio.h>
#include
<stdlib.h>
#include
<string.h>
#include
<assert.h>
#include
<errno.h>
#include
<stdint.h>
#include
<sys/time.h>
#include
<sys/types.h>
#include
<sys/stat.h>
#include
<unistd.h>
#include
<signal.h>
#include
<fcntl.h>
#include
<windows.h>
#include
<shlobj.h>
#include
<io.h>
#include
"util.h"
#include
"sema.h"
#include
"debug.h"
DEFINE_STATIC_LOCK
(
get_path_lock
);
#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__
int
dlclose
(
void
*
hd
)
{
if
(
hd
)
{
FreeLibrary
(
hd
);
return
0
;
}
return
-1
;
}
/* Return a string from the W32 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. */
static
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
)
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
;
if
(
RegOpenKeyEx
(
root_key
,
dir
,
0
,
KEY_READ
,
&
key_handle
)
)
{
if
(
root
)
return
NULL
;
/* no need for a RegClose, so return direct */
/* 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, so return direct */
}
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
;
}
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
);
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
);
}
}
leave
:
RegCloseKey
(
key_handle
);
return
result
;
}
/* This is a helper function to load and run a Windows function from
either of one DLLs. */
static
HRESULT
w32_shgetfolderpath
(
HWND
a
,
int
b
,
HANDLE
c
,
DWORD
d
,
LPSTR
e
)
{
static
int
initialized
;
static
HRESULT
(
WINAPI
*
func
)(
HWND
,
int
,
HANDLE
,
DWORD
,
LPSTR
);
if
(
!
initialized
)
{
static
char
*
dllnames
[]
=
{
"shell32.dll"
,
"shfolder.dll"
,
NULL
};
void
*
handle
;
int
i
;
initialized
=
1
;
for
(
i
=
0
,
handle
=
NULL
;
!
handle
&&
dllnames
[
i
];
i
++
)
{
handle
=
dlopen
(
dllnames
[
i
],
RTLD_LAZY
);
if
(
handle
)
{
func
=
dlsym
(
handle
,
"SHGetFolderPathA"
);
if
(
!
func
)
{
dlclose
(
handle
);
handle
=
NULL
;
}
}
}
}
if
(
func
)
return
func
(
a
,
b
,
c
,
d
,
e
);
else
return
-1
;
}
#if 0
static char *
find_program_in_registry (const char *name)
{
char *program = NULL;
program = read_w32_registry_string (NULL, "Software\\GNU\\GnuPG", name);
if (program)
{
int i;
TRACE2 (DEBUG_CTX, "gpgme:find_program_in_registry", 0,
"found %s in registry: `%s'", name, program);
for (i = 0; program[i]; i++)
{
if (program[i] == '/')
program[i] = '\\';
}
}
return program;
}
#endif
static
char
*
find_program_in_inst_dir
(
const
char
*
name
)
{
char
*
result
=
NULL
;
char
*
tmp
;
tmp
=
read_w32_registry_string
(
"HKEY_LOCAL_MACHINE"
,
"Software
\\
GNU
\\
GnuPG"
,
"Install Directory"
);
if
(
!
tmp
)
return
NULL
;
result
=
malloc
(
strlen
(
tmp
)
+
1
+
strlen
(
name
)
+
1
);
if
(
!
result
)
{
free
(
tmp
);
return
NULL
;
}
strcpy
(
stpcpy
(
stpcpy
(
result
,
tmp
),
"
\\
"
),
name
);
free
(
tmp
);
if
(
access
(
result
,
F_OK
))
{
free
(
result
);
return
NULL
;
}
return
result
;
}
static
char
*
find_program_at_standard_place
(
const
char
*
name
)
{
char
path
[
MAX_PATH
];
char
*
result
=
NULL
;
if
(
w32_shgetfolderpath
(
NULL
,
CSIDL_PROGRAM_FILES
,
NULL
,
0
,
path
)
>=
0
)
{
result
=
malloc
(
strlen
(
path
)
+
1
+
strlen
(
name
)
+
1
);
if
(
result
)
{
strcpy
(
stpcpy
(
stpcpy
(
result
,
path
),
"
\\
"
),
name
);
if
(
access
(
result
,
F_OK
))
{
free
(
result
);
result
=
NULL
;
}
}
}
return
result
;
}
const
char
*
_gpgme_get_gpg_path
(
void
)
{
static
char
*
gpg_program
;
LOCK
(
get_path_lock
);
#if 0
if (!gpg_program)
gpg_program = find_program_in_registry ("gpgProgram");
#endif
if
(
!
gpg_program
)
gpg_program
=
find_program_in_inst_dir
(
"gpg.exe"
);
if
(
!
gpg_program
)
gpg_program
=
find_program_at_standard_place
(
"GNU
\\
GnuPG
\\
gpg.exe"
);
UNLOCK
(
get_path_lock
);
return
gpg_program
;
}
const
char
*
_gpgme_get_gpgsm_path
(
void
)
{
static
char
*
gpgsm_program
;
LOCK
(
get_path_lock
);
#if 0
if (!gpgsm_program)
gpgsm_program = find_program_in_registry ("gpgsmProgram");
#endif
if
(
!
gpgsm_program
)
gpgsm_program
=
find_program_in_inst_dir
(
"gpgsm.exe"
);
if
(
!
gpgsm_program
)
gpgsm_program
=
find_program_at_standard_place
(
"GNU
\\
GnuPG
\\
gpgsm.exe"
);
UNLOCK
(
get_path_lock
);
return
gpgsm_program
;
}
const
char
*
_gpgme_get_gpgconf_path
(
void
)
{
static
char
*
gpgconf_program
;
LOCK
(
get_path_lock
);
#if 0
if (!gpgconf_program)
gpgconf_program = find_program_in_registry ("gpgconfProgram");
#endif
if
(
!
gpgconf_program
)
gpgconf_program
=
find_program_in_inst_dir
(
"gpgconf.exe"
);
if
(
!
gpgconf_program
)
gpgconf_program
=
find_program_at_standard_place
(
"GNU
\\
GnuPG
\\
gpgconf.exe"
);
UNLOCK
(
get_path_lock
);
return
gpgconf_program
;
}
const
char
*
_gpgme_get_g13_path
(
void
)
{
static
char
*
g13_program
;
LOCK
(
get_path_lock
);
#if 0
if (!g13_program)
g13_program = find_program_in_registry ("g13Program");
#endif
if
(
!
g13_program
)
g13_program
=
find_program_in_inst_dir
(
"g13.exe"
);
if
(
!
g13_program
)
g13_program
=
find_program_at_standard_place
(
"GNU
\\
GnuPG
\\
g13.exe"
);
UNLOCK
(
get_path_lock
);
return
g13_program
;
}
const
char
*
_gpgme_get_uiserver_socket_path
(
void
)
{
static
char
*
socket_path
;
char
*
homedir
;
const
char
name
[]
=
"S.uiserver"
;
if
(
socket_path
)
return
socket_path
;
homedir
=
_gpgme_get_default_homedir
();
if
(
!
homedir
)
return
NULL
;
socket_path
=
malloc
(
strlen
(
homedir
)
+
1
+
strlen
(
name
)
+
1
);
if
(
!
socket_path
)
return
NULL
;
strcpy
(
stpcpy
(
stpcpy
(
socket_path
,
homedir
),
"
\\
"
),
name
);
return
socket_path
;
}
const
char
*
_gpgme_get_w32spawn_path
(
void
)
{
static
char
*
w32spawn_program
;
LOCK
(
get_path_lock
);
if
(
!
w32spawn_program
)
w32spawn_program
=
find_program_in_inst_dir
(
"gpgme-w32spawn.exe"
);
if
(
!
w32spawn_program
)
w32spawn_program
=
find_program_at_standard_place
(
"GNU
\\
GnuPG
\\
gpgme-w32spawn.exe"
);
UNLOCK
(
get_path_lock
);
return
w32spawn_program
;
}
/* Return an integer value from gpgme specific configuration
entries. VALUE receives that value; function returns true if a value
has been configured and false if not. */
int
_gpgme_get_conf_int
(
const
char
*
key
,
int
*
value
)
{
char
*
tmp
=
read_w32_registry_string
(
NULL
,
"Software
\\
GNU
\\
gpgme"
,
key
);
if
(
!
tmp
)
return
0
;
*
value
=
atoi
(
tmp
);
free
(
tmp
);
return
1
;
}
void
_gpgme_allow_set_foreground_window
(
pid_t
pid
)
{
static
int
initialized
;
static
BOOL
(
WINAPI
*
func
)(
DWORD
);
void
*
handle
;
if
(
!
initialized
)
{
/* Available since W2000; thus we dynload it. */
initialized
=
1
;
handle
=
dlopen
(
"user32.dll"
,
RTLD_LAZY
);
if
(
handle
)
{
func
=
dlsym
(
handle
,
"AllowSetForegroundWindow"
);
if
(
!
func
)
{
dlclose
(
handle
);
handle
=
NULL
;
}
}
}
if
(
!
pid
||
pid
==
(
pid_t
)(
-1
))
{
TRACE1
(
DEBUG_ENGINE
,
"gpgme:AllowSetForegroundWindow"
,
0
,
"no action for pid %d"
,
(
int
)
pid
);
}
else
if
(
func
)
{
int
rc
=
func
(
pid
);
TRACE2
(
DEBUG_ENGINE
,
"gpgme:AllowSetForegroundWindow"
,
0
,
"called for pid %d; result=%d"
,
(
int
)
pid
,
rc
);
}
else
{
TRACE0
(
DEBUG_ENGINE
,
"gpgme:AllowSetForegroundWindow"
,
0
,
"function not available"
);
}
}
/* mkstemp extracted from libc/sysdeps/posix/tempname.c. Copyright
(C) 1991-1999, 2000, 2001, 2006 Free Software Foundation, Inc.
The GNU C 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. */
static
const
char
letters
[]
=
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
;
/* Generate a temporary file name based on TMPL. TMPL must match the
rules for mk[s]temp (i.e. end in "XXXXXX"). The name constructed
does not exist at the time of the call to mkstemp. TMPL is
overwritten with the result. */
static
int
mkstemp
(
char
*
tmpl
)
{
int
len
;
char
*
XXXXXX
;
static
uint64_t
value
;
uint64_t
random_time_bits
;
unsigned
int
count
;
int
fd
=
-1
;
int
save_errno
=
errno
;
/* A lower bound on the number of temporary files to attempt to
generate. The maximum total number of temporary file names that
can exist for a given template is 62**6. It should never be
necessary to try all these combinations. Instead if a reasonable
number of names is tried (we define reasonable as 62**3) fail to
give the system administrator the chance to remove the problems. */
#define ATTEMPTS_MIN (62 * 62 * 62)
/* The number of times to attempt to generate a temporary file. To
conform to POSIX, this must be no smaller than TMP_MAX. */
#if ATTEMPTS_MIN < TMP_MAX
unsigned
int
attempts
=
TMP_MAX
;
#else
unsigned
int
attempts
=
ATTEMPTS_MIN
;
#endif
len
=
strlen
(
tmpl
);
if
(
len
<
6
||
strcmp
(
&
tmpl
[
len
-
6
],
"XXXXXX"
))
{
errno
=
EINVAL
;
return
-1
;
}
/* This is where the Xs start. */
XXXXXX
=
&
tmpl
[
len
-
6
];
/* Get some more or less random data. */
{
FILETIME
ft
;
GetSystemTimeAsFileTime
(
&
ft
);
random_time_bits
=
(((
uint64_t
)
ft
.
dwHighDateTime
<<
32
)
|
(
uint64_t
)
ft
.
dwLowDateTime
);
}
value
+=
random_time_bits
^
getpid
();
for
(
count
=
0
;
count
<
attempts
;
value
+=
7777
,
++
count
)
{
uint64_t
v
=
value
;
/* Fill in the random bits. */
XXXXXX
[
0
]
=
letters
[
v
%
62
];
v
/=
62
;
XXXXXX
[
1
]
=
letters
[
v
%
62
];
v
/=
62
;
XXXXXX
[
2
]
=
letters
[
v
%
62
];
v
/=
62
;
XXXXXX
[
3
]
=
letters
[
v
%
62
];
v
/=
62
;
XXXXXX
[
4
]
=
letters
[
v
%
62
];
v
/=
62
;
XXXXXX
[
5
]
=
letters
[
v
%
62
];
fd
=
open
(
tmpl
,
O_RDWR
|
O_CREAT
|
O_EXCL
,
S_IRUSR
|
S_IWUSR
);
if
(
fd
>=
0
)
{
errno
=
save_errno
;
return
fd
;
}
else
if
(
errno
!=
EEXIST
)
return
-1
;
}
/* We got out of the loop because we ran out of combinations to try. */
errno
=
EEXIST
;
return
-1
;
}
int
_gpgme_mkstemp
(
int
*
fd
,
char
**
name
)
{
char
tmp
[
MAX_PATH
+
2
];
char
*
tmpname
;
int
err
;
*
fd
=
-1
;
*
name
=
NULL
;
err
=
GetTempPath
(
MAX_PATH
+
1
,
tmp
);
if
(
err
==
0
||
err
>
MAX_PATH
+
1
)
strcpy
(
tmp
,
"c:
\\
windows
\\
temp"
);
else
{
int
len
=
strlen
(
tmp
);
/* GetTempPath may return with \ on the end */
while
(
len
>
0
&&
tmp
[
len
-
1
]
==
'\\'
)
{
tmp
[
len
-1
]
=
'\0'
;
len
--
;
}
}
tmpname
=
malloc
(
strlen
(
tmp
)
+
13
+
1
);
if
(
!
tmpname
)
return
-1
;
strcpy
(
stpcpy
(
tmpname
,
tmp
),
"
\\
gpgme-XXXXXX"
);
*
fd
=
mkstemp
(
tmpname
);
if
(
fd
<
0
)
return
-1
;
*
name
=
tmpname
;
return
0
;
}
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Mon, Dec 23, 1:16 PM (1 m, 43 s)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
ca/13/9b10cf74b190a0cc2d9ff6308116
Attached To
rM GPGME
Event Timeline
Log In to Comment