/**************************************************************************** This offer void where prohibited, batteries not included, this product is sold as is without warranty either express or implied, no claims of merchantabilty have been made with regard to this product, end user assumes all liability with regard to the use of this product and no claims of injury, either fiduciary or personal, may be issued against the manufacturer. Use at your own risk, caveat emptor. The programmer has been certified virus free. This software is hereby released to the public domain; you break it, you fix it. Bug fixes, patches and feature recommendations gladly accepted (responses tempered to the attitude of the corespondent). Send intelligent discourse to grumble@compuserve.com, drivel to /dev/null. PROGRAM: script.c PURPOSE: Windows program control FUNCTIONS: WinMain() - calls initialization function, processes message loop InitApplication() - initializes window data and registers window InitInstance() - saves instance handle and creates main window MainWndProc() - processes messages HISTORY: 1.0 Initial release 12/17/97 1.1 Added command struct 01/08/98 1.2 Fixed small memory leak when 01/15/98 last line doesn't end with CR Changed onexist to use FindFirstFile 1.3 Added wildcard matches to the 01/19/98 while, send, and wait functions Fixed control character translation Added .script file extension Added additional error checking Fixed wait bug related to uninitialize waitcount Fixed string compare bug Fixed file size > 1024 bug 2.0 Structural rewrite 01/29/98 Create malloc'd structures containing functions and command strings. Create malloc'd structure containing labels and pointers. Use SW_SHOWMINNOACTIVE to start minimized windows so they don't interfere with open windows Save and restore top window Save and restore caps lock mode 2.1 Added shift function to special chars 04/15/98 Added return code to msgbox Added start directory to start command Fixed kbd arrow direction screwup Added escaped space (for leading blanks) ****************************************************************************/ #include #include #include #include #include #include #include #include #include #include "script.h" HANDLE hInst; MSG msg; HWND hWnd; UCHAR szAppName[20], szClassName[20]; UCHAR cmdbuf[_MAX_PATH + _MAX_FNAME + _MAX_EXT]; UCHAR errbuf[160]; struct cl { char command[10]; int nargs; int function; int attr; } cl[] = { { "send", NARG2, IDM_SEND, TRUE }, { "goto", NARG1, IDM_GOTO, FALSE }, { "wait", NARG1 | NARG2, IDM_WAIT, FALSE }, { "while", NARG1, IDM_WHILE, FALSE }, { "start", NARG1 | NARG2, IDM_START, FALSE }, { "msgbox", NARG1 | NARG2, IDM_MSGBOX, FALSE }, { "delay", NARG1, IDM_DELAY, FALSE }, { "onerror", NARG1, IDM_ONERR, FALSE }, { "onexist", NARG2, IDM_EXIST, FALSE }, { "onmsgrtn", NARG2, IDM_ONMSG, FALSE }, { "", 0, 0 } }; CMD *cmdstart; LABEL *labelstart; #define BLOCKSIZE 1024 /* * This routine does a string compare of s1 to s * it differs from the standard library lookup * in that it supports wildcard characters (?, *) * and it returns a boolean result, not a magnitude. * ? is a single character wildcard and will match * any character in the same position. * * is a 0-n character wildcard */ BOOL gstrscn(unsigned char *s, unsigned char *s1, WORD *s2, int first) { while (*s && (*s1 != 0xff || *s1)) { if (*s1 == MUWC && *s2 == KSPECIAL) { s1++; s2++; if (*s1) return gstrscn(s, s1, s2, TRUE); else return TRUE; } else if (first) { if (*s == *s1 || (*s1 == SIWC && *s2 == KSPECIAL)) { first = FALSE; s1++; s2++; } } else if (*s != *s1 && (*s1 != SIWC && *s2 != KSPECIAL)) return FALSE; else { s1++; s2++; } s++; } if (*s || (*s1 != 0xff && *s1)) return FALSE; return TRUE; } /* * Routine to convert hex character to int */ int HexToInt(char i) { i -= '0'; if (i > 0x30) i -= 0x27; else if (i > 0x10) i -= 0x7; return (int)(i); } /**************************************************************************** FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int) PURPOSE: calls initialization function, processes message loop ****************************************************************************/ int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR cmdline, int nCmdShow) { WIN32_FIND_DATA wf; HANDLE fh; lstrcpy(szAppName, "Script"); lstrcpy(szClassName, "ScriptClass"); strcpy(cmdbuf, cmdline); if (strstr(cmdbuf, ".") == NULL) // no extension supplied, try it as .scr first strcat(cmdbuf, ".scr"); if ((fh = FindFirstFile(cmdbuf, &wf)) == INVALID_HANDLE_VALUE) { strcat(cmdbuf, "ipt"); // not found, try it as .script if ((fh = FindFirstFile(cmdbuf, &wf)) == INVALID_HANDLE_VALUE) strcpy(cmdbuf, cmdline); // not found, no extension } if (fh != INVALID_HANDLE_VALUE) FindClose(fh); if (!InitApplication(hInstance)) return (FALSE); if ((fh = OpenScriptFile(cmdbuf)) == NULL) return (FALSE); if (!FileProc(fh)) { FreeCMD(cmdstart); FreeLabel(labelstart); CloseHandle(fh); return (FALSE); } CloseHandle(fh); if (!InitInstance(hInstance, nCmdShow)) return (FALSE); SetTimer(hWnd, 1, 1, NULL); while (GetMessage(&msg, 0, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (msg.wParam); } /**************************************************************************** FUNCTION: InitApplication(HANDLE) PURPOSE: Initializes window data and registers window class ****************************************************************************/ BOOL InitApplication(hInstance) HANDLE hInstance; { WNDCLASS wc; HBRUSH hbr; hbr = CreateSolidBrush(RGB(192, 192, 192)); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = MainWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = NULL; wc.hCursor = LoadCursor(hInstance, IDC_ARROW); wc.hbrBackground = hbr; wc.lpszMenuName = NULL; wc.lpszClassName = szClassName; return (RegisterClass(&wc)); } /**************************************************************************** FUNCTION: InitInstance(HANDLE, int) PURPOSE: Saves instance handle and creates main window ****************************************************************************/ BOOL InitInstance(HANDLE hInstance, int nCmdShow) { HDC hDC; hInst = hInstance; hWnd = CreateWindow( szClassName, szAppName, WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZE, 0, 0, 0, 0, HWND_DESKTOP, 0, hInstance, NULL ); if (!hWnd) return (FALSE); hDC = GetDC(hWnd); if (!hDC) return (FALSE); ReleaseDC(hWnd,hDC); return (TRUE); } /**************************************************************************** FUNCTION: OpenScriptFile(char *filename) PURPOSE: Reads file into buffer ****************************************************************************/ HANDLE OpenScriptFile(char *filename) { OPENFILENAME ofn; HANDLE fh; if (!strlen(cmdbuf)) { ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hWnd; ofn.hInstance = NULL; ofn.lpstrCustomFilter = NULL; ofn.nMaxCustFilter = 0; ofn.lpstrFilter = "Script files\0*.scr\0*.script\0"; ofn.nFilterIndex = 1; ofn.lpstrFile = (LPSTR)filename; ofn.nMaxFile = _MAX_PATH + _MAX_FNAME + _MAX_EXT; ofn.lpstrFileTitle = NULL; ofn.nMaxFileTitle = 0; ofn.lpstrTitle = NULL; ofn.lpstrInitialDir = NULL; ofn.Flags = OFN_SHOWHELP | OFN_OVERWRITEPROMPT; ofn.nFileOffset = 0; ofn.nFileExtension = 0; ofn.lCustData = 0L; ofn.lpfnHook = NULL; ofn.lpTemplateName = NULL; ofn.lpstrDefExt = "scr"; if (!GetOpenFileName((OPENFILENAME FAR *)&ofn)) return NULL; } if ((fh = CreateFile(cmdbuf, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) { sprintf(errbuf, "Unable to open %s for input", cmdbuf); MessageBox(hWnd, errbuf, "File error", MB_ICONSTOP | MB_SYSTEMMODAL); return NULL; } return fh; } /**************************************************************************** FUNCTION: ReadBlock(HANDLE FileHandle, unsigned char *buf) PURPOSE: Reads file into buffer ****************************************************************************/ int ReadBlock(HANDLE fh, unsigned char *buf, DWORD *rc) { if (!ReadFile(fh, buf, BLOCKSIZE, rc, NULL)) { FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language errbuf, sizeof(errbuf), NULL); MessageBox(hWnd, errbuf, "Read Error", MB_OK | MB_SYSTEMMODAL); return (FALSE); } if (!*rc) CloseHandle(fh); return TRUE; } /**************************************************************************** FUNCTION: FileProc(HANDLE fh) PURPOSE: Reads file into buffer and processes contents ****************************************************************************/ BOOL FileProc(HANDLE fh) { UCHAR seqchar; int comma = 0; int brseq; DWORD rc; unsigned char *p; int badesc; int badfunc; UCHAR buf[BLOCKSIZE]; UCHAR cbuf[256]; UCHAR *cmd; WORD attrbuf[256]; UCHAR *cmdptr; WORD *atrptr; int atrflag; int func; int i; UCHAR *s; LABEL *curlabel, *tmplabel; CMD *curcmd, *tmpcmd; int firstlabel = TRUE; int firstcmd = TRUE; int newlabel = FALSE; int curmessage; cmdptr = cbuf; atrflag = FALSE; atrptr = attrbuf; *atrptr = 0; brseq = 0; badesc = FALSE; badfunc = FALSE; curcmd = cmdstart; curlabel = labelstart; if (!ReadBlock(fh, buf, &rc)) return (FALSE); p = buf; for (;;) { if ((p - buf) == sizeof(buf)) { if (!ReadBlock(fh, buf, &rc)) return (FALSE); p = buf; atrflag = FALSE; } if ((DWORD)(p - buf) >= rc) // end of file (I think) return (TRUE); while (*p != 0xd && *p != 0xa && ((DWORD)(p - buf) < rc)) { if (!brseq && (*p == '\\' || *p == '$' || *p == '#')) // handle multiple sequences { seqchar = *p; p++; if (seqchar == '$' || seqchar == '#') brseq = 2; else brseq = 1; } else { if (brseq) { brseq--; switch (seqchar) { case '\\': switch (*p) { case 'n': *(cmdptr++) = 0x0d; atrptr++; *atrptr = 0; atrflag = TRUE; break; case ',': *(cmdptr++) = ','; atrptr++; *atrptr = 0; break; case 't': *(cmdptr++) = (UCHAR)KTAB; // escaped tabs are special *(atrptr++) |= KSPECIAL; *atrptr = 0; break; case '>': *(cmdptr++) = (UCHAR)RTAR; // escaped arrows are special *(atrptr++) |= KSPECIAL; *atrptr = 0; atrflag = TRUE; break; case '<': *(cmdptr++) = (UCHAR)LFAR; // escaped arrows are special *(atrptr++) |= KSPECIAL; *atrptr = 0; atrflag = TRUE; break; case '^': *(cmdptr++) = (UCHAR)UPAR; // escaped arrows are special *(atrptr++) |= KSPECIAL; *atrptr = 0; atrflag = TRUE; break; case 'v': *(cmdptr++) = (UCHAR)DNAR; // escaped arrows are special *(atrptr++) |= KSPECIAL; *atrptr = 0; atrflag = TRUE; break; case '\\': *(cmdptr++) = '\\'; // escaped \ are special atrptr++; *atrptr = 0; break; case '?': *(cmdptr++) = '?'; // escaped ? are special atrptr++; *atrptr = 0; break; case '*': *(cmdptr++) = '*'; // escaped * are special atrptr++; *atrptr = 0; break; case '$': *(cmdptr++) = '$'; // escaped $ are special atrptr++; *atrptr = 0; break; case '#': *(cmdptr++) = '#'; // escaped # are special atrptr++; *atrptr = 0; break; case '!': *(cmdptr++) = '!'; // escaped ! are special atrptr++; *atrptr = 0; break; case ' ': *(cmdptr++) = ' '; // escaped spaces are special atrptr++; *atrptr = 0; break; default: *(cmdptr++) = '\\'; // bad sequence *(cmdptr++) = *p; atrptr++; *atrptr = 0; badesc = TRUE; } break; case '$': // function keys if (*p >= '0' && *p <= '9') { if (brseq) func = (*p - '0') * 10; else { func += (*p - '0'); *(cmdptr++) = F0 - func; *(atrptr++) |= KSPECIAL; *atrptr = 0; atrflag = TRUE; } } else badfunc = TRUE; break; case '#': // hex character sequences if ((*p >= '0' && *p <= '9') || (*p >= 'A' && *p <= 'F') || (*p >= 'a' && *p <= 'f')) { if (brseq) func = HexToInt(*p) << 4; else { func += HexToInt(*p); *(cmdptr++) = func; atrptr++; *atrptr = 0; atrflag = TRUE; } } else badfunc = TRUE; break; } } else switch (*p) { case ',': // convert nonescaped commas to separator characters *(cmdptr++) = (UCHAR)SEP; comma++; // inc comma count atrptr++; *atrptr = 0; break; case '?': *(cmdptr++) = (UCHAR)SIWC; *atrptr |= KSPECIAL; atrptr++; *atrptr = 0; break; case '*': *(cmdptr++) = (UCHAR)MUWC; *atrptr |= KSPECIAL; atrptr++; *atrptr = 0; break; case '%': *atrptr |= KALT; atrflag = TRUE; break; case '^': *atrptr |= KCONTROL; atrflag = TRUE; break; case '!': *atrptr |= KSHIFT; atrflag = TRUE; break; default: *(cmdptr++) = *p; atrptr++; *atrptr = 0; } p++; } if ((p - buf) == sizeof(buf)) { if (!ReadBlock(fh, buf, &rc)) return (FALSE); p = buf; } } *cmdptr = 0; p++; if (badfunc) { for (i = 0; cbuf[i]; i++) if (cbuf[i] == SEP) cbuf[i] = ','; sprintf(errbuf, "Invalid function key\n%s", cbuf); MessageBox(hWnd, errbuf, "Command Error", MB_ICONSTOP | MB_SYSTEMMODAL); return (FALSE); } if (badesc) // exit expand case { for (i = 0; cbuf[i]; i++) if (cbuf[i] == SEP) cbuf[i] = ','; sprintf(errbuf, "Invalid escape sequence\n%s", cbuf); MessageBox(hWnd, errbuf, "Command Error", MB_ICONSTOP | MB_SYSTEMMODAL); return (FALSE); } // expand the string, figure out if a token or comment or blank // save the string and start processing (curmessage) // anything not recognized is assumed to be a syntax error if (strlen(cbuf)) { s = cbuf; while (*s == 0x20 || *s == 0x9) s++; // skip whitespace if (*s != ';') // line is a comment { if (*s == ':') // handle label { s++; tmplabel = (LABEL *)malloc(sizeof(struct label) + 1); if (firstlabel) { firstlabel = FALSE; labelstart = tmplabel; } else curlabel->next = tmplabel; curlabel = tmplabel; curlabel->labeltext = (char *)malloc(strlen(s) + 1); strcpy(curlabel->labeltext, s); curlabel->next = NULL; curlabel->line = NULL; newlabel = TRUE; } else if ((cmd = strstr(cbuf, "\377")) != NULL) { *(cmd++) = 0; while (*cmd == 0x20 || *cmd == 0x9) cmd++; i = 0; curmessage = 0; while (strlen(cl[i].command)) { if (!stricmp(s, cl[i].command)) { if (atrflag && !cl[i].attr) curmessage = BADSPEC; else if ((1 << comma) & cl[i].nargs) { tmpcmd = (CMD *)malloc(sizeof(struct cmd) + 1); if (firstcmd) { firstcmd = FALSE; cmdstart = tmpcmd; } else curcmd->next = tmpcmd; curcmd = tmpcmd; curcmd->function = cl[i].function; curcmd->cmdstring = (char *)malloc(strlen(cmd) + 1); strcpy(curcmd->cmdstring, cmd); curcmd->attrbuf = (WORD *)malloc(strlen(cmd) * sizeof(WORD)); memcpy(curcmd->attrbuf, &attrbuf[cmd - cbuf], strlen(cmd) * sizeof(WORD)); curcmd->next = NULL; if (newlabel) { curlabel->line = curcmd; newlabel = FALSE; } curmessage = GOODCMD; } else curmessage = PARMS; break; } i++; } if (!curmessage) curmessage = SYNTAX; } else { curmessage = SYNTAX; cmd = ""; } if (curmessage < 0) { if (curmessage == BADSPEC) sprintf(errbuf, "Control or Alt sequence not allowed with this command\n%s,%s", s, cmd); if (curmessage == PARMS) { for (i = 0; cmd[i]; i++) if (cmd[i] == SEP) cmd[i] = ','; sprintf(errbuf, "Invalid number of command parameters\n%s,%s", s, cmd); } if (curmessage == SYNTAX) sprintf(errbuf, "Syntax error\n%s,%s", s, cmd); MessageBox(hWnd, errbuf, "Command Error", MB_ICONSTOP | MB_SYSTEMMODAL); return (FALSE); } } } cmdptr = cbuf; atrflag = FALSE; atrptr = attrbuf; *atrptr = 0; comma = 0; } } /**************************************************************************** FUNCTION: FindLabel(char *) PURPOSE: Reads file into buffer and processes contents ****************************************************************************/ CMD *FindLabel(char *label) { LABEL *curlabel; curlabel = labelstart; while (curlabel != NULL) if (!strcmp(label, curlabel->labeltext)) return (curlabel->line); else curlabel = curlabel->next; return ((CMD *)-1); } /**************************************************************************** FUNCTION: FreeLabel(label *) PURPOSE: Free up memory used by label structures ****************************************************************************/ void FreeLabel(LABEL *label) { if (label == NULL) return; FreeLabel(label->next); free(label->labeltext); free(label); } /**************************************************************************** FUNCTION: FreeCMD(CMD *) PURPOSE: Free up memory used by command structures ****************************************************************************/ void FreeCMD(CMD *command) { if (command == NULL) return; FreeCMD(command->next); free(command->cmdstring); free(command->attrbuf); free(command); } /**************************************************************************** FUNCTION: MainWndProc(HWND, UINT, WPARAM, LPARAM) PURPOSE: Processes messages MESSAGES: WM_COMMAND - application menu (About dialog box) WM_CREATE - create window and objects WM_PAINT - update window, draw objects WM_DESTROY - destroy window COMMENTS: Handles to the objects you will use are obtained when the WM_CREATE message is received, and deleted when the WM_DESTROY message is received. The actual drawing is done whenever a WM_PAINT message is received. ****************************************************************************/ long FAR PASCAL MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; UCHAR module[128]; STARTUPINFO si; PROCESS_INFORMATION pi; int j, flags, ks; UCHAR *s, *p; WORD *s1; HWND GlobalhWnd, tmphWnd; HANDLE ftmp; WIN32_FIND_DATA fdata; UCHAR cmd[256]; static delay = 0; static int errlevel = 0; static int mboxrtn = 0; static int waitcount = 0; static UCHAR labelqry[80]; static CMD *curcmd; static CMD *nextcmd; static int stop = FALSE; switch (message) { case WM_COMMAND: switch (wParam) { /* wait for a program to exit */ case IDM_WHILE: errlevel = 0; if ((s = strstr(curcmd->cmdstring, "\377")) != NULL) // find separator character { if (!waitcount) { s++; while (*s == 0x20 || *s == 0x9) s++; sscanf(s, "%d", &waitcount); } } else waitcount = -1; if ((GlobalhWnd = GetTopWindow(NULL)) != NULL) do { if (GetWindowText(GlobalhWnd, module, sizeof(module))) if (gstrscn(module, curcmd->cmdstring, curcmd->attrbuf, FALSE)) { if (waitcount) { waitcount--; if (!waitcount) { errlevel = TRUE; break; } nextcmd = curcmd; // branch back here } break; } } while ((GlobalhWnd = GetNextWindow(GlobalhWnd, GW_HWNDNEXT)) != NULL); break; /* wait for specified delay (in 1/1000's of a second ) */ case IDM_DELAY: if (delay == 0) { sscanf(curcmd->cmdstring, "%d", &delay); nextcmd = curcmd; } else { delay--; if (delay != 0) nextcmd = curcmd; } break; /* send keys to window */ case IDM_SEND: stop = TRUE; if ((s = strstr(curcmd->cmdstring, "\377")) != NULL) // find separator character { s++; s1 = &curcmd->attrbuf[s - curcmd->cmdstring]; while ((*s == 0x20 || *s == 0x9) && !*s1) { s++; s1++; } if ((GlobalhWnd = GetTopWindow(NULL)) != NULL) do { if (GetWindowText(GlobalhWnd, module, sizeof(module))) if (gstrscn(module, curcmd->cmdstring, curcmd->attrbuf, FALSE)) { tmphWnd = GetForegroundWindow(); if ((ks = GetKeyState(VK_CAPITAL))) // toggle caps lock if on { keybd_event(VK_CAPITAL, 0, 0L, 0x10001L); keybd_event(VK_CAPITAL, 0, KEYEVENTF_KEYUP, 0xc0000001L); } while (*s) // send keystrokes { SetForegroundWindow(GlobalhWnd); if (!(*s1 & KSPECIAL)) j = VkKeyScan(*s) | *s1; else { switch (*s) { case RTAR: // right arrow j = VK_RIGHT; break; case LFAR: // left arrow j = VK_LEFT; break; case UPAR: // up arrow j = VK_UP; break; case DNAR: // down arrow j = VK_DOWN; break; case KTAB: j = VkKeyScan(0x9); break; case F1: j = VK_F1; break; case F2: j = VK_F2; break; case F3: j = VK_F3; break; case F4: j = VK_F4; break; case F5: j = VK_F5; break; case F6: j = VK_F6; break; case F7: j = VK_F7; break; case F8: j = VK_F8; break; case F9: j = VK_F9; break; case F10: j = VK_F10; break; case F11: j = VK_F11; break; case F12: j = VK_F12; break; } j |= *s1; } if (j & KALT) keybd_event(VK_MENU, 0, 0L, 0x10001L); if (j & KCONTROL) keybd_event(VK_CONTROL, 0, 0L, 1L); if (j & KSHIFT) keybd_event(VK_SHIFT, 0, 0L, 1L); keybd_event((char)(j & 0xff), 0, 0L, 1L); keybd_event((char)(j & 0xff), 0, KEYEVENTF_KEYUP, 0xc0000001L); if (j & KSHIFT) keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0xc0000001L); if (j & KCONTROL) keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0xc0000001L); if (j & KALT) keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0xc0000001L); s++; s1++; } SetForegroundWindow(tmphWnd); if (ks) // toggle caps lock if on { keybd_event(VK_CAPITAL, 0, 0L, 0x10001L); keybd_event(VK_CAPITAL, 0, KEYEVENTF_KEYUP, 0xc0000001L); } break; } } while ((GlobalhWnd = GetNextWindow(GlobalhWnd, GW_HWNDNEXT)) != NULL); } else { stop = TRUE; sprintf(errbuf, "Send error: Missing text in line"); MessageBox(hWnd, errbuf, "Command Error", MB_ICONSTOP | MB_SYSTEMMODAL); PostMessage(hWnd, WM_COMMAND, (WPARAM)IDM_QUIT, 0L); } stop = FALSE; break; /* start program in file after start token */ case IDM_START: strcpy(cmd, curcmd->cmdstring); si.wShowWindow = SW_SHOW; p = NULL; if ((s = strstr(cmd, "\377")) != NULL) { *(s++) = 0; if ((p = strstr(s, "\377")) != NULL) // check for startup directory *(p++) = 0; if (!stricmp(s, "min")) // si.wShowWindow = SW_SHOWMINIMIZED; si.wShowWindow = SW_SHOWMINNOACTIVE; else if (stricmp(s, "max")) { stop = TRUE; sprintf(errbuf, "Syntax error\nstart,%s,%s", cmd, s); MessageBox(hWnd, errbuf, "Command Error", MB_ICONSTOP | MB_SYSTEMMODAL); PostMessage(hWnd, WM_COMMAND, (WPARAM)IDM_QUIT, 0L); break; } } si.cb = sizeof(STARTUPINFO); si.lpReserved = NULL; si.lpDesktop = NULL; si.lpTitle = NULL; si.dwFlags = STARTF_USESHOWWINDOW; si.cbReserved2 = 0; si.lpReserved2 = NULL; errlevel = 0; if (!CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, p, &si, &pi)) errlevel = GetLastError(); break; /* wait for a window with the appropriate text to appear */ case IDM_WAIT: errlevel = 0; if ((s = strstr(curcmd->cmdstring, "\377")) != NULL) // find separator character { if (!waitcount) { s++; while (*s == 0x20 || *s == 0x9) s++; sscanf(s, "%d", &waitcount); } } else waitcount = -1; if ((GlobalhWnd = GetTopWindow(NULL)) != NULL) do { if (GetWindowText(GlobalhWnd, module, sizeof(module))) if (gstrscn(module, curcmd->cmdstring, curcmd->attrbuf, FALSE)) { waitcount = 0; break; } } while ((GlobalhWnd = GetNextWindow(GlobalhWnd, GW_HWNDNEXT)) != NULL); if (waitcount) { waitcount--; if (!waitcount) { errlevel = TRUE; break; } nextcmd = curcmd; // branch back here } break; /* check for file existence, branch if true */ case IDM_EXIST: strcpy(cmd, curcmd->cmdstring); s = strstr(cmd, "\377"); *(s++) = 0; if ((ftmp = FindFirstFile(cmd, &fdata)) == INVALID_HANDLE_VALUE) break; FindClose(ftmp); if ((nextcmd = FindLabel(s)) == (CMD *)-1) { stop = TRUE; sprintf(errbuf, "Label \"%s\" not found", s); MessageBox(hWnd, errbuf, "Command Error", MB_OK | MB_SYSTEMMODAL); PostMessage(hWnd, WM_COMMAND, (WPARAM)IDM_QUIT, 0L); } break; /* branch on the msgbox return value */ case IDM_ONMSG: strcpy(cmd, curcmd->cmdstring); s = strstr(cmd, "\377"); *(s++) = 0; if (!stricmp(cmd, "ABORT")) { if (mboxrtn != IDABORT) break; } else if (!stricmp(cmd, "CANCEL")) { if (mboxrtn != IDCANCEL) break; } else if (!stricmp(cmd, "IGNORE")) { if (mboxrtn != IDIGNORE) break; } else if (!stricmp(cmd, "NO")) { if (mboxrtn != IDNO) break; } else if (!stricmp(cmd, "OK")) { if (mboxrtn != IDOK) break; } else if (!stricmp(cmd, "RETRY")) { if (mboxrtn != IDRETRY) break; } else if (!stricmp(cmd, "YES")) { if (mboxrtn != IDYES) break; } else { stop = TRUE; sprintf(errbuf, "Syntax error\nonmsgrtn,%s,%s", cmd, s); MessageBox(hWnd, errbuf, "Command Error", MB_ICONSTOP | MB_SYSTEMMODAL); PostMessage(hWnd, WM_COMMAND, (WPARAM)IDM_QUIT, 0L); break; } if ((nextcmd = FindLabel(s)) == (CMD *)-1) { stop = TRUE; sprintf(errbuf, "Label \"%s\" not found", s); MessageBox(hWnd, errbuf, "Command Error", MB_OK | MB_SYSTEMMODAL); PostMessage(hWnd, WM_COMMAND, (WPARAM)IDM_QUIT, 0L); } break; /* onerror processing, if errlevel is false skip, else find label */ case IDM_ONERR: if (!errlevel) break; /* goto processing, branch to label */ case IDM_GOTO: if ((nextcmd = FindLabel(curcmd->cmdstring)) == (CMD *)-1) { stop = TRUE; MessageBox(hWnd, "Label not found", "Command Error", MB_OK | MB_SYSTEMMODAL); PostMessage(hWnd, WM_COMMAND, (WPARAM)IDM_QUIT, 0L); } break; /* generate a message box containing the given text */ case IDM_MSGBOX: stop = TRUE; strcpy(cmd, curcmd->cmdstring); if ((s = strstr(cmd, "\377")) != NULL) { *(s++) = 0; sscanf(s, "%d", &flags); } else flags = MB_OK | MB_SYSTEMMODAL; if (!strcmp(cmd, "$syserr")) { FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, errlevel, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language errbuf, sizeof(errbuf), NULL); mboxrtn = MessageBox(hWnd, errbuf, "Error", MB_OK | MB_SYSTEMMODAL); } else mboxrtn = MessageBox(hWnd, cmd, "Script message", flags); stop = FALSE; break; case IDM_QUIT: PostMessage(hWnd, WM_DESTROY, 0, 0L); break; } break; case WM_DESTROY: KillTimer(hWnd, 1); FreeCMD(cmdstart); FreeLabel(labelstart); PostQuitMessage(0); break; case WM_PAINT: BeginPaint (hWnd, &ps); EndPaint (hWnd, &ps); break; case WM_CREATE: nextcmd = cmdstart; break; case WM_TIMER: if (stop) break; curcmd = nextcmd; if (curcmd != NULL) { nextcmd = curcmd->next; PostMessage(hWnd, WM_COMMAND, (WPARAM)curcmd->function, 0L); } else PostMessage(hWnd, WM_COMMAND, (WPARAM)IDM_QUIT, 0L); break; default: return (DefWindowProc(hWnd, message, wParam, lParam)); } return ((long)NULL); }