Chinaunix首页 | 论坛 | 博客
  • 博客访问: 381419
  • 博文数量: 715
  • 博客积分: 40000
  • 博客等级: 大将
  • 技术积分: 5005
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-13 14:46
文章分类

全部博文(715)

文章存档

2011年(1)

2008年(714)

我的朋友

分类:

2008-10-13 16:31:39

        近来感觉在VCKBASE上有点手脚不勤,有些惭愧!有人问到关于cmd.exe的问题,希望能够对它的输入命令进行过滤。个人觉得如果从深度考虑还是有些难度的,毕竟在windows下,命令行窗口的消息流是不可访问的。所以也不可以用钩子等类似的机制进行处理。其实对于一般要求不高的实现来说,完全可以通过对cmd.exe的输入输入进行控制,实在对输入进行过滤同时还保留住cmd.exe的大部分功能。今天是周未,睡醒之后,觉得回问题应该用点心,所以花了个把小时写下了下面这段例子代码,顺便改掉手脚不勤的坏习惯^_^!

//=======================================
// Description: A sample to show how to filter cmd.exe
// Author     : Hercules Zeng
// Emailto    :

#include "stdafx.h"
#include
#include

#define BUFF_SIZE 16384 //16K
HANDLE g_hCmdStdinRead;
HANDLE g_hCmdStdinWrite;
HANDLE g_hCmdStdinWriteDup;
HANDLE g_hChildStdoutRead;
HANDLE g_hChildStdoutWrite;
HANDLE g_hChildStdoutReadDup;
HANDLE g_hInputHandle;
HANDLE g_hBackupStdin;
HANDLE g_hBackupStdout;

//----------------------------------------------------------------------------
void ErrorExit (LPTSTR lpszMessage)
{
 fprintf(stderr, "%s\n", lpszMessage);
 ExitProcess(0);
}

//----------------------------------------------------------------------------
BOOL CheckCmd(char* pBuffer)
{
 if(strcmp(pBuffer, "exit\r\n") == 0)
 {  
  ExitProcess(0);   
 }
 return TRUE;
}

//----------------------------------------------------------------------------
int EnterInfoCMD(void)
{
 DWORD dwReadCnt;
 DWORD dwWriteCnt;
 CHAR cBuffer[BUFF_SIZE];
 int  nCmdLen;

 memset(cBuffer, 0, BUFF_SIZE);
 if (! WriteFile(g_hCmdStdinWriteDup, cBuffer, strlen(cBuffer),
  &dwWriteCnt, NULL))
  return -1;
 Sleep(300);
 if( !ReadFile( g_hChildStdoutReadDup, cBuffer, BUFF_SIZE, &dwReadCnt,
  NULL) || dwReadCnt == 0) return -1;
 if (! WriteFile(g_hBackupStdout, cBuffer, dwReadCnt, &dwWriteCnt, NULL))
  return -1; 

 // Read from a file and write its contents to a pipe.
 for (;;)
 {
  memset(cBuffer, 0, BUFF_SIZE);
  if (! ReadFile(g_hInputHandle, cBuffer, BUFF_SIZE, &dwReadCnt, NULL) ||
   dwReadCnt == 0)
   break;
  // Add check-method here
  CheckCmd(cBuffer);
  nCmdLen = strlen(cBuffer);
  if (! WriteFile(g_hCmdStdinWriteDup, cBuffer, dwReadCnt,
   &dwWriteCnt, NULL)) break;

  BOOL bStripCmd = TRUE;
  for(;;)
  { 
   Sleep(300);
   memset(cBuffer, 0, BUFF_SIZE);
   if( !ReadFile( g_hChildStdoutReadDup, cBuffer, BUFF_SIZE, &dwReadCnt,
    NULL) || dwReadCnt == 0) break;

   if(bStripCmd)
   {
    if (! WriteFile(g_hBackupStdout, cBuffer + nCmdLen, dwReadCnt - nCmdLen, &dwWriteCnt, NULL))
     break;
   }
   else
   {
    if (! WriteFile(g_hBackupStdout, cBuffer, dwReadCnt, &dwWriteCnt, NULL))
     break;
   }
   bStripCmd = FALSE;
   if(cBuffer[dwReadCnt - 1] == '>')
    break;     
  }
 }

 // Close the pipe handle so the child process stops reading.
 if (! CloseHandle(g_hCmdStdinWriteDup))
  ErrorExit("Close pipe failed\n");

 return 0;
}

