root/vic/trunk/win32.c @ 734

Revision 734, 12.1 KB (checked in by ucackha, 16 years ago)

Added registry code from RAT + tidying up. Kris

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2 * Copyright (c) 1996 The Regents of the University of California.
3 * All rights reserved.
4 *
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.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *      This product includes software developed by the Network Research
16 *      Group at Lawrence Berkeley National Laboratory.
17 * 4. Neither the name of the University nor of the Laboratory may be used
18 *    to endorse or promote products derived from this software without
19 *    specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * This module contributed by John Brezak <brezak@apollo.hp.com>.
34 * January 31, 1996
35 */
36#ifndef lint
37static char rcsid[] =
38    "@(#) $Header$ (LBL)";
39#endif
40
41#include <assert.h>
42#include <io.h>
43#include <process.h>
44#include <fcntl.h>
45#include <windows.h>
46#include <malloc.h>
47#include <string.h>
48#include <stdio.h>
49#include <time.h>
50#include <winsock.h>
51#include <tk.h>
52#include "config.h"
53
54int
55uname(struct utsname *ub)
56{
57    char *ptr;
58    DWORD version;
59    SYSTEM_INFO sysinfo;
60    char hostname[4096];
61   
62    version = GetVersion();
63    GetSystemInfo(&sysinfo);
64   
65    switch (sysinfo.wProcessorArchitecture) {
66    case PROCESSOR_ARCHITECTURE_INTEL:
67        (void)strcpy(ub->machine, "ix86");
68        break;
69    case PROCESSOR_ARCHITECTURE_MIPS :
70        (void)strcpy(ub->machine, "mips");
71        break;
72    case PROCESSOR_ARCHITECTURE_ALPHA:
73        (void)strcpy(ub->machine, "alpha");
74        break;
75    case PROCESSOR_ARCHITECTURE_PPC:
76        (void)strcpy(ub->machine, "ppc");
77        break;
78    default:
79        (void)strcpy(ub->machine, "unknown");
80        break;
81    }
82   
83    if (version < 0x80000000) {
84        (void)strcpy(ub->version, "NT");
85    }
86    else if (LOBYTE(LOWORD(version))<4) {
87        (void)strcpy(ub->version, "Win32s");
88    }
89    else                                /* Win95 */ {
90        (void)strcpy(ub->version, "Win95");
91    }
92    (void)sprintf(ub->release, "%u.%u",
93                  (DWORD)(LOBYTE(LOWORD(version))),
94                  (DWORD)(HIBYTE(LOWORD(version))));
95    (void)strcpy(ub->sysname, "Windows");
96    if (gethostname(hostname, sizeof(hostname)) == 0) {
97        if (ptr = strchr(hostname, '.'))
98            *ptr = '\0';
99    }
100    else {
101        perror("uname: gethostname failed");
102        strcpy(hostname, "FAILURE");
103    }
104    strncpy(ub->nodename, hostname, sizeof(ub->nodename));
105    ub->nodename[_SYS_NMLN - 1] = '\0';
106    return 0;
107}
108
109int gettimeofday(struct timeval *p, struct timezone *z)
110{
111    if (p) {
112        extern void TclpGetTime(Tcl_Time*);
113        Tcl_Time tt;
114
115        TclpGetTime(&tt);
116        p->tv_sec = tt.sec;
117        p->tv_usec = tt.usec;
118    }
119    if (z) {
120        TIME_ZONE_INFORMATION tz;
121        GetTimeZoneInformation(&tz);
122        z->tz_minuteswest = tz.Bias ;
123        z->tz_dsttime = tz.StandardBias != tz.Bias;
124    }
125    return 0;
126}
127
128int
129strcasecmp(const char *s1, const char *s2)
130{
131    return stricmp(s1, s2);
132}
133
134uid_t
135getuid(void)
136{
137    return 0;
138   
139}
140
141gid_t
142getgid(void)
143{
144    return 0;
145}
146
147int
148gethostid(void)
149{
150    /*XXX*/
151    return 0;
152}
153
154int
155nice(int pri)
156{
157    return 0;
158}
159
160extern void TkWinXInit(HINSTANCE hInstance);
161extern int main(int argc, const char *argv[]);
162extern int __argc;
163extern char **__argv;
164
165static char argv0[255];         /* Buffer used to hold argv0. */
166
167char *__progname = "main";
168
169int APIENTRY
170WinMain(
171    HINSTANCE hInstance,
172    HINSTANCE hPrevInstance,
173    LPSTR lpszCmdLine,
174    int nCmdShow)
175{
176    char *p;
177    WSADATA WSAdata;
178
179    /* XXX
180     * initialize our socket interface plus the tcl 7.5 socket
181     * interface (since they redefine some routines we call).
182     * eventually we should just call the tcl sockets but at
183     * the moment that's hard to set up since they only support
184     * tcp in the notifier.
185     */
186    if (WSAStartup(MAKEWORD (1, 1), &WSAdata)) {
187        perror("Windows Sockets init failed");
188        abort();
189    }
190    TclHasSockets(NULL);
191
192    TkWinXInit(hInstance);
193
194    /*
195     * Increase the application queue size from default value of 8.
196     * At the default value, cross application SendMessage of WM_KILLFOCUS
197     * will fail because the handler will not be able to do a PostMessage!
198     * This is only needed for Windows 3.x, since NT dynamically expands
199     * the queue.
200     */
201    SetMessageQueue(64);
202
203    GetModuleFileName(NULL, argv0, 255);
204    p = argv0;
205    __progname = strrchr(p, '/');
206    if (__progname != NULL) {
207        __progname++;
208    }
209    else {
210        __progname = strrchr(p, '\\');
211        if (__progname != NULL) {
212            __progname++;
213        } else {
214            __progname = p;
215        }
216    }
217   
218    return main(__argc, (const char**)__argv);
219}
220
221void
222ShowMessage(int level, char *msg)
223{
224    MessageBeep(level);
225    MessageBox(NULL, msg, __progname,
226               level | MB_OK | MB_TASKMODAL | MB_SETFOREGROUND);
227}
228
229static char szTemp[4096];
230
231int
232printf(const char *fmt, ...)
233{
234    int retval;
235   
236    va_list ap;
237    va_start (ap, fmt);
238    retval = vsprintf(szTemp, fmt, ap);
239    OutputDebugString(szTemp);
240    ShowMessage(MB_ICONINFORMATION, szTemp);
241    va_end (ap);
242
243    return(retval);
244}
245
246int
247fprintf(FILE *f, const char *fmt, ...)
248{
249    int retval;
250   
251    va_list ap;
252    va_start (ap, fmt);
253    if (f == stderr) {
254        retval = vsprintf(szTemp, fmt, ap);
255        OutputDebugString(szTemp);
256        ShowMessage(MB_ICONERROR, szTemp);
257        va_end (ap);
258    }
259    else
260        retval = vfprintf(f, fmt, ap);
261   
262    return(retval);
263}
264
265void
266perror(const char *msg)
267{
268    DWORD cMsgLen;
269    CHAR *msgBuf;
270    DWORD dwError = GetLastError();
271   
272    cMsgLen = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
273                            FORMAT_MESSAGE_ALLOCATE_BUFFER | 40, NULL,
274                            dwError,
275                            MAKELANGID(0, SUBLANG_ENGLISH_US),
276                            (LPTSTR) &msgBuf, 512,
277                            NULL);
278    if (!cMsgLen)
279        fprintf(stderr, "%s%sError code %lu\n",
280                msg?msg:"", msg?": ":"", dwError);
281    else {
282        fprintf(stderr, "%s%s%s\n", msg?msg:"", msg?": ":"", msgBuf);
283        LocalFree((HLOCAL)msgBuf);
284    }
285}
286
287int
288WinPutsCmd(ClientData clientData, Tcl_Interp *interp, int argc, char **argv)
289{
290    FILE *f;
291    int i, newline;
292    char *fileId;
293
294    i = 1;
295    newline = 1;
296    if ((argc >= 2) && (strcmp(argv[1], "-nonewline") == 0)) {
297        newline = 0;
298        i++;
299    }
300    if ((i < (argc-3)) || (i >= argc)) {
301        Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
302                " ?-nonewline? ?fileId? string\"", (char *) NULL);
303        return TCL_ERROR;
304    }
305
306    /*
307     * The code below provides backwards compatibility with an old
308     * form of the command that is no longer recommended or documented.
309     */
310
311    if (i == (argc-3)) {
312        if (strncmp(argv[i+2], "nonewline", strlen(argv[i+2])) != 0) {
313            Tcl_AppendResult(interp, "bad argument \"", argv[i+2],
314                    "\": should be \"nonewline\"", (char *) NULL);
315            return TCL_ERROR;
316        }
317        newline = 0;
318    }
319    if (i == (argc-1)) {
320        fileId = "stdout";
321    } else {
322        fileId = argv[i];
323        i++;
324    }
325
326    if (strcmp(fileId, "stdout") == 0 || strcmp(fileId, "stderr") == 0) {
327        char *result;
328
329        if (newline) {
330            int len = strlen(argv[i]);
331            result = ckalloc(len+2);
332            memcpy(result, argv[i], len);
333            result[len] = '\n';
334            result[len+1] = 0;
335        } else {
336            result = argv[i];
337        }
338        OutputDebugString(result);
339        if (newline)
340            ckfree(result);
341    } else {
342        return TCL_OK;
343        clearerr(f);
344        fputs(argv[i], f);
345        if (newline) {
346            fputc('\n', f);
347        }
348        if (ferror(f)) {
349            Tcl_AppendResult(interp, "error writing \"", fileId,
350                    "\": ", Tcl_PosixError(interp), (char *) NULL);
351            return TCL_ERROR;
352        }
353    }
354    return TCL_OK;
355}
356
357int
358WinGetUserName(clientData, interp, argc, argv)
359    ClientData clientData;
360    Tcl_Interp *interp;                 /* Current interpreter. */
361    int argc;                           /* Number of arguments. */
362    char **argv;                        /* Argument strings. */
363{
364    char user[256];
365    int size = sizeof(user);
366   
367    if (!GetUserName(user, &size)) {
368        Tcl_AppendResult(interp, "GetUserName failed", NULL);
369        return TCL_ERROR;
370    }
371    Tcl_AppendResult(interp, user, NULL);
372    return TCL_OK;
373}
374
375static HKEY
376regroot(root)
377    char *root;
378{
379    if (strcasecmp(root, "HKEY_LOCAL_MACHINE") == 0)
380        return HKEY_LOCAL_MACHINE;
381    else if (strcasecmp(root, "HKEY_CURRENT_USER") == 0)
382        return HKEY_CURRENT_USER;
383    else if (strcasecmp(root, "HKEY_USERS") == 0)
384        return HKEY_USERS;
385    else if (strcasecmp(root, "HKEY_CLASSES_ROOT") == 0)
386        return HKEY_CLASSES_ROOT;
387    else
388        return NULL;
389}
390
391
392int 
393WinReg(ClientData clientdata, Tcl_Interp *interp, int argc, char **argv)
394{
395        static char szBuf[255], szOutBuf[255];
396        char *szRegRoot = NULL, *szRegPath = NULL, *szValueName;
397        int cbOutBuf = 255;
398        HKEY hKey, hKeyResult;
399        DWORD dwDisp;
400
401        if (argc < 4 || argc > 5) {
402                Tcl_AppendResult(interp, "wrong number of args\n", szBuf, NULL);
403                return TCL_ERROR;
404        }
405       
406        strcpy(szBuf, argv[2]);
407        szValueName = argv[3];
408        szRegRoot   = szBuf;
409        szRegPath   = strchr(szBuf, '\\');
410
411        if (szRegPath == NULL || szValueName == NULL) {
412                Tcl_AppendResult(interp, "registry path is wrongly written\n", szBuf, NULL);
413                return TCL_ERROR;
414        }
415       
416        *szRegPath = '\x0';
417        szRegPath++;
418
419        hKey = regroot(szRegRoot);
420       
421        if (hKey == (HKEY)-1) {
422                Tcl_AppendResult(interp, "root not found %s", szRegRoot, NULL);
423                return TCL_ERROR;
424        }
425
426        if (ERROR_SUCCESS != RegCreateKeyEx(hKey, szRegPath, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKeyResult, &dwDisp)) {
427                Tcl_AppendResult(interp, "Could not open key", szRegRoot, szRegPath, NULL);
428                return TCL_ERROR;
429        }
430
431        if (argc == 4 && !strcmp(argv[1],"get")) {
432                DWORD dwType = REG_SZ;
433                if (ERROR_SUCCESS != RegQueryValueEx(hKeyResult, szValueName, 0, &dwType, szOutBuf, &cbOutBuf)) {
434                        RegCloseKey(hKeyResult);
435                        Tcl_AppendResult(interp, "Could not set value", szValueName, NULL);
436                        return TCL_ERROR;       
437                }
438                Tcl_SetResult(interp, szOutBuf, TCL_STATIC);   
439        } else if (argc == 5 && !strcmp(argv[1], "set")) {
440                if (ERROR_SUCCESS != RegSetValueEx(hKeyResult, szValueName, 0, REG_SZ, argv[4], strlen(argv[4]))) {
441                        RegCloseKey(hKeyResult);
442                        Tcl_AppendResult(interp, "Could not set value", szValueName, argv[4], NULL);
443                        return TCL_ERROR;
444                }
445        }
446        RegCloseKey(hKeyResult);
447        return TCL_OK;
448}
449
450int
451RegGetValue(HKEY* key, char *subkey, char *value, char *dst, int dlen)
452{
453        HKEY lkey;     
454        LONG r;
455        LONG len;
456        DWORD type;
457 
458        r = RegOpenKeyEx(*key, subkey, 0, KEY_READ, &lkey);
459 
460        if (ERROR_SUCCESS == r) {
461                r = RegQueryValueEx(lkey, value, 0, &type, NULL, &len);
462                if (ERROR_SUCCESS == r && len <= dlen && type == REG_SZ) {
463                        type = REG_SZ;
464                        r = RegQueryValueEx(lkey, value, 0, &type, dst, &len);
465                } else {
466                        SetLastError(r);
467                        perror("");
468                }
469        } else {
470                SetLastError(r);
471                perror("");
472                return FALSE;
473        }
474        RegCloseKey(lkey);
475        return TRUE;
476}
Note: See TracBrowser for help on using the browser.