DEFINITIONS
This source file includes following functions.
- Win32API_FreeLibrary
- Win32API_initialize
- c_m
- Win32API_Call
- Init_Win32API
1
2
3
4
5 #if !defined _MSC_VER && !defined NT
6 #define WIN32_LEAN_AND_MEAN
7 #include <windows.h>
8 #include <stdio.h>
9 #endif
10
11 #if defined(_MSC_VER)
12 #if defined(_M_ALPHA)
13 #ifdef __cplusplus
14 extern "C" { long __asm(char *,...); };
15 #else
16 long __asm(char *,...);
17 #endif
18 #pragma intrinsic(__asm)
19 #endif
20 #endif
21
22 #define _T_VOID 0
23 #define _T_NUMBER 1
24 #define _T_POINTER 2
25 #define _T_INTEGER 3
26
27 typedef char *ApiPointer(void);
28 typedef long ApiNumber(void);
29 typedef void ApiVoid(void);
30 typedef int ApiInteger(void);
31
32 #include "ruby.h"
33
34 typedef struct {
35 HANDLE dll;
36 HANDLE proc;
37 VALUE dllname;
38 VALUE import;
39 VALUE export;
40 } Win32API;
41
42 static void
43 Win32API_FreeLibrary(hdll)
44 HINSTANCE hdll;
45 {
46 FreeLibrary(hdll);
47 }
48
49 static VALUE
50 Win32API_initialize(self, dllname, proc, import, export)
51 VALUE self;
52 VALUE dllname;
53 VALUE proc;
54 VALUE import;
55 VALUE export;
56 {
57 HANDLE hproc;
58 HINSTANCE hdll;
59 VALUE str;
60 VALUE a_import;
61 VALUE *ptr;
62 char *s;
63 int i;
64 int len;
65 int ex;
66
67 SafeStringValue(dllname);
68 SafeStringValue(proc);
69 hdll = LoadLibrary(RSTRING(dllname)->ptr);
70 if (!hdll)
71 rb_raise(rb_eRuntimeError, "LoadLibrary: %s\n", RSTRING(dllname)->ptr);
72 rb_iv_set(self, "__hdll__", Data_Wrap_Struct(self, 0, Win32API_FreeLibrary, hdll));
73 hproc = GetProcAddress(hdll, RSTRING(proc)->ptr);
74 if (!hproc) {
75 str = rb_str_new3(proc);
76 str = rb_str_cat(str, "A", 1);
77 hproc = GetProcAddress(hdll, RSTRING(str)->ptr);
78 if (!hproc)
79 rb_raise(rb_eRuntimeError, "GetProcAddress: %s or %s\n",
80 RSTRING(proc)->ptr, RSTRING(str)->ptr);
81 }
82 rb_iv_set(self, "__dll__", UINT2NUM((unsigned long)hdll));
83 rb_iv_set(self, "__dllname__", dllname);
84 rb_iv_set(self, "__proc__", UINT2NUM((unsigned long)hproc));
85
86 a_import = rb_ary_new();
87 switch (TYPE(import)) {
88 case T_NIL:
89 break;
90 case T_ARRAY:
91 ptr = RARRAY(import)->ptr;
92 for (i = 0, len = RARRAY(import)->len; i < len; i++) {
93 SafeStringValue(ptr[i]);
94 switch (*(char *)RSTRING(ptr[i])->ptr) {
95 case 'N': case 'n': case 'L': case 'l':
96 rb_ary_push(a_import, INT2FIX(_T_NUMBER));
97 break;
98 case 'P': case 'p':
99 rb_ary_push(a_import, INT2FIX(_T_POINTER));
100 break;
101 case 'I': case 'i':
102 rb_ary_push(a_import, INT2FIX(_T_INTEGER));
103 break;
104 }
105 }
106 break;
107 default:
108 SafeStringValue(import);
109 s = RSTRING(import)->ptr;
110 for (i = 0, len = RSTRING(import)->len; i < len; i++) {
111 switch (*s++) {
112 case 'N': case 'n': case 'L': case 'l':
113 rb_ary_push(a_import, INT2FIX(_T_NUMBER));
114 break;
115 case 'P': case 'p':
116 rb_ary_push(a_import, INT2FIX(_T_POINTER));
117 break;
118 case 'I': case 'i':
119 rb_ary_push(a_import, INT2FIX(_T_INTEGER));
120 break;
121 }
122 }
123 break;
124 }
125 rb_iv_set(self, "__import__", a_import);
126
127 if (NIL_P(export)) {
128 ex = _T_VOID;
129 } else {
130 SafeStringValue(export);
131 switch (*RSTRING(export)->ptr) {
132 case 'V': case 'v':
133 ex = _T_VOID;
134 break;
135 case 'N': case 'n': case 'L': case 'l':
136 ex = _T_NUMBER;
137 break;
138 case 'P': case 'p':
139 ex = _T_POINTER;
140 break;
141 case 'I': case 'i':
142 ex = _T_INTEGER;
143 break;
144 }
145 }
146 rb_iv_set(self, "__export__", INT2FIX(ex));
147
148 return Qnil;
149 }
150
151 #ifdef __BORLANDC__
152 int c_m( FARPROC api, long* p )
153 {
154 long pp[16];
155 memcpy( pp, p, 16*sizeof(long) );
156 return api();
157 }
158 #endif
159
160 static VALUE
161 Win32API_Call(argc, argv, obj)
162 int argc;
163 VALUE *argv;
164 VALUE obj;
165 {
166 VALUE args;
167
168 FARPROC ApiFunction;
169
170 ApiPointer *ApiFunctionPointer;
171 ApiNumber *ApiFunctionNumber;
172 ApiVoid *ApiFunctionVoid;
173 ApiInteger *ApiFunctionInteger;
174
175 long lParam;
176 char *pParam;
177
178 VALUE Return;
179
180 VALUE obj_proc;
181 VALUE obj_import;
182 VALUE obj_export;
183 VALUE import_type;
184 int nimport, timport, texport, i;
185 int items;
186 int ret;
187 #ifdef __BORLANDC__
188 long* ptr;
189 long p[16];
190 #endif
191
192 items = rb_scan_args(argc, argv, "0*", &args);
193
194 obj_proc = rb_iv_get(obj, "__proc__");
195
196 ApiFunction = (FARPROC)NUM2ULONG(obj_proc);
197
198 obj_import = rb_iv_get(obj, "__import__");
199 obj_export = rb_iv_get(obj, "__export__");
200 nimport = RARRAY(obj_import)->len;
201 texport = FIX2INT(obj_export);
202
203 if (items != nimport)
204 rb_raise(rb_eRuntimeError, "Wrong number of parameters: expected %d, got %d.\n",
205 nimport, items);
206
207 if (0 < nimport) {
208 #ifdef __BORLANDC__
209 ptr = p + ( nimport - 1 );
210 #endif
211 for (i = nimport - 1; 0 <= i; i--) {
212 VALUE str;
213 import_type = rb_ary_entry(obj_import, i);
214 timport = FIX2INT(import_type);
215 switch (timport) {
216 case _T_NUMBER:
217 case _T_INTEGER:
218 lParam = NUM2ULONG(rb_ary_entry(args, i));
219 #if defined(_MSC_VER) || defined(__LCC__)
220 #if defined(_M_IX86)
221 _asm {
222 mov eax, lParam
223 push eax
224 }
225 #elif defined(_M_ALPHA)
226 __asm(
227 "ldl r0, 0(%0);"
228 "stq r0, -(sp);"
229 , lParam
230 );
231 #else
232 #error
233 #endif
234 #elif defined(__BORLANDC__)
235 *ptr = lParam;
236 --ptr;
237 #elif defined __GNUC__
238 asm volatile ("pushl %0" :: "g" (lParam));
239 #else
240 #error
241 #endif
242 break;
243 case _T_POINTER:
244 str = rb_ary_entry(args, i);
245 if (NIL_P(str)) {
246 pParam = 0;
247 } else if (FIXNUM_P(str)){
248 pParam = (char *)NUM2ULONG(str);
249 } else {
250 StringValue(str);
251 rb_str_modify(str);
252 pParam = StringValuePtr(str);
253 }
254 #if defined(_MSC_VER) || defined(__LCC__)
255 #if defined(_M_IX86)
256 _asm {
257 mov eax, pParam
258 push eax
259 }
260 #elif defined(_M_ALPHA)
261 __asm(
262 "ldl r0, 0(%0);"
263 "stq r0, -(sp);"
264 , pParam
265 );
266 #else
267 #error
268 #endif
269 #elif defined(__BORLANDC__)
270 *ptr = (long)pParam;
271 --ptr;
272 #elif defined __GNUC__
273 asm volatile ("pushl %0" :: "g" (pParam));
274 #else
275 #error
276 #endif
277 break;
278 }
279 }
280 }
281
282 #if defined __GNUC__
283 asm volatile ("call *%1" : "=r" (ret) : "g" (ApiFunction));
284 switch (texport) {
285 case _T_NUMBER:
286 case _T_INTEGER:
287 Return = INT2NUM(ret);
288 break;
289 case _T_POINTER:
290 Return = rb_str_new2((char *)ret);
291 break;
292 case _T_VOID:
293 default:
294 Return = INT2NUM(0);
295 break;
296 }
297 #else
298 switch (texport) {
299 case _T_NUMBER:
300 #if defined(__BORLANDC__)
301 Return = INT2NUM((long)c_m(ApiFunction, p));
302 #else
303 ApiFunctionNumber = (ApiNumber *) ApiFunction;
304 Return = INT2NUM(ApiFunctionNumber());
305 #endif
306 break;
307 case _T_POINTER:
308 #if defined(__BORLANDC__)
309 Return = rb_str_new2((char *)c_m(ApiFunction, p));
310 #else
311 ApiFunctionPointer = (ApiPointer *) ApiFunction;
312 Return = rb_str_new2((char *)ApiFunctionPointer());
313 #endif
314 break;
315 case _T_INTEGER:
316 #if defined(__BORLANDC__)
317 Return = INT2NUM((int)c_m(ApiFunction, p));
318 #else
319 ApiFunctionInteger = (ApiInteger *) ApiFunction;
320 Return = INT2NUM(ApiFunctionInteger());
321 #endif
322 break;
323 case _T_VOID:
324 default:
325 ApiFunctionVoid = (ApiVoid *) ApiFunction;
326 ApiFunctionVoid();
327 Return = INT2NUM(0);
328 break;
329 }
330 #endif
331 return Return;
332 }
333
334 void
335 Init_Win32API()
336 {
337 VALUE cWin32API = rb_define_class("Win32API", rb_cObject);
338 rb_define_method(cWin32API, "initialize", Win32API_initialize, 4);
339 rb_define_method(cWin32API, "call", Win32API_Call, -1);
340 rb_define_alias(cWin32API, "Call", "call");
341 }