Wide
String Handling in Windows
Before we discuss the handling of multiple processes in Windows, it is
necessary to have a short discussion of the handling of strings.
Since Windows NT 4, Windows has used Unicode as its
default text encoding format. Unicode defines support for greater than 8-bit
encoding of characters. Windows uses UTF-16 format, known as wide character encoding, which uses two
bytes per character. Many Windows functions are defined with two entry points:
a Unicode version that has a W appended, for wide character, or an ANSI
character entry point that is appended with an A. For example, the CreateMutex() function call has a supporting CreateMutexW() and a CreateMutexA(). At
compile time, the appropriate function call will be made depending on whether UNICODE is defined. Since Windows uses wide characters inter-nally, the ANSI
entry points are just wrappers around the wide versions of the function calls
with appropriate string conversion.
The 16-bit character type is wchar_t. This can be used as a replacement for the char type. WCHAR is an equivalent method of specifying a wide string.
However, strings of characters in source code are interpreted as being ANSI
8-bit characters, which is why they need to be specified as being wide
characters. This can be performed using the L specifier or using the TEXT() macro,
as demonstrated in Listing 6.24. We will need to use these macros in later
examples when we specify string constants.
Listing 6.24 Assigning
a Compile-Time Value to a Wide Character String
wchar_t mystring1[] = L"Some text";
WCHAR mystring2[] = TEXT("More text");
The TEXT() macro is useful in that when UNICODE is defined, it translates a string to wide character format. When UNICODE is not defined, it leaves the string as ANSI 8-bit text. The TCHAR type
behaves in a similar way, resolving to wchar_t when UNICODE is
defined, or char
otherwise.
Some functions are defined as macros that resolve
differently depending on whether UNICODE is defined. For example, the main function _tmain() resolves either to wmain() when
UNICODE is defined or to
main() otherwise. Similarly,
_tprintf() will
either resolve to wprintf() or printf().
Creating
Processes
To create a new process, the first process calls CreateProcess(), which takes a number of parameters. The three critical parameters are
the name (and any parameters) of the process to be run, together with a pointer
to a STARTUPINFO
structure and a PROCESS_ INFORMATION
structure. Table 6.4 shows the full parameters to
this function.
Table 6.4 Parameters
Passed to CreateProcess()
The first parameter is the application name, and
the second parameter is the com-mand line. These two parameters work together.
If either is null, the other is used as the entire command line. Otherwise, the
application named by the first argument is executed but passed the command line
given by the second argument. This means that the first parameter of the
command line should be a repeat of the name of the application.
There are two further considerations: The Unicode
version of this function, CreateProcessW(), is
called, and the command line can be modified; hence, it should
always be stored in a variable rather than a
constant string. Second, if the application name is null, then the application
executed will be the first whitespace-delimited text in the command line. If
the path to the application contains a space, then the entire path and name
should be enclosed in quotes.
The third and fourth parameters are optional
pointers to SECURITY_ATTRIBUTES. The
first gives the attributes for the created process, and the second of these is
attributes for the first thread of the created process. These attributes
principally determine whether child processes of the created process will
inherit any handles owned by the created process. A null value for these pointers
provides the created process with the default attributes.
Both the STARTUPINFO and PROCESS_INFORMATION
structures should be zero-filled before the call. The cb member of the STARTUPINFO
structure needs to be set to the size of the structure. The call to CreateProcess() will record information in these struc-tures. The most important
information will be the handle of the new process that is recorded in the hProcess member of the PROCESS_INFORMATION
structure.
Listing 6.25 shows the steps necessary to create a
new process. If the application is started with a command-line parameter, the
process will print this out and then create a child process without any
parameters. If the process is started without any parameters, it prints out a
message indicating this and exits.
Listing 6.25 Starting
a New Process
#include
<Windows.h>
int
_tmain( int argc, _TCHAR* argv[] )
{
STARTUPINFO startup_info;
PROCESS_INFORMATION process_info;
if ( argc>1 )
{
wprintf( L"Argument %s\n", argv[1] );
wprintf( L"Starting child process\n" );
ZeroMemory( &process_info, sizeof(process_info)
); ZeroMemory( &startup_info, sizeof(startup_info) ); startup_info.cb =
sizeof(startup_info);
if (CreateProcess( argv[0], 0, 0,
0, 0, 0, 0, 0,
&startup_info,
&process_info )==0 )
{
printf( "ERROR %i\n", GetLastError() );
}
WaitForSingleObject( process_info.hProcess, INFINITE );
}
else
{
printf( "No arguments\n" );
}
getchar();
}
The handle of the created process is returned in process_info.hProcess. This handle is used in the call to WaitForSingleObject(). This call returns when the child process exits.
The call to getchar() at the
end of the code is there to wait for the Enter key to be pressed before the
process exits.
To pass arguments to a child process, it is necessary to repeat the
application name as the first command-line parameter. The entire command line
gets passed to the child process. Listing 6.26 shows the situation where the
child process is started with a single additional argument.
Listing 6.26 Passing
Arguments to a New Process
#include <Windows.h>
int _tmain( int argc, _TCHAR* argv[] )
{
STARTUPINFO startup_info;
PROCESS_INFORMATION process_info;
if ( argc==1 )
{
printf( "No arguments given starting child process\n" );
wchar_t
argument[256];
wsprintf(
argument, L"\"%s\" Hello", argv[0] );
ZeroMemory( &process_info, sizeof(process_info)
); ZeroMemory( &startup_info, sizeof(startup_info) ); startup_info.cb =
sizeof(startup_info);
if (CreateProcess( argv[0], argument, 0, 0, 0, 0, 0, 0,
&startup_info, &process_info )==0 )
{
printf( "ERROR %i\n", GetLastError() );
}
WaitForSingleObject( process_info.hProcess, INFINITE );
}
else
{
wprintf( L"Argument %s\n", argv[1] );
}
getchar();
}
Related Topics
Privacy Policy, Terms and Conditions, DMCA Policy and Compliant
Copyright © 2018-2023 BrainKart.com; All Rights Reserved. Developed by Therithal info, Chennai.