Add a general purpose hashtable pattern matcher
[jimtcl.git] / jim-win32.c
blob93ae0efff3439d7ec71c15e468824e485880d633
1 /*
2 * WIN32 extension
4 * Copyright (C) 2005 Pat Thoyts <patthoyts@users.sourceforge.net>
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials
15 * provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21 * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 * The views and conclusions contained in the software and documentation
31 * are those of the authors and should not be interpreted as representing
32 * official policies, either expressed or implied, of the Jim Tcl Project.
35 #include "jim.h"
36 #include "jimautoconf.h"
38 /* Apparently windows.h and cygwin don't mix, but we seem to get
39 * away with it here. Use at your own risk under cygwin
41 #if defined(__CYGWIN__)
42 #define WIN32_LEAN_AND_MEAN
43 #include <windows.h>
44 #endif
46 #include <shellapi.h>
47 #include <lmcons.h>
48 #include <psapi.h>
49 #include <ctype.h>
51 #if _MSC_VER >= 1000
52 #pragma comment(lib, "shell32")
53 #pragma comment(lib, "user32")
54 #pragma comment(lib, "advapi32")
55 #pragma comment(lib, "psapi")
56 #endif /* _MSC_VER >= 1000 */
58 static Jim_Obj *
59 Win32ErrorObj(Jim_Interp *interp, const char * szPrefix, DWORD dwError)
61 Jim_Obj *msgObj = NULL;
62 char * lpBuffer = NULL;
63 DWORD dwLen = 0;
65 dwLen = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER
66 | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, LANG_NEUTRAL,
67 (char *)&lpBuffer, 0, NULL);
68 if (dwLen < 1) {
69 dwLen = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER
70 | FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
71 "code 0x%1!08X!%n", 0, LANG_NEUTRAL,
72 (char *)&lpBuffer, 0, (va_list *)&dwError);
75 msgObj = Jim_NewStringObj(interp, szPrefix, -1);
76 if (dwLen > 0) {
77 char *p = lpBuffer + dwLen - 1; /* remove cr-lf at end */
78 for ( ; p && *p && isspace(UCHAR(*p)); p--)
80 *++p = 0;
81 Jim_AppendString(interp, msgObj, ": ", 2);
82 Jim_AppendString(interp, msgObj, lpBuffer, -1);
84 LocalFree((HLOCAL)lpBuffer);
85 return msgObj;
88 /* win32.ShellExecute verb file args */
89 static int
90 Win32_ShellExecute(Jim_Interp *interp, int objc, Jim_Obj * const *objv)
92 int r;
93 const char *verb, *file, *parm = NULL;
94 char cwd[MAX_PATH + 1];
96 if (objc < 3 || objc > 4) {
97 Jim_WrongNumArgs(interp, 1, objv, "verb path ?parameters?");
98 return JIM_ERR;
100 verb = Jim_String(objv[1]);
101 file = Jim_String(objv[2]);
102 GetCurrentDirectoryA(MAX_PATH + 1, cwd);
103 if (objc == 4)
104 parm = Jim_String(objv[3]);
105 r = (int)ShellExecuteA(NULL, verb, file, parm, cwd, SW_SHOWNORMAL);
106 if (r < 33)
107 Jim_SetResult(interp,
108 Win32ErrorObj(interp, "ShellExecute", GetLastError()));
109 return (r < 33) ? JIM_ERR : JIM_OK;
113 /* win32.FindWindow title ?class? */
114 static int
115 Win32_FindWindow(Jim_Interp *interp, int objc, Jim_Obj * const *objv)
117 const char *title = NULL, *class = NULL;
118 HWND hwnd = NULL;
119 int r = JIM_OK;
121 if (objc < 2 || objc > 3) {
122 Jim_WrongNumArgs(interp, 1, objv, "title ?class?");
123 return JIM_ERR;
125 title = Jim_String(objv[1]);
126 if (objc == 3)
127 class = Jim_String(objv[2]);
128 hwnd = FindWindowA(class, title);
130 if (hwnd == NULL) {
131 Jim_SetResult(interp,
132 Win32ErrorObj(interp, "FindWindow", GetLastError()));
133 r = JIM_ERR;
134 } else {
135 Jim_SetResult(interp, Jim_NewIntObj(interp, (long)hwnd));
137 return r;
140 /* win32.CloseWindow windowHandle */
141 static int
142 Win32_CloseWindow(Jim_Interp *interp, int objc, Jim_Obj * const *objv)
144 long hwnd;
146 if (objc != 2) {
147 Jim_WrongNumArgs(interp, 1, objv, "?windowHandle?");
148 return JIM_ERR;
150 if (Jim_GetLong(interp, objv[1], &hwnd) != JIM_OK)
151 return JIM_ERR;
152 if (!CloseWindow((HWND)hwnd)) {
153 Jim_SetResult(interp,
154 Win32ErrorObj(interp, "CloseWindow", GetLastError()));
155 return JIM_ERR;
157 return JIM_OK;
160 static int
161 Win32_GetActiveWindow(Jim_Interp *interp, int objc, Jim_Obj * const *objv)
163 Jim_SetResult(interp, Jim_NewIntObj(interp, (DWORD)GetActiveWindow()));
164 return JIM_OK;
167 static int
168 Win32_SetActiveWindow(Jim_Interp *interp, int objc, Jim_Obj * const *objv)
170 HWND hwnd, old;
171 int r = JIM_OK;
173 if (objc != 2) {
174 Jim_WrongNumArgs(interp, 1, objv, "windowHandle");
175 return JIM_ERR;
177 r = Jim_GetLong(interp, objv[1], (long *)&hwnd);
178 if (r == JIM_OK) {
179 old = SetActiveWindow(hwnd);
180 if (old == NULL) {
181 Jim_SetResult(interp,
182 Win32ErrorObj(interp, "SetActiveWindow", GetLastError()));
183 r = JIM_ERR;
184 } else {
185 Jim_SetResult(interp, Jim_NewIntObj(interp, (long)old));
188 return r;
191 static int
192 Win32_SetForegroundWindow(Jim_Interp *interp, int objc, Jim_Obj * const *objv)
194 HWND hwnd;
195 int r = JIM_OK;
197 if (objc != 2) {
198 Jim_WrongNumArgs(interp, 1, objv, "windowHandle");
199 return JIM_ERR;
201 r = Jim_GetLong(interp, objv[1], (long *)&hwnd);
202 if (r == JIM_OK) {
203 if (!SetForegroundWindow(hwnd)) {
204 Jim_SetResult(interp,
205 Win32ErrorObj(interp, "SetForegroundWindow", GetLastError()));
206 r = JIM_ERR;
209 return r;
212 static int
213 Win32_Beep(Jim_Interp *interp, int objc, Jim_Obj * const *objv)
215 long freq, duration;
216 int r = JIM_OK;
218 if (objc != 3) {
219 Jim_WrongNumArgs(interp, 1, objv, "freq duration");
220 return JIM_ERR;
222 r = Jim_GetLong(interp, objv[1], &freq);
223 if (r == JIM_OK)
224 r = Jim_GetLong(interp, objv[2], &duration);
225 if (freq < 0x25) freq = 0x25;
226 if (freq > 0x7fff) freq = 0x7fff;
227 if (r == JIM_OK) {
228 if (!Beep(freq, duration)) {
229 Jim_SetResult(interp,
230 Win32ErrorObj(interp, "Beep", GetLastError()));
231 r = JIM_ERR;
234 return r;
237 static int
238 Win32_GetComputerName(Jim_Interp *interp, int objc, Jim_Obj * const *objv)
240 char name[MAX_COMPUTERNAME_LENGTH + 1];
241 DWORD size = MAX_COMPUTERNAME_LENGTH;
242 int r = JIM_OK;
244 if (objc != 1) {
245 Jim_WrongNumArgs(interp, 1, objv, "");
246 return JIM_ERR;
249 if (GetComputerNameA(name, &size)) {
250 Jim_Obj *nameObj = Jim_NewStringObj(interp, name, size);
251 Jim_SetResult(interp, nameObj);
252 } else {
253 Jim_SetResult(interp,
254 Win32ErrorObj(interp, "GetComputerName", GetLastError()));
255 r = JIM_ERR;
258 return r;
261 static int
262 Win32_GetUserName(Jim_Interp *interp, int objc, Jim_Obj * const *objv)
264 char name[UNLEN + 1];
265 DWORD size = UNLEN;
266 int r = JIM_OK;
268 if (objc != 1) {
269 Jim_WrongNumArgs(interp, 1, objv, "");
270 return JIM_ERR;
273 if (GetUserNameA(name, &size)) {
274 Jim_Obj *nameObj = Jim_NewStringObj(interp, name, size);
275 Jim_SetResult(interp, nameObj);
276 } else {
277 Jim_SetResult(interp,
278 Win32ErrorObj(interp, "GetUserName", GetLastError()));
279 r = JIM_ERR;
282 return r;
285 static int
286 Win32_GetModuleFileName(Jim_Interp *interp, int objc, Jim_Obj * const *objv)
288 HMODULE hModule = NULL;
289 char path[MAX_PATH];
290 DWORD len = 0;
292 if (objc > 2) {
293 Jim_WrongNumArgs(interp, 1, objv, "?moduleid?");
294 return JIM_ERR;
297 if (objc == 2) {
298 if (Jim_GetLong(interp, objv[1], (long *)&hModule) != JIM_OK) {
299 return JIM_ERR;
303 len = GetModuleFileNameA(hModule, path, MAX_PATH);
304 if (len != 0) {
305 Jim_Obj *pathObj = Jim_NewStringObj(interp, path, len);
306 Jim_SetResult(interp, pathObj);
307 } else {
308 Jim_SetResult(interp,
309 Win32ErrorObj(interp, "GetModuleFileName", GetLastError()));
310 return JIM_ERR;
313 return JIM_OK;
316 static int
317 Win32_GetVersion(Jim_Interp *interp, int objc, Jim_Obj * const *objv)
319 Jim_SetResult(interp, Jim_NewIntObj(interp, GetVersion()));
320 return JIM_OK;
323 static int
324 Win32_GetTickCount(Jim_Interp *interp, int objc, Jim_Obj * const *objv)
326 Jim_SetResult(interp, Jim_NewIntObj(interp, GetTickCount()));
327 return JIM_OK;
330 static int
331 Win32_GetSystemTime(Jim_Interp *interp, int objc, Jim_Obj * const *objv)
333 Jim_Obj *a[16];
334 size_t n = 0;
335 SYSTEMTIME t;
336 GetSystemTime(&t);
338 #define JIMADD(name) \
339 a[n++] = Jim_NewStringObj(interp, #name, -1); \
340 a[n++] = Jim_NewIntObj(interp, t.w ## name )
342 JIMADD(Year);
343 JIMADD(Month);
344 JIMADD(DayOfWeek);
345 JIMADD(Day);
346 JIMADD(Hour);
347 JIMADD(Minute);
348 JIMADD(Second);
349 JIMADD(Milliseconds);
350 #undef JIMADD
352 Jim_SetResult(interp, Jim_NewListObj(interp, a, n));
353 return JIM_OK;
356 /* function not available on mingw or cygwin */
357 #if !defined(__MINGW32__) && !defined(__CYGWIN__)
358 // FIX ME: win2k+ so should do version checks really.
359 static int
360 Win32_GetPerformanceInfo(Jim_Interp *interp, int objc, Jim_Obj * const *objv)
362 Jim_Obj *a[26];
363 size_t n = 0;
364 PERFORMANCE_INFORMATION pi;
366 if (!GetPerformanceInfo(&pi, sizeof(pi))) {
367 Jim_SetResult(interp,
368 Win32ErrorObj(interp, "GetPerformanceInfo", GetLastError()));
369 return JIM_ERR;
372 #define JIMADD(name) \
373 a[n++] = Jim_NewStringObj(interp, #name, -1); \
374 a[n++] = Jim_NewIntObj(interp, pi. name )
376 JIMADD(CommitTotal);
377 JIMADD(CommitLimit);
378 JIMADD(CommitPeak);
379 JIMADD(PhysicalTotal);
380 JIMADD(PhysicalAvailable);
381 JIMADD(SystemCache);
382 JIMADD(KernelTotal);
383 JIMADD(KernelPaged);
384 JIMADD(KernelNonpaged);
385 JIMADD(PageSize);
386 JIMADD(HandleCount);
387 JIMADD(ProcessCount);
388 JIMADD(ThreadCount);
389 #undef JIMADD
391 Jim_SetResult(interp, Jim_NewListObj(interp, a, n));
392 return JIM_OK;
394 #endif
396 static int
397 Win32_SetComputerName(Jim_Interp *interp, int objc, Jim_Obj * const *objv)
399 int r = JIM_OK;
400 const char *name;
401 if (objc != 2) {
402 Jim_WrongNumArgs(interp, 1, objv, "computername");
403 return JIM_ERR;
405 name = Jim_String(objv[1]);
406 if (!SetComputerNameA(name)) {
407 Jim_SetResult(interp,
408 Win32ErrorObj(interp, "SetComputerName", GetLastError()));
409 r = JIM_ERR;
411 return r;
414 static int
415 Win32_GetModuleHandle(Jim_Interp *interp, int objc, Jim_Obj * const *objv)
417 HMODULE hModule = NULL;
418 const char *name = NULL;
420 if (objc < 1 || objc > 2) {
421 Jim_WrongNumArgs(interp, 1, objv, "?name?");
422 return JIM_ERR;
424 if (objc == 2)
425 name = Jim_String(objv[1]);
426 hModule = GetModuleHandleA(name);
427 if (hModule == NULL) {
428 Jim_SetResult(interp,
429 Win32ErrorObj(interp, "GetModuleHandle", GetLastError()));
430 return JIM_ERR;
432 Jim_SetResult(interp, Jim_NewIntObj(interp, (unsigned long)hModule));
433 return JIM_OK;
436 static int
437 Win32_LoadLibrary(Jim_Interp *interp, int objc, Jim_Obj * const *objv)
439 HMODULE hLib = NULL;
440 if (objc != 2) {
441 Jim_WrongNumArgs(interp, 1, objv, "path");
442 return JIM_ERR;
444 hLib = LoadLibraryA(Jim_String(objv[1]));
445 if (hLib == NULL) {
446 Jim_SetResult(interp,
447 Win32ErrorObj(interp, "LoadLibrary", GetLastError()));
448 return JIM_ERR;
450 Jim_SetResult(interp, Jim_NewIntObj(interp, (unsigned long)hLib));
451 return JIM_OK;
454 static int
455 Win32_FreeLibrary(Jim_Interp *interp, int objc, Jim_Obj * const *objv)
457 HMODULE hModule = NULL;
458 int r = JIM_OK;
460 if (objc != 2) {
461 Jim_WrongNumArgs(interp, 1, objv, "hmodule");
462 return JIM_ERR;
465 r = Jim_GetLong(interp, objv[1], (long *)&hModule);
466 if (r == JIM_OK) {
467 if (!FreeLibrary(hModule)) {
468 Jim_SetResult(interp,
469 Win32ErrorObj(interp, "FreeLibrary", GetLastError()));
470 r = JIM_ERR;
474 return r;
478 /* ---------------------------------------------------------------------- */
481 Jim_win32Init(Jim_Interp *interp)
483 if (Jim_PackageProvide(interp, "win32", "1.0", JIM_ERRMSG))
484 return JIM_ERR;
486 #define CMD(name) \
487 Jim_CreateCommand(interp, "win32." #name , Win32_ ## name , NULL, NULL)
489 CMD(ShellExecute);
490 CMD(FindWindow);
491 CMD(CloseWindow);
492 CMD(GetActiveWindow);
493 CMD(SetActiveWindow);
494 CMD(SetForegroundWindow);
495 CMD(Beep);
496 CMD(GetComputerName);
497 CMD(SetComputerName);
498 CMD(GetUserName);
499 CMD(GetModuleFileName);
500 CMD(GetVersion);
501 CMD(GetTickCount);
502 CMD(GetSystemTime);
503 #if !defined(__MINGW32__) && !defined(__CYGWIN__)
504 CMD(GetPerformanceInfo);
505 #endif
506 CMD(GetModuleHandle);
507 CMD(LoadLibrary);
508 CMD(FreeLibrary);
510 return JIM_OK;