WINDOWS pipeline technology
DETROX
I don't know if you have used this program, and they don't decompress the function, but call the DOS program PKZIP to complete the decompression of the ZIP package. However, in the program running, there is no window of the DOS console and everything should appear in the information displayed under the DOS. This design is beautiful and prevents minority, fast users, and close your DOS window in advance. Now let's discuss how this feature is implemented with anonymous pipeline technology.
The pipeline technology has been long, and it is believed that many people are most familiar with pipe technology in the DOS command. When we want a file, if you want him to page the reality, you can enter
C: /> Type Autoexec.bat | More
Here "|" is the pipe operator. He is used by TYPE output as a read end, which is the pipeline established by the written end of the input.
More pipelines used in Windows are also anonymous pipes, which is created via the API function CreatePipe.
BOOL CREATEPIPE
Phandle Hreadpipe, // Pointer to the read end handle
Phandle hwritepipe, // Pointer to the write end handle
LPSecurity_Attributes LPPIPEATTRIBUTES, / / Pointer to the security attribute structure
DWORD NSIZE // Pipeline capacity
);
In the above parameters, you should pay attention to hreadpipe, hwritepipe is a pointer to the handle, not a handle (I am wrong when I first used it). Nsize is generally specified as 0 to allow the system to determine the capacity of the pipe. Now see the security attribute structure, security_attributes.
Typedef struct _security_attributes {// SA
DWord NLENGTH;
LPVOID LPSECURITYDESCRIPTOR;
Bool binherithandle;
Security_attribute;
NLENGTH is the size of the structure, naturally it is obtained with SizeOf. LPSecurityDescriptor is a security descriptor (a string of a C-style). BinheritHandle He pointed out if the security described object can be inherited by the newly created process. Don't worry about their specific meaning, you will naturally know when you use it.
Ok, let's create a pipeline now.
Handle Hreadpipe, HWritePipe;
Security_attributes sa;
Sa.nlength = sizeof (security_attributes);
sa.lpsecurityDescriptor = null; // Using the system default security descriptor
sa.binherithandle = true; / / must be true, otherwise the handle cannot be inherited.
CreeaTepipe (& Hreadpipe, & HWritePipe, & Sa, 0);
OK, our pipeline is built. Of course, this is not the ultimate goal, our purpose is to redirect what the program on DOS is redirected to an Edit control of a Windows program. So we also need to start a DOS program first, but you can't show the window of the DOS console (otherwise not stuffing). We create a DOS program with CreateProcesss.
Bool createprocess
LPCTSTSTR LPAPPLICATIONNAME, / / C-Style string: the name of the application
LPTSTR LPCOMMANDLINE, / / C-Style string: executed command
LPSecurity_attributes lpprocessattributes, // Process security properties
LPSecurity_attributes lpthreadattributes, // thread security properties
Bool binherithandles, // Whether to inherit the handle of the handle DWORD dwcreationFlags, // creation flag
LPVOID LPENVIRONMENT, / / C-Style string: Environment settings
LPCTSTR LPCURRENTDIRECTORY, / / C-Style string: Execute Directory
LPStartupInfo lpstartupinfo, // Start information
LPPROCESS_INFORMATION LPPROCESSINFORMATION / / Process Information
);
Don't walk, the parameters are more, but most of you need to fill yourself if you don't fill a null. LPApplication is just a bit. LPCommandline, but the command you want to execute must be written seriously. Come, we look at LPProcessAttributes and LPTHREADATTRIBUTES how to set it. Hey? Isn't this just that? For A, but it is simpler than just. Because we just create a process, he can be inherited, so these two values are NULL. BinheritHandles is also a must set to True, because we must let the new process can output information to the process of calling his process, you must let the new process inherit the handle of the process. We don't have anything else to create, so DWCREATIONFLAGS is NULL. LpenVironment and LPCurrentDirectory are finished according to your own request, usually null. The next LPStartupinfo is the key, we have to look at it seriously.
Typedef struct _startupinfo {// si
DWORD CB;
LPTSTR LPRESERVED;
LPTSTR LPDESKTOP;
LPTSTR LPTITLE;
DWORD DWX;
DWORD DWY;
DWORD DWXSIZE;
DWORD DWYSIZE;
DWORD DWXCOUNTCHARS;
DWORD DWYCOUNTCHARS;
DWORD DWFILLATTRIBUTE;
DWORD DWFLAGS;
Word wshowwindow;
Word cbreserved2;
LPBYTE LPRESERVED2;
Handle hstdinput;
Handle hstdoutput;
Handle hstderror;
} Startupinfo, * lpstartupinfo;
inverted! So many parameters, a one is sure to die. Yes, MS has long thought of being exhausted. So providing the API function GetStartupinfo, a rescued life.
Void getStartupinfo
LPstartupinfo LPStartupinfo
);
This function is used to get the StartupInfo of the current process. Our new process base root is almost the startupinfo of the current process, just borrow it. Then make a small modification.
There are such a few places we have to change: CB, DWFLAGS, HSTDOUTPUT, HSTDERROR, WSHOWINDOW. Let's talk about CB, he refers to the size of Startupinfo, or the old manifests SIZEOF. Besides WshowWindow, he has developed a realistic state of the window when the new process is created, this property is of course given SW_HIDE, isn't we hide the newly built DOS process? Haha, see HSTDOUTPUT and HSTDERROR, standard output and error output handles. The key place is here, as long as we set these two handles to hwrite, once our process has standard output, we will write to our anonymous pipeline that we have just established, we use the pipe's HREADPIPE handle to read the content Is it going to achieve our goal? Oh, it's really easy to say it. These few key parameters have been completed, don't forget DWFLAGS. He is used to develop this pile of parameters in StartupInfo. Since we use HSTDOUTPUT, HSTDERROR and WSHOWINDOW That DWFLAGS is given to Startf_useshowWindow | Startf_usestDHandles. Ok, now go back to the last parameter of CreateProcess LPProcessInformation (Tired!). Oh, this parameter does not need to be filled with himself. He is the information returned by CreateProcess, as long as it gives him an address of a process_information structure.
Maximic is high, and the pipeline is connected to the standard output of the new process, and one end can be read with the API function readfile. Wait, wrong, our pipeline has problems. We gave HWRITE to HSTDOUTPUT and HSTDERROR, then open a pipe writing in the new process when the new process starts, and we use createPipe in the current process to create a pipe, then there is this in the current process. The write end of the pipe is hwrite. Ok, there is a deformity pipe with two writes and a read-out end here. Such pipes must have problems. Since the current process does not use the write, we must turn off the writing of the current process. In this way, our pipeline is really successful. To see the source program written by VC :
/ *
* Enter the DIR /? Help from the CEDIT control of the MFC application through pipe technology.
* VC 6.0 WinXP pass
*
* DETROX, 2003
* /
Void cpipedlg :: onbutton1 ()
{
Security_attributes sa;
Handle Hread, hwrite;
Sa.nlength = sizeof (security_attributes);
Sa.lpsecurityDescriptor = null;
Sa.binherithandle = true;
IF (! Cread, & Hwrite, & Sa, 0)) {
"" ERROR On CREATEPIPE () ");
Return;
}
Startupinfo Si;
Process_information pi;
Si.cb = sizeof (startupinfo);
GetStartupInfo (& Si);
Si.hstderRor = hwrite;
Si.hstdoutput = hwrite;
Si.WShowWindow = sw_hide;
Si.dwflags = startf_useshowwindow | startf_usestdhandles; if (! createprocess (null, "c: //windows//system32//cmd.exe/c DIR /?"
, NULL, NULL, TRUE, NULL, NULL, NULL, & Si, & PI) {
"" Error On CreateProcess () ");
Return;
}
CloseHandle (HWRITE);
CHAR BUFFER [4096] = {0};
DWORD BYTESREAD;
While (true) {
IF (readfile (Hread, Buffer, 4095, & Bytesread, NULL) == NULL)
Break;
m_edit1 = buffer;
Updatedata (FALSE);
Sleep (200);
}
}