Advertisement
Advertisement
| 02.07.2008 at 02:47PM PST, ID: 23146285 |
|
[x]
Attachment Details
|
||
|
[x]
The Solution Rating System
|
||
|
With so many solutions, how can you tell which solutions are most likely to help you and which ones are not? To provide you with a tool to use, we rate our solutions based on various elements that most accurately determine if a solution is a quality solution. To explain what factors affect the solution rating, here are the elements we take into consideration when formulating our solution rating.
Your Input Matters If you have any suggestions that you would like to make for our rating system, please ask a question in the Suggestions Zone of Community Support. Thank you! |
||
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227: 228: 229: 230: 231: 232: 233: 234: 235: 236: 237: 238: 239: 240: 241: 242: 243: 244: 245: 246: 247: 248: 249: 250: 251: 252: 253: 254: 255: 256: 257: 258: 259: 260: 261: 262: 263: 264: 265: 266: 267: 268: 269: 270: 271: 272: 273: 274: 275: 276: 277: 278: 279: 280: 281: 282: 283: 284: 285: 286: 287: 288: 289: 290: 291: 292: 293: 294: 295: 296: 297: 298: 299: 300: 301: 302: 303: 304: 305: 306: 307: 308: 309: 310: 311: 312: 313: 314: 315: 316: 317: 318: 319: 320: 321: 322: 323: 324: 325: 326: 327: 328: 329: 330: 331: 332: 333: 334: 335: 336: 337: 338: 339: 340: 341: 342: 343: 344: 345: 346: 347: 348: 349: 350: 351: 352: 353: 354: 355: 356: 357: 358: 359: 360: 361: 362: 363: 364: 365: 366: 367: 368: 369: 370: 371: 372: 373: 374: 375: 376: 377: 378: 379: 380: 381: 382: 383: 384: 385: 386: 387: 388: 389: 390: 391: 392: 393: 394: 395: 396: 397: 398: 399: 400: 401: 402: 403: 404: 405: 406: 407: 408: 409: 410: 411: 412: 413: 414: 415: 416: 417: 418: 419: 420: 421: 422: 423: 424: 425: 426: 427: 428: 429: 430: 431: 432: 433: 434: 435: 436: 437: 438: 439: 440: 441: 442: 443: 444: 445: 446: 447: 448: 449: 450: 451: 452: 453: 454: 455: 456: 457: 458: 459: 460: |
// .h file
#pragma once
#include <string.h>
#include <iostream>
#include <sstream>
#include <stdlib.h>
//#include <windows.h>
#include <afxwin.h>
#include <string.h>
#include <tchar.h>
class Shell
{
public:
Shell();
//int Execute(char* cmd, char* outbuf, char* startDir = NULL);
int Execute(char* cmd, std::string* outstr, char* startDir = NULL);
HANDLE ExecuteAsync(char* cmd, std::string* outstr, char* startDir = NULL);
HANDLE hChildProcess;
HANDLE hStdIn; // Handle to parents std input.
HANDLE hPipeWrite; // Handle to parents std input.
BOOL bRunThread;
std::string str;
//DWORD WINAPI GetAndSendInputThread(LPVOID lpvThreadParam);
void ReadAndHandleOutput(HANDLE hPipeRead);
HANDLE PrepAndLaunchRedirectedChild(char* cmd, HANDLE hChildStdOut,
HANDLE hChildStdIn,
HANDLE hChildStdErr, char* startDir);
void ErrorExit(LPTSTR lpszFunction);
void DebugError(char *pszAPI);
char* _cmd;
std::string* _outstr;
};
struct EXECARGS
{
Shell* Shell;
char* Cmd;
char* StartDir;
std::string* OutStr;
};
//C++ file
#define WINVER 0x0400
#include "Shell.h"
#include <process.h>
/*++
Copyright (c) 1998 Microsoft Corporation
Module Name:
Redirect.c
Description:
This sample illustrates how to spawn a child console based
application with redirected standard handles.
The following import libraries are required:
user32.lib
Dave McPherson (davemm) 11-March-98
--*/
DWORD WINAPI GetAndSendInputThread(LPVOID lpvThreadParam);
Shell::Shell()
{
hChildProcess = NULL;
hStdIn = NULL; // Handle to parents std input.
bRunThread = TRUE;
hPipeWrite = NULL;
}
unsigned int __stdcall ExecuteOnThread(void* lpvThreadParam)
{
EXECARGS* args = (EXECARGS*)lpvThreadParam;
int ret = args->Shell->Execute(args->Cmd,args->OutStr,args->StartDir);
delete args;
return ret;
}
HANDLE Shell::ExecuteAsync(char* cmd, std::string* outstr, char* startDir)
{
EXECARGS* args = new EXECARGS;
args->Shell = this;
args->Cmd = cmd;
args->OutStr = outstr;
args->StartDir = startDir;
unsigned int dwThreadId;
HANDLE hThread = (HANDLE)_beginthreadex(
NULL, // pointer to security attributes
0, // initial thread stack size
ExecuteOnThread, // pointer to thread function
args, // argument for new thread
0, // creation flags (immediate)
&dwThreadId // pointer to receive thread ID
);
return hThread;
}
//outbuf will be assigned new memory, so we must send in an uninitialized pointer
int Shell::Execute(char* cmd, std::string* outstr, char* startDir)
{
HANDLE hProc;
DWORD ret;
#ifdef _DEBUG
printf("Shell: cmd=%s\nShell: startDir=%s\n",cmd,startDir);
#endif
//if we aren't looking for the console output
if( outstr == NULL)
{
printf("Executing with no console capture\n");
hProc = PrepAndLaunchRedirectedChild(cmd,NULL,NULL,NULL,startDir);
ret = STILL_ACTIVE;
do
{
Sleep(200);
GetExitCodeProcess(hProc,&ret);
}
while(ret == STILL_ACTIVE);
return ret;
}
HANDLE hOutputReadTmp,hOutputRead,hOutputWrite;
HANDLE hInputWriteTmp,hInputRead,hInputWrite;
HANDLE hErrorWrite;
HANDLE hThread;
DWORD ThreadId;
SECURITY_ATTRIBUTES sa;
// Set up the security attributes struct.
sa.nLength= sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
// Create the child output pipe.
if (!CreatePipe(&hOutputReadTmp,&hOutputWrite,&sa,0))
DebugError("CreatePipe");
// Create a duplicate of the output write handle for the std error
// write handle. This is necessary in case the child application
// closes one of its std output handles.
if (!DuplicateHandle(GetCurrentProcess(),hOutputWrite,
GetCurrentProcess(),&hErrorWrite,0,
TRUE,DUPLICATE_SAME_ACCESS))
DebugError("DuplicateHandle");
// Create the child input pipe.
if (!CreatePipe(&hInputRead,&hInputWriteTmp,&sa,0))
DebugError("CreatePipe");
// Create new output read handle and the input write handles. Set
// the Properties to FALSE. Otherwise, the child inherits the
// properties and, as a result, non-closeable handles to the pipes
// are created.
if (!DuplicateHandle(GetCurrentProcess(),hOutputReadTmp,
GetCurrentProcess(),
&hOutputRead, // Address of new handle.
0,FALSE, // Make it uninheritable.
DUPLICATE_SAME_ACCESS))
DebugError("DupliateHandle");
if (!DuplicateHandle(GetCurrentProcess(),hInputWriteTmp,
GetCurrentProcess(),
&hInputWrite, // Address of new handle.
0,FALSE, // Make it uninheritable.
DUPLICATE_SAME_ACCESS))
DebugError("DupliateHandle");
// Close inheritable copies of the handles you do not want to be
// inherited.
if (!CloseHandle(hOutputReadTmp)) DebugError("CloseHandle");
if (!CloseHandle(hInputWriteTmp)) DebugError("CloseHandle");
// Get std input handle so you can close it and force the ReadFile to
// fail when you want the input thread to exit.
if ( (hStdIn = GetStdHandle(STD_INPUT_HANDLE)) ==
INVALID_HANDLE_VALUE )
DebugError("GetStdHandle");
hProc = PrepAndLaunchRedirectedChild(cmd,hOutputWrite,hInputRead,hErrorWrite,startDir);
if(!hProc)
{
#ifdef _DEBUG
printf("Shell: Error PrepAndLaunchRedirectChild\n");
#endif
return -1;
}
// Close pipe handles (do not continue to modify the parent).
// You need to make sure that no handles to the write end of the
// output pipe are maintained in this process or else the pipe will
// not close when the child process exits and the ReadFile will hang.
if (!CloseHandle(hOutputWrite)) DebugError("CloseHandle");
if (!CloseHandle(hInputRead )) DebugError("CloseHandle");
if (!CloseHandle(hErrorWrite)) DebugError("CloseHandle");
if(1) // != NULL)
{
// Launch the thread that gets the input and sends it to the child.
hPipeWrite = hInputWrite;
// hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)GetAndSendInputThread,
// (LPVOID)hInputWrite,0,&ThreadId);
//TODO: change to _createthread
hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)GetAndSendInputThread,
(LPVOID)this,0,&ThreadId);
if (hThread == NULL) DebugError("CreateThread");
// Read the child's output.
str = "";
ReadAndHandleOutput(hOutputRead);
// Redirection is complete
*outstr = str;
// Force the read on the input to return by closing the stdin handle.
//this is causing a problem.. so just ignore it and it will go away!
if (!CloseHandle(hStdIn)) DebugError("CloseHandle");
// Tell the thread to exit and wait for thread to die.
bRunThread = FALSE;
if (WaitForSingleObject(hThread,INFINITE) == WAIT_FAILED)
DebugError("WaitForSingleObject");
if (!CloseHandle(hOutputRead)) DebugError("CloseHandle");
if (!CloseHandle(hInputWrite)) DebugError("CloseHandle");
}
ret = STILL_ACTIVE;
do
{
Sleep(200);
GetExitCodeProcess(hProc,&ret);
}
while(ret == STILL_ACTIVE);
#ifdef _DEBUG
printf("Shell: terminated properly\n");
#endif
return ret;
}
///////////////////////////////////////////////////////////////////////
// PrepAndLaunchRedirectedChild
// Sets up STARTUPINFO structure, and launches redirected child.
///////////////////////////////////////////////////////////////////////
HANDLE Shell::PrepAndLaunchRedirectedChild(char* cmd, HANDLE hChildStdOut,
HANDLE hChildStdIn,
HANDLE hChildStdErr, char* startDir)
{
PROCESS_INFORMATION pi;
STARTUPINFO si;
// Set up the start up info struct.
ZeroMemory(&si,sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
si.hStdOutput = hChildStdOut;
si.hStdInput = hChildStdIn;
si.hStdError = hChildStdErr;
// Use this if you want to hide the child:
si.wShowWindow = SW_HIDE;
// Note that dwFlags must include STARTF_USESHOWWINDOW if you want to
// use the wShowWindow flags.
// Launch the process that you want to redirect (in this case,
// Child.exe). Make sure Child.exe is in the same directory as
// redirect.c launch redirect from a command line to prevent location
// confusion.
// if (!CreateProcess(NULL,"dir",NULL,NULL,TRUE,
// CREATE_NEW_CONSOLE,NULL,NULL,&si,&pi))
// DebugError("CreateProcess");
//LPTSTR szCmdline=TEXT("c:\\windows\\system32\\ipconfig.exe");
SECURITY_ATTRIBUTES sa;
//ZeroMemory(&sa,sizeof(SECURITY_ATTRIBUTES));
sa.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR) malloc(SECURITY_DESCRIPTOR_MIN_LENGTH);
InitializeSecurityDescriptor(sa.lpSecurityDescriptor, PROCESS_QUERY_INFORMATION);
SetSecurityDescriptorDacl(sa.lpSecurityDescriptor,TRUE,(PACL) NULL,FALSE);
//sa.lpSecurityDescriptor = PROCESS_QUERY_INFORMATION;
sa.bInheritHandle = 1;
sa.nLength = sizeof(sa);
char* startDirParam = startDir;
if(startDir == 0)
startDirParam = 0;
else
{
if(strlen(startDir) == 0) //strlen throws exception if startDir == 0
startDirParam = 0;
}
// BOOL procCreated = CreateProcess(NULL, cmd, NULL, 0, 1, CREATE_NO_WINDOW, 0, startDirParam, &si, &pi);
BOOL procCreated = CreateProcess(NULL, cmd, NULL, 0, 1, 0, 0, startDirParam, &si, &pi);
if(!procCreated)
{
#ifdef _DEBUG
CString debugStr;
LPVOID lpMsgBuf;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL );
debugStr.Format("Shell CreateProc: %u, %s",dw,lpMsgBuf);
OutputDebugString(debugStr.GetBuffer());
printf("%s\n",debugStr.GetBuffer());
#endif
}
delete sa.lpSecurityDescriptor; //because of malloc
if(!procCreated)
DebugError("CreateProcess");
// Set global child process handle to cause threads to exit.
hChildProcess = pi.hProcess;
// Close any unnecessary handles.
if (!CloseHandle(pi.hThread)) DebugError("CloseHandle");
return hChildProcess;
}
///////////////////////////////////////////////////////////////////////
// ReadAndHandleOutput
// Monitors handle for input. Exits when child exits or pipe breaks.
///////////////////////////////////////////////////////////////////////
void Shell::ReadAndHandleOutput(HANDLE hPipeRead)
{
CHAR lpBuffer[256];
DWORD nBytesRead;
while(TRUE)
{
BOOL readS = ReadFile(hPipeRead,lpBuffer,sizeof(lpBuffer),
&nBytesRead,NULL);
if (!readS)
{
if (GetLastError() == ERROR_BROKEN_PIPE)
break; // pipe done - normal exit path.
else
DebugError("ReadFile"); // Something bad happened.
}
str.append(lpBuffer,nBytesRead);
}
}
///////////////////////////////////////////////////////////////////////
// GetAndSendInputThread
// Thread procedure that monitors the console for input and sends input
// to the child process through the input pipe.
// This thread ends when the child application exits.
///////////////////////////////////////////////////////////////////////
DWORD WINAPI GetAndSendInputThread(LPVOID lpvThreadParam)
{
CHAR read_buff[256];
DWORD nBytesRead,nBytesWrote;
//HANDLE hPipeWrite = (HANDLE)lpvThreadParam;
Shell* tthis = (Shell*)lpvThreadParam;
// Get input from our console and send it to child through the pipe.
while (tthis->bRunThread)
{
nBytesRead = 0;
BOOL readS = ReadConsole(tthis->hStdIn,read_buff,1,&nBytesRead,NULL);
if(!readS)
{
break;
//DebugError("ReadConsole");
}
read_buff[nBytesRead] = '\0'; // Follow input with a NULL.
if (!WriteFile(tthis->hPipeWrite,read_buff,nBytesRead,&nBytesWrote,NULL))
{
if (GetLastError() == ERROR_NO_DATA)
break; // Pipe was closed (normal exit path).
else
tthis->DebugError("WriteFile");
}
}
return 1;
}
void Shell::DebugError(char *pszAPI)
{
LPVOID lpvMessageBuffer;
CHAR szPrintBuffer[512];
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpvMessageBuffer, 0, NULL);
wsprintf(szPrintBuffer,
"ERROR: API = %s.\n error code = %d.\n message = %s.\n",
pszAPI, GetLastError(), (char *)lpvMessageBuffer);
OutputDebugString(szPrintBuffer);
LocalFree(lpvMessageBuffer);
}
void Shell::ErrorExit(LPTSTR lpszFunction)
{
LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL );
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
(lstrlen((LPCTSTR)lpMsgBuf)+lstrlen((LPCTSTR)lpszFunction)+40)*sizeof(TCHAR));
wsprintf((LPTSTR)lpDisplayBuf,
TEXT("%s failed with error %d: %s"),
lpszFunction, dw, lpMsgBuf);
MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);
LocalFree(lpMsgBuf);
LocalFree(lpDisplayBuf);
ExitProcess(dw);
}
|