xref: /openbsd-src/gnu/usr.bin/perl/ext/DynaLoader/dl_win32.xs (revision f2da64fbbbf1b03f09f390ab01267c93dfd77c4c)
1 /* dl_win32.xs
2  *
3  * Platform:	Win32 (Windows NT/Windows 95)
4  * Author:	Wei-Yuen Tan (wyt@hip.com)
5  * Created:	A warm day in June, 1995
6  *
7  * Modified:
8  *    August 23rd 1995 - rewritten after losing everything when I
9  *                       wiped off my NT partition (eek!)
10  */
11 
12 /* Porting notes:
13 
14 I merely took Paul's dl_dlopen.xs, took out extraneous stuff and
15 replaced the appropriate SunOS calls with the corresponding Win32
16 calls.
17 
18 */
19 
20 #define WIN32_LEAN_AND_MEAN
21 #ifdef __GNUC__
22 #define Win32_Winsock
23 #endif
24 #include <windows.h>
25 #include <string.h>
26 
27 #define PERL_NO_GET_CONTEXT
28 
29 #include "EXTERN.h"
30 #include "perl.h"
31 #include "win32.h"
32 
33 #include "XSUB.h"
34 
35 typedef struct {
36     SV *	x_error_sv;
37 } my_cxtx_t;		/* this *must* be named my_cxtx_t */
38 
39 #define DL_CXT_EXTRA	/* ask for dl_cxtx to be defined in dlutils.c */
40 #include "dlutils.c"	/* SaveError() etc	*/
41 
42 #define dl_error_sv	(dl_cxtx.x_error_sv)
43 
44 static char *
45 OS_Error_String(pTHX)
46 {
47     dMY_CXT;
48     DWORD err = GetLastError();
49     STRLEN len;
50     if (!dl_error_sv)
51 	dl_error_sv = newSVpvn("",0);
52     PerlProc_GetOSError(dl_error_sv,err);
53     return SvPV(dl_error_sv,len);
54 }
55 
56 static void
57 dl_private_init(pTHX)
58 {
59     (void)dl_generic_private_init(aTHX);
60 }
61 
62 /*
63     This function assumes the list staticlinkmodules
64     will be formed from package names with '::' replaced
65     with '/'. Thus Win32::OLE is in the list as Win32/OLE
66 */
67 static int
68 dl_static_linked(char *filename)
69 {
70     const char * const *p;
71     char *ptr, *hptr;
72     static const char subStr[] = "/auto/";
73     char szBuffer[MAX_PATH];
74 
75     /* avoid buffer overflow when called with invalid filenames */
76     if (strlen(filename) >= sizeof(szBuffer))
77         return 0;
78 
79     /* change all the '\\' to '/' */
80     strcpy(szBuffer, filename);
81     for(ptr = szBuffer; ptr = strchr(ptr, '\\'); ++ptr)
82 	*ptr = '/';
83 
84     /* delete the file name */
85     ptr = strrchr(szBuffer, '/');
86     if(ptr != NULL)
87 	*ptr = '\0';
88 
89     /* remove leading lib path */
90     ptr = strstr(szBuffer, subStr);
91     if(ptr != NULL)
92 	ptr += sizeof(subStr)-1;
93     else
94 	ptr = szBuffer;
95 
96     for (p = staticlinkmodules; *p;p++) {
97 	if (hptr = strstr(ptr, *p)) {
98 	    /* found substring, need more detailed check if module name match */
99 	    if (hptr==ptr) {
100 		return strcmp(ptr, *p)==0;
101 	    }
102 	    if (hptr[strlen(*p)] == 0)
103 		return hptr[-1]=='/';
104 	}
105     };
106     return 0;
107 }
108 
109 MODULE = DynaLoader	PACKAGE = DynaLoader
110 
111 BOOT:
112     (void)dl_private_init(aTHX);
113 
114 void
115 dl_load_file(filename,flags=0)
116     char *		filename
117     int			flags
118     PREINIT:
119     void *retv;
120     CODE:
121   {
122     DLDEBUG(1,PerlIO_printf(Perl_debug_log,"dl_load_file(%s):\n", filename));
123     if (dl_static_linked(filename) == 0) {
124 	retv = PerlProc_DynaLoad(filename);
125     }
126     else
127 	retv = (void*) Win_GetModuleHandle(NULL);
128     DLDEBUG(2,PerlIO_printf(Perl_debug_log," libref=%x\n", retv));
129     ST(0) = sv_newmortal() ;
130     if (retv == NULL)
131 	SaveError(aTHX_ "load_file:%s",
132 		  OS_Error_String(aTHX)) ;
133     else
134 	sv_setiv( ST(0), (IV)retv);
135   }
136 
137 int
138 dl_unload_file(libref)
139     void *	libref
140   CODE:
141     DLDEBUG(1,PerlIO_printf(Perl_debug_log, "dl_unload_file(%lx):\n", PTR2ul(libref)));
142     RETVAL = FreeLibrary(libref);
143     if (!RETVAL)
144         SaveError(aTHX_ "unload_file:%s", OS_Error_String(aTHX)) ;
145     DLDEBUG(2,PerlIO_printf(Perl_debug_log, " retval = %d\n", RETVAL));
146   OUTPUT:
147     RETVAL
148 
149 void
150 dl_find_symbol(libhandle, symbolname)
151     void *	libhandle
152     char *	symbolname
153     PREINIT:
154     void *retv;
155     CODE:
156     DLDEBUG(2,PerlIO_printf(Perl_debug_log,"dl_find_symbol(handle=%x, symbol=%s)\n",
157 		      libhandle, symbolname));
158     retv = (void*) GetProcAddress((HINSTANCE) libhandle, symbolname);
159     DLDEBUG(2,PerlIO_printf(Perl_debug_log,"  symbolref = %x\n", retv));
160     ST(0) = sv_newmortal() ;
161     if (retv == NULL)
162 	SaveError(aTHX_ "find_symbol:%s",
163 		  OS_Error_String(aTHX)) ;
164     else
165 	sv_setiv( ST(0), (IV)retv);
166 
167 
168 void
169 dl_undef_symbols()
170     CODE:
171 
172 
173 
174 # These functions should not need changing on any platform:
175 
176 void
177 dl_install_xsub(perl_name, symref, filename="$Package")
178     char *		perl_name
179     void *		symref
180     char *		filename
181     CODE:
182     DLDEBUG(2,PerlIO_printf(Perl_debug_log,"dl_install_xsub(name=%s, symref=%x)\n",
183 		      perl_name, symref));
184     ST(0) = sv_2mortal(newRV((SV*)newXS(perl_name,
185 					(void(*)(pTHX_ CV *))symref,
186 					filename)));
187 
188 
189 char *
190 dl_error()
191     CODE:
192     dMY_CXT;
193     RETVAL = dl_last_error;
194     OUTPUT:
195     RETVAL
196 
197 #if defined(USE_ITHREADS)
198 
199 void
200 CLONE(...)
201     CODE:
202     MY_CXT_CLONE;
203 
204     PERL_UNUSED_VAR(items);
205 
206     /* MY_CXT_CLONE just does a memcpy on the whole structure, so to avoid
207      * using Perl variables that belong to another thread, we create our
208      * own for this thread.
209      */
210     MY_CXT.x_dl_last_error = newSVpvn("", 0);
211 
212 #endif
213 
214 # end.
215