lists: fix crash in ListInsertElements
[jimtcl.git] / jim-win32.c
blob5837c18e21070ed0aec0bb58befe371c54d46283
1 /*-
2 * Copyright (c) 2005 Pat Thoyts <patthoyts@users.sourceforge.net>
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
26 * $Id$
28 * WIN32 extension
31 #define STRICT
32 #define WIN32_LEAN_AND_MEAN
33 #include <windows.h>
34 #include <tchar.h>
35 #include <shellapi.h>
36 #include <lmcons.h>
37 #include <ctype.h>
39 #define JIM_EXTENSION
40 #include "jim.h"
42 #if _MSC_VER >= 1000
43 #pragma comment(lib, "shell32")
44 #pragma comment(lib, "user32")
45 #pragma comment(lib, "advapi32")
46 #pragma comment(lib, "psapi")
47 #endif /* _MSC_VER >= 1000 */
49 static HINSTANCE g_hInstance = 0;
51 BOOL APIENTRY
52 DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID reserved)
54 JIM_NOTUSED(reserved);
55 if (dwReason == DLL_PROCESS_ATTACH) {
56 g_hInstance = hInstance;
58 return TRUE;
61 static Jim_Obj *
62 Win32ErrorObj(Jim_Interp *interp, const char * szPrefix, DWORD dwError)
64 Jim_Obj *msgObj = NULL;
65 char * lpBuffer = NULL;
66 DWORD dwLen = 0;
68 dwLen = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER
69 | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, LANG_NEUTRAL,
70 (char *)&lpBuffer, 0, NULL);
71 if (dwLen < 1) {
72 dwLen = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER
73 | FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
74 "code 0x%1!08X!%n", 0, LANG_NEUTRAL,
75 (char *)&lpBuffer, 0, (va_list *)&dwError);
78 msgObj = Jim_NewStringObj(interp, szPrefix, -1);
79 if (dwLen > 0) {
80 char *p = lpBuffer + dwLen - 1; /* remove cr-lf at end */
81 for ( ; p && *p && isspace(*p); p--)
83 *++p = 0;
84 Jim_AppendString(interp, msgObj, ": ", 2);
85 Jim_AppendString(interp, msgObj, lpBuffer, -1);
87 LocalFree((HLOCAL)lpBuffer);
88 return msgObj;
91 /* win32.ShellExecute verb file args */
92 static int
93 Win32_ShellExecute(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
95 int r;
96 const char *verb, *file, *parm = NULL;
97 char cwd[MAX_PATH + 1];
99 if (objc < 3 || objc > 4) {
100 Jim_WrongNumArgs(interp, 1, objv, "verb path ?parameters?");
101 return JIM_ERR;
103 verb = Jim_GetString(objv[1], NULL);
104 file = Jim_GetString(objv[2], NULL);
105 GetCurrentDirectoryA(MAX_PATH + 1, cwd);
106 if (objc == 4)
107 parm = Jim_GetString(objv[3], NULL);
108 r = (int)ShellExecuteA(NULL, verb, file, parm, cwd, SW_SHOWNORMAL);
109 if (r < 33)
110 Jim_SetResult(interp,
111 Win32ErrorObj(interp, "ShellExecute", GetLastError()));
112 return (r < 33) ? JIM_ERR : JIM_OK;
116 /* win32.FindWindow title ?class? */
117 static int
118 Win32_FindWindow(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
120 const char *title = NULL, *class = NULL;
121 HWND hwnd = NULL;
122 int r = JIM_OK;
124 if (objc < 2 || objc > 3) {
125 Jim_WrongNumArgs(interp, 1, objv, "title ?class?");
126 return JIM_ERR;
128 title = Jim_GetString(objv[1], NULL);
129 if (objc == 3)
130 class = Jim_GetString(objv[2], NULL);
131 hwnd = FindWindowA(class, title);
133 if (hwnd == NULL) {
134 Jim_SetResult(interp,
135 Win32ErrorObj(interp, "FindWindow", GetLastError()));
136 r = JIM_ERR;
137 } else {
138 Jim_SetResult(interp, Jim_NewIntObj(interp, (long)hwnd));
140 return r;
143 /* win32.CloseWindow windowHandle */
144 static int
145 Win32_CloseWindow(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
147 long hwnd;
149 if (objc != 2) {
150 Jim_WrongNumArgs(interp, 1, objv, "?windowHandle?");
151 return JIM_ERR;
153 if (Jim_GetLong(interp, objv[1], &hwnd) != JIM_OK)
154 return JIM_ERR;
155 if (!CloseWindow((HWND)hwnd)) {
156 Jim_SetResult(interp,
157 Win32ErrorObj(interp, "CloseWindow", GetLastError()));
158 return JIM_ERR;
160 return JIM_OK;
163 static int
164 Win32_DestroyWindow(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
166 long hwnd;
168 if (objc != 2) {
169 Jim_WrongNumArgs(interp, 1, objv, "?windowHandle?");
170 return JIM_ERR;
172 if (Jim_GetLong(interp, objv[1], &hwnd) != JIM_OK)
173 return JIM_ERR;
174 if (!DestroyWindow((HWND)hwnd)) {
175 Jim_SetResult(interp,
176 Win32ErrorObj(interp, "DestroyWindow", GetLastError()));
177 return JIM_ERR;
179 return JIM_OK;
182 static LRESULT CALLBACK
183 JimWin32WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
185 int objc = 0, r;
186 Jim_Obj *objv[16];
187 Jim_Interp *interp = (Jim_Interp *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
189 if (interp) {
190 objv[objc++] = Jim_NewStringObj(interp, "WndProc", -1);
191 switch (uMsg) {
192 case WM_CREATE:
193 //Jim_EvalObjVector(interp, objc, objv);
194 break;
195 case WM_COMMAND:
196 objv[objc++] = Jim_NewIntObj(interp, HIWORD(wParam));
197 objv[objc++] = Jim_NewIntObj(interp, LOWORD(wParam));
198 objv[objc++] = Jim_NewIntObj(interp, lParam);
199 r = Jim_EvalObjVector(interp, objc, objv);
200 if (r == JIM_BREAK) return 0L;
201 break;
204 return DefWindowProc(hwnd, uMsg, wParam, lParam);
207 static int
208 Win32_RegisterClass(Jim_Interp *interp, int objc, Jim_Obj *const objv[])
210 WNDCLASSEXA wc;
212 if (objc < 2 || objc > 3) {
213 Jim_WrongNumArgs(interp, 1, objv, "classname ?windowproc?");
214 return JIM_ERR;
217 // FIX ME: deal with the windowproc
219 wc.cbSize = sizeof(WNDCLASSEX);
220 wc.style = CS_HREDRAW | CS_VREDRAW;
221 wc.lpfnWndProc = DefWindowProc;
222 wc.cbClsExtra = 16;
223 wc.cbWndExtra = 0;
224 wc.hInstance = g_hInstance;
225 wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
226 wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
227 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
228 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
229 wc.lpszMenuName = wc.lpszClassName = Jim_GetString(objv[1], NULL);
231 if (objc == 3) {
232 wc.lpfnWndProc = JimWin32WindowProc;
235 if (!RegisterClassExA(&wc)) {
236 Jim_SetResult(interp,
237 Win32ErrorObj(interp, "RegisterClassEx", GetLastError()));
238 return JIM_ERR;
241 return JIM_OK;
244 static int
245 Win32_CreateWindow(Jim_Interp *interp, int objc, Jim_Obj *const objv[])
247 int r = JIM_ERR;
248 HWND hwnd, hwndParent = HWND_DESKTOP;
249 DWORD style = WS_VISIBLE | WS_OVERLAPPEDWINDOW;
250 UINT id = 0;
251 const char *class, *title;
253 if (objc < 3 || objc > 5) {
254 Jim_WrongNumArgs(interp, 1, objv, "class title ?parent? ?id?");
255 return JIM_ERR;
258 class = Jim_GetString(objv[1], NULL);
259 title = Jim_GetString(objv[2], NULL);
260 if (objc == 4) {
261 if (Jim_GetLong(interp, objv[3], (long *)&hwndParent) != JIM_OK)
262 return JIM_ERR;
263 style = WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
265 if (objc == 5) {
266 if (Jim_GetLong(interp, objv[4], (long *)&id) != JIM_OK)
267 return JIM_ERR;
270 hwnd = CreateWindowA(class, title, style,
271 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
272 hwndParent, (HMENU)id, g_hInstance, NULL);
273 if (hwnd) {
274 SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)interp);
275 Jim_SetResult(interp, Jim_NewIntObj(interp, (DWORD)hwnd));
276 r = JIM_OK;
277 } else {
278 Jim_SetResult(interp,
279 Win32ErrorObj(interp, "CreateWindow", GetLastError()));
280 r = JIM_ERR;
283 return r;
286 static int
287 Win32_UpdateWindow(Jim_Interp *interp, int objc, Jim_Obj *const objv[])
289 HWND hwnd;
291 if (objc != 2) {
292 Jim_WrongNumArgs(interp, 1, objv, "hwnd");
293 return JIM_ERR;
295 if (Jim_GetLong(interp, objv[1], (long *)&hwnd) != JIM_OK)
296 return JIM_ERR;
297 if (!UpdateWindow(hwnd)) {
298 Jim_SetResult(interp,
299 Win32ErrorObj(interp, "UpdateWindow", GetLastError()));
300 return JIM_ERR;
302 return JIM_OK;
305 static int
306 Win32_MoveWindow(Jim_Interp *interp, int objc, Jim_Obj *const objv[])
308 HWND hwnd;
309 int n, param[4];
311 if (objc != 6) {
312 Jim_WrongNumArgs(interp, 1, objv, "hwnd x y width height");
313 return JIM_ERR;
315 if (Jim_GetLong(interp, objv[1], (long *)&hwnd) != JIM_OK)
316 return JIM_ERR;
317 for (n = 2; n < 6; n++) {
318 if (Jim_GetLong(interp, objv[n], (long*)&param[n-2]) != JIM_OK)
319 return JIM_ERR;
322 if (!MoveWindow(hwnd, param[0], param[1], param[2], param[3], TRUE)) {
323 Jim_SetResult(interp,
324 Win32ErrorObj(interp, "MoveWindow", GetLastError()));
325 return JIM_ERR;
327 return JIM_OK;
330 static int
331 Win32_ShowWindow(Jim_Interp *interp, int objc, Jim_Obj *const objv[])
333 HWND hwnd;
334 int cmd;
335 const char *cmds[] = {
336 "SW_HIDE", "SW_SHOWNORMAL", "SW_SHOWMINIMIZED", "SW_MAXIMIZE",
337 "SW_SHOWNOACTIVATE", "SW_SHOW", "SW_MINIMIZE", "SW_SHOWMINNOACTIVE",
338 "SW_SHOWNA", "SW_RESTORE", "SW_SHOWDEFAULT", "SW_FORCEMINIMIZE",
339 NULL
341 if (objc != 3) {
342 Jim_WrongNumArgs(interp, 1, objv, "windowhandle option");
343 return JIM_ERR;
345 if (Jim_GetLong(interp, objv[1], (long *)&hwnd) != JIM_OK)
346 return JIM_ERR;
347 if (Jim_GetEnum(interp, objv[2], cmds, &cmd, "command", JIM_ERRMSG) != JIM_OK)
348 return JIM_ERR;
351 if (!ShowWindow(hwnd, cmd)) {
352 Jim_SetResult(interp,
353 Win32ErrorObj(interp, "ShowWindow", GetLastError()));
354 return JIM_ERR;
356 return JIM_OK;
359 static int
360 Win32_GetActiveWindow(Jim_Interp *interp, int objc, Jim_Obj *const objv[])
362 JIM_NOTUSED(objc);
363 JIM_NOTUSED(objv);
365 Jim_SetResult(interp, Jim_NewIntObj(interp, (DWORD)GetActiveWindow()));
366 return JIM_OK;
369 static int
370 Win32_SetActiveWindow(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
372 HWND hwnd, old;
373 int r = JIM_OK;
375 if (objc != 2) {
376 Jim_WrongNumArgs(interp, 1, objv, "windowHandle");
377 return JIM_ERR;
379 r = Jim_GetLong(interp, objv[1], (long *)&hwnd);
380 if (r == JIM_OK) {
381 old = SetActiveWindow(hwnd);
382 if (old == NULL) {
383 Jim_SetResult(interp,
384 Win32ErrorObj(interp, "SetActiveWindow", GetLastError()));
385 r = JIM_ERR;
386 } else {
387 Jim_SetResult(interp, Jim_NewIntObj(interp, (long)old));
390 return r;
393 static int
394 Win32_SetForegroundWindow(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
396 HWND hwnd;
397 int r = JIM_OK;
399 if (objc != 2) {
400 Jim_WrongNumArgs(interp, 1, objv, "windowHandle");
401 return JIM_ERR;
403 r = Jim_GetLong(interp, objv[1], (long *)&hwnd);
404 if (r == JIM_OK) {
405 if (!SetForegroundWindow(hwnd)) {
406 Jim_SetResult(interp,
407 Win32ErrorObj(interp, "SetForegroundWindow", GetLastError()));
408 r = JIM_ERR;
411 return r;
414 static int
415 Win32_Beep(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
417 long freq, duration;
418 int r = JIM_OK;
420 if (objc != 3) {
421 Jim_WrongNumArgs(interp, 1, objv, "freq duration");
422 return JIM_ERR;
424 r = Jim_GetLong(interp, objv[1], &freq);
425 if (r == JIM_OK)
426 r = Jim_GetLong(interp, objv[2], &duration);
427 if (freq < 0x25) freq = 0x25;
428 if (freq > 0x7fff) freq = 0x7fff;
429 if (r == JIM_OK) {
430 if (!Beep(freq, duration)) {
431 Jim_SetResult(interp,
432 Win32ErrorObj(interp, "Beep", GetLastError()));
433 r = JIM_ERR;
436 return r;
439 static int
440 Win32_GetComputerName(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
442 char name[MAX_COMPUTERNAME_LENGTH + 1];
443 DWORD size = MAX_COMPUTERNAME_LENGTH;
444 int r = JIM_OK;
446 if (objc != 1) {
447 Jim_WrongNumArgs(interp, 1, objv, "");
448 return JIM_ERR;
451 if (GetComputerNameA(name, &size)) {
452 Jim_Obj *nameObj = Jim_NewStringObj(interp, name, size);
453 Jim_SetResult(interp, nameObj);
454 } else {
455 Jim_SetResult(interp,
456 Win32ErrorObj(interp, "GetComputerName", GetLastError()));
457 r = JIM_ERR;
460 return r;
463 static int
464 Win32_GetUserName(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
466 char name[UNLEN + 1];
467 DWORD size = UNLEN;
468 int r = JIM_OK;
470 if (objc != 1) {
471 Jim_WrongNumArgs(interp, 1, objv, "");
472 return JIM_ERR;
475 if (GetUserNameA(name, &size)) {
476 Jim_Obj *nameObj = Jim_NewStringObj(interp, name, size);
477 Jim_SetResult(interp, nameObj);
478 } else {
479 Jim_SetResult(interp,
480 Win32ErrorObj(interp, "GetUserName", GetLastError()));
481 r = JIM_ERR;
484 return r;
487 static int
488 Win32_GetModuleFileName(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
490 HMODULE hModule = NULL;
491 char path[MAX_PATH];
492 DWORD len = 0;
494 if (objc > 2) {
495 Jim_WrongNumArgs(interp, 1, objv, "?moduleid?");
496 return JIM_ERR;
499 if (objc == 2) {
500 if (Jim_GetLong(interp, objv[1], (long *)&hModule) != JIM_OK) {
501 return JIM_ERR;
505 len = GetModuleFileNameA(hModule, path, MAX_PATH);
506 if (len != 0) {
507 Jim_Obj *pathObj = Jim_NewStringObj(interp, path, len);
508 Jim_SetResult(interp, pathObj);
509 } else {
510 Jim_SetResult(interp,
511 Win32ErrorObj(interp, "GetModuleFileName", GetLastError()));
512 return JIM_ERR;
515 return JIM_OK;
518 static int
519 Win32_GetVersion(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
521 JIM_NOTUSED(objc);
522 JIM_NOTUSED(objv);
524 Jim_SetResult(interp, Jim_NewIntObj(interp, GetVersion()));
525 return JIM_OK;
528 static int
529 Win32_GetTickCount(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
531 JIM_NOTUSED(objc);
532 JIM_NOTUSED(objv);
534 Jim_SetResult(interp, Jim_NewIntObj(interp, GetTickCount()));
535 return JIM_OK;
538 static int
539 Win32_GetSystemTime(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
541 Jim_Obj *a[16];
542 size_t n = 0;
543 SYSTEMTIME t;
544 JIM_NOTUSED(objc);
545 JIM_NOTUSED(objv);
547 GetSystemTime(&t);
549 #define JIMADD(name) \
550 a[n++] = Jim_NewStringObj(interp, #name, -1); \
551 a[n++] = Jim_NewIntObj(interp, t.w ## name )
553 JIMADD(Year);
554 JIMADD(Month);
555 JIMADD(DayOfWeek);
556 JIMADD(Day);
557 JIMADD(Hour);
558 JIMADD(Minute);
559 JIMADD(Second);
560 JIMADD(Milliseconds);
561 #undef JIMADD
563 Jim_SetResult(interp, Jim_NewListObj(interp, a, n));
564 return JIM_OK;
567 static int
568 Win32_GetSystemInfo(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
570 Jim_Obj *a[20];
571 SYSTEM_INFO si;
572 int n = 0;
573 struct pa_map { int arch; const char *name; };
574 struct pa_map *p, map[] = {
575 { PROCESSOR_ARCHITECTURE_INTEL, "intel" },
576 { PROCESSOR_ARCHITECTURE_MIPS, "mips" },
577 { PROCESSOR_ARCHITECTURE_ALPHA, "alpha" },
578 { PROCESSOR_ARCHITECTURE_PPC, "ppc" },
579 { PROCESSOR_ARCHITECTURE_SHX, "shx" },
580 { PROCESSOR_ARCHITECTURE_ARM, "arm" },
581 { PROCESSOR_ARCHITECTURE_IA64, "ia64" },
582 { PROCESSOR_ARCHITECTURE_ALPHA64,"alpha64" },
583 { PROCESSOR_ARCHITECTURE_MSIL, "msil" },
584 { PROCESSOR_ARCHITECTURE_AMD64, "amd64"},
585 { PROCESSOR_ARCHITECTURE_IA32_ON_WIN64, "ia32onwin64" },
586 { PROCESSOR_ARCHITECTURE_UNKNOWN,"unknown" }
588 JIM_NOTUSED(objc);
589 JIM_NOTUSED(objv);
591 GetSystemInfo(&si);
593 a[n++] = Jim_NewStringObj(interp, "ProcessorArchitecture", -1);
594 for (p = map; p->arch != PROCESSOR_ARCHITECTURE_UNKNOWN; ++p) {
595 if (p->arch == si.wProcessorArchitecture) {
596 break;
599 a[n++] = Jim_NewStringObj(interp, p->name, -1);
601 #define JIMADD(name,element) \
602 a[n++] = Jim_NewStringObj(interp, #name, -1); \
603 a[n++] = Jim_NewIntObj(interp, (jim_wide)si. ## element )
605 JIMADD(PageSize, dwPageSize);
606 JIMADD(MinimumApplicationAddress, lpMinimumApplicationAddress);
607 JIMADD(MaximumApplicationAddress, lpMaximumApplicationAddress);
608 JIMADD(ActiveProcessorMask, dwActiveProcessorMask);
609 JIMADD(NumberOfProcessors, dwNumberOfProcessors);
610 JIMADD(ProcessorType, dwProcessorType);
611 JIMADD(AllocationGranularity, dwAllocationGranularity);
612 JIMADD(ProcessorLevel, wProcessorLevel);
613 JIMADD(ProcessorRevision, wProcessorRevision);
614 #undef JIMADD
616 Jim_SetResult(interp, Jim_NewListObj(interp, a, n));
617 return JIM_OK;
620 // Declared here because its not available without recent versions of the
621 // Platform SDK. mingw32 doesn't declare it all either.
622 typedef struct _PERFORMANCE_INFORMATION {
623 DWORD cb;
624 SIZE_T CommitTotal;
625 SIZE_T CommitLimit;
626 SIZE_T CommitPeak;
627 SIZE_T PhysicalTotal;
628 SIZE_T PhysicalAvailable;
629 SIZE_T SystemCache;
630 SIZE_T KernelTotal;
631 SIZE_T KernelPaged;
632 SIZE_T KernelNonpaged;
633 SIZE_T PageSize;
634 DWORD HandleCount;
635 DWORD ProcessCount;
636 DWORD ThreadCount;
637 } PERFORMANCE_INFORMATION;
638 typedef BOOL (__stdcall *LPFNGETPERFORMANCEINFO)(PERFORMANCE_INFORMATION *, DWORD);
640 static int
641 Win32_GetPerformanceInfo(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
643 Jim_Obj *a[26];
644 size_t n = 0;
645 PERFORMANCE_INFORMATION pi;
646 LPFNGETPERFORMANCEINFO lpfnGetPerformanceInfo = NULL;
647 HMODULE hLib = (HMODULE)Jim_CmdPrivData(interp);
648 JIM_NOTUSED(objc);
649 JIM_NOTUSED(objv);
651 if (hLib != NULL)
652 lpfnGetPerformanceInfo = (LPFNGETPERFORMANCEINFO)GetProcAddress(hLib, "GetPerformanceInfo");
653 if (lpfnGetPerformanceInfo == NULL) {
654 /* should never happen */
655 Jim_SetResultString(interp, "argh!", -1);
656 return JIM_ERR;
659 pi.cb = sizeof(pi);
660 if (!lpfnGetPerformanceInfo(&pi, sizeof(pi))) {
661 Jim_SetResult(interp,
662 Win32ErrorObj(interp, "GetPerformanceInfo", GetLastError()));
663 return JIM_ERR;
666 #define JIMADD(name) \
667 a[n++] = Jim_NewStringObj(interp, #name, -1); \
668 a[n++] = Jim_NewIntObj(interp, pi.name )
670 JIMADD(CommitTotal);
671 JIMADD(CommitLimit);
672 JIMADD(CommitPeak);
673 JIMADD(PhysicalTotal);
674 JIMADD(PhysicalAvailable);
675 JIMADD(SystemCache);
676 JIMADD(KernelTotal);
677 JIMADD(KernelPaged);
678 JIMADD(KernelNonpaged);
679 JIMADD(PageSize);
680 JIMADD(HandleCount);
681 JIMADD(ProcessCount);
682 JIMADD(ThreadCount);
683 #undef JIMADD
685 Jim_SetResult(interp, Jim_NewListObj(interp, a, n));
686 return JIM_OK;
689 #if WINVER >= 0x0500
690 static int
691 Win32_GetCursorInfo(Jim_Interp *interp, int objc, Jim_Obj *const objv[])
693 Jim_Obj *a[8];
694 size_t n = 0;
695 CURSORINFO ci;
697 JIM_NOTUSED(objc);
698 JIM_NOTUSED(objv);
700 ci.cbSize = sizeof(ci);
701 if (!GetCursorInfo(&ci)) {
702 Jim_SetResult(interp,
703 Win32ErrorObj(interp, "GetCursorInfo", GetLastError()));
704 return JIM_ERR;
707 #define JIMADDN(name) a[n++] = Jim_NewStringObj(interp, #name, -1);
708 #define JIMADDV(v) a[n++] = Jim_NewIntObj(interp, (v));
709 JIMADDN(flags); JIMADDV(ci.flags);
710 JIMADDN(hCursor); JIMADDV((DWORD)ci.hCursor);
711 JIMADDN(x); JIMADDV(ci.ptScreenPos.x);
712 JIMADDN(y); JIMADDV(ci.ptScreenPos.y);
713 #undef JIMADDN
714 #undef JIMADDV
716 Jim_SetResult(interp, Jim_NewListObj(interp, a, n));
717 return JIM_OK;
720 static BOOL
721 Win32_GetLastInputInfo(Jim_Interp *interp, int objc, Jim_Obj *const objv[])
723 struct lastinputinfo_t {
724 UINT cbSize;
725 DWORD dwTime;
726 } lii;
727 typedef BOOL (__stdcall *LPFNGETLASTINPUTINFO)(struct lastinputinfo_t *);
728 LPFNGETLASTINPUTINFO lpfnGetLastInputInfo = NULL;
729 HMODULE hLib = (HMODULE)Jim_CmdPrivData(interp);
730 JIM_NOTUSED(objc);
731 JIM_NOTUSED(objv);
733 if (hLib != NULL)
734 lpfnGetLastInputInfo = (LPFNGETLASTINPUTINFO)GetProcAddress(hLib, "GetLastInputInfo");
735 if (lpfnGetLastInputInfo == NULL) {
736 Jim_SetResultString(interp, "command not available on this platform", -1);
737 return JIM_ERR;
740 lii.cbSize = sizeof(lii);
741 if (!lpfnGetLastInputInfo(&lii)) {
742 Jim_SetResult(interp,
743 Win32ErrorObj(interp, "GetLastInputInfo", GetLastError()));
744 return JIM_ERR;
746 Jim_SetResult(interp, Jim_NewIntObj(interp, lii.dwTime));
747 return JIM_OK;
750 #define F(x) { #x , x }
751 typedef struct { const char *s; unsigned long f; } ANIMATEWINDOWFLAGSMAP;
752 static ANIMATEWINDOWFLAGSMAP AnimateWindowFlagsMap[] = {
753 F(AW_SLIDE), F(AW_ACTIVATE), F(AW_BLEND), F(AW_HIDE), F(AW_CENTER),
754 F(AW_HOR_POSITIVE), F(AW_HOR_NEGATIVE), F(AW_VER_POSITIVE),
755 F(AW_VER_NEGATIVE), { NULL, 0 }
757 #undef F
759 static int
760 GetAnimateWindowFlagsFromObj(Jim_Interp *interp, Jim_Obj *listObj, DWORD *flags)
762 int r = JIM_OK, n, nLength;
763 *flags = 0;
764 Jim_ListLength(interp, listObj, &nLength);
765 if (r == JIM_OK) {
766 for (n = 0; n < nLength; n++) {
767 ANIMATEWINDOWFLAGSMAP *p;
768 Jim_Obj *obj;
769 r = Jim_ListIndex(interp, listObj, n, &obj, 1);
770 for (p = AnimateWindowFlagsMap; r == JIM_OK && p->s != NULL; p++) {
771 size_t len;
772 const char *name = Jim_GetString(obj, &len);
773 if (strncmp(p->s, name, len) == 0) {
774 *flags |= p->f;
775 break;
778 if (p->s == NULL) {
779 Jim_SetResultString(interp, "invalid option", -1);
780 return JIM_ERR;
785 return r;
788 static int
789 Win32_AnimateWindow(Jim_Interp *interp, int objc, Jim_Obj *const objv[])
791 HWND hwnd;
792 DWORD dwTime = 0, dwFlags = 0;
793 struct map_t { const char* s; DWORD f; };
795 if (objc != 4) {
796 Jim_WrongNumArgs(interp, 1, objv, "windowhandle time flags");
797 return JIM_ERR;
800 if (Jim_GetLong(interp, objv[1], (long *)&hwnd) != JIM_OK)
801 return JIM_ERR;
802 if (Jim_GetLong(interp, objv[2], &dwTime) != JIM_OK)
803 return JIM_ERR;
804 if (GetAnimateWindowFlagsFromObj(interp, objv[3], &dwFlags) != JIM_OK)
805 return JIM_ERR;
807 if (!AnimateWindow(hwnd, dwTime, dwFlags)) {
808 DWORD err = GetLastError();
809 Jim_Obj *errObj;
810 if (err == ERROR_SUCCESS)
811 errObj = Jim_NewStringObj(interp, "error: "
812 " calling thread does not own the window", -1);
813 else
814 errObj = Win32ErrorObj(interp, "AnimateWindow", err);
815 Jim_SetResult(interp, errObj);
816 return JIM_ERR;
818 return JIM_OK;
821 #endif /* WINVER >= 0x0500 */
823 static int
824 Win32_GetCursorPos(Jim_Interp *interp, int objc, Jim_Obj *const objv[])
826 Jim_Obj *a[2];
827 POINT pt;
828 JIM_NOTUSED(objc);
829 JIM_NOTUSED(objv);
831 if (!GetCursorPos(&pt)) {
832 Jim_SetResult(interp,
833 Win32ErrorObj(interp, "GetCursorPos", GetLastError()));
834 return JIM_ERR;
836 a[0] = Jim_NewIntObj(interp, pt.x);
837 a[1] = Jim_NewIntObj(interp, pt.y);
838 Jim_SetResult(interp, Jim_NewListObj(interp, a, 2));
839 return JIM_OK;
842 static int
843 Win32_SetCursorPos(Jim_Interp *interp, int objc, Jim_Obj *const objv[])
845 int r = JIM_OK;
846 POINT pt;
848 if (objc != 3) {
849 Jim_WrongNumArgs(interp, 1, objv, "x y");
850 return JIM_ERR;
853 r = Jim_GetLong(interp, objv[1], &pt.x);
854 if (r == JIM_OK)
855 r = Jim_GetLong(interp, objv[2], &pt.y);
856 if (r == JIM_OK) {
857 if (!SetCursorPos(pt.x, pt.y)) {
858 Jim_SetResult(interp,
859 Win32ErrorObj(interp, "SetCursorPos", GetLastError()));
860 r = JIM_ERR;
863 return r;
866 static int
867 Win32_GetCursor(Jim_Interp *interp, int objc, Jim_Obj *const objv[])
869 HCURSOR hCursor;
870 JIM_NOTUSED(objc);
871 JIM_NOTUSED(objv);
873 hCursor = GetCursor();
874 Jim_SetResult(interp, Jim_NewIntObj(interp, (DWORD)hCursor));
875 return JIM_OK;
878 static int
879 Win32_SetCursor(Jim_Interp *interp, int objc, Jim_Obj *const objv[])
881 HCURSOR hCursor;
882 int r = JIM_OK;
884 if (objc != 2) {
885 Jim_WrongNumArgs(interp, 1, objv, "hCursor");
886 return JIM_ERR;
889 r = Jim_GetLong(interp, objv[1], (long *)&hCursor);
890 if (r == JIM_OK) {
891 hCursor = SetCursor(hCursor);
892 Jim_SetResult(interp, Jim_NewIntObj(interp, (DWORD)hCursor));
894 return r;
897 #ifndef IDC_HAND
898 #define IDC_HAND MAKEINTRESOURCE(32649)
899 #endif
901 static int
902 Win32_LoadCursor(Jim_Interp *interp, int objc, Jim_Obj *const objv[])
904 HCURSOR hCursor;
905 int ndx;
906 static const char *name[] = {
907 "appstarting", "arrow", "cross", "hand", "help", "ibeam",
908 "icon", "no", "size", "sizeall", "sizenesw", "sizens",
909 "sizenwse", "sizewe", "uparrow", "wait", NULL
911 static LPCTSTR id[] = {
912 IDC_APPSTARTING, IDC_ARROW, IDC_CROSS, IDC_HAND, IDC_HELP, IDC_IBEAM,
913 IDC_ICON, IDC_NO, IDC_SIZEALL, IDC_SIZEALL, IDC_SIZENESW, IDC_SIZENS,
914 IDC_SIZENWSE, IDC_UPARROW, IDC_WAIT, NULL
917 if (objc != 2) {
918 Jim_WrongNumArgs(interp, 1, objv, "name");
919 return JIM_ERR;
922 if (Jim_GetEnum(interp, objv[1], name, &ndx, "cursor name", JIM_ERRMSG) != JIM_OK)
923 return JIM_ERR;
925 hCursor = LoadCursor((HINSTANCE)NULL, id[ndx]);
926 if (hCursor == NULL) {
927 Jim_SetResult(interp,
928 Win32ErrorObj(interp, "LoadCursor", GetLastError()));
929 return JIM_ERR;
932 Jim_SetResult(interp, Jim_NewIntObj(interp, (DWORD)hCursor));
933 return JIM_OK;
936 static int
937 Win32_SetComputerName(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
939 int r = JIM_OK;
940 const char *name;
941 if (objc != 2) {
942 Jim_WrongNumArgs(interp, 1, objv, "computername");
943 return JIM_ERR;
945 name = Jim_GetString(objv[1], NULL);
946 if (!SetComputerNameA(name)) {
947 Jim_SetResult(interp,
948 Win32ErrorObj(interp, "SetComputerName", GetLastError()));
949 r = JIM_ERR;
951 return r;
954 static int
955 Win32_GetModuleHandle(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
957 HMODULE hModule = NULL;
958 const char *name = NULL;
960 if (objc < 1 || objc > 2) {
961 Jim_WrongNumArgs(interp, 1, objv, "?name?");
962 return JIM_ERR;
964 if (objc == 2)
965 name = Jim_GetString(objv[1], NULL);
966 hModule = GetModuleHandleA(name);
967 if (hModule == NULL) {
968 Jim_SetResult(interp,
969 Win32ErrorObj(interp, "GetModuleHandle", GetLastError()));
970 return JIM_ERR;
972 Jim_SetResult(interp, Jim_NewIntObj(interp, (unsigned long)hModule));
973 return JIM_OK;
976 static int
977 Win32_LoadLibrary(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
979 HMODULE hLib = NULL;
980 if (objc != 2) {
981 Jim_WrongNumArgs(interp, 1, objv, "path");
982 return JIM_ERR;
984 hLib = LoadLibraryA(Jim_GetString(objv[1], NULL));
985 if (hLib == NULL) {
986 Jim_SetResult(interp,
987 Win32ErrorObj(interp, "LoadLibrary", GetLastError()));
988 return JIM_ERR;
990 Jim_SetResult(interp, Jim_NewIntObj(interp, (unsigned long)hLib));
991 return JIM_OK;
994 static int
995 Win32_FreeLibrary(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
997 HMODULE hModule = NULL;
998 int r = JIM_OK;
1000 if (objc != 2) {
1001 Jim_WrongNumArgs(interp, 1, objv, "hmodule");
1002 return JIM_ERR;
1005 r = Jim_GetLong(interp, objv[1], (long *)&hModule);
1006 if (r == JIM_OK) {
1007 if (!FreeLibrary(hModule)) {
1008 Jim_SetResult(interp,
1009 Win32ErrorObj(interp, "FreeLibrary", GetLastError()));
1010 r = JIM_ERR;
1014 return r;
1018 /* ----------------------------------------------------------------------
1019 * Filesystem APIs
1022 static int
1023 Win32_CreateDirectory(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
1025 const char * path;
1027 if (objc != 2) {
1028 Jim_WrongNumArgs(interp, 1, objv, "path");
1029 return JIM_ERR;
1032 path = Jim_GetString(objv[1], NULL);
1033 if (!CreateDirectoryA(path, NULL)) {
1034 Jim_SetResult(interp,
1035 Win32ErrorObj(interp, "CreateDirectory", GetLastError()));
1036 return JIM_ERR;
1039 return JIM_OK;
1042 static int
1043 Win32_RemoveDirectory(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
1045 const char * path;
1047 if (objc != 2) {
1048 Jim_WrongNumArgs(interp, 1, objv, "path");
1049 return JIM_ERR;
1052 path = Jim_GetString(objv[1], NULL);
1053 if (!RemoveDirectoryA(path)) {
1054 Jim_SetResult(interp,
1055 Win32ErrorObj(interp, "RemoveDirectory", GetLastError()));
1056 return JIM_ERR;
1059 return JIM_OK;
1063 * CopyFile, MoveFile, CreateFile, DeleteFile, LockFile,
1064 * ReadFile and WriteFile should get rolled into a stream/channel thing.
1067 /* ----------------------------------------------------------------------
1068 * Cleanup for dynamically loaded commands.
1071 static void
1072 Win32_ReleasePrivLib(Jim_Interp *interp, void *clientData)
1074 HMODULE hLib = (HMODULE)clientData;
1075 JIM_NOTUSED(interp);
1076 if (hLib)
1077 FreeLibrary(hLib);
1080 /* ----------------------------------------------------------------------
1081 * package load function.
1084 DLLEXPORT int
1085 Jim_OnLoad(Jim_Interp *interp)
1087 HMODULE hLib;
1089 Jim_InitExtension(interp);
1090 if (Jim_PackageProvide(interp, "win32", "1.0", JIM_ERRMSG) != JIM_OK)
1091 return JIM_ERR;
1093 #define CMD(name) \
1094 Jim_CreateCommand(interp, "win32." #name , Win32_ ## name , NULL, NULL)
1096 CMD(ShellExecute);
1097 CMD(RegisterClass);
1098 CMD(CreateWindow);
1099 CMD(FindWindow);
1100 CMD(CloseWindow);
1101 CMD(ShowWindow);
1102 CMD(MoveWindow);
1103 CMD(UpdateWindow);
1104 CMD(DestroyWindow);
1105 CMD(GetActiveWindow);
1106 CMD(SetActiveWindow);
1107 CMD(SetForegroundWindow);
1108 CMD(GetCursorPos);
1109 CMD(SetCursorPos);
1110 CMD(GetCursor);
1111 CMD(SetCursor);
1112 CMD(LoadCursor);
1113 CMD(Beep);
1114 CMD(GetComputerName);
1115 CMD(SetComputerName);
1116 CMD(GetUserName);
1117 CMD(GetModuleFileName);
1118 CMD(GetVersion);
1119 CMD(GetTickCount);
1120 CMD(GetSystemTime);
1121 CMD(GetSystemInfo);
1122 CMD(GetModuleHandle);
1123 CMD(LoadLibrary);
1124 CMD(FreeLibrary);
1125 CMD(CreateDirectory);
1126 CMD(RemoveDirectory);
1128 #if WINVER >= 0x0500
1129 CMD(GetCursorInfo);
1130 CMD(AnimateWindow);
1131 #endif
1133 /* Check that this DLL is available before creating the command. */
1134 hLib = LoadLibrary(_T("psapi"));
1135 if (hLib != NULL) {
1136 Jim_CreateCommand(interp, "win32.GetPerformanceInfo",
1137 Win32_GetPerformanceInfo, hLib, Win32_ReleasePrivLib);
1139 #if WINVER >= 0x0500
1140 hLib = LoadLibrary(_T("user32"));
1141 if (hLib != NULL) {
1142 Jim_CreateCommand(interp, "win32.GetLastInputInfo",
1143 Win32_GetLastInputInfo, hLib, Win32_ReleasePrivLib);
1145 #endif /* WINVER >= 0x0500 */
1147 return JIM_OK;