The R Project SVN R

Rev

Rev 67595 | Rev 83696 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4394 ripley 1
/*
6098 pd 2
 *  R : A Computer Language for Statistical Data Analysis
3
 *  Copyright (C) 1995-1996 Robert Gentleman and Ross Ihaka
67595 ripley 4
 *  Copyright (C) 1997-2014 The R Core Team
4394 ripley 5
 *
6
 *  This program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; either version 2 of the License, or
9
 *  (at your option) any later version.
10
 *
11
 *  This program is distributed in the hope that it will be useful,
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *  GNU General Public License for more details.
15
 *
16
 *  You should have received a copy of the GNU General Public License
42300 ripley 17
 *  along with this program; if not, a copy is available at
68956 ripley 18
 *  https://www.R-project.org/Licenses/
4394 ripley 19
 */
20
 
22312 duncan 21
/*  Dynamic Loading Support: See ../main/Rdynload.c and ../include/Rdynpriv.h
4394 ripley 22
 */
23
 
5222 ripley 24
#ifdef HAVE_CONFIG_H
10986 ripley 25
# include <config.h>
5222 ripley 26
#endif
27
 
10986 ripley 28
#include <string.h>
29
#include <stdlib.h>
11499 ripley 30
#include <Defn.h>
31
#include <Rmath.h>
4394 ripley 32
#include <direct.h>
36901 ripley 33
#define WIN32_LEAN_AND_MEAN 1
43904 ripley 34
/* Eventually #define _WIN32_WINNT 0x0502 for SetDllDirectoryA */
4394 ripley 35
#include <windows.h>
36
 
43904 ripley 37
/* SetDllDirectory is supported under XP SP1 and later.
38
   If called with a non-NULL argument it sets the argument to be
39
   the second item on the DLL search path (after the application
40
   launch directory).  This is removed if called with NULL.
41
 
42
   Prior to XP SP1 the second item was the current directory, but this
43
   has (by default, 'safe DLL search mode') been moved below the
44
   Windows dirs.  Using SetDllDirectory removes it altogether.
45
 
46
   We fudge this via the current directory in earlier systems.
47
 */
48
typedef BOOL (WINAPI *PSDD)(LPCTSTR);
49
 
50
int setDLLSearchPath(const char *path)
51
{
52
    int res = 0; /* failure */
53
    PSDD p = (PSDD) -1;
54
    static char wd[MAX_PATH] = "";  /* stored real current directory */
45070 ripley 55
 
61960 ripley 56
    // XP SP1 and later.
43904 ripley 57
    if(p == (PSDD) -1)
58
	p = (PSDD) GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")),
59
				  "SetDllDirectoryA");
60
    if(p) {
61
	res = p(path);
62
    } else { /* Windows 2000 */
63
	if(path) {
64
	    GetCurrentDirectory(MAX_PATH, wd);
44177 ripley 65
	    SetCurrentDirectory(path);
43904 ripley 66
	} else if (wd[0]) {
67
	    SetCurrentDirectory(wd);
68
	    wd[0] = '\0';
69
	}
70
    }
71
    return res;
72
}
73
 
15776 hornik 74
#include <R_ext/Rdynload.h>
75
#include <Rdynpriv.h>
4394 ripley 76
 
77
 
45070 ripley 78
	/* Inserts the specified DLL at the head of the DLL list */
79
	/* Returns 1 if the library was successfully added */
80
	/* and returns 0 if the library table is full or */
81
	/* or if LoadLibrary fails for some reason. */
14077 duncan 82
 
83
static void fixPath(char *path)
4394 ripley 84
{
14080 ripley 85
    char *p;
14077 duncan 86
    for(p = path; *p != '\0'; p++) if(*p == '\\') *p = '/';
4394 ripley 87
}
88
 
45070 ripley 89
static HINSTANCE R_loadLibrary(const char *path, int asLocal, int now,
43904 ripley 90
			       const char *search);
14077 duncan 91
static DL_FUNC getRoutine(DllInfo *info, char const *name);
60604 ripley 92
#ifdef CACHE_DLL_SYM
14077 duncan 93
static void R_deleteCachedSymbols(DllInfo *dll);
60604 ripley 94
#endif
4394 ripley 95
 
14077 duncan 96
static void R_getDLLError(char *buf, int len);
41785 ripley 97
static void GetFullDLLPath(SEXP call, char *buf, const char *path);
4394 ripley 98
 
14077 duncan 99
static void closeLibrary(HINSTANCE handle)
100
{
14080 ripley 101
    FreeLibrary(handle);
14077 duncan 102
}
4394 ripley 103
 
14077 duncan 104
void InitFunctionHashing()
105
{
106
    R_osDynSymbol->loadLibrary = R_loadLibrary;
107
    R_osDynSymbol->dlsym = getRoutine;
108
    R_osDynSymbol->closeLibrary = closeLibrary;
109
    R_osDynSymbol->getError = R_getDLLError;
4394 ripley 110
 
60604 ripley 111
#ifdef CACHE_DLL_SYM
14077 duncan 112
    R_osDynSymbol->deleteCachedSymbols = R_deleteCachedSymbols;
113
    R_osDynSymbol->lookupCachedSymbol = Rf_lookupCachedSymbol;
60604 ripley 114
#endif
14077 duncan 115
 
116
    R_osDynSymbol->fixPath = fixPath;
117
    R_osDynSymbol->getFullDLLPath = GetFullDLLPath;
118
}
119
 
