/*++ Copyright (c) 1991-92 Microsoft Corporation Module Name: tsec.c Abstract: Test for the security functionality in service controller. Author: Rita Wong (ritaw) 16-Mar-1992 Environment: User Mode - Win32 Revision History: --*/ #include #include #include #include #include // IN, BOOL, LPTSTR, etc. #include #ifndef UNICODE #define UNICODE #endif #include // Win32 service control APIs DWORD TestOpenService( IN SC_HANDLE hScManager, OUT LPSC_HANDLE hService, IN LPWSTR ServiceName, IN DWORD DesiredAccess, IN DWORD ExpectedError ); DWORD TestOpenSCManager( OUT LPSC_HANDLE hScManager, IN LPWSTR DatabaseName, IN DWORD DesiredAccess, IN DWORD ExpectedError ); DWORD TestEnumServicesStatus( IN SC_HANDLE hSCManager, IN DWORD ExpectedError ); DWORD TestQueryServiceStatus( IN SC_HANDLE hService, IN DWORD ExpectedError ); DWORD TestControlService( IN SC_HANDLE hService, IN DWORD ControlCode, IN DWORD ExpectedError ); DWORD TestStartService( IN SC_HANDLE hService, IN DWORD ExpectedError ); VOID DisplayStatus( IN LPWSTR ServiceName OPTIONAL, IN LPSERVICE_STATUS ServiceStatus ); BYTE WorkBuffer[1024]; VOID __cdecl main( void ) { DWORD status; SC_HANDLE hScManager; SC_HANDLE hService; PSECURITY_DESCRIPTOR lpSecurity = (PSECURITY_DESCRIPTOR) WorkBuffer; DWORD BytesRequired; // // Bad database name // (void) TestOpenSCManager( &hScManager, L"Bogus", 0, ERROR_INVALID_NAME ); // // Failed database name // (void) TestOpenSCManager( &hScManager, L"SERVICESFAILED", 0, ERROR_DATABASE_DOES_NOT_EXIST ); // // Active database name // if (TestOpenSCManager( &hScManager, L"SERVICESactive", 0, NO_ERROR ) == NO_ERROR) { (void) CloseServiceHandle(hScManager); } // // Invalid desired access // (void) TestOpenSCManager( &hScManager, NULL, 0xff00, ERROR_ACCESS_DENIED ); // // Valid desired access // if (TestOpenSCManager( &hScManager, NULL, SC_MANAGER_CONNECT, NO_ERROR ) == NO_ERROR) { // // Invalid operation follows // (void) TestEnumServicesStatus( hScManager, ERROR_ACCESS_DENIED ); (void) TestOpenService( hScManager, &hService, L"Lumpy", 0xf000, ERROR_ACCESS_DENIED ); (void) TestOpenService( hScManager, &hService, L"Lu mpy", SERVICE_QUERY_STATUS, ERROR_INVALID_NAME ); (void) TestOpenService( hScManager, &hService, L"\\Lumpy", SERVICE_QUERY_STATUS, ERROR_INVALID_NAME ); (void) TestOpenService( hScManager, &hService, L"Lum/py", SERVICE_QUERY_STATUS, ERROR_INVALID_NAME ); (void) TestOpenService( hScManager, &hService, L"Lump", SERVICE_QUERY_STATUS, ERROR_SERVICE_DOES_NOT_EXIST ); // // Service handle opened with only query access // status = TestOpenService( hScManager, &hService, L"Lumpy", SERVICE_QUERY_STATUS, NO_ERROR ); if (status == NO_ERROR) { (void) TestControlService( hService, SERVICE_CONTROL_PAUSE, ERROR_ACCESS_DENIED ); (void) TestStartService( hService, ERROR_ACCESS_DENIED ); (void) TestQueryServiceStatus( hService, NO_ERROR ); (void) CloseServiceHandle(hService); } // // Test QueryServiceObjectSecurity and SetServiceObjectSecurity // status = TestOpenService( hScManager, &hService, L"Lumpy", READ_CONTROL | WRITE_DAC, NO_ERROR ); if (status == NO_ERROR) { if (QueryServiceObjectSecurity( hService, DACL_SECURITY_INFORMATION, lpSecurity, sizeof(WorkBuffer), &BytesRequired )) { printf("QueryServiceObjectSecurity: OK. BytesRequired=%lu\n", BytesRequired); if (SetServiceObjectSecurity( hService, DACL_SECURITY_INFORMATION, lpSecurity )) { printf("SetServiceObjectSecurity: OK.\n"); } else { printf("SetServiceObjectSecurity: Failed=%lu\n", GetLastError()); } } else { printf("QueryServiceObjectSecurity: Failed=%lu\n", GetLastError()); } (void) CloseServiceHandle(hService); } (void) CloseServiceHandle(hScManager); } // // Try MAXIMUM_ALLOWED desired access // status = TestOpenSCManager( &hScManager, NULL, MAXIMUM_ALLOWED, NO_ERROR ); if (status == NO_ERROR) { (void) TestEnumServicesStatus( hScManager, NO_ERROR ); (void) CloseServiceHandle(hScManager); } } DWORD TestOpenSCManager( OUT LPSC_HANDLE hScManager, IN LPWSTR DatabaseName, IN DWORD DesiredAccess, IN DWORD ExpectedError ) { DWORD status = NO_ERROR; if (DatabaseName != NULL) { printf("OpenSCManager: DatabaseName=%ws, DesiredAccess=%08lx\n", DatabaseName, DesiredAccess); } else { printf("OpenSCManager: DatabaseName=(null), DesiredAccess=%08lx\n", DesiredAccess); } *hScManager = OpenSCManager( NULL, DatabaseName, DesiredAccess ); if (*hScManager == (SC_HANDLE) NULL) { status = GetLastError(); if (ExpectedError != status) { printf(" FAILED. Expected %lu, got %lu\n", ExpectedError, status); return status; } } else { if (ExpectedError != NO_ERROR) { printf(" FAILED. Expected %lu, got NO_ERROR\n", ExpectedError); return NO_ERROR; } } printf(" Got %lu as expected\n", status); return status; } DWORD TestOpenService( IN SC_HANDLE hScManager, OUT LPSC_HANDLE hService, IN LPWSTR ServiceName, IN DWORD DesiredAccess, IN DWORD ExpectedError ) { DWORD status = NO_ERROR; printf("OpenService: ServiceName=%ws, DesiredAccess=%08lx\n", ServiceName, DesiredAccess); *hService = OpenService( hScManager, ServiceName, DesiredAccess ); if (*hService == (SC_HANDLE) NULL) { status = GetLastError(); if (ExpectedError != status) { printf(" FAILED. Expected %lu, got %lu\n", ExpectedError, status); return status; } } else { if (ExpectedError != NO_ERROR) { printf(" FAILED. Expected %lu, got NO_ERROR\n", ExpectedError); return NO_ERROR; } } printf(" Got %lu as expected\n", status); return status; } DWORD TestEnumServicesStatus( IN SC_HANDLE hSCManager, IN DWORD ExpectedError ) { DWORD status = NO_ERROR; BYTE OutputBuffer[1024]; LPENUM_SERVICE_STATUS EnumBuffer = (LPENUM_SERVICE_STATUS) OutputBuffer; DWORD BytesNeeded; DWORD EntriesRead; DWORD i; if (! EnumServicesStatus( hSCManager, SERVICE_TYPE_ALL, SERVICE_STATE_ALL, EnumBuffer, 1024, &BytesNeeded, &EntriesRead, NULL )) { status = GetLastError(); } if (ExpectedError != status) { printf(" FAILED. Expected %lu, got %lu\n", ExpectedError, status); return status; } else { printf(" Got %lu as expected\n", status); } if ((status == NO_ERROR) || (status == ERROR_MORE_DATA)) { for (i = 0; i < EntriesRead; i++) { for (i = 0; i < EntriesRead; i++) { DisplayStatus( EnumBuffer->lpServiceName, &(EnumBuffer->ServiceStatus)); EnumBuffer++; } } } return status; } DWORD TestQueryServiceStatus( IN SC_HANDLE hService, IN DWORD ExpectedError ) { DWORD status = NO_ERROR; SERVICE_STATUS ServiceStatus; printf("QueryService: \n"); if (! QueryServiceStatus( hService, &ServiceStatus )) { status = GetLastError(); } if (ExpectedError != status) { printf(" FAILED. Expected %lu, got %lu\n", ExpectedError, status); return status; } if (status == NO_ERROR) { DisplayStatus(NULL, &ServiceStatus); } printf(" Got %lu as expected\n", status); return status; } DWORD TestControlService( IN SC_HANDLE hService, IN DWORD ControlCode, IN DWORD ExpectedError ) { DWORD status = NO_ERROR; SERVICE_STATUS ServiceStatus; printf("ControlService: Control=%08lx\n", ControlCode); if (! ControlService( hService, ControlCode, &ServiceStatus )) { status = GetLastError(); } if (ExpectedError != status) { printf(" FAILED. Expected %lu, got %lu\n", ExpectedError, status); return status; } if (status == NO_ERROR) { DisplayStatus(NULL, &ServiceStatus); } printf(" Got %lu as expected\n", status); return status; } DWORD TestStartService( IN SC_HANDLE hService, IN DWORD ExpectedError ) { DWORD status = NO_ERROR; printf("StartService: \n"); if (! StartService( hService, 0, NULL )) { status = GetLastError(); } if (ExpectedError != status) { printf(" FAILED. Expected %lu, got %lu\n", ExpectedError, status); return status; } printf(" Got %lu as expected\n", status); return status; } VOID DisplayStatus( IN LPWSTR ServiceName OPTIONAL, IN LPSERVICE_STATUS ServiceStatus ) /*++ Routine Description: Displays the service name and the service status. | |SERVICE_NAME: messenger | TYPE : WIN32 | STATE : ACTIVE SERVICE_STOPPABLE SERVICE_PAUSABLE | EXIT_CODE : 0xC002001 | CHECKPOINT : 0x00000001 | WAIT_HINT : 0x00003f21 | Arguments: ServiceName - This is a pointer to a string containing the name of the service. ServiceStatus - This is a pointer to a SERVICE_STATUS structure from which information is to be displayed. Return Value: none. --*/ { if (ARGUMENT_PRESENT(ServiceName)) { printf("\nSERVICE_NAME: %ws\n", ServiceName); } printf(" TYPE : %lx ", ServiceStatus->dwServiceType); switch(ServiceStatus->dwServiceType){ case SERVICE_WIN32: printf("WIN32 \n"); break; case SERVICE_DRIVER: printf("DRIVER \n"); break; default: printf(" ERROR \n"); } printf(" STATE : %lx ", ServiceStatus->dwCurrentState); switch(ServiceStatus->dwCurrentState){ case SERVICE_STOPPED: printf("STOPPED "); break; case SERVICE_START_PENDING: printf("START_PENDING "); break; case SERVICE_STOP_PENDING: printf("STOP_PENDING "); break; case SERVICE_RUNNING: printf("RUNNING "); break; case SERVICE_CONTINUE_PENDING: printf("CONTINUE_PENDING "); break; case SERVICE_PAUSE_PENDING: printf("PAUSE_PENDING "); break; case SERVICE_PAUSED: printf("PAUSED "); break; default: printf(" ERROR "); } // // Print Controls Accepted Information // if (ServiceStatus->dwControlsAccepted & SERVICE_ACCEPT_STOP) { printf(" (STOPPABLE,"); } else { printf(" (NOT_STOPPABLE,"); } if (ServiceStatus->dwControlsAccepted & SERVICE_ACCEPT_PAUSE_CONTINUE) { printf("PAUSABLE )\n"); } else { printf("NOT_PAUSABLE )\n"); } // // Print Exit Code // printf(" WIN32_EXIT_CODE : 0x%lx\n", ServiceStatus->dwWin32ExitCode ); printf(" SERVICE_EXIT_CODE : 0x%lx\n", ServiceStatus->dwServiceSpecificExitCode ); // // Print CheckPoint & WaitHint Information // printf(" CHECKPOINT : 0x%lx\n", ServiceStatus->dwCheckPoint); printf(" WAIT_HINT : 0x%lx\n", ServiceStatus->dwWaitHint ); return; }