/* * Copyright (c) 1996 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the Network Research * Group at Lawrence Berkeley National Laboratory. * 4. Neither the name of the University nor of the Laboratory may be used * to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * This module contributed by John Brezak . * January 31, 1996 * * @(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/common/win32.c,v 1.5 1999/07/02 21:02:10 haoboy Exp $ (LBL) */ #ifdef WIN32 #include #include #include #include #include #include #include #include #include #include #include #include "config.h" #include /* forward declarations */ int WinGetUserName(ClientData, Tcl_Interp*, int ac, char**av); int WinGetHostName(ClientData, Tcl_Interp*, int ac, char**av); int WinPutRegistry(ClientData, Tcl_Interp*, int ac, char**av); int WinGetRegistry(ClientData, Tcl_Interp*, int ac, char**av); void TkConsoleCreate(); int TkConsoleInit(Tcl_Interp* interp); int uname(struct utsname *ub) { char *ptr; DWORD version; SYSTEM_INFO sysinfo; char hostname[4096]; version = GetVersion(); GetSystemInfo(&sysinfo); switch (sysinfo.wProcessorArchitecture) { case PROCESSOR_ARCHITECTURE_INTEL: (void)strcpy(ub->machine, "ix86"); break; case PROCESSOR_ARCHITECTURE_MIPS : (void)strcpy(ub->machine, "mips"); break; case PROCESSOR_ARCHITECTURE_ALPHA: (void)strcpy(ub->machine, "alpha"); break; case PROCESSOR_ARCHITECTURE_PPC: (void)strcpy(ub->machine, "ppc"); break; default: (void)strcpy(ub->machine, "unknown"); break; } if (version < 0x80000000) { (void)strcpy(ub->version, "NT"); } else if (LOBYTE(LOWORD(version))<4) { (void)strcpy(ub->version, "Win32s"); } else /* Win95 */ { (void)strcpy(ub->version, "Win95"); } (void)sprintf(ub->release, "%u.%u", (DWORD)(LOBYTE(LOWORD(version))), (DWORD)(HIBYTE(LOWORD(version)))); (void)strcpy(ub->sysname, "Windows"); if (gethostname(hostname, sizeof(hostname)) == 0) { if (ptr = strchr(hostname, '.')) *ptr = '\0'; } else { perror("uname: gethostname failed"); strcpy(hostname, "FAILURE"); } strncpy(ub->nodename, hostname, sizeof(ub->nodename)); ub->nodename[_SYS_NMLN - 1] = '\0'; return 0; } int strcasecmp(const char *s1, const char *s2) { return stricmp(s1, s2); } uid_t getuid(void) { return 1; } gid_t getgid(void) { return 0; } int gethostid(void) { /*XXX*/ return 0; } __inline int nice(int pri) { return 0; } extern void TkWinXInit(HINSTANCE hInstance); extern int main(int argc, const char *argv[]); extern int __argc; extern char **__argv; static char argv0[255]; /* Buffer used to hold argv0. */ char *__progname = "mash"; void ShowMessage(int level, char *msg) { MessageBeep(level); MessageBox(NULL, msg, __progname, level | MB_OK | MB_TASKMODAL | MB_SETFOREGROUND); } int SetupConsole() { /* * stuff from knowledge base Q105305 (see that for details) * open a console and do the work around to get the console to work in all * cases */ int hCrt; FILE *hf=0; const COORD screenSz = {80, 5000}; /* size of console buffer */ AllocConsole(); hf=0; hCrt = _open_osfhandle( (long)GetStdHandle(STD_OUTPUT_HANDLE), _O_TEXT); if (hCrt!=-1) hf = _fdopen(hCrt, "w"); if (hf!=0) *stdout = *hf; if (hCrt==-1 || hf==0 || 0!=setvbuf(stdout, NULL, _IONBF, 0)) { ShowMessage(MB_ICONINFORMATION, "unable to mount reroute stdout"); return FALSE; } SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), screenSz); hf=0; hCrt = _open_osfhandle( (long)GetStdHandle(STD_ERROR_HANDLE), _O_TEXT); if (hCrt!=-1) hf = _fdopen(hCrt, "w"); if (hf!=0) *stderr = *hf; if (hCrt==-1 || hf==0 || 0!=setvbuf(stderr, NULL, _IONBF, 0)) { ShowMessage(MB_ICONINFORMATION, "reroute stderr failed in SetupConsole"); return FALSE; } hf=0; hCrt = _open_osfhandle((long)GetStdHandle(STD_INPUT_HANDLE), _O_TEXT); if (hCrt!=-1) hf = _fdopen(hCrt, "r"); if (hf!=0) *stdin = *hf; if (hCrt==-1 || hf==0 || 0!=setvbuf(stdin, NULL, _IONBF, 0)) { ShowMessage(MB_ICONINFORMATION, "reroute stdin failed in SetupConsole"); return FALSE; } return TRUE; } int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { char *p; WSADATA WSAdata; int retcode; setlocale(LC_ALL, "C"); /* XXX * initialize our socket interface plus the tcl 7.5 socket * interface (since they redefine some routines we call). * eventually we should just call the tcl sockets but at * the moment that's hard to set up since they only support * tcp in the notifier. */ if (WSAStartup(MAKEWORD (1, 1), &WSAdata)) { perror("Windows Sockets init failed"); abort(); } /* TclHasSockets(NULL); TkWinXInit(hInstance); */ /* * Increase the application queue size from default value of 8. * At the default value, cross application SendMessage of WM_KILLFOCUS * will fail because the handler will not be able to do a PostMessage! * This is only needed for Windows 3.x, since NT dynamically expands * the queue. */ SetMessageQueue(64); GetModuleFileName(NULL, argv0, 255); p = argv0; __progname = strrchr(p, '/'); if (__progname != NULL) { __progname++; } else { __progname = strrchr(p, '\\'); if (__progname != NULL) { __progname++; } else { __progname = p; } } if (__argc>1) { SetupConsole(); } retcode=main(__argc, (const char**)__argv); if (retcode!=0) { assert(FALSE); /* don't die without letting user know why */ } return retcode; } #if 0 static char szTemp[4096]; int printf(const char *fmt, ...) { int retval; va_list ap; va_start (ap, fmt); retval = vsprintf(szTemp, fmt, ap); OutputDebugString(szTemp); ShowMessage(MB_ICONINFORMATION, szTemp); va_end (ap); return(retval); } int fprintf(FILE *f, const char *fmt, ...) { int retval; va_list ap; va_start (ap, fmt); if (f == stderr) { retval = vsprintf(szTemp, fmt, ap); OutputDebugString(szTemp); ShowMessage(MB_ICONERROR, szTemp); va_end (ap); } else retval = vfprintf(f, fmt, ap); return(retval); } void perror(const char *msg) { DWORD cMsgLen; CHAR *msgBuf; DWORD dwError = GetLastError(); cMsgLen = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | 40, NULL, dwError, MAKELANGID(0, SUBLANG_ENGLISH_US), (LPTSTR) &msgBuf, 512, NULL); if (!cMsgLen) fprintf(stderr, "%s%sError code %lu\n", msg?msg:"", msg?": ":"", dwError); else { fprintf(stderr, "%s%s%s\n", msg?msg:"", msg?": ":"", msgBuf); LocalFree((HLOCAL)msgBuf); } } int WinPutsCmd(clientData, interp, argc, argv) ClientData clientData; /* ConsoleInfo pointer. */ Tcl_Interp *interp; /* Current interpreter. */ int argc; /* Number of arguments. */ char **argv; /* Argument strings. */ { int i, newline; char *fileId; i = 1; newline = 1; if ((argc >= 2) && (strcmp(argv[1], "-nonewline") == 0)) { newline = 0; i++; } if ((i < (argc-3)) || (i >= argc)) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " ?-nonewline? ?fileId? string\"", (char *) NULL); return TCL_ERROR; } /* * The code below provides backwards compatibility with an old * form of the command that is no longer recommended or documented. */ if (i == (argc-3)) { if (strncmp(argv[i+2], "nonewline", strlen(argv[i+2])) != 0) { Tcl_AppendResult(interp, "bad argument \"", argv[i+2], "\": should be \"nonewline\"", (char *) NULL); return TCL_ERROR; } newline = 0; } if (i == (argc-1)) { fileId = "stdout"; } else { fileId = argv[i]; i++; } if (strcmp(fileId, "stdout") == 0 || strcmp(fileId, "stderr") == 0) { char *result; int level; if (newline) { int len = strlen(argv[i]); result = ckalloc(len+2); memcpy(result, argv[i], len); result[len] = '\n'; result[len+1] = 0; } else { result = argv[i]; } if (strcmp(fileId, "stdout") == 0) { level = MB_ICONINFORMATION; } else { level = MB_ICONERROR; } OutputDebugString(result); ShowMessage(level, result); if (newline) ckfree(result); return TCL_OK; } else { extern int Tcl_PutsCmd(ClientData clientData, Tcl_Interp *interp, int argc, char **argv); return (Tcl_PutsCmd(clientData, interp, argc, argv)); } } #endif int WinGetUserName(clientData, interp, argc, argv) ClientData clientData; Tcl_Interp *interp; /* Current interpreter. */ int argc; /* Number of arguments. */ char *argv[]; /* Argument strings. */ { char user[256]; int size = sizeof(user); if (!GetUserName(user, &size)) { Tcl_AppendResult(interp, "GetUserName failed", NULL); return TCL_ERROR; } Tcl_AppendResult(interp, user, NULL); return TCL_OK; } int WinGetHostName(clientData, interp, argc, argv) ClientData clientData; Tcl_Interp *interp; /* Current interpreter. */ int argc; /* Number of arguments. */ char *argv[]; /* Argument strings. */ { char hostname[MAXGETHOSTSTRUCT]; if (SOCKET_ERROR == gethostname(hostname, MAXGETHOSTSTRUCT)) { Tcl_AddErrorInfo(interp, "gethostname failed!"); } Tcl_AppendResult(interp, hostname, NULL); return TCL_OK; } static HKEY regroot(root) char *root; { if (strcasecmp(root, "HKEY_LOCAL_MACHINE") == 0) return HKEY_LOCAL_MACHINE; else if (strcasecmp(root, "HKEY_CURRENT_USER") == 0) return HKEY_CURRENT_USER; else if (strcasecmp(root, "HKEY_USERS") == 0) return HKEY_USERS; else if (strcasecmp(root, "HKEY_CLASSES_ROOT") == 0) return HKEY_CLASSES_ROOT; else return NULL; } int WinGetRegistry(clientData, interp, argc, argv) ClientData clientData; Tcl_Interp *interp; /* Current interpreter. */ int argc; /* Number of arguments. */ char **argv; /* Argument strings. */ { HKEY hKey, hRootKey; DWORD dwType; DWORD len, retCode; CHAR *regRoot, *regPath, *keyValue, *keyData; int retval = TCL_ERROR; if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], "key value\"", (char *) NULL); return TCL_ERROR; } regRoot = argv[1]; keyValue = argv[2]; regPath = strchr(regRoot, '\\'); *regPath++ = '\0'; if ((hRootKey = regroot(regRoot)) == NULL) { Tcl_AppendResult(interp, "Unknown registry root \"", regRoot, "\"", NULL); return (TCL_ERROR); } retCode = RegOpenKeyEx(hRootKey, regPath, 0, KEY_READ, &hKey); if (retCode == ERROR_SUCCESS) { retCode = RegQueryValueEx(hKey, keyValue, NULL, &dwType, NULL, &len); if (retCode == ERROR_SUCCESS && dwType == REG_SZ && len) { keyData = (CHAR *) ckalloc(len); retCode = RegQueryValueEx(hKey, keyValue, NULL, NULL, keyData, &len); if (retCode == ERROR_SUCCESS) { Tcl_AppendResult(interp, keyData, NULL); free(keyData); retval = TCL_OK; } } RegCloseKey(hKey); } if (retval == TCL_ERROR) { Tcl_AppendResult(interp, "Cannot find registry entry \"", regRoot, "\\", regPath, "\\", keyValue, "\"", NULL); } return (retval); } int WinPutRegistry(clientData, interp, argc, argv) ClientData clientData; Tcl_Interp *interp; /* Current interpreter. */ int argc; /* Number of arguments. */ char **argv; /* Argument strings. */ { HKEY hKey, hRootKey; DWORD retCode; CHAR *regRoot, *regPath, *keyValue, *keyData; DWORD new; int result = TCL_OK; if (argc != 4) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], "key value data\"", (char *) NULL); return TCL_ERROR; } regRoot = argv[1]; keyValue = argv[2]; keyData = argv[3]; regPath = strchr(regRoot, '\\'); *regPath++ = '\0'; if ((hRootKey = regroot(regRoot)) == NULL) { Tcl_AppendResult(interp, "Unknown registry root \"", regRoot, "\"", NULL); return (TCL_ERROR); } retCode = RegCreateKeyEx(hRootKey, regPath, 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &new); if (retCode == ERROR_SUCCESS) { retCode = RegSetValueEx(hKey, keyValue, 0, REG_SZ, keyData, strlen(keyData)); if (retCode != ERROR_SUCCESS) { Tcl_AppendResult(interp, "unable to set key \"", regRoot, "\\", regPath, "\" with value \"", keyValue, "\"", (char *) NULL); result = TCL_ERROR; } RegCloseKey(hKey); } else { Tcl_AppendResult(interp, "unable to create key \"", regRoot, "\\", regPath, "\"", (char *) NULL); result = TCL_ERROR; } return (result); } int platformInit(Tcl_Interp* interp) { /* tcl.CreateCommand("puts", WinPutsCmd, (ClientData)0); */ Tcl_CreateCommand(interp, "getusername", WinGetUserName, (ClientData)0, (Tcl_CmdDeleteProc*)0); Tcl_CreateCommand(interp, "gethostname", WinGetHostName, (ClientData)0, (Tcl_CmdDeleteProc*)0); Tcl_CreateCommand(interp, "putregistry", WinPutRegistry, (ClientData)0, (Tcl_CmdDeleteProc*)0); Tcl_CreateCommand(interp, "getregistry", WinGetRegistry, (ClientData)0, (Tcl_CmdDeleteProc*)0); #ifndef NO_TK /* * Initialize the console only if we are running as an interactive * application. */ if (0==strcmp(Tcl_GetVar(interp, "tcl_interactive", TCL_GLOBAL_ONLY), "1")) { /* * Create the console channels and install them as the standard * channels. All I/O will be discarded until TkConsoleInit is * called to attach the console to a text widget. */ TkConsoleCreate(); if (TkConsoleInit(interp) == TCL_ERROR) { fprintf(stderr, "error calling TkConsoleInit\n"); } } #endif return TCL_OK; } #endif