cmd.exe 源代码中的ExecPgm()函数

/********************* START OF SPECIFICATION **************************/
/*                                                                     */
/* SUBROUTINE NAME: ExecPgm                                            */
/*                                                                     */
/* DESCRIPTIVE NAME: Call DosExecPgm to execute External Command       */
/*                                                                     */
/* FUNCTION: Execute External Commands with DosExecPgm                 */
/*           This routine calls DosExecPgm to execute the command.     */
/*                                                                     */
/*                                                                     */
/* NOTES: This is a new routine added for OS/2 1.1 release.            */
/*                                                                     */
/*                                                                     */
/* ENTRY POINT: ExecPgm                                                */
/*    LINKAGE: NEAR                                                    */
/*                                                                     */
/* INPUT: n - the parse tree node containing the command to be executed*/
/*                                                                     */
/*        ai - the asynchronous indicator                              */
/*           - 0 = Exec synchronous with parent                        */
/*           - 1 = Exec asynchronous and discard child return code     */
/*           - 2 = Exec asynchronous and save child return code        */
/*                                                                     */
/*        wf - the wait flag                                           */
/*           - 0 = Wait for process completion                         */
/*           - 1 = Return immediately (Pipes)                          */
/*                                                                     */
/* OUTPUT: None.                                                       */
/*                                                                     */
/* EXIT-NORMAL:                                                        */
/*         If synchronous execution, the return code of the command is */
/*         returned.                                                   */
/*                                                                     */
/*         If asynchronous execution, the return code of the exec call */
/*         is returned.                                                */
/*                                                                     */
/* EXIT-ERROR:                                                         */
/*         Return FAILURE to the caller.                               */
/*                                                                     */
/* EFFECTS:                                                            */
/*                                                                     */
/* INTERNAL REFERENCES:                                                */
/*      ROUTINES:                                                      */
/*       ExecError - Handles execution error                           */
/*       PutStdErr - Print an error message                            */
/*       WaitProc - wait for the termination of the specified process, */
/*                  its child process, and  related pipelined          */
/*                  processes.                                         */
/*                                                                     */
/*                                                                     */
/* EXTERNAL REFERENCES:                                                */
/*      ROUTINES:                                                      */
/*       DOSEXECPGM      - Execute the specified program               */
/*       DOSSMSETTITLE   - Set title for the presentation manager      */
/*                                                                     */
/********************** END  OF SPECIFICATION **************************/

int
ExecPgm(
    IN struct cmdnode *n,
    IN TCHAR *onb,
    IN unsigned int ai,
    IN unsigned int  wf,
    IN TCHAR * argptr,
    IN TCHAR * fnptr,
    IN TCHAR * tptr
    )
{
        int i ;                                 /* Work variable           */
        BOOL b;
        BOOL VdmProcess = FALSE;
        BOOL WowProcess = FALSE;
        BOOL GuiProcess = FALSE;

        HDESK   hdesk;
        LPTSTR  lpDesktop;
        DWORD   cbDesktop = 0;
        HWINSTA hwinsta;
        LPTSTR  p;
        DWORD   cbWinsta = 0;

        TCHAR   szValEqExitCodeEnvVar [20];
        TCHAR   szValEqExitCodeAsciiEnvVar [12];


        STARTUPINFO StartupInfo;
        PROCESS_INFORMATION ChildProcessInfo;

        memset( &StartupInfo, 0, sizeof( StartupInfo ) );
        StartupInfo.cb = sizeof( StartupInfo );
        StartupInfo.lpTitle = tptr;
        StartupInfo.dwX = 0;
        StartupInfo.dwY = 1;
        StartupInfo.dwXSize = 100;
        StartupInfo.dwYSize = 100;
        StartupInfo.dwFlags = 0;//STARTF_SHELLOVERRIDE;
        StartupInfo.wShowWindow = SW_SHOWNORMAL;


        // Pass current Desktop to a new process.

        hwinsta = GetProcessWindowStation();
        GetUserObjectInformation( hwinsta, UOI_NAME, NULL, 0, &cbWinsta );

        hdesk = GetThreadDesktop ( GetCurrentThreadId() );
        GetUserObjectInformation (hdesk, UOI_NAME, NULL, 0, &cbDesktop);

        if ((lpDesktop = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, cbDesktop + cbWinsta + 32) ) != NULL ) {
            p = lpDesktop;
            if ( GetUserObjectInformation (hwinsta, UOI_NAME, p, cbWinsta, &cbWinsta) ) {
                if (cbWinsta > 0) {
                    p += ((cbWinsta/sizeof(TCHAR))-1);
                    *p++ = L'\\';
                }
                if ( GetUserObjectInformation (hdesk, UOI_NAME, p, cbDesktop, &cbDesktop) ) {
                    StartupInfo.lpDesktop = lpDesktop;
                }
            }
        }

        b = CreateProcess( fnptr,
                           argptr,
                           (LPSECURITY_ATTRIBUTES) NULL,
                           (LPSECURITY_ATTRIBUTES) NULL,
                           TRUE,
                           0,
                           NULL,
                           CurDrvDir,
                           &StartupInfo,
                           &ChildProcessInfo
                         );
        HeapFree (GetProcessHeap(), 0, lpDesktop);
        if (!b) {
            DosErr = i = GetLastError();
            if (fEnableExtensions && DosErr == ERROR_BAD_EXE_FORMAT) {
                SHELLEXECUTEINFO sei;

                memset(&sei, 0, sizeof(sei));
                //
                // Use the DDEWAIT flag so apps can finish their DDE conversation
                // before ShellExecuteEx returns.  Otherwise, apps like Word will
                // complain when they try to exit, confusing the user.
                //
                sei.cbSize = sizeof(sei);
                sei.fMask = SEE_MASK_HASTITLE |
                            SEE_MASK_NO_CONSOLE |
                            SEE_MASK_FLAG_DDEWAIT |
                            SEE_MASK_NOCLOSEPROCESS;
                sei.lpFile = fnptr;
                sei.lpClass = tptr;
                sei.lpParameters = n->argptr;
                sei.lpDirectory = CurDrvDir;
                sei.nShow = StartupInfo.wShowWindow;
                if (!ShellExecuteEx(&sei)) {
                    if ((DWORD)sei.hInstApp == 0) {
                        DosErr = ERROR_NOT_ENOUGH_MEMORY;
                    } else if ((DWORD)sei.hInstApp == HINSTANCE_ERROR) {
                        DosErr = ERROR_FILE_NOT_FOUND;
                    } else {
                        DosErr = (unsigned)sei.hInstApp;
                    }
                } else {
                    //
                    // Successfully invoked correct application via
                    // file association.  Code below will check to see
                    // if application is a GUI app and if so turn it into
                    // an ASYNC exec.
                    //
                    hChildProcess = sei.hProcess;
                    goto shellexecsuccess;
                }
            }
            mystrcpy( onb, fnptr );
            ExecError( onb ) ;

            return(FAILURE) ;
        }
        hChildProcess = ChildProcessInfo.hProcess;
        CloseHandle(ChildProcessInfo.hThread);
