#include "stdinc.h" #pragma hdrstop #include #include "sxsserviceserver.h" EXTERN_C RPC_IF_HANDLE SxsStoreManager_ServerIfHandle; BOOL CServiceStatus::Initialize( PCWSTR pcwszServiceName, LPHANDLER_FUNCTION pHandler, DWORD dwServiceType, DWORD dwControlsAccepted, DWORD dwInitialState ) { NTSTATUS status = STATUS_SUCCESS; BOOL fSuccess = FALSE; // // Double-initialization isn't a bad thing, but it's frowned on. // ASSERT(m_StatusHandle == NULL); if (m_StatusHandle != NULL) return TRUE; InitializeCriticalSection(&m_CSection); // // Register this service as owning the service status // m_StatusHandle = RegisterServiceCtrlHandler(pcwszServiceName, pHandler); if (m_StatusHandle == NULL) { goto Failure; } // // Set the initial state of the world // ZeroMemory(static_cast(this), sizeof(SERVICE_STATUS)); this->dwServiceType = dwServiceType; this->dwCurrentState = dwInitialState; this->dwControlsAccepted = dwControlsAccepted; if (!SetServiceStatus(m_StatusHandle, this)) { goto Failure; } return TRUE; Failure: { const DWORD dwLastError = ::GetLastError(); DeleteCriticalSection(&m_CSection); m_StatusHandle = NULL; SetLastError(dwLastError); } return FALSE; } BOOL CServiceStatus::SetServiceState( DWORD dwStatus, DWORD dwCheckpoint ) { BOOL fSuccess = FALSE; EnterCriticalSection(&m_CSection); __try { if (m_StatusHandle != NULL) { this->dwCurrentState = dwStatus; if (dwCheckpoint != 0xFFFFFFFF) { this->dwCheckPoint = dwCheckpoint; } fSuccess = SetServiceStatus(m_StatusHandle, this); } } __finally { LeaveCriticalSection(&m_CSection); } return fSuccess; } // // In-place construction // bool CServiceStatus::Construct( CServiceStatus *&pServiceStatusTarget ) { ASSERT(pServiceStatusTarget == NULL); return (pServiceStatusTarget = new CServiceStatus) != NULL; } EXTERN_C HANDLE g_hFakeServiceControllerThread = INVALID_HANDLE_VALUE; EXTERN_C DWORD g_dwFakeServiceControllerThreadId = 0; EXTERN_C PSVCHOST_GLOBAL_DATA g_pGlobalServiceData = NULL; BYTE g_rgbServiceStatusStorage[sizeof(CServiceStatus)]; EXTERN_C CServiceStatus *g_pServiceStatus = NULL; // // The service host will call this to send in API callbacks // VOID SvchostPushServiceGlobals( PSVCHOST_GLOBAL_DATA pGlobals ) { ASSERT(g_pGlobalServiceData == NULL); g_pGlobalServiceData = pGlobals; } PVOID operator new(size_t cb, PVOID pv) { return pv; } // // Control handler for service notifications // VOID ServiceHandler( DWORD dwControlCode ) { return; } #define CHECKPOINT_ZERO (0) #define CHECKPOINT_RPC_STARTED (1) // // Stop the service with an error code, ERROR_SUCCESS for a successful stoppage // VOID ShutdownService( DWORD dwLastError ) { return; } // // Where the fun starts // VOID WINAPI ServiceMain( DWORD dwServiceArgs, LPWSTR lpServiceArgList[] ) { NTSTATUS status = STATUS_SUCCESS; // // svchost must have given us some global data before we got to this point. // ASSERT(g_pGlobalServiceData != NULL); ASSERT(g_pServiceStatus == NULL); g_pServiceStatus = new (g_rgbServiceStatusStorage) CServiceStatus; if (!g_pServiceStatus->Initialize( SXS_STORE_SERVICE_NAME, ServiceHandler, SERVICE_WIN32, SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE, SERVICE_START_PENDING)) { DebugPrint(DBGPRINT_LVL_ERROR, "Can't start service status handler, error 0x%08lx\n", ::GetLastError()); } // // Go initialize RPC, and register our interface. If this fails, we shut down. // status = g_pGlobalServiceData->StartRpcServer( SXS_STORE_SERVICE_NAME, SxsStoreManager_ServerIfHandle); if (!NT_SUCCESS(status)) { ShutdownService(status); return; } // // Tell the world that we're off and running // g_pServiceStatus->SetServiceState(SERVICE_RUNNING); return; } DWORD WINAPI FakeServiceController(PVOID pvCookie); // // This stub will start a dispatch thread, and then call into the // service main function // BOOL FakeRunningAsService() { // // Create a thread running the service dispatch function, and then call // the service main function to get things rolling // g_hFakeServiceControllerThread = CreateThread( NULL, 0, FakeServiceController, 0, 0, &g_dwFakeServiceControllerThreadId); if (g_hFakeServiceControllerThread == NULL) { return FALSE; } ServiceMain(0, NULL); return TRUE; } VOID __cdecl wmain(INT argc, WCHAR** argv) { SERVICE_TABLE_ENTRYW SxsGacServiceEntries[] = { { SXS_STORE_SERVICE_NAME, ServiceMain }, { NULL, NULL } }; BOOL RunningAsService = TRUE; BOOL fSuccess = FALSE; if (argc > 1 && (lstrcmpiW(argv[1], L"notservice") == 0)) { RunningAsService = FALSE; } if (RunningAsService) { fSuccess = StartServiceCtrlDispatcherW(SxsGacServiceEntries); if (!fSuccess) { const DWORD dwError = ::GetLastError(); DebugPrint(DBGPRINT_LVL_ERROR, "Failed starting service dispatch, error %ld\n", dwError); } } else { fSuccess = FakeRunningAsService(); if (!fSuccess) { const DWORD dwError = ::GetLastError(); DebugPrint(DBGPRINT_LVL_ERROR, "Failed faking service startup, error %ld\n", dwError); } } return; }