60604 ripley 120
#ifdef CACHE_DLL_SYM
14077 duncan 121
static void R_deleteCachedSymbols(DllInfo *dll)
4394 ripley 122
{
14080 ripley 123
    int i;
10557 ripley 124
    for(i = nCPFun - 1; i >= 0; i--)
14077 duncan 125
	if(!strcmp(CPFun[i].pkg, dll->name)) {
10557 ripley 126
	    if(i < nCPFun - 1) {
127
		strcpy(CPFun[i].name, CPFun[--nCPFun].name);
128
		strcpy(CPFun[i].pkg, CPFun[nCPFun].pkg);
129
		CPFun[i].func = CPFun[nCPFun].func;
130
	    } else nCPFun--;
7849 ripley 131
	}
4394 ripley 132
}
60604 ripley 133
#endif
4394 ripley 134
 
38811 ripley 135
#ifndef _MCW_EM
45070 ripley 136
_CRTIMP unsigned int __cdecl
38811 ripley 137
_controlfp (unsigned int unNew, unsigned int unMask);
138
_CRTIMP unsigned int __cdecl _clearfp (void);
139
/* Control word masks for unMask */
140
#define	_MCW_EM		0x0008001F	/* Error masks */
141
#define	_MCW_IC		0x00040000	/* Infinity */
142
#define	_MCW_RC		0x00000300	/* Rounding */
143
#define	_MCW_PC		0x00030000	/* Precision */
144
#endif
145
 
45070 ripley 146
HINSTANCE R_loadLibrary(const char *path, int asLocal, int now,
43904 ripley 147
			const char *search)
14077 duncan 148
{
14080 ripley 149
    HINSTANCE tdlh;
22138 murdoch 150
    unsigned int dllcw, rcw;
43904 ripley 151
    int useSearch = search && search[0];
14080 ripley 152
 
23382 murdoch 153
    rcw = _controlfp(0,0) & ~_MCW_IC;  /* Infinity control is ignored */
22166 murdoch 154
    _clearfp();
43904 ripley 155
    if(useSearch) setDLLSearchPath(search);
14077 duncan 156
    tdlh = LoadLibrary(path);
43904 ripley 157
    if(useSearch) setDLLSearchPath(NULL);
22614 ripley 158
    dllcw = _controlfp(0,0) & ~_MCW_IC;
22138 murdoch 159
    if (dllcw != rcw) {
43904 ripley 160
	_controlfp(rcw, _MCW_EM | _MCW_IC | _MCW_RC | _MCW_PC);
54049 ripley 161
	if (LOGICAL(GetOption1(install("warn.FPU")))[0])
43904 ripley 162
	    warning(_("DLL attempted to change FPU control word from %x to %x"),
163
		    rcw,dllcw);
164
    }
14080 ripley 165
    return(tdlh);
14077 duncan 166
}
4394 ripley 167
 
14077 duncan 168
static DL_FUNC getRoutine(DllInfo *info, char const *name)
4394 ripley 169
{
14080 ripley 170
    DL_FUNC f;
171
    f = (DL_FUNC) GetProcAddress(info->handle, name);
172
    return(f);
14077 duncan 173
}
4394 ripley 174
 
14077 duncan 175
static void R_getDLLError(char *buf, int len)
176
{
53423 ripley 177
    LPSTR lpMsgBuf, p;
178
    char *q;
14080 ripley 179
    FormatMessage(
180
	FORMAT_MESSAGE_ALLOCATE_BUFFER |
181
	FORMAT_MESSAGE_FROM_SYSTEM |
182
	FORMAT_MESSAGE_IGNORE_INSERTS,
183
	NULL,
184
	GetLastError(),
185
	MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
53443 ripley 186
	(LPSTR) &lpMsgBuf,
14080 ripley 187
	0,
188
	NULL
189
	);
190
    strcpy(buf, "LoadLibrary failure:  ");
53423 ripley 191
    q = buf + strlen(buf);
192
    /* It seems that Win 7 returns error messages with CRLF terminators */
193
    for (p = lpMsgBuf; *p; p++) if (*p != '\r') *q++ = *p;
14080 ripley 194
    LocalFree(lpMsgBuf);
4394 ripley 195
}
196
 
41785 ripley 197
static void GetFullDLLPath(SEXP call, char *buf, const char *path)
4394 ripley 198
{
10557 ripley 199
    char *p;
200
 
4394 ripley 201
    if ((path[0] != '/') && (path[0] != '\\') && (path[1] != ':')) {
202
	if (!getcwd(buf, MAX_PATH))
32888 ripley 203
	    errorcall(call, _("cannot get working directory"));
4394 ripley 204
	strcat(buf, "\\");
205
	strcat(buf, path);
206
    } else
207
	strcpy(buf, path);
10557 ripley 208
    /* fix slashes to allow inconsistent usage later */
209
    for (p = buf; *p; p++) if (*p == '\\') *p = '/';
4394 ripley 210
}