//----------------------------------------------------------------------------
BOOL CreateCMDProcess()
{  
 PROCESS_INFORMATION piProcInfo;
 STARTUPINFO siStartInfo;
 BOOL bRtn = FALSE;
 ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
 ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
 siStartInfo.cb = sizeof(STARTUPINFO);

 // Create the child process.
 TCHAR tcsExename[MAX_PATH];
 TCHAR tcsParam[MAX_PATH * 2];
 TCHAR tcsCmd[MAX_PATH];
 if( 0 == GetModuleFileName(NULL, tcsExename, MAX_PATH)
  ||  0 == GetEnvironmentVariable(_T("COMSPEC"), tcsCmd, MAX_PATH))
  return FALSE;

 // get short filename for command shell program
 if( 0 == GetShortPathName(tcsExename, tcsExename, MAX_PATH))
  return FALSE;

 bRtn = CreateProcess(NULL,
  tcsCmd,       // command line
  NULL,          // process security attributes
  NULL,          // primary thread security attributes
  TRUE,          // handles are inherited
  0,             // creation flags
  NULL,          // use parent's environment
  NULL,          // use parent's current directory
  &siStartInfo,  // STARTUPINFO pointer
  &piProcInfo);  // receives PROCESS_INFORMATION

 if (bRtn == 0)
 {
  ErrorExit("CreateProcess failed\n");
  return FALSE;
 }
 else
 {
  CloseHandle(piProcInfo.hProcess);
  CloseHandle(piProcInfo.hThread);
  return bRtn;
 }
}

//----------------------------------------------------------------------------
DWORD main()
{
 SECURITY_ATTRIBUTES saAttr;
 BOOL fSuccess;
 // Set the bInheritHandle flag so pipe handles are inherited.
 saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
 saAttr.bInheritHandle = TRUE;
 saAttr.lpSecurityDescriptor = NULL;

 // The steps for redirecting child process's STDOUT:
 //     1. Save current STDOUT, to be restored later.
 //     2. Create anonymous pipe to be STDOUT for child process.
 //     3. Set STDOUT of the parent process to be write handle to
 //        the pipe, so it is inherited by the child process.
 //     4. Create a noninheritable duplicate of the read handle and
 //        close the inheritable read handle.

 // Save the handle to the current STDOUT.
 g_hBackupStdout = GetStdHandle(STD_OUTPUT_HANDLE);

 // Create a pipe for the child process's STDOUT.
 if (! CreatePipe(&g_hChildStdoutRead, &g_hChildStdoutWrite, &saAttr, 0))
  ErrorExit("Stdout pipe creation failed\n");

 // Set a write handle to the pipe to be STDOUT.
 if (! SetStdHandle(STD_OUTPUT_HANDLE, g_hChildStdoutWrite))
  ErrorExit("Redirecting STDOUT failed");

 // Create noninheritable read handle and close the inheritable read
 // handle.

 fSuccess = DuplicateHandle(GetCurrentProcess(), g_hChildStdoutRead,
  GetCurrentProcess(), &g_hChildStdoutReadDup , 0,
  FALSE,
  DUPLICATE_SAME_ACCESS);
 if( !fSuccess )
  ErrorExit("DuplicateHandle failed");
 CloseHandle(g_hChildStdoutRead);

 // The steps for redirecting child process's STDIN:
 //     1.  Save current STDIN, to be restored later.
 //     2.  Create anonymous pipe to be STDIN for child process.
 //     3.  Set STDIN of the parent to be the read handle to the
 //         pipe, so it is inherited by the child process.
 //     4.  Create a noninheritable duplicate of the write handle,
 //         and close the inheritable write handle.

 // Save the handle to the current STDIN.
 g_hBackupStdin = GetStdHandle(STD_INPUT_HANDLE);

 // Create a pipe for the child process's STDIN.
 if (! CreatePipe(&g_hCmdStdinRead, &g_hCmdStdinWrite, &saAttr, 0))
  ErrorExit("Stdin pipe creation failed\n");

 // Set a read handle to the pipe to be STDIN.
 if (! SetStdHandle(STD_INPUT_HANDLE, g_hCmdStdinRead))
  ErrorExit("Redirecting Stdin failed");

 // Duplicate the write handle to the pipe so it is not inherited.
 fSuccess = DuplicateHandle(GetCurrentProcess(), g_hCmdStdinWrite,
  GetCurrentProcess(), &g_hCmdStdinWriteDup, 0,
  FALSE,                  // not inherited
  DUPLICATE_SAME_ACCESS);
 if (! fSuccess)
  ErrorExit("DuplicateHandle failed");

 CloseHandle(g_hCmdStdinWrite);

 // Now create the child process.
 fSuccess = CreateCMDProcess();
 if (! fSuccess)
  ErrorExit("Create process failed");

 // After process creation, restore the saved STDIN and STDOUT.
 if (! SetStdHandle(STD_INPUT_HANDLE, g_hBackupStdin))
  ErrorExit("Re-redirecting Stdin failed\n");

 if (! SetStdHandle(STD_OUTPUT_HANDLE, g_hBackupStdout))
  ErrorExit("Re-redirecting Stdout failed\n");

 // Get a handle to the parent's input file.
 g_hInputHandle = g_hBackupStdin;

 if (g_hInputHandle == INVALID_HANDLE_VALUE)
  ErrorExit("no input file\n");

 EnterInfoCMD();
 return 0;
}

 


--------------------next---------------------

阅读(206) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~