windows-nt/Source/XPSP1/NT/base/wow64/wow64svc/server/wow64svc.c
2020-09-26 16:20:57 +08:00

811 lines
17 KiB
C

/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
sources
Abstract:
main file for the wow64svc
Author:
ATM Shafiqul Khalid (askhalid) 3-March-2000
Revision History:
--*/
#include "Wow64svc.h"
BOOL
SetWow64InitialRegistryLayout ();
SERVICE_STATUS Wow64ServiceStatus;
SERVICE_STATUS_HANDLE Wow64ServiceStatusHandle;
BOOL ServiceDebug;
HANDLE Wow64SvcHeapHandle;
SERVICE_TABLE_ENTRY ServiceDispatchTable[] = {
{ WOW64_SERVICE_NAME, Wow64ServiceMain },
{ NULL, NULL }
};
LPTSTR NextParam (
LPTSTR lpStr
)
/*++
Routine Description
Point to the next parameter in the commandline.
Arguments:
lpStr - pointer to the current command line
Return Value:
TRUE if the function succeed, FALSE otherwise.
--*/
{
WCHAR ch = L' ';
if (lpStr == NULL )
return NULL;
if ( *lpStr == 0 )
return lpStr;
while ( ( *lpStr != 0 ) && ( lpStr[0] != ch )) {
if ( ( lpStr [0] == L'\"') || ( lpStr [0] == L'\'') )
ch = lpStr [0];
lpStr++;
}
if ( ch !=L' ' ) lpStr++;
while ( ( *lpStr != 0 ) && (lpStr[0] == L' ') )
lpStr++;
return lpStr;
}
DWORD CopyParam (
LPTSTR lpDestParam,
LPTSTR lpCommandParam
)
/*++
Routine Description
Copy the current parameter to lpDestParam.
Arguments:
lpDestParam - that receive current parameter
lpCommandParam - pointer to the current command line
Return Value:
TRUE if the function succeed, FALSE otherwise.
--*/
{
DWORD dwLen = 0;
WCHAR ch = L' ';
*lpDestParam = 0;
if ( ( lpCommandParam [0] == L'\"') || ( lpCommandParam [0] == L'\'') ) {
ch = lpCommandParam [0];
lpCommandParam++;
};
while ( ( lpCommandParam [0] ) != ch && ( lpCommandParam [0] !=0 ) ) {
*lpDestParam++ = *lpCommandParam++;
dwLen++;
if ( dwLen>255 ) return FALSE;
}
if ( ch != L' ' && ch != lpCommandParam [0] )
return FALSE;
else lpCommandParam++;
*lpDestParam = 0;
return TRUE;
}
int __cdecl
main()
/*++
Routine Description:
Main entry point for the TIFF image viewer.
Arguments:
None.
Return Value:
Return code, zero for success.
--*/
{
int rVal;
HKEY hKey;
DWORD Ret;
LPTSTR p;
DWORD Action = 0;
LPTSTR Username;
LPTSTR Password;
PWCHAR lptCmdLine = GetCommandLine ();
SvcDebugPrint(("\nWow64svc module......%S", lptCmdLine));
lptCmdLine = NextParam ( lptCmdLine );
while ( ( lptCmdLine != NULL ) && ( lptCmdLine[0] != 0 ) ) {
if ( lptCmdLine[0] != L'-' && lptCmdLine[0] != L'/') {
SvcDebugPrint ( ("\nSorry! incorrect parameter....."));
SvcDebugPrint ( ("\n Uses: wow64svc -[i/r/d]"));
return FALSE;
}
switch ( lptCmdLine[1] ) {
case L'i':
case L'I':
//
// Temporary heck ignore installing this service
// You can delete the registry key as well for the initial sync
//
InitializeWow64OnBoot (2);
//
// write sync value Key.....
//
hKey = OpenNode (L"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce");
if (hKey != NULL)
{
Ret = RegSetValueEx(
hKey,
L"WOW64_SYNC",
0,
REG_SZ,
(PBYTE)L"wow64.exe -y",
sizeof (L"wow64.exe -y")
);
RegCloseKey (hKey);
}
return 0;
case L'r':
case L'R':Action = 2;
break;
case L'd':
case L'D':
Action = 3;
break;
case L's':
case L'S':
StartWow64Service ();
return 0;
break;
case L'x':
case L'X':
StopWow64Service ();
return 0;
break;
case L'q':
case L'Q':
QueryWow64Service ();
return 0;
break;
case L'y':
case L'Y':
//
// Initial Sync registry
//
Wow64SyncCLSID ();
return 0;
default:
SvcDebugPrint ( ("\nSorry! incorrect parameter.....pass2"));
SvcDebugPrint ( ("\n Uses: wow64svc -[i/r/d]"));
return FALSE;
}
lptCmdLine = NextParam ( lptCmdLine );
}
switch( Action ) {
case 1:
rVal = InstallService( NULL, NULL );
if (rVal == 0) {
//LogMessage( MSG_INSTALL_SUCCESS );
} else {
//LogMessage( MSG_INSTALL_FAIL, GetLastErrorText( rVal ) );
}
return rVal;
case 2:
rVal = RemoveService();
if (rVal == 0) {
//LogMessage( MSG_REMOVE_SUCCESS );
} else {
//LogMessage( MSG_REMOVE_FAIL, GetLastErrorText( rVal ) );
}
return rVal;
case 3:
ServiceDebug = TRUE;
//ConsoleDebugOutput = TRUE;
return ServiceStart();
}
SvcDebugPrint ( ("\nAttempt to run as a survice ......."));
if (!InitReflector ())
SvcDebugPrint ( ("\nSorry! couldn't initialize reflector thread, exiting"));
if (!StartServiceCtrlDispatcher( ServiceDispatchTable)) {
rVal = GetLastError();
SvcDebugPrint(( "StartServiceCtrlDispatcher error =%d", rVal ));
return rVal;
}
return 0;
}
DWORD
InstallService(
LPTSTR Username,
LPTSTR Password
)
/*++
Routine Description:
Service installation function. This function just
calls the service controller to install the Wow64 service.
It is required that the Wow64 service run in the context
of a user so that the service can access MAPI, files on
disk, the network, etc.
Arguments:
Username - User name where the service runs.
Password - Password for the user name.
Return Value:
Return code. Return zero for success, all other
values indicate errors.
--*/
{
DWORD rVal = 0;
SC_HANDLE hSvcMgr;
SC_HANDLE hService;
//
// do the registration for the reflector thread in the registry.
//
PopulateReflectorTable ();
SvcDebugPrint ( ("\nInstalling service........"));
hSvcMgr = OpenSCManager(
NULL,
NULL,
SC_MANAGER_ALL_ACCESS
);
if (!hSvcMgr) {
rVal = GetLastError();
SvcDebugPrint(( "\ncould not open service manager: error code = %u", rVal ));
return rVal;
}
hService = CreateService(
hSvcMgr,
WOW64_SERVICE_NAME,
WOW64_DISPLAY_NAME,
SERVICE_ALL_ACCESS,
SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START, //SERVICE_DEMAND_START, //SERVICE_AUTO_START,
SERVICE_ERROR_NORMAL,
WOW64_IMAGE_NAME,
NULL,
NULL,
NULL,
Username,
Password
);
if (!hService) {
rVal = GetLastError();
SvcDebugPrint(( "\ncould not create Wow64 service: error code = %u", rVal ));
return rVal;
}
CloseServiceHandle( hService );
CloseServiceHandle( hSvcMgr );
SvcDebugPrint ( ("\nInstalled services with ret code: %d", rVal));
return rVal;
}
DWORD
RemoveService(
void
)
/*++
Routine Description:
Service removal function. This function just
calls the service controller to remove the Wow64 service.
Arguments:
None.
Return Value:
Return code. Return zero for success, all other
values indicate errors.
--*/
{
DWORD rVal = 0;
SC_HANDLE hSvcMgr;
SC_HANDLE hService;
hSvcMgr = OpenSCManager(
NULL,
NULL,
SC_MANAGER_ALL_ACCESS
);
if (!hSvcMgr) {
rVal = GetLastError();
SvcDebugPrint(( "could not open service manager: error code = %u", rVal ));
return rVal;
}
hService = OpenService(
hSvcMgr,
WOW64_SERVICE_NAME,
SERVICE_ALL_ACCESS
);
if (!hService) {
rVal = GetLastError();
SvcDebugPrint(( "could not open the Wow64 service: error code = %u", rVal ));
return rVal;
}
if (ControlService( hService, SERVICE_CONTROL_STOP, &Wow64ServiceStatus )) {
//
// wait for 1 second
//
Sleep( 1000 );
while( QueryServiceStatus( hService, &Wow64ServiceStatus ) ) {
if ( Wow64ServiceStatus.dwCurrentState == SERVICE_STOP_PENDING ) {
Sleep( 1000 );
} else {
break;
}
}
if (Wow64ServiceStatus.dwCurrentState != SERVICE_STOPPED) {
rVal = GetLastError();
SvcDebugPrint(("could not stop the Wow64 service: error code = %u", rVal ));
return rVal;
}
}
if (!DeleteService( hService )) {
rVal = GetLastError();
SvcDebugPrint(( "could not delete the Wow64 service: error code = %u", rVal ));
return rVal;
}
CloseServiceHandle( hService );
CloseServiceHandle( hSvcMgr );
return rVal;
}
VOID
Wow64ServiceMain(
DWORD argc,
LPTSTR *argv
)
/*++
Routine Description:
This is the service main that is called by the
service controller.
Arguments:
argc - argument count
argv - argument array
Return Value:
None.
--*/
{
DWORD Rval;
//
// Setup initial registry link and layout for wow64 after boot.
//
SetWow64InitialRegistryLayout ();
Wow64ServiceStatus.dwServiceType = SERVICE_WIN32;
Wow64ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
Wow64ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;
Wow64ServiceStatus.dwWin32ExitCode = 0;
Wow64ServiceStatus.dwServiceSpecificExitCode = 0;
Wow64ServiceStatus.dwCheckPoint = 0;
Wow64ServiceStatus.dwWaitHint = 0;
Wow64ServiceStatusHandle = RegisterServiceCtrlHandler(
WOW64_SERVICE_NAME,
Wow64ServiceCtrlHandler
);
if (!Wow64ServiceStatusHandle) {
SvcDebugPrint(( "RegisterServiceCtrlHandler failed %d", GetLastError() ));
return;
}
Rval = ServiceStart();
if (Rval) {
//
// the service failed to start correctly
//
ReportServiceStatus( SERVICE_RUNNING, 0, 0);
return;
}
ReportServiceStatus( SERVICE_RUNNING, 0, 0);
return;
}
VOID
Wow64ServiceCtrlHandler(
DWORD Opcode
)
/*++
Routine Description:
This is the Wow64 service control dispatch function.
Arguments:
Opcode - requested control code
Return Value:
None.
--*/
{
switch(Opcode) {
case SERVICE_CONTROL_PAUSE:
ReportServiceStatus( SERVICE_PAUSED, 0, 0 );
break;
case SERVICE_CONTROL_CONTINUE:
ReportServiceStatus( SERVICE_RUNNING, 0, 0 );
break;
case SERVICE_CONTROL_STOP:
if (ServiceStop () == 0)
ReportServiceStatus( SERVICE_STOPPED, 0, 0 );
return;
case SERVICE_CONTROL_INTERROGATE:
// fall through to send current status
break;
default:
SvcDebugPrint(( "Unrecognized opcode %ld", Opcode ));
break;
}
ReportServiceStatus( 0, 0, 0 );
return;
}
DWORD
ReportServiceStatus(
DWORD CurrentState,
DWORD Win32ExitCode,
DWORD WaitHint
)
/*++
Routine Description:
This function updates the service control manager's status information for the Wow64 service.
Arguments:
CurrentState - Indicates the current state of the service
Win32ExitCode - Specifies a Win32 error code that the service uses to
report an error that occurs when it is starting or stopping.
WaitHint - Specifies an estimate of the amount of time, in milliseconds,
that the service expects a pending start, stop, or continue
operation to take before the service makes its next call to the
SetServiceStatus function with either an incremented dwCheckPoint
value or a change in dwCurrentState.
Return Value:
Return code. Return zero for success, all other
values indicate errors.
--*/
{
static DWORD CheckPoint = 1;
BOOL rVal;
Wow64ServiceStatus.dwCurrentState = CurrentState;
/*
if (CurrentState == SERVICE_START_PENDING) {
Wow64ServiceStatus.dwControlsAccepted = 0;
} else {
Wow64ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
}
if (CurrentState) {
Wow64ServiceStatus.dwCurrentState = CurrentState;
}
Wow64ServiceStatus.dwWin32ExitCode = Win32ExitCode;
Wow64ServiceStatus.dwWaitHint = WaitHint;
if ((Wow64ServiceStatus.dwCurrentState == SERVICE_RUNNING) ||
(Wow64ServiceStatus.dwCurrentState == SERVICE_STOPPED ) ) {
Wow64ServiceStatus.dwCheckPoint = 0;
} else {
Wow64ServiceStatus.dwCheckPoint = CheckPoint++;
}
*/
//
// Report the status of the service to the service control manager.
//
rVal = SetServiceStatus( Wow64ServiceStatusHandle, &Wow64ServiceStatus );
if (!rVal) {
SvcDebugPrint(( "SetServiceStatus() failed: ec=%d", GetLastError() ));
}
return rVal;
}
DWORD
StartWow64Service ()
/*++
Routine Description:
This function Start wow64 service.
Arguments:
None.
Return Value:
Return code. Return zero for success, all other
values indicate errors.
--*/
{
DWORD rVal=0;
SC_HANDLE hSvcMgr;
SC_HANDLE hService;
SvcDebugPrint ( ("\ntrying to start service......"));
hSvcMgr = OpenSCManager(
NULL,
NULL,
SC_MANAGER_ALL_ACCESS
);
if (!hSvcMgr) {
rVal = GetLastError();
SvcDebugPrint(( "\ncould not open service manager: error code = %u", rVal ));
return rVal;
}
hService = OpenService( hSvcMgr, WOW64_SERVICE_NAME, SERVICE_ALL_ACCESS );
if ( !hService ) {
rVal = GetLastError();
SvcDebugPrint(( "\ncould not open service:%s error code = %u", WOW64_SERVICE_NAME, rVal ));
return rVal;
}
if (! StartService( hService, 0, NULL) ) {
rVal = GetLastError();
SvcDebugPrint(( "\ncould not start service:%s error code = %u", WOW64_SERVICE_NAME, rVal ));
return rVal;
}
SvcDebugPrint(( "\nservice:%s started successfully error code = %u", WOW64_SERVICE_NAME, rVal ));
return 0;
}
DWORD
StopWow64Service ()
/*++
Routine Description:
This function Stop wow64 service.
Arguments:
None.
Return Value:
Return code. Return zero for success, all other
values indicate errors.
--*/
{
DWORD rVal=0;
SC_HANDLE hSvcMgr;
SC_HANDLE hService;
SvcDebugPrint ( ("\ntrying to start service......"));
hSvcMgr = OpenSCManager(
NULL,
NULL,
SC_MANAGER_ALL_ACCESS
);
if (!hSvcMgr) {
rVal = GetLastError();
SvcDebugPrint(( "\ncould not open service manager: error code = %u", rVal ));
return rVal;
}
hService = OpenService( hSvcMgr, WOW64_SERVICE_NAME, SERVICE_ALL_ACCESS );
if ( !hService ) {
rVal = GetLastError();
SvcDebugPrint(( "\ncould not open service:%S error code = %u", WOW64_SERVICE_NAME, rVal ));
return rVal;
}
if (!ControlService( hService, SERVICE_CONTROL_PAUSE, &Wow64ServiceStatus )) {
rVal = GetLastError();
SvcDebugPrint(( "\nSorry! couldn't stop the service:%S error code = %u", WOW64_SERVICE_NAME, rVal ));
return rVal;
}
SvcDebugPrint(( "\nservice:%S stopped successfully error code = %u", WOW64_SERVICE_NAME, rVal ));
return 0;
}
DWORD
QueryWow64Service ()
/*++
Routine Description:
This function log the current status of wow64 service.
Arguments:
None.
Return Value:
Return code. Return zero for success, all other
values indicate errors.
--*/
{
DWORD rVal=0;
SC_HANDLE hSvcMgr;
SC_HANDLE hService;
SvcDebugPrint ( ("\ntrying to start service......"));
hSvcMgr = OpenSCManager(
NULL,
NULL,
SC_MANAGER_ALL_ACCESS
);
if (!hSvcMgr) {
rVal = GetLastError();
SvcDebugPrint(( "\ncould not open service manager: error code = %u", rVal ));
return rVal;
}
hService = OpenService( hSvcMgr, WOW64_SERVICE_NAME, SERVICE_ALL_ACCESS );
if ( !hService ) {
rVal = GetLastError();
SvcDebugPrint(( "\ncould not open service:%S error code = %u", WOW64_SERVICE_NAME, rVal ));
return rVal;
}
QueryServiceStatus( hService, &Wow64ServiceStatus );
{
SvcDebugPrint ( ("\nStatus: %d, [pending %d] [running %d]",Wow64ServiceStatus.dwCurrentState, SERVICE_STOP_PENDING, SERVICE_RUNNING));
}
SvcDebugPrint(( "\nservice:%S started successfully error code = %u", WOW64_SERVICE_NAME, rVal ));
return 0;
}