Setting the Windows service access controls C program example

 

 

// For WinXp as a target

#define _WIN32_WINNT 0x0501

#include <windows.h>

#include <aclapi.h>

#include <stdio.h>

#include <tchar.h>

 

// Simple user defined error messages...

void DisplayError(DWORD dwError, LPTSTR pszAPI)

{

LPVOID lpvMessageBuffer;

FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |

FORMAT_MESSAGE_FROM_SYSTEM,

NULL, dwError,

MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),

(LPTSTR)&lpvMessageBuffer, 0, NULL);

 

// Display the string.

_tprintf(TEXT("ERROR: API = %s.\n"), pszAPI);

_tprintf(TEXT(" error code = %u.\n"), dwError);

_tprintf(TEXT(" message = %s.\n"), (LPTSTR)lpvMessageBuffer);

 

// Free the buffer allocated by the system.

LocalFree(lpvMessageBuffer);

ExitProcess(dwError);

}

 

// Using _tmain(), TCHAR - A WCHAR if UNICODE/wide character is defined, a CHAR otherwise.

int _tmain(int argc, TCHAR *argv[])

{

BOOL bDaclPresent = FALSE;

BOOL bDaclDefaulted = FALSE;

DWORD dwError = 0;

DWORD dwSize = 0;

EXPLICIT_ACCESS ea;

PACL pacl = NULL;

PACL pNewAcl = NULL;

PSECURITY_DESCRIPTOR psd;

SC_HANDLE schManager = NULL;

SC_HANDLE schService = NULL;

SECURITY_DESCRIPTOR sd;

 

if (argc != 2)

{

_tprintf(TEXT("Usage: %s [service name].\n"), argv[0]);

_tprintf(TEXT("Please try again.\n"));

return 1;

}

 

// Obtain a handle to the Service Controller.

schManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);

 

if (schManager == NULL)

DisplayError(GetLastError(), TEXT("OpenSCManager()"));

else

_tprintf(TEXT("OpenSCManager(), handle to the service controller obtained successfully.\n"));

 

// Obtain a handle to the service.

schService = OpenService(schManager, argv[1], READ_CONTROL | WRITE_DAC);

 

if (schService == NULL)

DisplayError(GetLastError(), TEXT("OpenService()"));

else

_tprintf(TEXT("OpenSCManager(), handle to the service obtained successfully.\n"));

 

// Get the current security descriptor.

if (!QueryServiceObjectSecurity(schService, DACL_SECURITY_INFORMATION, &psd, 0, &dwSize))

{

if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)

{

psd = (PSECURITY_DESCRIPTOR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize);

if (psd == NULL)

{

DisplayError(0, TEXT("HeapAlloc()"));

// note HeapAlloc() does not support GetLastError()

}

else

_tprintf(TEXT("HeapAlloc() looks OK.\n"));

if (!QueryServiceObjectSecurity(schService, DACL_SECURITY_INFORMATION, psd, dwSize, &dwSize))

DisplayError(GetLastError(), TEXT("QueryServiceObjectSecurity()"));

else

_tprintf(TEXT("QueryServiceObjectSecurity() looks OK.\n"));

}

else

DisplayError(GetLastError(), TEXT("QueryServiceObjectSecurity()"));

}

 

// Get the DACL...

if (!GetSecurityDescriptorDacl(psd, &bDaclPresent, &pacl, &bDaclDefaulted))

DisplayError(GetLastError(), TEXT("GetSecurityDescriptorDacl()"));

else

_tprintf(TEXT("GetSecurityDescriptorDacl() looks OK.\n"));

 

// Build the ACE.

BuildExplicitAccessWithName(&ea, TEXT("GUEST"), SERVICE_START | SERVICE_STOP | READ_CONTROL | DELETE, SET_ACCESS, NO_INHERITANCE);

dwError = SetEntriesInAcl(1, &ea, pacl, &pNewAcl);

if (dwError != ERROR_SUCCESS)

DisplayError(dwError, TEXT("SetEntriesInAcl()"));

else

