diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/mvdm/dos/command/cmdmisc.c | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to '')
-rw-r--r-- | private/mvdm/dos/command/cmdmisc.c | 897 |
1 files changed, 897 insertions, 0 deletions
diff --git a/private/mvdm/dos/command/cmdmisc.c b/private/mvdm/dos/command/cmdmisc.c new file mode 100644 index 000000000..4e8ed2557 --- /dev/null +++ b/private/mvdm/dos/command/cmdmisc.c @@ -0,0 +1,897 @@ +/* cmdmisc.c - Misc. SVC routines of Command.lib + * + * + * Modification History: + * + * Sudeepb 17-Sep-1991 Created + */ + +#include "cmd.h" + +#include <cmdsvc.h> +#include <demexp.h> +#include <softpc.h> +#include <mvdm.h> +#include <ctype.h> +#include <memory.h> +#include "oemuni.h" +#include "nt_pif.h" +#include "nt_uis.h" // For resource id + + +VOID GetWowKernelCmdLine(VOID); +extern ULONG fSeparateWow; + +VOID cmdGetNextCmd (VOID) +{ +LPSTR lpszCmd; +PCMDINFO pCMDInfo; +ULONG cb; +PREDIRCOMPLETE_INFO pRdrInfo; +VDMINFO MyVDMInfo; + +char *pSrc, *pDst; +char achCurDirectory[MAXIMUM_VDM_CURRENT_DIR + 4]; +char CmdLine[MAX_PATH]; + + // + // This routine is called once for WOW VDMs, to retrieve the + // "krnl386" command line. + // 5 + if (VDMForWOW) { + GetWowKernelCmdLine(); + return; + } + + VDMInfo.VDMState = 0; + pCMDInfo = (LPVOID) GetVDMAddr ((USHORT)getDS(),(USHORT)getDX()); + + VDMInfo.ErrorCode = FETCHWORD(pCMDInfo->ReturnCode); + VDMInfo.CmdSize = sizeof(CmdLine); + VDMInfo.CmdLine = CmdLine; + VDMInfo.AppName = (PVOID)GetVDMAddr(FETCHWORD(pCMDInfo->ExecPathSeg), + FETCHWORD(pCMDInfo->ExecPathOff)); + VDMInfo.AppLen = FETCHWORD(pCMDInfo->ExecPathSize); + VDMInfo.PifLen = 0; + VDMInfo.EnviornmentSize = 0; + VDMInfo.Enviornment = NULL; + VDMInfo.CurDrive = 0; + VDMInfo.TitleLen = 0; + VDMInfo.ReservedLen = 0; + VDMInfo.DesktopLen = 0; + VDMInfo.CurDirectoryLen = MAX_PATH + 1; + VDMInfo.CurDirectory = achCurDirectory; + + if(IsFirstCall){ + VDMInfo.VDMState = ASKING_FOR_FIRST_COMMAND; + VDMInfo.ErrorCode = 0; + + DeleteConfigFiles(); // get rid of the temp boot files + + // When COMMAND.COM issues first cmdGetNextCmd, it has + // a completed environment already(cmdGetInitEnvironment), + // Therefore, we don't have to ask environment from BASE + cmdVDMEnvBlk.lpszzEnv = (PVOID)GetVDMAddr(FETCHWORD(pCMDInfo->EnvSeg),0); + cmdVDMEnvBlk.cchEnv = FETCHWORD(pCMDInfo->EnvSize); + + //clear bits that track printer flushing + host_lpt_flush_initialize(); + } + else { + + // program has terminated. If the termiation was issued from + // second(or later) instance of command.com(cmd.exe), don't + // reset the flag. + if (Exe32ActiveCount == 0) + DontCheckDosBinaryType = FALSE; + + // tell the base our new current directories (in ANSI) + // we don't do it on repeat call(the shell out case is handled in + // return exit code + if (!IsRepeatCall) { + cmdUpdateCurrentDirectories((BYTE)pCMDInfo->CurDrive); + } + + VDMInfo.VDMState = 0; + if(!IsRepeatCall){ + demCloseAllPSPRecords (); + + if (!pfdata.CloseOnExit && DosSessionId) + nt_block_event_thread(1); + else + nt_block_event_thread(0); + + if (DosSessionId) { + if (!pfdata.CloseOnExit){ + char achTitle[MAX_PATH]; + char achInactive[60]; //should be plenty for 'inactive' + strcpy (achTitle, "["); + if (!LoadString(GetModuleHandle(NULL), EXIT_NO_CLOSE, + achInactive, 60)) + strcat (achTitle, "Inactive "); + else + strcat(achTitle, achInactive); + cb = strlen(achTitle); + // GetConsoleTitleA and SetConsoleTitleA + // are working on OEM character set. + GetConsoleTitleA(achTitle + cb, MAX_PATH - cb - 1); + cb = strlen(achTitle); + achTitle[cb] = ']'; + achTitle[cb + 1] = '\0'; + SetConsoleTitleA(achTitle); + Sleep(INFINITE); + } + else { + VdmExitCode = VDMInfo.ErrorCode; + TerminateVDM(); + } + } + fBlock = TRUE; + } + } + + if(IsRepeatCall) { + VDMInfo.VDMState |= ASKING_FOR_SECOND_TIME; + if( VDMInfo.ErrorCode != 0 ) + IsRepeatCall = FALSE; + } + + VDMInfo.VDMState |= ASKING_FOR_DOS_BINARY; + + if (!IsFirstCall && !(VDMInfo.VDMState & ASKING_FOR_SECOND_TIME)) { + pRdrInfo = (PREDIRCOMPLETE_INFO) FETCHDWORD(pCMDInfo->pRdrInfo); + if (cmdCheckCopyForRedirection (pRdrInfo) == FALSE) + VDMInfo.ErrorCode = ERROR_NOT_ENOUGH_MEMORY; + } + + // Leave the current directory in a safe place, so that other 32bit + // apps etc. can delnode this directory (and other such operations) later. + if ( IsFirstCall == FALSE && IsRepeatCall == FALSE ) + SetCurrentDirectory (cmdHomeDirectory); + + // TSRExit will be set to 1, only if we are coming from command.com's + // prompt and user typed an exit. We need to kill our parent also, so we + // should write an exit in the console buffer. + if (FETCHWORD(pCMDInfo->fTSRExit)) { + cmdPushExitInConsoleBuffer (); + } + + /** + Merging environment is required if + (1). Not the first comamnd && + (2). NTVDM is running on an existing console || + NTVDM has been shelled out. + Note that WOW doesn't need enviornment merging. + **/ + if (!DosEnvCreated && !IsFirstCall && (!DosSessionId || Exe32ActiveCount)) { + RtlZeroMemory(&MyVDMInfo, sizeof(VDMINFO)); + MyVDMInfo.VDMState = ASKING_FOR_ENVIRONMENT | ASKING_FOR_DOS_BINARY; + if (IsRepeatCall) { + MyVDMInfo.VDMState |= ASKING_FOR_SECOND_TIME; + MyVDMInfo.ErrorCode = 0; + } + else + MyVDMInfo.ErrorCode = VDMInfo.ErrorCode; + MyVDMInfo.Enviornment = lpszzVDMEnv32; + MyVDMInfo.EnviornmentSize = (USHORT) cchVDMEnv32; + if (!GetNextVDMCommand(&MyVDMInfo) && MyVDMInfo.EnviornmentSize > cchVDMEnv32) { + MyVDMInfo.Enviornment = realloc(lpszzVDMEnv32, MyVDMInfo.EnviornmentSize); + if (MyVDMInfo.Enviornment == NULL) { + RcErrorDialogBox(EG_MALLOC_FAILURE, NULL, NULL); + TerminateVDM(); + } + lpszzVDMEnv32 = MyVDMInfo.Enviornment; + cchVDMEnv32 = MyVDMInfo.EnviornmentSize; + MyVDMInfo.VDMState = ASKING_FOR_DOS_BINARY | ASKING_FOR_ENVIRONMENT | + ASKING_FOR_SECOND_TIME; + + MyVDMInfo.TitleLen = + MyVDMInfo.DesktopLen = + MyVDMInfo.ReservedLen = + MyVDMInfo.CmdSize = + MyVDMInfo.AppLen = + MyVDMInfo.PifLen = + MyVDMInfo.CurDirectoryLen = 0; + MyVDMInfo.ErrorCode = 0; + if (!GetNextVDMCommand(&MyVDMInfo)) { + RcErrorDialogBox(EG_ENVIRONMENT_ERR, NULL, NULL); + TerminateVDM(); + } + } + if (!cmdCreateVDMEnvironment(&cmdVDMEnvBlk)) { + RcErrorDialogBox(EG_ENVIRONMENT_ERR, NULL, NULL); + TerminateVDM(); + } + DosEnvCreated = TRUE; + VDMInfo.ErrorCode = 0; + } + if (cmdVDMEnvBlk.cchEnv > FETCHWORD(pCMDInfo->EnvSize)) { + setAX((USHORT)cmdVDMEnvBlk.cchEnv); + setCF(1); + IsFirstCall = FALSE; + IsRepeatCall = TRUE; + return; + } + if (DosEnvCreated) + VDMInfo.VDMState |= ASKING_FOR_SECOND_TIME; + + if(!GetNextVDMCommand(&VDMInfo)){ + RcErrorDialogBox(EG_ENVIRONMENT_ERR, NULL, NULL); + TerminateVDM(); + } + + + IsRepeatCall = FALSE; + IsFirstCall = FALSE; + + if(fBlock){ + nt_resume_event_thread(); + fBlock = FALSE; + } + + // Sync VDMs enviornment variables for current directories + cmdSetDirectories (lpszzVDMEnv32, &VDMInfo); + + // tell DOS that this is a dos executable and no further checking is + // necessary + *pIsDosBinary = 1; + + + // Check for PIF files. If a pif file is being executed extract the + // executable name, command line, current directory and title from the pif + // file and place the stuff appropriately in VDMInfo. Note, if pif file + // is invalid, we dont do any thing to vdminfo. In such a case we + // pass the pif as it is to scs to execute which we know will fail and + // will come back to cmdGettNextCmd with proper error code. + + cmdCheckForPIF (&VDMInfo); + + + // + // if forcedos, then don't check binary type on int 21 exec process, + // so that child spawns stay in dos land. Begining with NT 4.0 forcedos.exe + // no longer uses pif files to force execution of a binary as a dos exe. + // It now uses a bit in CreateProcess (dwCreationFlags). + // + + DontCheckDosBinaryType = (VDMInfo.dwCreationFlags & CREATE_FORCEDOS) != 0; + + + // convert exec path name to upper case. This is what command.com expect + if (_strupr(VDMInfo.AppName) == NULL) { + pSrc = VDMInfo.AppName; + while (*pSrc) + *pSrc++ = (char)toupper((int)*pSrc); + } + // figure out the extention type + // at least one char for the base name plus + // EXTENTION_STRING_LEN for the extention + // plus the NULL char + if (VDMInfo.AppLen > 1 + EXTENTION_STRING_LEN + 1) { + pSrc = (PCHAR)VDMInfo.AppName + VDMInfo.AppLen - 5; + if (!strncmp(pSrc, EXE_EXTENTION_STRING, EXTENTION_STRING_LEN)) + STOREWORD(pCMDInfo->ExecExtType, EXE_EXTENTION); + else if (!strncmp(pSrc, COM_EXTENTION_STRING, EXTENTION_STRING_LEN)) + STOREWORD(pCMDInfo->ExecExtType, COM_EXTENTION); + else if (!strncmp(pSrc, BAT_EXTENTION_STRING, EXTENTION_STRING_LEN)) + STOREWORD(pCMDInfo->ExecExtType, BAT_EXTENTION); + else + STOREWORD(pCMDInfo->ExecExtType, UNKNOWN_EXTENTION); + } + else + STOREWORD(pCMDInfo->ExecExtType, UNKNOWN_EXTENTION); + + // tell command.com the length of the app full path name. + STOREWORD(pCMDInfo->ExecPathSize, VDMInfo.AppLen); + + // + // Prepare ccom's UCOMBUF + // + lpszCmd = (PVOID)GetVDMAddr(FETCHWORD(pCMDInfo->CmdLineSeg), + FETCHWORD(pCMDInfo->CmdLineOff)); + + // Copy filepart of AppName excluding extension to ccom's buffer + pSrc = strrchr(VDMInfo.AppName, '\\'); + if (!pSrc) { + pSrc = VDMInfo.AppName; + } + else { + pSrc++; + } + pDst = lpszCmd + 2; + while (*pSrc && *pSrc != '.') { + *pDst++ = *pSrc++; + } + cb = strlen(CmdLine); + + // cmd line must be terminated with "\0xd\0xa\0". This is either done + // by BASE or cmdCheckForPif function(cmdpif.c). + + ASSERT((cb >= 2) && (0xd == CmdLine[cb - 2]) && (0xa == CmdLine[cb - 1])); + + // if cmd line is not blank, separate program base name and + // cmd line with a SPACE. If it IS blank, do not insert any white chars + // or we end up passing white chars to the applications as cmd line + // and some applications just can not live with that. + // We do not strip leading white characters in the passed command line + // so the application sees the original data. + if (cb > 2) + *pDst++ = ' '; + + // append the command tail(at least, "\0xd\0xa") + strncpy(pDst, CmdLine, cb + 1); + + // set the count + // cb has the cmd line length including the terminated 0xd and 0xa + // It does NOT count the terminated NULL char. + ASSERT((cb + pDst - lpszCmd - 2) <= 127); + + // minus 2 because the real data in lpszCmd start from lpszCmd[2] + lpszCmd[1] = (CHAR)(cb + pDst - lpszCmd - 2); + + + + if (DosEnvCreated) { + VDMInfo.Enviornment = (PVOID)GetVDMAddr(FETCHWORD(pCMDInfo->EnvSeg),0); + RtlMoveMemory(VDMInfo.Enviornment, + cmdVDMEnvBlk.lpszzEnv, + cmdVDMEnvBlk.cchEnv + ); + STOREWORD(pCMDInfo->EnvSize,cmdVDMEnvBlk.cchEnv); + free(cmdVDMEnvBlk.lpszzEnv); + DosEnvCreated = FALSE; + } + + STOREWORD(pCMDInfo->fBatStatus,(USHORT)VDMInfo.fComingFromBat); + STOREWORD(pCMDInfo->CurDrive,VDMInfo.CurDrive); + STOREWORD(pCMDInfo->NumDrives,nDrives); + VDMInfo.CodePage = (ULONG) cmdMapCodePage (VDMInfo.CodePage); + STOREWORD(pCMDInfo->CodePage,(USHORT)VDMInfo.CodePage); + + cmdVDMEnvBlk.lpszzEnv = NULL; + cmdVDMEnvBlk.cchEnv = 0; + + IsFirstVDM = FALSE; + + // Handle Standard IO redirection + pRdrInfo = cmdCheckStandardHandles (&VDMInfo,&pCMDInfo->bStdHandles); + STOREDWORD(pCMDInfo->pRdrInfo,(ULONG)pRdrInfo); + + // Tell DOS that it has to invalidate the CDSs + *pSCS_ToSync = (CHAR)0xff; + setCF(0); + + return; +} + + + +VOID GetWowKernelCmdLine(VOID) +{ +CMDINFO UNALIGNED *pCMDInfo; +PCHAR pch, pEnvStrings; +PCHAR pSlash; +int Len; +LPSTR pszCmdLine; + + + DeleteConfigFiles(); // get rid of the temp boot files + host_lpt_flush_initialize(); + + // + // Only a few things need be set for WOW. + // 1. NumDrives + // 2. Environment (get from current 32-bit env.) + // 3. Kernel CmdLine (get from ntvdm command tail) + // 4. Current drive + // + + pCMDInfo = (LPVOID) GetVDMAddr ((USHORT)getDS(),(USHORT)getDX()); + pCMDInfo->NumDrives = nDrives; + + // + // Get the process's environment into lpszzVDMEnv32 and count + // its size into cchVDMEnv32. + // + + pEnvStrings = pch = lpszzVDMEnv32 = GetEnvironmentStrings(); + cchVDMEnv32 = 0; + while (pch[0] || pch[1]) { + cchVDMEnv32++; + pch++; + } + cchVDMEnv32 += 2; // two terminating nulls not counted in loop. + + // + // Transform environment to suit VDM. cmdCreateVDMEnvironment + // uses lpszzVDMEnv32 and cchVDMEnv32 as the source. + // + + if (!cmdCreateVDMEnvironment(&cmdVDMEnvBlk)) { + RcErrorDialogBox(EG_ENVIRONMENT_ERR, NULL, NULL); + TerminateVDM(); + } + + // + // Copy the transformed environment to real mode mem and then free it. + // + + pch = (PVOID)GetVDMAddr(FETCHWORD(pCMDInfo->EnvSeg),0); + RtlMoveMemory(pch, + cmdVDMEnvBlk.lpszzEnv, + cmdVDMEnvBlk.cchEnv + ); + STOREWORD(pCMDInfo->EnvSize,cmdVDMEnvBlk.cchEnv); + free(cmdVDMEnvBlk.lpszzEnv); + // GetEnvironmentStrings needs us to call its corresponding function + // to free the memory it allocated. + FreeEnvironmentStrings(pEnvStrings); + + // + // Get the command line parameter, which consists of a fully + // qualified short path file name: "-a %SystemRoot%\system32\krnl386.exe". + // + // Note that the first token of cmdline is "%SystemRoot%\system32\ntvdm ", + // and may be a long file name surrounded by quotes. + // + pszCmdLine = GetCommandLine(); + if (pszCmdLine) { + + // skip leading spaces + while (*pszCmdLine && !isgraph(*pszCmdLine)) { + pszCmdLine++; + } + + // skip first token + if (*pszCmdLine == '"') { + pszCmdLine++; + while (*pszCmdLine && *pszCmdLine++ != '"') + ; + } + else { + while (isgraph(*pszCmdLine)) { + pszCmdLine++; + } + } + + // mov to beg of WowKernelPathName + pszCmdLine = strstr(pszCmdLine, " -a "); + pszCmdLine += 4; + while (*pszCmdLine && *pszCmdLine == ' ') { + pszCmdLine++; + } + } + + if (!pszCmdLine || !*pszCmdLine) { + RcErrorDialogBox(EG_ENVIRONMENT_ERR, NULL, NULL); + TerminateVDM(); + } + + + // + // Copy first token to ExecPath, and find the beg of the file part. + // + Len = FETCHWORD(pCMDInfo->ExecPathSize); + pch = (PVOID)GetVDMAddr(FETCHWORD(pCMDInfo->ExecPathSeg), + FETCHWORD(pCMDInfo->ExecPathOff)); + + pSlash = pszCmdLine; + while (--Len && isgraph(*pszCmdLine)) { + if (*pszCmdLine == '\\') { + pSlash = pszCmdLine + 1; + } + *pch++ = *pszCmdLine++; + } + *pch = '\0'; + pCMDInfo->ExecPathSize -= Len; + pCMDInfo->ExecExtType = EXE_EXTENTION; // for WOW, use EXE extention + + pszCmdLine = pSlash; // filepart begins here + + + // + // Copy filepart of first token and rest to CmdLine buffer + // + Len = FETCHWORD(pCMDInfo->CmdLineSize); + pch = (PVOID)GetVDMAddr(FETCHWORD(pCMDInfo->CmdLineSeg), + FETCHWORD(pCMDInfo->CmdLineOff)); + + while (--Len && *pszCmdLine) { + *pch++ = *pszCmdLine++; + } + strcpy(pch, "\x0d\x0a"); + + + *pIsDosBinary = 1; + IsRepeatCall = FALSE; + IsFirstCall = FALSE; + + // Tell DOS that it has to invalidate the CDSs + *pSCS_ToSync = (CHAR)0xff; + setCF(0); + + return; +} + + +/* cmdGetCurrentDir - Return the current directory for a drive. + * + * + * Entry - Client (DS:SI) - buffer to return the directory + * Client (AL) - drive being queried (0 = A) + * + * EXIT - SUCCESS Client (CY) clear + * FAILURE Client (CY) set + * (AX) = 0 (Directory was bigger than 64) + * (AX) = 1 (the drive is not valid) + * + */ + +VOID cmdGetCurrentDir (VOID) +{ +PCHAR lpszCurDir; +UCHAR chDrive; +CHAR EnvVar[] = "=?:"; +CHAR RootName[] = "?:\\"; +DWORD EnvVarLen; +UINT DriveType; + + + lpszCurDir = (PCHAR) GetVDMAddr ((USHORT)getDS(),(USHORT)getSI()); + chDrive = getAL(); + EnvVar[1] = chDrive + 'A'; + RootName[0] = chDrive + 'A'; + + // if the drive doesn't exist, blindly clear the environment var + // and return error + DriveType = demGetPhysicalDriveType(chDrive); + if (DriveType == DRIVE_UNKNOWN) { + DriveType = GetDriveTypeOem(RootName); + } + + if (DriveType == DRIVE_UNKNOWN || DriveType == DRIVE_NO_ROOT_DIR){ + SetEnvironmentVariableOem(EnvVar, NULL); + setCF(1); + setAX(0); + return; + } + + if((EnvVarLen = GetEnvironmentVariableOem (EnvVar,lpszCurDir, + MAXIMUM_VDM_CURRENT_DIR+3)) == 0){ + + // if its not in env then and drive exist then we have'nt + // yet touched it. + strcpy(lpszCurDir, RootName); + SetEnvironmentVariableOem (EnvVar,RootName); + setCF(0); + return; + } + if (EnvVarLen > MAXIMUM_VDM_CURRENT_DIR+3) { + setCF(1); + setAX(0); + } + else { + setCF(0); + } + return; +} + +/* cmdSetInfo - Set the address of SCS_ToSync variable in DOSDATA. + * This variable is set whenever SCS dispatches a new + * command to command.com. Setting of this variable + * indicates to dos to validate all the CDS structures + * for local drives. + * + * + * Entry - Client (DS:DX) - pointer to SCSINFO. + * + * EXIT - None + */ + +VOID cmdSetInfo (VOID) +{ + + pSCSInfo = (PSCSINFO) GetVDMAddr (getDS(),getDX()); + + pSCS_ToSync = (PCHAR) &pSCSInfo->SCS_ToSync; + + pIsDosBinary = (BYTE *) GetVDMAddr(getDS(), getBX()); + + pFDAccess = (WORD *) GetVDMAddr(getDS(), getCX()); + return; +} + + +VOID cmdSetDirectories (PCHAR lpszzEnv, VDMINFO * pVdmInfo) +{ +LPSTR lpszVal; +CHAR ch, chDrive, achEnvDrive[] = "=?:"; + + ch = pVdmInfo->CurDrive + 'A'; + if (pVdmInfo->CurDirectoryLen != 0){ + SetCurrentDirectory(pVdmInfo->CurDirectory); + achEnvDrive[1] = ch; + SetEnvironmentVariable(achEnvDrive, pVdmInfo->CurDirectory); + } + if (lpszzEnv) { + while(*lpszzEnv) { + if(*lpszzEnv == '=' && + (chDrive = toupper(*(lpszzEnv+1))) >= 'A' && + chDrive <= 'Z' && + (*(PCHAR)((ULONG)lpszzEnv+2) == ':') && + chDrive != ch) { + lpszVal = (PCHAR)((ULONG)lpszzEnv + 4); + achEnvDrive[1] = chDrive; + SetEnvironmentVariable (achEnvDrive,lpszVal); + } + lpszzEnv = strchr(lpszzEnv,'\0'); + lpszzEnv++; + } + } +} + +static BOOL fConOutput = FALSE; + +VOID cmdComSpec (VOID) +{ +LPSTR lpszCS; + + + if(IsFirstCall == FALSE) + return; + + lpszCS = (LPVOID) GetVDMAddr ((USHORT)getDS(),(USHORT)getDX()); + strcpy(lpszComSpec,"COMSPEC="); + strcpy(lpszComSpec+8,lpszCS); + cbComSpec = strlen(lpszComSpec) +1; + + setAL((BYTE)(!fConOutput || VDMForWOW)); + + return; +} + + +VOID cmdSaveWorld (VOID) +{ +#ifdef CHECK_IT_LATER +SAVEWORLD VDMState; +HANDLE hFile; +PCHAR pVDM; +DWORD dwBytesWritten; + + if(IsFirstVDMInSystem) { + IsFirstVDMInSystem = FALSE; + if ((hFile = CreateFile("c:\\nt\\bin86\\savevdm.wld", + GENERIC_WRITE, + 0, + NULL, + OPEN_ALWAYS, + 0, + NULL)) == (HANDLE)-1){ + SaveWorldCreated = FALSE; + return; + } + VDMState.ax = getAX(); + VDMState.bx = getBX(); + VDMState.cx = getCX(); + VDMState.dx = getDX(); + VDMState.cs = getCS(); + VDMState.ss = getSS(); + VDMState.ds = getDS(); + VDMState.es = getES(); + VDMState.si = getSI(); + VDMState.di = getDI(); + VDMState.bp = getBP(); + VDMState.sp = getSP(); + VDMState.ip = getIP() + 1; + VDMState.flag = 0; + VDMState.ImageSize = 1024*1024; + + pVDM = (PVOID)GetVDMAddr(0,0); + + if (WriteFile (hFile, + (LPVOID)&VDMState, + (DWORD)sizeof(VDMState), + &dwBytesWritten, + NULL) == FALSE){ + SaveWorldCreated = FALSE; + CloseHandle(hFile); + return; + } + + if (WriteFile (hFile, + (LPVOID)pVDM, + (DWORD)VDMState.ImageSize, + &dwBytesWritten, + NULL) == FALSE){ + SaveWorldCreated = FALSE; + CloseHandle(hFile); + return; + } + CloseHandle(hFile); + } +#endif + return; +} + + +/* cmdInitConsole - Let Video VDD know that it can start console output + * operations. + * + * + * Entry - None + * + * + * EXIT - None + * + */ + +VOID cmdInitConsole (VOID) +{ + if (fConOutput == FALSE) { + fConOutput = TRUE; + nt_init_event_thread (); + } + return; +} + + +/* cmdMapCodePage - Map the Win32 Code page to DOS code page + */ + +USHORT cmdMapCodePage (ULONG CodePage) +{ + // Currently We understand US code page only + if (CodePage == 1252) + return 437; + else + return ((USHORT)CodePage); +} + + + +/* GetWOWShortCutInfo - returns the startupinf.reserved field of + * vdminfo for the first wow task. + * + * Input - Bufsize - pointer to bufsize + * Buf - buffer where the info is returned + * + * Output + * Success - returns TRUE, BufSize has the length of buffer filled in + * Failure - returns FALSE, Bufsize has the required buffer size. + */ + +BOOL GetWOWShortCutInfo (PULONG Bufsize, PVOID Buf) +{ + if (*Bufsize >= VDMInfo.ReservedLen) { + *Bufsize = VDMInfo.ReservedLen; + if (Bufsize) + strncpy (Buf, VDMInfo.Reserved, VDMInfo.ReservedLen); + return TRUE; + } + else { + *Bufsize = VDMInfo.ReservedLen; + return FALSE; + } +} + +VOID cmdUpdateCurrentDirectories(BYTE CurDrive) +{ + DWORD cchRemain, cchCurDir; + CHAR *lpszCurDir; + BYTE Drive; + DWORD DriveType; + CHAR achName[] = "=?:"; + CHAR RootName[] = "?:\\"; + + + // allocate new space for the new current directories + lpszzCurrentDirectories = (CHAR*) malloc(MAX_PATH); + cchCurrentDirectories = 0; + cchRemain = MAX_PATH; + lpszCurDir = lpszzCurrentDirectories; + if (lpszCurDir != NULL) { + Drive = 0; + // current directory is the first entry + achName[1] = CurDrive + 'A'; + cchCurrentDirectories = GetEnvironmentVariable( + achName, + lpszCurDir, + cchRemain + ); + + if (cchCurrentDirectories == 0 || cchCurrentDirectories > MAX_PATH) { + free(lpszzCurrentDirectories); + lpszzCurrentDirectories = NULL; + cchCurrentDirectories = 0; + return; + } + + cchRemain -= ++cchCurrentDirectories; + // we got current directory already. Keep the drive number + lpszCurDir += cchCurrentDirectories; + + while (Drive < 26) { + + // ignore invalid drives and current drive + if (Drive != CurDrive) { + DriveType = demGetPhysicalDriveType(Drive); + if (DriveType == DRIVE_UNKNOWN) { + RootName[0] = (CHAR)('A' + Drive); + DriveType = GetDriveTypeOem(RootName); + } + + if (DriveType != DRIVE_UNKNOWN && + DriveType != DRIVE_NO_ROOT_DIR ) + { + achName[1] = Drive + 'A'; + cchCurDir = GetEnvironmentVariable( + achName, + lpszCurDir, + cchRemain + ); + if(cchCurDir > cchRemain) { + lpszCurDir = (CHAR *)realloc(lpszzCurrentDirectories, + cchRemain + MAX_PATH + cchCurrentDirectories + ); + if (lpszCurDir == NULL) { + free(lpszzCurrentDirectories); + lpszzCurrentDirectories = NULL; + cchCurrentDirectories = 0; + return; + } + lpszzCurrentDirectories = lpszCurDir; + lpszCurDir += cchCurrentDirectories; + cchRemain += MAX_PATH; + cchCurDir = GetEnvironmentVariable( + achName, + lpszCurDir, + cchRemain + ); + } + if (cchCurDir != 0) { + // GetEnvironmentVariable doesn't count the NULL char + lpszCurDir += ++cchCurDir; + cchRemain -= cchCurDir; + cchCurrentDirectories += cchCurDir; + } + } + } + // next drive + Drive++; + } + + + lpszCurDir = lpszzCurrentDirectories; + // need space for the ending NULL and shrink the space if necessary + lpszzCurrentDirectories = (CHAR *) realloc(lpszCurDir, cchCurrentDirectories + 1); + if (lpszzCurrentDirectories != NULL && cchCurrentDirectories != 0){ + lpszzCurrentDirectories[cchCurrentDirectories++] = '\0'; + SetVDMCurrentDirectories(cchCurrentDirectories, lpszzCurrentDirectories); + free(lpszzCurrentDirectories); + lpszzCurrentDirectories = NULL; + cchCurrentDirectories = 0; + } + else { + free(lpszCurDir); + cchCurrentDirectories = 0; + } + + } +} + +/* This SVC function tells command.com, if the VDM was started without an + * existing console. If so, on finding a TSR, command.com will return + * back to GetNextVDMCommand, rather than putting its own popup. + * + * Entry - None + * + * Exit - Client (AL) = 0 if started with an existing console + * Client (AL) = 1 if started with new console + */ + +VOID cmdGetStartInfo (VOID) +{ + setAL((BYTE) (DosSessionId ? 1 : 0)); + return; +} |