WinProcess.cpp
上传用户:cnxinhai
上传日期:2013-08-06
资源大小:265k
文件大小:13k
源码类别:

DVD

开发平台:

Visual C++

  1. /* This is the class that handles the Windows system functionality.
  2.  * Process and thread stuff is handled here.
  3.  *
  4.  * Copyright (C) 2001, 2002  Adam Schlag
  5.  */
  6. /*
  7.  * FreeBurn Software License
  8.  * (based on the Apache Software License)
  9.  * 
  10.  * Version 1.1
  11.  * 
  12.  * Copyright (c) 2001, 2002 The FreeBurn Project. All rights reserved.
  13.  * 
  14.  * Redistribution and use in source and binary forms, with or without 
  15.  * modification, are permitted provided that the following conditions are met:
  16.  * 
  17.  * 1. Redistributions of source code must retain the above copyright 
  18.  * notice, this list of conditions and the following disclaimer.
  19.  * 
  20.  * 2. Redistributions in binary form must reproduce the above copyright 
  21.  * notice, this list of conditions and the following disclaimer in the 
  22.  * documentation and/or other materials provided with the distribution.
  23.  * 
  24.  * 3. The end-user documentation included with the redistribution, if any, must 
  25.  * include the following acknowledgment:
  26.  * 
  27.  *  "This product includes software developed by the FreeBurn 
  28.  *     Project (http://freeburn.sourceforge.net/)."
  29.  * 
  30.  * Alternately, this acknowledgment may appear in the software itself, 
  31.  * if and wherever such third-party acknowledgments normally appear.
  32.  * 
  33.  * 4. The names "FreeBurn" and "FreeBurn Project" must not be 
  34.  * used to endorse or promote products derived from this software 
  35.  * without prior written permission. For written permission, please 
  36.  * contact aschlag@users.sourceforge.net.
  37.  * 
  38.  * 5. Products derived from this software may not be called "FreeBurn", 
  39.  * nor may "FreeBurn" appear in their name, without prior written 
  40.  * permission of the FreeBurn Project.
  41.  * 
  42.  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED 
  43.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
  44.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
  45.  * DISCLAIMED. IN NO EVENT SHALL THE FREEBURN PROJECT OR ITS 
  46.  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
  47.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
  48.  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 
  49.  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 
  50.  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
  51.  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 
  52.  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
  53.  * SUCH DAMAGE.
  54.  * 
  55.  * This software consists of voluntary contributions made by many 
  56.  * individuals on behalf of the FreeBurn Project. For more 
  57.  * information on the FreeBurn Project and FreeBurn, please see 
  58.  * <http://freeburn.sourceforge.net/>.
  59.  * 
  60.  * This software is distributed with software that is released under the GNU 
  61.  * General Public License (GPL).  You can find the terms of this license in the
  62.  * file GPL.txt distributed in this package.  You can find information on the
  63.  * software distributed with this package in the file PROGRAMS.txt.
  64.  */
  65. // included for using Windows process/thread stuff
  66. #include <windows.h>
  67. // include file for FOX library
  68. #include <fx.h>
  69. // include file for BaseThread, so we can use CBaseThread
  70. #include "BaseThread.h"
  71. // include file for this class
  72. #include "WinProcess.h"
  73. // top-level FreeBurn include/definition file
  74. #include "FreeburnDefs.h"
  75. // This constructor sets up all the class data
  76. // that will be used later
  77. CWinProcess::CWinProcess() : CBaseThread()
  78. {
  79.     // We want these handles to be inherited by
  80.     // the thread we'll create, so we need to set
  81.     // up a SECURITY_ATTRIBUTES struct saying that
  82.     // we want to do that.
  83.     SECURITY_ATTRIBUTES sa;
  84.     // set the length of sa to the size of SECURITY_ATTRIBUTES
  85.     sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  86.     // sa is only used to set up events, so it doesn't matter
  87.     // if handles are inherited, and we don't need a Security
  88.     // Descriptor pointer, so we set these as follows:
  89.     sa.bInheritHandle = TRUE;
  90.     sa.lpSecurityDescriptor = NULL;
  91.     // Initialize to some kind of null value the basic class data
  92.     m_stdoutReadHandle = NULL;
  93.     m_stdinWriteHandle = NULL;
  94.     m_charsRead        = 0;
  95.     strcpy(m_readBuffer, "");
  96.     // This creates the event that output is ready 
  97.     // to be read from using getStringText()
  98.     m_processEvent  = CreateEvent(&sa, FALSE, FALSE, "WinProcessEvent");
  99.     // This creates the event that the process is complete
  100.     m_completeEvent = CreateEvent(&sa, FALSE, FALSE, "WinProcessCompleteEvent");
  101.     // This creates the semaphore to serialize reading/writing to m_readBuffer
  102.     m_threadSemaphore = CreateSemaphore(&sa, 0, 1, "WinProcessSemaphore");
  103. }
  104. // Class destructor, closes all open handles
  105. CWinProcess::~CWinProcess()
  106. {
  107.     CloseHandle(m_processEvent);
  108.     CloseHandle(m_completeEvent);
  109.     CloseHandle(m_threadSemaphore);
  110. }
  111. // returns m_processEvent
  112. FXInputHandle CWinProcess::getProcessEventHandle()
  113. {
  114.     return m_processEvent;
  115. }
  116. // returns m_completeEvent
  117. FXInputHandle CWinProcess::getCompleteEventHandle()
  118. {
  119.     return m_completeEvent;
  120. }
  121. // This creates the process with the given command
  122. FXint CWinProcess::createCommandWithPipes(FXString& commandString)
  123. {
  124.     // Handles for creating the pipes
  125.     HANDLE              hTempStdoutRead;
  126.     HANDLE              hTempStdinWrite;
  127.     HANDLE              hStdinRead;
  128.     HANDLE              hStdoutWrite;
  129.     
  130.     // Other variables for the child process and
  131.     // file i/o stuff
  132.     SECURITY_ATTRIBUTES secatt;
  133.     PROCESS_INFORMATION procinfo;
  134.     STARTUPINFO         startinfo;
  135.     BOOL                bOk;
  136.     FXchar*             command;
  137.     // get the command string
  138.     command = (char*)commandString.text();
  139.     
  140.     // Set up the SECURITY_ATTRIBUTES for the stdout/stderr pipe
  141.     // this is the same as we did in the class constructor.
  142.     secatt.nLength              = sizeof(SECURITY_ATTRIBUTES);
  143.     secatt.bInheritHandle       = TRUE;
  144.     secatt.lpSecurityDescriptor = NULL;
  145.     
  146.     // Create a pipe for sending the child stdin
  147.     if (!CreatePipe(&hStdinRead, &hTempStdinWrite, &secatt, 0))
  148.     {
  149.         return -1;  // return an error number for tracking later if needed
  150.     }
  151.     // Create a pipe for getting the child stdout/stderr
  152.     if (! CreatePipe(&hTempStdoutRead, &hStdoutWrite, &secatt, 0))
  153.     {
  154.         return -1;  // return an error number for tracking later if needed
  155.     }
  156.     // Duplicate the write end of the stdin handle, so the handle
  157.     // isn't inherited when the child process is created.
  158.     bOk = DuplicateHandle(GetCurrentProcess(),      // The process with handle to duplicate
  159.                           hTempStdinWrite,          // the actual handle to duplicate
  160.                           GetCurrentProcess(),      // handle of the process to duplicate to
  161.                           &m_stdinWriteHandle,      // pointer to the duplicate handle
  162.                           0,                        // access for duplicate handle
  163.                           FALSE,                    // handle inheritance flag (we don't want to inherit)
  164.                           DUPLICATE_SAME_ACCESS);   // optional actions
  165.     //check if DuplicateHandle() went ok
  166.     if (!bOk)
  167.     {
  168.         return -4;
  169.     }
  170.     // Duplicate the read end of the handle, so funny stuff
  171.     // doesn't happen when reading later.
  172.     // see the comments above for what each field is for
  173.     bOk = DuplicateHandle(GetCurrentProcess(), 
  174.                           hTempStdoutRead,
  175.                           GetCurrentProcess(),
  176.                           &m_stdoutReadHandle,
  177.                           0,
  178.                           FALSE,
  179.                           DUPLICATE_SAME_ACCESS);
  180.     // check if DuplicateHandle() went ok
  181.     if (!bOk)
  182.     {
  183.         return -4;
  184.     }
  185.     
  186.     // close the temporary write stdin handle
  187.     if (!CloseHandle(hTempStdinWrite))
  188.     {
  189.         return -5;
  190.     }
  191.     // Close the temporary read handle
  192.     if (!CloseHandle(hTempStdoutRead))
  193.     {
  194.         return -5;
  195.     }
  196.     // Setup the PROCESS_INFORMATION variable for the
  197.     // child process
  198.     ZeroMemory(&procinfo, sizeof(PROCESS_INFORMATION));
  199.     // Setup the STARTUPINFO variable for the
  200.     // child process
  201.     ZeroMemory(&startinfo, sizeof(STARTUPINFO));    // clear the memory here
  202.     startinfo.cb          = sizeof(STARTUPINFO);    // set the size
  203.     startinfo.dwFlags     = STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;  // flags to use
  204.     startinfo.wShowWindow = SW_HIDE;                // hide the process (we don't want to see it)
  205.     startinfo.hStdInput   = hStdinRead;             // stdin handle
  206.     startinfo.hStdOutput  = hStdoutWrite;           // stdout handle
  207.     startinfo.hStdError   = hStdoutWrite;           // stderr handle
  208.     // Create the child process to execute cdrecord
  209.     if (!CreateProcess(NULL,    // pointer to name of executable module (NULL, we're using command line)
  210.                   command,      // pointer to the command line string we want to execute
  211.                   NULL,         // pointer to process security attributes (we're not using any)
  212.                   NULL,         // pointer to thread security attributes (again, not necessary)
  213.                   TRUE,         // handle inheritance flag (inherit the handles for stdin/stdout/stderr)
  214.                   DETACHED_PROCESS, // creation flags (create the process detached from our own)
  215.                   NULL,         // pointer to new environment block (not using this)
  216.                   NULL,         // pointer to current directory name (just use the programs current directory)
  217.                   &startinfo,   // pointer to STARTUPINFO
  218.                   &procinfo))   // pointer to PROCESS_INFORMATION
  219.     {
  220.         return -6;
  221.     }
  222.     // close the write end of the stdout/stderr pipe,
  223.     CloseHandle(hStdinRead);
  224.     // so we can read from the pipe
  225.     CloseHandle(hStdoutWrite);
  226.     // we don't need the thread or process handles,
  227.     // so let's close them too
  228.     CloseHandle(procinfo.hThread);
  229.     CloseHandle(procinfo.hProcess);
  230.     // start the thread to process I/O
  231.     start();
  232.     // return another error if the thread wouldn't start
  233.     // for some freaky reason
  234.     if (m_status != STARTED)
  235.     {
  236.         return -7;
  237.     }
  238.     
  239.     // Success!
  240.     return 0;
  241. }
  242. // This returns the contents and length of m_readBuffer
  243. // (m_charsRead is the length of m_readBuffer).  
  244. // It also releases the semaphore, so the thread reading the process
  245. // output can continue.
  246. FXint CWinProcess::getStringText(FXString& outputString)
  247. {
  248.     // make sure the string is empty
  249.     outputString.clear();
  250.     
  251.     // append the string in the buffer to the output string
  252.     outputString.append(m_readBuffer);
  253.     
  254.     // let the thread know it can keep getting output
  255.     ReleaseSemaphore(m_threadSemaphore, 1, NULL);
  256.     return 0;
  257. }
  258. // This is the function that will be run in the thread...
  259. void CWinProcess::theThreadFunc(void)
  260. {
  261.     // variables for the read
  262.     BOOL bOk;
  263.     
  264.     // close the input handle
  265.     CloseHandle(m_stdinWriteHandle);
  266.     // loop until we're done getting output
  267.     for(;;)
  268.     {
  269.         // Read from the process' output pipe
  270.         bOk = ReadFile(m_stdoutReadHandle, m_readBuffer, CONSOLE_LINE_SIZE, (DWORD*)(&m_charsRead), NULL);
  271.     
  272.         // if ReadFile() didn't return ok, or if it read zero chars,
  273.         // we're done, so break out of the loop
  274.         if (!bOk || m_charsRead == 0)
  275.         {
  276.             break;
  277.         }
  278.         
  279.         // put a '' at the end of the buffer so it's a terminated string
  280.         // and there aren't funny errors later when reading the string
  281.         m_readBuffer[m_charsRead] = '';
  282.         
  283.         // fire the event that another process/thread/whatever
  284.         // can read the string m_readBuffer
  285.         // If it doesn't work, change the thread status
  286.         if (!SetEvent(m_processEvent))
  287.         {
  288.             m_status = THREAD_ERROR;
  289.         }
  290.         // Now wait for the string to be read before we overwrite it
  291.         WaitForSingleObject(m_threadSemaphore, INFINITE);
  292.         // Reset the values of m_charsRead and m_readBuffer, so we
  293.         // know they can't corrupt anything
  294.         m_charsRead = 0;
  295.         strcpy(m_readBuffer, "");
  296.         
  297.     }
  298.     // We're done with reading output, so close
  299.     // the process' output handle
  300.     CloseHandle(m_stdoutReadHandle);
  301.     // fire the event that the thread is done processing
  302.     // I/O from the process.
  303.     // If it doesn't work, change the thread status to
  304.     // an error.
  305.     if (!SetEvent(m_completeEvent))
  306.     {
  307.         m_status = THREAD_ERROR;
  308.     }
  309.     
  310.     // we're done, so change the thread status
  311.     // to complete.
  312.     m_status = COMPLETED;
  313. }