RE: How to load a "loadable object" that has a non-default file extension ?
[perl.git] / win32 / dl_win32.xs
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     char **p;
71     char *ptr, *hptr;
72     static char subStr[] = "/auto/";
73     char szBuffer[MAX_PATH];
74
75     /* change all the '\\' to '/' */
76     strcpy(szBuffer, filename);
77     for(ptr = szBuffer; ptr = strchr(ptr, '\\'); ++ptr)
78         *ptr = '/';
79
80     /* delete the file name */
81     ptr = strrchr(szBuffer, '/');
82     if(ptr != NULL)
83         *ptr = '\0';
84
85     /* remove leading lib path */
86     ptr = strstr(szBuffer, subStr);
87     if(ptr != NULL)
88         ptr += sizeof(subStr)-1;
89     else
90         ptr = szBuffer;
91
92     for (p = staticlinkmodules; *p;p++) {
93         if (hptr = strstr(ptr, *p)) {
94             /* found substring, need more detailed check if module name match */
95             if (hptr==ptr) {
96                 return strcmp(ptr, *p)==0;
97             }
98             if (hptr[strlen(*p)] == 0)
99                 return hptr[-1]=='/';
100         }
101     };
102     return 0;
103 }
104
105 MODULE = DynaLoader     PACKAGE = DynaLoader
106
107 BOOT:
108     (void)dl_private_init(aTHX);
109
110 void *
111 dl_load_file(filename,flags=0)
112     char *              filename
113     int                 flags
114     PREINIT:
115     CODE:
116   {
117     DLDEBUG(1,PerlIO_printf(Perl_debug_log,"dl_load_file(%s):\n", filename));
118     if (dl_static_linked(filename) == 0) {
119         RETVAL = PerlProc_DynaLoad(filename);
120     }
121     else
122         RETVAL = (void*) Win_GetModuleHandle(NULL);
123     DLDEBUG(2,PerlIO_printf(Perl_debug_log," libref=%x\n", RETVAL));
124     ST(0) = sv_newmortal() ;
125     if (RETVAL == NULL)
126         SaveError(aTHX_ "load_file:%s",
127                   OS_Error_String(aTHX)) ;
128     else
129         sv_setiv( ST(0), (IV)RETVAL);
130   }
131
132 int
133 dl_unload_file(libref)
134     void *      libref
135   CODE:
136     DLDEBUG(1,PerlIO_printf(Perl_debug_log, "dl_unload_file(%lx):\n", PTR2ul(libref)));
137     RETVAL = FreeLibrary(libref);
138     if (!RETVAL)
139         SaveError(aTHX_ "unload_file:%s", OS_Error_String(aTHX)) ;
140     DLDEBUG(2,PerlIO_printf(Perl_debug_log, " retval = %d\n", RETVAL));
141   OUTPUT:
142     RETVAL
143
144 void *
145 dl_find_symbol(libhandle, symbolname)
146     void *      libhandle
147     char *      symbolname
148     CODE:
149     DLDEBUG(2,PerlIO_printf(Perl_debug_log,"dl_find_symbol(handle=%x, symbol=%s)\n",
150                       libhandle, symbolname));
151     RETVAL = (void*) GetProcAddress((HINSTANCE) libhandle, symbolname);
152     DLDEBUG(2,PerlIO_printf(Perl_debug_log,"  symbolref = %x\n", RETVAL));
153     ST(0) = sv_newmortal() ;
154     if (RETVAL == NULL)
155         SaveError(aTHX_ "find_symbol:%s",
156                   OS_Error_String(aTHX)) ;
157     else
158         sv_setiv( ST(0), (IV)RETVAL);
159
160
161 void
162 dl_undef_symbols()
163     PPCODE:
164
165
166
167 # These functions should not need changing on any platform:
168
169 void
170 dl_install_xsub(perl_name, symref, filename="$Package")
171     char *              perl_name
172     void *              symref 
173     char *              filename
174     CODE:
175     DLDEBUG(2,PerlIO_printf(Perl_debug_log,"dl_install_xsub(name=%s, symref=%x)\n",
176                       perl_name, symref));
177     ST(0) = sv_2mortal(newRV((SV*)newXS(perl_name,
178                                         (void(*)(pTHX_ CV *))symref,
179                                         filename)));
180
181
182 char *
183 dl_error()
184     CODE:
185     dMY_CXT;
186     RETVAL = dl_last_error;
187     OUTPUT:
188     RETVAL
189
190 # end.