shellexecsuccess:

#ifndef WIN95_CMD
        VdmProcess = (ULONG)(hChildProcess) & 1;
        WowProcess = (ULONG)(hChildProcess) & 2;
#endif // WIN95_CMD
        if (fEnableExtensions &&
            CurBat == 0 &&
            !fSingleBatchLine &&
            !fSingleCmdLine &&
            ai == AI_SYNC &&
            (WowProcess || GetProcessSubsystemType(hChildProcess) == IMAGE_SUBSYSTEM_WINDOWS_GUI)
           ) {
            //
            // If extensions enabled and doing a synchronous exec of a GUI
            // application, then change it into an asynchronous exec, with the
            // return code discarded, ala Win 3.x and Win 95 COMMAND.COM
            //
            ai = AI_DSCD;
            GuiProcess = TRUE;
        }

        i = SUCCESS;
        start_type = EXECPGM;

        if (ai == AI_SYNC) {             /* Async exec...   */
                LastRetCode = WaitProc((unsigned)hChildProcess);
                i = LastRetCode ;

                //
                // this is added initially to support new network batch scripts
                // but it can be used by any process.
                //
                // always set "=ExitCode" env. variable as string of 8 hex digits
                // representing LastRetCode

                _stprintf (szValEqExitCodeEnvVar, TEXT("%08X"), i);
                SetEnvVar(szNameEqExitCodeEnvVar, szValEqExitCodeEnvVar, &CmdEnv);

                // IF   LastRetCode printable
                // THEN set "=ExitCodeAscii" env. variable equal LastRetCode
                // ELSE remove "=ExitCodeAscii" env. variable

                if ( (i >= 0x20) &&  (i <= 0x7e) )  {       // isprint
                    _stprintf (szValEqExitCodeAsciiEnvVar, TEXT("%01C"), i);
                    SetEnvVar(szNameEqExitCodeAsciiEnvVar, szValEqExitCodeAsciiEnvVar, &CmdEnv);
                }
                else
                    SetEnvVar(szNameEqExitCodeAsciiEnvVar, TEXT("\0"), &CmdEnv);


#ifndef WIN95_CMD
                if (VdmProcess) {
                    RestoreCurrentDirectories();
                }
#endif // WIN95_CMD
        }

/*  If real async (discarding retcode), just print PID and return.  If
 *  piped process (keeping retcode but not waiting) just store PID for
 *  ePipe and return SUCCESS from exec.  Else, wait around for the return
 *  code before going back.
 */
        if (ai == AI_DSCD) {                    /* DETach only     */
                if (!GuiProcess)
                        PutStdErr(MSG_PID_IS, ONEARG, argstr1(TEXT("%u"), (unsigned long)hChildProcess));
                CloseHandle(ChildProcessInfo.hProcess);
                hChildProcess = NULL ;
        } else if (ai == AI_KEEP) {             /* Async exec...   */
                if (wf == CW_W_YES) {           /* ...normal type  */
                        LastRetCode = WaitProc((unsigned)hChildProcess);
                        i = LastRetCode ;
                        hChildProcess = NULL ;
                } else {                        /* Async exec...   */
                        PipePid = hChildProcess ;        /* M035      */
                        hChildProcess = NULL ;
                } ;
        } ;


        return(i) ;             /* i == return from DOSEXECPGM     */

}


位于cext.c中,创建了一个进程,来代替execve()函数。

https://www.box.com/s/an36i11fpfpmy24bm435

下载cmd.exe【nt4】的源代码。


cmd.exe的源代码,nt4的


http://download.csdn.net/download/chexlong/3854651

nt4ddk

2k环境下安装后的ddk目录的压缩包,只安装了头文件和库。

https://www.box.com/s/1nusatzniim6gcjmga37

nt4-ddk,压缩包,2k环境下安装的编译nt4的

你可能感兴趣的:(cmd.exe 源代码中的ExecPgm()函数)