/* Copyright (c) Microsoft Corporation */ #include #include #include "nt.h" #include "ntrtl.h" #include "nturtl.h" #include "windows.h" #include "delayimp.h" #include "strsafe.h" #include "sxsvc1.h" #define NUMBER_OF(x) (sizeof(x)/sizeof((x)[0])) typedef struct _SERVICE_CONTEXT { HANDLE ServiceHandle; SERVICE_STATUS ServiceStatus; } SERVICE_CONTEXT, *PSERVICE_CONTEXT; PVOID MemAlloc(SIZE_T n) { return HeapAlloc(GetProcessHeap(), 0, n); } VOID MemFree(PVOID p) { HeapFree(GetProcessHeap(), 0, p); } BOOL WINAPI DllEntry( HINSTANCE hInst, DWORD dwReason, PVOID pvReserved ) { switch (dwReason) { case DLL_PROCESS_ATTACH: DisableThreadLibraryCalls(hInst); break; } return TRUE; } #if 0 BOOL ChangePathExtensionW(PWSTR Buffer, SIZE_T BufferSize, PCWSTR NewExtension) { SIZE_T OldLength = 0; SIZE_T NewLength = 0; PWSTR OldExtension = NULL; SIZE_T NewExtensionLength = 0; SIZE_T OldExtensionLength = 0; SIZE_T Counter = 0; OldLength = wcslen(Buffer); if (NewExtension[0] == '.') { NewExtension += 1; } NewExtensionLength = wcslen(NewExtension); if ((NewExtensionLength + 1) >= BufferSize) { return FALSE; } for (Counter = 0; Counter != OldLength; ++Counter) { SIZE_T Index = (OldLength - 1 - Counter); if (Buffer[Index] == '.') { OldExtension = Buffer + Index + 1; break; } if (Buffer[Index] == '\\' || Buffer[Index] == '/') { break; } } if (OldExtension == NULL) { if (OldLength + 1 + NewExtensionLength >= BufferSize) { return FALSE; } Buffer[OldLength] = '.'; CopyMemory(Buffer + OldLength + 1, NewExtension, NewExtensionLength * sizeof(WCHAR)); Buffer[OldLength + 1 + NewExtensionLength + 1] = 0; return TRUE; } OldExtensionLength = wcslen(OldExtension); NewLength = OldLength - OldExtensionLength + NewExtensionLength; if (NewLength + 1 >= BufferSize) { return FALSE; } CopyMemory(Buffer + OldLength - OldExtensionLength, NewExtension, NewExtensionLength * sizeof(WCHAR)); Buffer[OldLength - OldExtensionLength + NewExtensionLength] = 0; return TRUE; } #endif HMODULE GetMyModule(VOID) { return (HMODULE)&__ImageBase; } void GetMyFullPathW(PWSTR Buffer, DWORD BufferSize) { Buffer[0] = 0; GetModuleFileNameW(GetMyModule(), Buffer, BufferSize); } void strcatfW(PWSTR Buffer, SIZE_T n, PCWSTR Format, ...) { va_list Args; va_start(Args, Format); if (n != 0 && Buffer != NULL && Format != NULL) { SIZE_T i = wcslen(Buffer); if (i < n) { SIZE_T j = n - i; StringCchVPrintfW(Buffer + i, j, Format, Args); } Buffer[n - 1] = 0; } va_end(Args); } const STRING EmptyString = RTL_CONSTANT_STRING(""); const STRING * DbgServiceControlToString( DWORD dw ) { const STRING * String = &EmptyString; switch (dw) { #define CASE(x) case x: { const static STRING y = RTL_CONSTANT_STRING(#x); String = &y; } break; CASE(SERVICE_CONTROL_CONTINUE) CASE(SERVICE_CONTROL_INTERROGATE) CASE(SERVICE_CONTROL_NETBINDADD) CASE(SERVICE_CONTROL_NETBINDDISABLE) CASE(SERVICE_CONTROL_NETBINDENABLE) CASE(SERVICE_CONTROL_NETBINDREMOVE) CASE(SERVICE_CONTROL_PARAMCHANGE) CASE(SERVICE_CONTROL_PAUSE) CASE(SERVICE_CONTROL_SHUTDOWN) CASE(SERVICE_CONTROL_STOP) CASE(SERVICE_CONTROL_DEVICEEVENT) CASE(SERVICE_CONTROL_HARDWAREPROFILECHANGE) CASE(SERVICE_CONTROL_POWEREVENT) CASE(SERVICE_CONTROL_SESSIONCHANGE) #undef CASE } return String; } DWORD WINAPI ServiceHandlerEx( DWORD dwControl, // requested control code DWORD dwEventType, // event type LPVOID lpEventData, // event data LPVOID lpContext // user-defined context data ) { BOOL CallSetStatus = FALSE; PSERVICE_CONTEXT ServiceContext = (PSERVICE_CONTEXT)lpContext; DbgPrint("sxsvc1: %Z\n", DbgServiceControlToString(dwControl)); if (ServiceContext == NULL) { DbgPrint("sxsvc1: got null context\n"); return (DWORD)-1; } switch (dwControl) { case SERVICE_CONTROL_CONTINUE: ServiceContext->ServiceStatus.dwCurrentState = SERVICE_RUNNING; CallSetStatus = TRUE; break; case SERVICE_CONTROL_INTERROGATE: CallSetStatus = TRUE; break; case SERVICE_CONTROL_NETBINDADD: break; case SERVICE_CONTROL_NETBINDDISABLE: break; case SERVICE_CONTROL_NETBINDENABLE: break; case SERVICE_CONTROL_NETBINDREMOVE: break; case SERVICE_CONTROL_PARAMCHANGE: break; case SERVICE_CONTROL_PAUSE: ServiceContext->ServiceStatus.dwCurrentState = SERVICE_PAUSED; CallSetStatus = TRUE; break; case SERVICE_CONTROL_SHUTDOWN: ServiceContext->ServiceStatus.dwCurrentState = SERVICE_STOPPED; CallSetStatus = TRUE; break; case SERVICE_CONTROL_STOP: ServiceContext->ServiceStatus.dwCurrentState = SERVICE_STOPPED; CallSetStatus = TRUE; break; case SERVICE_CONTROL_DEVICEEVENT: break; case SERVICE_CONTROL_HARDWAREPROFILECHANGE: break; case SERVICE_CONTROL_POWEREVENT: break; case SERVICE_CONTROL_SESSIONCHANGE: break; } if (CallSetStatus) { SetServiceStatus(ServiceContext->ServiceHandle, &ServiceContext->ServiceStatus); } return NO_ERROR; } VOID WINAPI ServiceMain( DWORD argc, PWSTR argv[] ) { const static WCHAR MyFullPathFormat[] = L"MyFullPath: %ls: "; const static WCHAR CurrentActCtxFormat[] = L"CurrentActCtx: %p: "; HANDLE FileHandle = 0; SIZE_T Length = 0; SIZE_T i = 0; PWSTR MyFullPath = 0; PWSTR Buffer = 0; HANDLE CurrentActCtx = 0; DWORD BytesWritten = 0; PSERVICE_CONTEXT ServiceContext = 0; MyFullPath = (PWSTR)MemAlloc(MAX_PATH); if (MyFullPath == NULL) goto Exit; MyFullPath[0] = 0; GetMyFullPathW(MyFullPath, MAX_PATH); FileHandle = CreateFileW(L"C:\\sxsvc.log", GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (FileHandle == INVALID_HANDLE_VALUE) { goto Exit; } Length = 0; if (argc != 0 && argv != NULL) { for (i = 0 ; i < argc ; i++ ) { Length += wcslen(argv[i]) + 1; } } Length += wcslen(MyFullPath) + NUMBER_OF(MyFullPathFormat); Length += sizeof(PVOID) * 8 + NUMBER_OF(CurrentActCtxFormat); Length += 1; Buffer = (PWSTR)MemAlloc(Length * sizeof(WCHAR)); if (Buffer == NULL) { goto Exit; } Buffer[0] = 0; strcatfW(Buffer, Length, MyFullPathFormat, MyFullPath); if (argc != 0 && argv != NULL) { for (i = 0 ; i < argc ; i++ ) { strcatfW(Buffer, Length, L"%ls ", argv[i]); } } GetCurrentActCtx(&CurrentActCtx); strcatfW(Buffer, Length, CurrentActCtxFormat, CurrentActCtx); WriteFile(FileHandle, Buffer, wcslen(Buffer), &BytesWritten, NULL); #if DBG DbgPrint("sxsvc1: %ls\n", Buffer); #endif ServiceContext = (PSERVICE_CONTEXT)MemAlloc(sizeof(*ServiceContext)); if (ServiceContext == NULL) { DbgPrint("sxsvc1: out of memory line %ld\n", (ULONG)__LINE__); } RtlZeroMemory(ServiceContext, sizeof(*ServiceContext)); ServiceContext->ServiceHandle = RegisterServiceCtrlHandlerExW(ServiceName, ServiceHandlerEx, ServiceContext); if (ServiceContext->ServiceHandle == 0) { DbgPrint("sxsvc1: RegisterServiceCtrlHandlerExW failed 0x%lx\n", (ULONG)GetLastError()); goto Exit; } ServiceContext->ServiceStatus.dwServiceType = ServiceTypeValue; ServiceContext->ServiceStatus.dwCurrentState = SERVICE_RUNNING; ServiceContext->ServiceStatus.dwControlsAccepted |= SERVICE_ACCEPT_STOP; ServiceContext->ServiceStatus.dwControlsAccepted |= SERVICE_ACCEPT_SHUTDOWN; ServiceContext->ServiceStatus.dwControlsAccepted |= SERVICE_ACCEPT_PAUSE_CONTINUE; ServiceContext->ServiceStatus.dwControlsAccepted |= SERVICE_ACCEPT_PARAMCHANGE; ServiceContext->ServiceStatus.dwControlsAccepted |= SERVICE_ACCEPT_SESSIONCHANGE; ServiceContext->ServiceStatus.dwWin32ExitCode = NO_ERROR; SetServiceStatus(ServiceContext->ServiceHandle, &ServiceContext->ServiceStatus); ServiceContext = NULL; Exit: if (FileHandle != NULL) CloseHandle(FileHandle); MemFree(Buffer); MemFree(MyFullPath); MemFree(ServiceContext); } #if 0 int __cdecl wmain(int argc, wchar_t ** argv) { WCHAR Buffer[MAX_PATH]; int i = 0; for ( i = 1 ; i < argc ; i += 2) { StringCchCopyW(Buffer, NUMBER_OF(Buffer), argv[i]); ChangePathExtensionW(Buffer, NUMBER_OF(Buffer), argv[i + 1]); printf("%ls\n", Buffer); } return 0; } #endif