_tprintf(TEXT("SetEntriesInAcl() looks OK.\n"));

 

// Initialize a NEW Security Descriptor.

if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))

DisplayError(GetLastError(), TEXT("InitializeSecurityDescriptor()"));

else

_tprintf(TEXT("SetEntriesInAcl() looks OK.\n"));

 

// Set the new DACL in the Security Descriptor.

if (!SetSecurityDescriptorDacl(&sd, TRUE, pNewAcl, FALSE))

DisplayError(GetLastError(), TEXT("SetSecurityDescriptorDacl()"));

else

_tprintf(TEXT("SetSecurityDescriptorDacl() looks OK.\n"));

 

// Set the new DACL for the service object.

if (!SetServiceObjectSecurity(schService, DACL_SECURITY_INFORMATION, &sd))

DisplayError(GetLastError(), TEXT("SetServiceObjectSecurity()"));

else

_tprintf(TEXT("SetServiceObjectSecurity() looks OK.\n"));

 

// Close the handles.

if (!CloseServiceHandle(schManager))

DisplayError(GetLastError(), TEXT("CloseServiceHandle() schManager"));

else

_tprintf(TEXT("CloseServiceHandle() schManager looks OK.\n"));

 

if (!CloseServiceHandle(schService))

DisplayError(GetLastError(), TEXT("CloseServiceHandle() schService"));

else

_tprintf(TEXT("CloseServiceHandle() schService looks OK.\n"));

 

// Free buffers.

LocalFree((HLOCAL)pNewAcl);

HeapFree(GetProcessHeap(), 0, (LPVOID)psd);

return 0;

}

 

Output examples:

(This program run at the command prompt)

 

F:\vc2005project\cplus\debug>cplus

Usage: cplus [service name].

Please try again.

 

 

F:\vc2005project\cplus\debug>cplus NetLogon

OpenSCManager(), handle to the service controller obtained successfully.

OpenSCManager(), handle to the service obtained successfully.

HeapAlloc() looks OK.

QueryServiceObjectSecurity() looks OK.

GetSecurityDescriptorDacl() looks OK.

SetEntriesInAcl() looks OK.

SetEntriesInAcl() looks OK.

SetSecurityDescriptorDacl() looks OK.

SetServiceObjectSecurity() looks OK.

CloseServiceHandle() schManager looks OK.

CloseServiceHandle() schService looks OK.

 

 

F:\vc2005project\cplus\debug>cplus Browser

OpenSCManager(), handle to the service controller obtained successfully.

OpenSCManager(), handle to the service obtained successfully.

HeapAlloc() looks OK.

QueryServiceObjectSecurity() looks OK.

GetSecurityDescriptorDacl() looks OK.

SetEntriesInAcl() looks OK.

SetEntriesInAcl() looks OK.

SetSecurityDescriptorDacl() looks OK.

SetServiceObjectSecurity() looks OK.

CloseServiceHandle() schManager looks OK.

CloseServiceHandle() schService looks OK.

F:\vc2005project\cplus\debug>

 

 

Compiler: Visual C++ Express Edition 2005

Compiled on Platform: Windows XP Pro SP2

Target platform: none, just for learning and fun

Header file: Standard and Windows

Additional library: Windows Platform SDK

Additional project setting: Set project to be compiled as C. Click Project menu->your_project_name Properties->Configuration Properties->C/C++->Advanced->Compiled As: Compiled as C Code (/TC)

Other info: non-CLR or unmanaged. Need to add Advapi32.lib (Advapi32.dll) to the project. Click the Project menu->Select the your_project_name Properties... sub menu->Expand the Configuration Properties folder on the left pane->Expand the Linker subfolder->Select the Input subfolder->Select the Additional Dependencies field on the right pane->Click the ... at the end of the field->Type in 'Advapi32.lib' in the empty pane->Click the OK button->Click the OK button second time to close the project Properties dialog.

To do: Setting the Windows service access controls C program example

To show: The Windows services program in C source code using the Win32 library

 

 

C and C++ Programming Resources | C & C++ Code Example Index