wine
path
dll
Inside
WINEDLLPATH
More than 1 year has passed since last update.

目次


Inside Wine; WINEDLLPATH


WINEDLLPATH の不具合

調べてみると、/wine/libs/wine/loader.c の中の build_dll_path() 関数の中で、環境変数 WINEDLLPATH が、読み取られ、: を 0x00 に変えてから、dll_paths[] 配列に : で区切られたそれぞれの文字列の先頭アドレスを代入している。

しかし、その処理に入る前に、get_dlldir() 関数が NULL 以外を返した場合、dll_paths[0] にその関数が返した文字列のアドレスを入れてしまう。

そして、実際の get_dlldir() は、"/usr/local/bin/../lib/wine" という文字列を返してくるので、そっちのパスの方が、WINEDLLPATH の優先順位よりも上になってしまう。

get_dlldir() は、


~/wine/libs/wine/config.c

/* retrieve the default dll dir */

const char *get_dlldir( const char **default_dlldir )
{
*default_dlldir = DLLDIR;
return dlldir;
}

となっているが、DLLDIR は、Makefile の中で、gcc に -D オプションによってコンパイル開始時の #define マクロ として文字列が渡されている。


修正箇所

c:~/wine/libs/wine/loader.c の build_dll_path() 関数を変更する。

make すると、c:~/wine/libs/wine/libwine.so.1.0

が作成される。

これを、自分のアプリの場合にだけは使われるようにする。


旧関数


~/wine/libs/wine/loader.c

/* build the dll load path from the WINEDLLPATH variable */

static void build_dll_path(void)
{
int len, count = 0;
char *p, *path = getenv( "WINEDLLPATH" );
const char *dlldir = get_dlldir( &default_dlldir );

if (path)
{
/* count how many path elements we need */
path = strdup(path);
p = path;
while (*p)
{
while (*p == ':') p++;
if (!*p) break;
count++;
while (*p && *p != ':') p++;
}
}

dll_paths = malloc( (count+2) * sizeof(*dll_paths) );
nb_dll_paths = 0;

if (dlldir)
{
dll_path_maxlen = strlen(dlldir);
dll_paths[nb_dll_paths++] = dlldir;
}
else if ((build_dir = wine_get_build_dir()))
{
dll_path_maxlen = strlen(build_dir) + sizeof("/programs");
}

if (count)
{
p = path;
while (*p)
{
while (*p == ':') *p++ = 0;
if (!*p) break;
dll_paths[nb_dll_paths] = p;
while (*p && *p != ':') p++;
if (p - dll_paths[nb_dll_paths] > dll_path_maxlen)
dll_path_maxlen = p - dll_paths[nb_dll_paths];
nb_dll_paths++;
}
}

/* append default dll dir (if not empty) to path */
if ((len = strlen(default_dlldir)) > 0)
{
if (len > dll_path_maxlen) dll_path_maxlen = len;
dll_paths[nb_dll_paths++] = default_dlldir;
}
}



新関数


~/wine/libs/wine/loader.c

/* build the dll load path from the WINEDLLPATH variable */

static void build_dll_path(void)
{
int len, count = 0;
char *p, *path = getenv( "WINEDLLPATH" );
const char *dlldir = get_dlldir( &default_dlldir );

if (path)
{
/* count how many path elements we need */
path = strdup(path);
p = path;
while (*p)
{
while (*p == ':') p++;
if (!*p) break;
count++;
while (*p && *p != ':') p++;
}
}

dll_paths = malloc( (count+2) * sizeof(*dll_paths) );
nb_dll_paths = 0;

dll_path_maxlen = 0;

if (count)
{
p = path;
while (*p)
{
while (*p == ':') *p++ = 0;
if (!*p) break;
dll_paths[nb_dll_paths] = p;
while (*p && *p != ':') p++;
if (p - dll_paths[nb_dll_paths] > dll_path_maxlen)
dll_path_maxlen = p - dll_paths[nb_dll_paths];
nb_dll_paths++;
}
}

if (dlldir) {
int len = strlen(dlldir);
if ( len > dll_path_maxlen ) {
dll_path_maxlen = len;
}
dll_paths[nb_dll_paths++] = dlldir;
}
else if ((build_dir = wine_get_build_dir())) {
int len = strlen(build_dir) + sizeof("/programs");
if ( len > dll_path_maxlen ) {
dll_path_maxlen = len;
}
}

/* append default dll dir (if not empty) to path */
if ((len = strlen(default_dlldir)) > 0) {
if (len > dll_path_maxlen) {
dll_path_maxlen = len;
}
dll_paths[nb_dll_paths++] = default_dlldir;
}

#if 1
int cnt;
for ( cnt = 0; cnt < nb_dll_paths; cnt++ ) {
fprintf( stderr, "%d: %s\n", cnt, dll_paths[cnt] );
}
#endif
}



以下のようなスクリプトを作っておく。

自分のアプリを実行する前に、

$ . myenv

として、先頭に 「.」を付けて環境変数が設定されるようにする。

export LD_LIBRARY_PATH=.

によって、カレント・ディレクトリにある、libwine.so.1

が探されるようになる。

$ ln -s /media/Yyyy/my_winedev/wine/libs/wine/libwine.so.1.0 libwine.so.1

などとして、カレント・ディレクトリに本体へのリンクを作っておく。

パスに付いては、詳細は省略する。以下のスクリプトは自分の場合。

WINEDLLPATH の設定の仕方は、ソースを検索すると、英語だが、自然言語で書かれているので読む。


myenv

#!/bin/sh

#
# $ . myenv [ret]
#
# として読みこます事。冒頭の「. 」(ドットと空白) が重要
#

PATH=/media/Yyyy/my_winedev/bin2/bin:$PATH

DLL=/media/Yyyy/my_winedev/wine/dlls

WINEDLLPATH=$DLL/winex11.drv
WINEDLLPATH+=:$DLL/gdi32
WINEDLLPATH+=:$DLL/user32
WINEDLLPATH+=:/media/Yyyy/my_winedev/bin2/lib/wine

export WINEDLLPATH

export WINESERVER=/media/Yyyy/my_winedev/wine/server/wineserver

export LD_LIBRARY_PATH=.