windows-nt/Source/XPSP1/NT/base/ntsetup/win95upg/tools/pipe/pipe.c

487 lines
8.7 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1998 Microsoft Corporation
Module Name:
pipe.c
Abstract:
Implements IPC pipe to support migisol.exe.
Author:
Jim Schmidt (jimschm) 21-Sept-1998
Revision History:
<full name> (<alias>) <date> <comments>
--*/
#include "pch.h"
HANDLE g_hHeap;
HINSTANCE g_hInst;
static PCTSTR g_Mode;
static HANDLE g_ProcessHandle;
static BOOL g_Host;
VOID
pCloseIpcData (
VOID
);
BOOL
pOpenIpcData (
VOID
);
BOOL
pCreateIpcData (
IN PSECURITY_ATTRIBUTES psa
);
BOOL WINAPI MigUtil_Entry (HINSTANCE, DWORD, PVOID);
VOID
pTestPipeMechanism (
VOID
);
BOOL
pCallEntryPoints (
DWORD Reason
)
{
HINSTANCE Instance;
//
// Simulate DllMain
//
Instance = g_hInst;
//
// Initialize the common libs
//
if (!MigUtil_Entry (Instance, Reason, NULL)) {
return FALSE;
}
return TRUE;
}
BOOL
Init (
VOID
)
{
g_hHeap = GetProcessHeap();
g_hInst = GetModuleHandle (NULL);
return pCallEntryPoints (DLL_PROCESS_ATTACH);
}
VOID
Terminate (
VOID
)
{
pCallEntryPoints (DLL_PROCESS_DETACH);
}
VOID
HelpAndExit (
VOID
)
{
//
// This routine is called whenever command line args are wrong
//
_ftprintf (
stderr,
TEXT("Command Line Syntax:\n\n")
TEXT(" pipe/F:file]\n")
TEXT("\nDescription:\n\n")
TEXT(" PIPE is a test tool of the IPC mechanism for migration\n")
TEXT(" DLLs.\n")
TEXT("\nArguments:\n\n")
TEXT(" (none)\n")
);
exit (1);
}
OUR_CRITICAL_SECTION g_cs;
CHAR g_Buf[2048];
VOID
Dump (
PCSTR Str
)
{
EnterOurCriticalSection (&g_cs);
printf ("%s\n", Str);
LeaveOurCriticalSection (&g_cs);
}
INT
__cdecl
_tmain (
INT argc,
PCTSTR argv[]
)
{
INT i;
PCTSTR FileArg;
InitializeOurCriticalSection (&g_cs);
for (i = 1 ; i < argc ; i++) {
if (argv[i][0] == TEXT('/') || argv[i][0] == TEXT('-')) {
switch (_totlower (_tcsnextc (&argv[i][1]))) {
case TEXT('f'):
//
// Sample option - /f:file
//
if (argv[i][2] == TEXT(':')) {
FileArg = &argv[i][3];
} else if (i + 1 < argc) {
FileArg = argv[++i];
} else {
HelpAndExit();
}
break;
default:
HelpAndExit();
}
} else {
//
// Parse other args that don't require / or -
//
// None
HelpAndExit();
}
}
//
// Begin processing
//
if (!Init()) {
return 0;
}
pTestPipeMechanism();
//
// End of processing
//
Terminate();
return 0;
}
BOOL
pOpenIpcA (
IN BOOL Win95Side,
IN PCSTR ExePath, OPTIONAL
IN PCSTR MigrationDllPath, OPTIONAL
IN PCSTR WorkingDir OPTIONAL
)
/*++
Routine Description:
OpenIpc has two modes of operation, depending on who the caller is. If the
caller is w95upg.dll or w95upgnt.dll, then the IPC mode is called "host mode."
If the caller is migisol.exe, then the IPC mode is called "remote mode."
In host mode, OpenIpc creates all of the objects necessary to implement
the IPC. This includes two events, DoCommand and GetResults, and a
file mapping. After creating the objects, the remote process is launched.
In remote mode, OpenIpc opens the existing objects that have already
been created.
Arguments:
Win95Side - Used in host mode only. Specifies that w95upg.dll is running
when TRUE, or that w95upgnt.dll is running when FALSE.
ExePath - Specifies the command line for migisol.exe. Specifies NULL
to indicate remote mode.
MigrationDllPath - Used in host mode only. Specifies the migration DLL
path. Ignored in remote mode.
WorkingDir - Used in host mode only. Specifies the working directory path
for the migration DLL. Ignored in remote mode.
Return value:
TRUE if the IPC channel was opened. If host mode, TRUE indicates that
migisol.exe is up and running. If remote mode, TRUE indicates that
migisol is ready for commands.
--*/
{
CHAR CmdLine[MAX_CMDLINE];
STARTUPINFOA si;
PROCESS_INFORMATION pi;
BOOL ProcessResult;
HANDLE SyncEvent = NULL;
HANDLE ObjectArray[2];
DWORD rc;
PSECURITY_DESCRIPTOR psd = NULL;
SECURITY_ATTRIBUTES sa, *psa;
BOOL Result = FALSE;
#ifdef DEBUG
g_Mode = ExePath ? TEXT("host") : TEXT("remote");
#endif
__try {
g_ProcessHandle = NULL;
g_Host = (ExePath != NULL);
if (ISNT()) {
//
// Create nul DACL for NT
//
ZeroMemory (&sa, sizeof (sa));
psd = (PSECURITY_DESCRIPTOR) MemAlloc (g_hHeap, 0, SECURITY_DESCRIPTOR_MIN_LENGTH);
if (!InitializeSecurityDescriptor (psd, SECURITY_DESCRIPTOR_REVISION)) {
__leave;
}
if (!SetSecurityDescriptorDacl (psd, TRUE, (PACL) NULL, FALSE)) {
__leave;
}
sa.nLength = sizeof (sa);
sa.lpSecurityDescriptor = psd;
psa = &sa;
} else {
psa = NULL;
}
if (g_Host) {
//
// Create the IPC objects
//
if (!pCreateIpcData (psa)) {
DEBUGMSG ((DBG_ERROR, "Cannot create IPC channel"));
__leave;
}
g_ProcessHandle = CreateEvent (NULL, TRUE, TRUE, NULL);
} else { // !g_Host
//
// Open the IPC objects
//
if (!pOpenIpcData()) {
DEBUGMSG ((DBG_ERROR, "Cannot open IPC channel"));
__leave;
}
//
// Set event notifying setup that we've created our mailslot
//
SyncEvent = OpenEvent (EVENT_ALL_ACCESS, FALSE, TEXT("win9xupg"));
SetEvent (SyncEvent);
}
Result = TRUE;
}
__finally {
//
// Cleanup code
//
PushError();
if (!Result) {
CloseIpc();
}
if (SyncEvent) {
CloseHandle (SyncEvent);
}
if (psd) {
MemFree (g_hHeap, 0, psd);
}
PopError();
}
return Result;
}
DWORD
WINAPI
pHostThread (
PVOID Arg
)
{
CHAR Buf[2048];
PBYTE Data;
DWORD DataSize;
DWORD ResultCode;
DWORD LogId;
DWORD LogId2;
BOOL b;
if (pOpenIpcA (FALSE, TEXT("*"), TEXT("*"), TEXT("*"))) {
Dump ("Host: SendIpcCommand");
StringCopyA (Buf, "This is a test command");
b = SendIpcCommand (IPC_QUERY, Buf, SizeOfString (Buf));
wsprintfA (g_Buf, "Host: b=%u rc=%u", b, GetLastError());
Dump (g_Buf);
Dump ("Host: GetIpcCommandResults");
b = GetIpcCommandResults (15000, &Data, &DataSize, &ResultCode, &LogId, &LogId2);
wsprintfA (
g_Buf,
"Host: b=%u rc=%u\n"
" Data=%s\n"
" DataSize=%u\n"
" ResultCode=%u\n"
" LogId=%u\n",
b,
GetLastError(),
Data,
DataSize,
ResultCode,
LogId
);
Dump (g_Buf);
} else {
Dump ("Host: CreateIpcData failed!");
}
return 0;
}
DWORD
WINAPI
pRemoteThread (
PVOID Arg
)
{
CHAR Buf[2048];
PBYTE Data;
DWORD DataSize;
DWORD Command;
BOOL b;
Sleep (1000);
if (pOpenIpcA (FALSE, NULL, NULL, NULL)) {
Dump ("Remote: GetIpcCommand");
b = GetIpcCommand (15000, &Command, &Data, &DataSize);
wsprintfA (
g_Buf,
"Remote: b=%u rc=%u\n"
" Data=%s\n"
" DataSize=%u\n"
" Command=%u\n",
b,
GetLastError(),
Data,
DataSize,
Command
);
Dump (g_Buf);
Dump ("Remote: SendIpcCommandResults");
StringCopyA (Buf, "Results are positive!");
b = SendIpcCommandResults (ERROR_SUCCESS, 100, 0, Buf, SizeOfString (Buf));
wsprintfA (g_Buf, "Remote: b=%u rc=%u", b, GetLastError());
Dump (g_Buf);
} else {
Dump ("Remote: OpenIpcData failed!");
}
return 0;
}
VOID
pTestPipeMechanism (
VOID
)
{
HANDLE Threads[2];
Threads[0] = StartThread (pHostThread, NULL);
Threads[1] = StartThread (pRemoteThread, NULL);
WaitForMultipleObjects (2, Threads, TRUE, INFINITE);
}