821 lines
21 KiB
C
821 lines
21 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1995 Microsoft Corporation
|
|||
|
|
|||
|
Module Name :
|
|||
|
|
|||
|
svcsetup.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
Setup program for installing / removing the Internet Services.
|
|||
|
This enables setting up the Service GUID and protocol bindings.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Murali R. Krishnan ( MuraliK ) 08-March-1995
|
|||
|
|
|||
|
Project:
|
|||
|
|
|||
|
Internet Services Setup Application
|
|||
|
|
|||
|
Functions Exported:
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
NOTE:
|
|||
|
There are sections in this code which should be modified
|
|||
|
whenever a new service is added.
|
|||
|
|
|||
|
Please look for begin_modifiable_code to identify the code that
|
|||
|
may require modification when a new service is added.
|
|||
|
|
|||
|
|
|||
|
-MuraliK
|
|||
|
--*/
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/************************************************************
|
|||
|
* Include Headers
|
|||
|
************************************************************/
|
|||
|
|
|||
|
#include <nt.h>
|
|||
|
#include <ntrtl.h>
|
|||
|
#include <nturtl.h>
|
|||
|
|
|||
|
#include <ntsam.h>
|
|||
|
#include <ntlsa.h>
|
|||
|
|
|||
|
#include <stdio.h>
|
|||
|
#include <stdlib.h>
|
|||
|
#include <windows.h>
|
|||
|
#include <winsock2.h>
|
|||
|
#include <nspapi.h>
|
|||
|
|
|||
|
//#include <inetasrv.h>
|
|||
|
#include <ftpd.h>
|
|||
|
#include <w3svc.h>
|
|||
|
#include <msnsvc.h>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
// begin_modifiable_code
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// For each service create a GUID using uuidgen and store it in static
|
|||
|
// variable for further use below.
|
|||
|
// Gopher Service GUID: 62388f10-58a2-11ce-bec8-00aa0047ae4e
|
|||
|
//
|
|||
|
|
|||
|
static GUID g_GopherGuid = { 0x62388f10, 0x58a2, 0x11ce, 0xbe, 0xc8,
|
|||
|
0x00, 0xaa, 0x00, 0x47, 0xae, 0x4e };
|
|||
|
|
|||
|
static GUID g_HTTPGuid = { 0x585908c0, 0x6305, 0x11ce, 0xae, 0x00,
|
|||
|
0x00, 0xaa, 0x00, 0x4a, 0x38, 0xb9 };
|
|||
|
|
|||
|
static GUID g_FTPGuid = { 0x91604620, 0x6305, 0x11ce, 0xae, 0x00,
|
|||
|
0x00, 0xaa, 0x00, 0x4a, 0x38, 0xb9 };
|
|||
|
|
|||
|
static GUID g_MsnGuid = { 0x11f5d300, 0xada7, 0x11ce, 0xb4, 0x8f,
|
|||
|
0x00, 0xaa, 0x00, 0x6c, 0x35, 0x02 };
|
|||
|
|
|||
|
//
|
|||
|
// For each of the service make an entry in the following list of services
|
|||
|
//
|
|||
|
// Format for each service info is:
|
|||
|
// ServiceInfo( SymbolicName, ServiceName, DisplayName, TcpPort,
|
|||
|
// pointer-to-guid-for-the-service)
|
|||
|
//
|
|||
|
// This is a macro. Please be considerate to use a terminating "\"
|
|||
|
//
|
|||
|
|
|||
|
# define AllServicesInfo() \
|
|||
|
ServiceInfo( GOPHER_SERVICE, "GopherSvc", \
|
|||
|
"Microsoft Gopher Service (1995)", \
|
|||
|
( 70), &g_GopherGuid, \
|
|||
|
GOPHERD_ANONYMOUS_SECRET_W, \
|
|||
|
GOPHERD_ROOT_SECRET_W) \
|
|||
|
\
|
|||
|
ServiceInfo( W3_SERVICE_NAME, "W3Svc", \
|
|||
|
"Microsoft HTTP Service (1995)", \
|
|||
|
(80), &g_HTTPGuid, \
|
|||
|
W3_ANONYMOUS_SECRET_W, \
|
|||
|
W3_ROOT_SECRET_W) \
|
|||
|
\
|
|||
|
ServiceInfo( FTP_SERVICE_NAME, "FtpSvc", \
|
|||
|
"Microsoft FTP Service (1995)", \
|
|||
|
(21), &g_FTPGuid, \
|
|||
|
FTPD_ANONYMOUS_SECRET_W, \
|
|||
|
FTPD_ROOT_SECRET_W) \
|
|||
|
\
|
|||
|
ServiceInfo( MSN_SERVICE_NAME, "MsnSvc", \
|
|||
|
"MSN Gateway Service (1995)", \
|
|||
|
(568), &g_MsnGuid, \
|
|||
|
MSN_ANONYMOUS_SECRET_W, \
|
|||
|
MSN_ROOT_SECRET_W) \
|
|||
|
|
|||
|
//
|
|||
|
// end_modifiable_code
|
|||
|
//
|
|||
|
|
|||
|
|
|||
|
|
|||
|
// begin_unmodifiable_code
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Few convenience macros
|
|||
|
//
|
|||
|
|
|||
|
// For setting up the Values in ServiceTypeValue structure.
|
|||
|
# define SetServiceTypeValues( pSvcTypeValue, dwNS, dwType, dwSize, lpValName, lpVal) \
|
|||
|
( pSvcTypeValue)->dwNameSpace = ( dwNS); \
|
|||
|
( pSvcTypeValue)->dwValueType = ( dwType); \
|
|||
|
( pSvcTypeValue)->dwValueSize = ( dwSize); \
|
|||
|
( pSvcTypeValue)->lpValueName = ( lpValName); \
|
|||
|
( pSvcTypeValue)->lpValue = (PVOID ) ( lpVal); \
|
|||
|
|
|||
|
# define SetServiceTypeValuesDword( pSvcTypeValue, dwNS, lpValName, lpVal) \
|
|||
|
SetServiceTypeValues( (pSvcTypeValue), (dwNS), REG_DWORD, sizeof( DWORD), \
|
|||
|
( lpValName), ( lpVal))
|
|||
|
|
|||
|
|
|||
|
|
|||
|
typedef struct _ServiceSetupInfo {
|
|||
|
|
|||
|
char * m_pszServiceName;
|
|||
|
char * m_pszDisplayName;
|
|||
|
DWORD m_tcpPort; // TCP/IP port number
|
|||
|
LPGUID m_lpGuid;
|
|||
|
WCHAR * m_pszAnonPwdSecret; // Anonymous password secret name
|
|||
|
WCHAR * m_pszRootPwdSecret; // Virtual roots password secret name
|
|||
|
|
|||
|
} ServiceSetupInfo;
|
|||
|
|
|||
|
//
|
|||
|
// Macro to be used for defining a value for ServiceSetupInfo structure
|
|||
|
//
|
|||
|
# define ServiceInfoValue( svcName, dispName, tcpPort, lpGuid, AnonPwd, RootPwd) \
|
|||
|
{ svcName, dispName, tcpPort, lpGuid, AnonPwd, RootPwd }
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Form an enumerated list of the service names. These form the
|
|||
|
// index into the array of service setup information structures.
|
|||
|
//
|
|||
|
|
|||
|
# define ServiceInfo( sym, svc, disp, tcpport, lpGuid, AnonPwd, RootPwd) \
|
|||
|
i ## sym,
|
|||
|
|
|||
|
typedef enum {
|
|||
|
|
|||
|
AllServicesInfo()
|
|||
|
iMaxService
|
|||
|
|
|||
|
} eServiceInfo;
|
|||
|
|
|||
|
# undef ServiceInfo
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Form the array of ServiceSetyupInfo objects.
|
|||
|
//
|
|||
|
|
|||
|
# define ServiceInfo( sym, svc, disp, tcpport, lpGuid, AnonPwd, RootPwd) \
|
|||
|
ServiceInfoValue( svc, disp, tcpport, lpGuid, AnonPwd, RootPwd),
|
|||
|
|
|||
|
static ServiceSetupInfo g_svcSetupInfo[] = {
|
|||
|
|
|||
|
AllServicesInfo()
|
|||
|
{ NULL, NULL, 0, 0, NULL, NULL} // a sentinel for the array
|
|||
|
};
|
|||
|
|
|||
|
# undef ServiceInfo
|
|||
|
|
|||
|
// end_unmodifiable_code
|
|||
|
|
|||
|
|
|||
|
/************************************************************
|
|||
|
* Functions
|
|||
|
************************************************************/
|
|||
|
|
|||
|
//
|
|||
|
// Local functions
|
|||
|
//
|
|||
|
|
|||
|
|
|||
|
static BOOL
|
|||
|
CreateServiceEntry( IN char * pszServiceName,
|
|||
|
IN char * pszDisplayName,
|
|||
|
IN char * pszPath);
|
|||
|
|
|||
|
static BOOL
|
|||
|
CreateEventLogEntry( IN char * pszServiceName,
|
|||
|
IN char * pszServicePath
|
|||
|
);
|
|||
|
|
|||
|
static VOID PrintUsageMessage( IN char * pszProgramName);
|
|||
|
|
|||
|
static BOOL
|
|||
|
PerformSetService( IN const ServiceSetupInfo * pSvcSetupInfo,
|
|||
|
IN DWORD svcOperation);
|
|||
|
|
|||
|
DWORD
|
|||
|
SetSecret(
|
|||
|
IN LPWSTR Server,
|
|||
|
IN LPWSTR SecretName,
|
|||
|
IN LPWSTR pSecret,
|
|||
|
IN DWORD cbSecret
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
|
|||
|
int __cdecl
|
|||
|
main( int argc, char * argv[] )
|
|||
|
{
|
|||
|
BOOL fRet = TRUE;
|
|||
|
|
|||
|
char * pszProgram = argv[ 0];
|
|||
|
char * pszOperation;
|
|||
|
char * pszSvc;
|
|||
|
|
|||
|
int i;
|
|||
|
ServiceSetupInfo * pSvcSetupInfo = NULL;
|
|||
|
DWORD svcOperation = SERVICE_ADD_TYPE;
|
|||
|
|
|||
|
//
|
|||
|
// Parse the command line arguments.
|
|||
|
//
|
|||
|
|
|||
|
if ( argc != 3) {
|
|||
|
|
|||
|
PrintUsageMessage( argv[ 0]);
|
|||
|
return ( 1);
|
|||
|
}
|
|||
|
|
|||
|
pszSvc = argv[ 1];
|
|||
|
pszOperation = argv[ 2];
|
|||
|
|
|||
|
//
|
|||
|
// Lookup the service setup info structure from the array
|
|||
|
// command line argument 1 is the service name.
|
|||
|
// Find the associated service setup info structure.
|
|||
|
//
|
|||
|
for( i = 0; i < iMaxService; i++) {
|
|||
|
|
|||
|
if ( _stricmp( g_svcSetupInfo[ i].m_pszServiceName, pszSvc) == 0) {
|
|||
|
|
|||
|
pSvcSetupInfo = ( g_svcSetupInfo + i);
|
|||
|
break;
|
|||
|
}
|
|||
|
} // for
|
|||
|
|
|||
|
|
|||
|
if ( pSvcSetupInfo == NULL) {
|
|||
|
|
|||
|
fprintf( stderr, " Unknown Service Name %s specified.\n", pszSvc);
|
|||
|
PrintUsageMessage( pszProgram);
|
|||
|
return ( 1);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Identify the operation to be performed and execute the same.
|
|||
|
//
|
|||
|
|
|||
|
if ( _strnicmp( pszOperation, "/add", 4) == 0) {
|
|||
|
|
|||
|
svcOperation = SERVICE_ADD_TYPE;
|
|||
|
|
|||
|
} else if ( _strnicmp( pszOperation, "/delete", 4) == 0) {
|
|||
|
|
|||
|
svcOperation = SERVICE_DELETE_TYPE;
|
|||
|
|
|||
|
} else if ( _strnicmp( pszOperation, "/svc:", 5) == 0) {
|
|||
|
|
|||
|
fRet = CreateServiceEntry( pSvcSetupInfo->m_pszServiceName,
|
|||
|
pSvcSetupInfo->m_pszDisplayName,
|
|||
|
strchr( pszOperation, ':') + 1);
|
|||
|
|
|||
|
} else if ( _strnicmp( pszOperation, "/eventlog:", 10) == 0) {
|
|||
|
|
|||
|
fRet = CreateEventLogEntry( pSvcSetupInfo->m_pszServiceName,
|
|||
|
strchr( pszOperation, ':') + 1);
|
|||
|
} else {
|
|||
|
|
|||
|
PrintUsageMessage( pszProgram);
|
|||
|
SetLastError( ERROR_INVALID_PARAMETER);
|
|||
|
fRet = FALSE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
fRet = fRet && PerformSetService( pSvcSetupInfo, svcOperation);
|
|||
|
|
|||
|
return ( (fRet) ? NO_ERROR : GetLastError());
|
|||
|
} // main()
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
PrintUsageMessage( IN char * pszProgramName)
|
|||
|
/*++
|
|||
|
Prints the usage message along with possible list of services allowed.
|
|||
|
--*/
|
|||
|
{
|
|||
|
int i;
|
|||
|
|
|||
|
fprintf( stderr,
|
|||
|
"Usage:\n %s <service-name> "
|
|||
|
" [ /add | /delete | /svc:<path-of-process>"
|
|||
|
" /eventlog:<eventlog-messages-binary> \n",
|
|||
|
pszProgramName);
|
|||
|
|
|||
|
//
|
|||
|
// Print the services name.
|
|||
|
//
|
|||
|
|
|||
|
fprintf( stderr, "\t Possible Services: \n\t\tName\t Other Details\n");
|
|||
|
|
|||
|
for( i = 0; i < iMaxService; i++) {
|
|||
|
|
|||
|
fprintf( stderr, "\t\t %s [ %s] TcpPort=%d) \n",
|
|||
|
g_svcSetupInfo[ i].m_pszServiceName,
|
|||
|
g_svcSetupInfo[ i].m_pszDisplayName,
|
|||
|
g_svcSetupInfo[ i].m_tcpPort
|
|||
|
);
|
|||
|
} // for
|
|||
|
|
|||
|
return;
|
|||
|
} // PrintUsageMessage()
|
|||
|
|
|||
|
|
|||
|
/************************************************************
|
|||
|
* Following are general functions usable by other Internet services
|
|||
|
************************************************************/
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
static BOOL
|
|||
|
PerformSetService( IN const ServiceSetupInfo * pSvcSetupInfo,
|
|||
|
IN DWORD svcOperation)
|
|||
|
{
|
|||
|
int err;
|
|||
|
|
|||
|
WSADATA WsaData;
|
|||
|
|
|||
|
SERVICE_INFO serviceInfo;
|
|||
|
LPSERVICE_TYPE_INFO_ABS lpServiceTypeInfo ;
|
|||
|
LPSERVICE_TYPE_VALUE_ABS lpServiceTypeValues ;
|
|||
|
BYTE serviceTypeInfoBuffer[sizeof(SERVICE_TYPE_INFO) + 1024];
|
|||
|
// Buffer large enough for 3 values ( SERVICE_TYPE_VALUE_ABS)
|
|||
|
|
|||
|
DWORD Value1 = 1 ;
|
|||
|
DWORD TcpPortValue = pSvcSetupInfo->m_tcpPort;
|
|||
|
DWORD statusFlags;
|
|||
|
|
|||
|
//
|
|||
|
// Initialize Windows Sockets DLL
|
|||
|
//
|
|||
|
|
|||
|
err = WSAStartup( 0x0101, & WsaData);
|
|||
|
if ( err == SOCKET_ERROR) {
|
|||
|
|
|||
|
fprintf( stderr, " WSAStartup() Failed. Error = %ld\n",
|
|||
|
GetLastError());
|
|||
|
return ( FALSE);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Setup the service information to be passed to SetService() for adding
|
|||
|
// or deleting this service. Most of the SERVICE_INFO fields are not
|
|||
|
// required for add or delete operation. The main things of interests are
|
|||
|
// GUIDs and ServiceSpecificInfo structure.
|
|||
|
//
|
|||
|
|
|||
|
memset( (PVOID ) & serviceInfo, 0, sizeof( serviceInfo)); //null all fields
|
|||
|
|
|||
|
serviceInfo.lpServiceType = pSvcSetupInfo->m_lpGuid;
|
|||
|
|
|||
|
//
|
|||
|
// The "Blob" will contain the service specific information.
|
|||
|
// In this case, fill it with a SERVICE_TYPE_INFO_ABS structure
|
|||
|
// and associated information.
|
|||
|
//
|
|||
|
serviceInfo.ServiceSpecificInfo.pBlobData = serviceTypeInfoBuffer;
|
|||
|
serviceInfo.ServiceSpecificInfo.cbSize = sizeof( serviceTypeInfoBuffer);
|
|||
|
|
|||
|
|
|||
|
lpServiceTypeInfo = (LPSERVICE_TYPE_INFO_ABS ) serviceTypeInfoBuffer;
|
|||
|
|
|||
|
//
|
|||
|
// There's only one value for TCP.
|
|||
|
//
|
|||
|
|
|||
|
lpServiceTypeInfo->dwValueCount = 1;
|
|||
|
lpServiceTypeInfo->lpTypeName = pSvcSetupInfo->m_pszServiceName;
|
|||
|
|
|||
|
lpServiceTypeValues = lpServiceTypeInfo->Values;
|
|||
|
|
|||
|
SetServiceTypeValuesDword( ( lpServiceTypeValues + 0),
|
|||
|
NS_DNS,
|
|||
|
SERVICE_TYPE_VALUE_TCPPORT,
|
|||
|
&TcpPortValue);
|
|||
|
|
|||
|
//
|
|||
|
// Finally, call SetService to actually perform the operation.
|
|||
|
//
|
|||
|
|
|||
|
err = SetService(
|
|||
|
NS_DEFAULT, // all default name spaces
|
|||
|
svcOperation, // either ADD or DELETE
|
|||
|
0, // dwFlags not used
|
|||
|
&serviceInfo, // the service info structure
|
|||
|
NULL, // lpServiceAsyncInfo
|
|||
|
&statusFlags // additional status information
|
|||
|
);
|
|||
|
|
|||
|
if ( err != NO_ERROR ) {
|
|||
|
|
|||
|
fprintf( stderr, "SetService failed: %ld\n", GetLastError( ) );
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
printf( "SetService( %s) succeeded, status flags = %ld\n",
|
|||
|
pSvcSetupInfo->m_pszServiceName, statusFlags );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Create the LSA secrets for the anonymous user password and the virtual
|
|||
|
// root passwords
|
|||
|
//
|
|||
|
|
|||
|
if ( !SetSecret( NULL,
|
|||
|
pSvcSetupInfo->m_pszAnonPwdSecret,
|
|||
|
L"",
|
|||
|
sizeof(WCHAR) ) ||
|
|||
|
!SetSecret( NULL,
|
|||
|
pSvcSetupInfo->m_pszRootPwdSecret,
|
|||
|
L"",
|
|||
|
sizeof(WCHAR) ))
|
|||
|
{
|
|||
|
err = GetLastError();
|
|||
|
|
|||
|
fprintf( stderr,
|
|||
|
"SetService( %s ) failed to create Lsa Secrets for anonymous\n"
|
|||
|
"username password or virtual root passwords. Error = %d\n",
|
|||
|
pSvcSetupInfo->m_pszServiceName,
|
|||
|
err);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// For HTTP, set the catapult impersonation user for the proxy
|
|||
|
//
|
|||
|
|
|||
|
if ( pSvcSetupInfo->m_lpGuid == &g_HTTPGuid )
|
|||
|
{
|
|||
|
if ( !SetSecret( NULL,
|
|||
|
W3_PROXY_USER_SECRET_W,
|
|||
|
L"",
|
|||
|
sizeof(WCHAR) ))
|
|||
|
{
|
|||
|
err = GetLastError();
|
|||
|
|
|||
|
fprintf( stderr,
|
|||
|
"SetService( %s ) failed to create Lsa Secrets proxy user\n"
|
|||
|
"Error = %d\n",
|
|||
|
pSvcSetupInfo->m_pszServiceName,
|
|||
|
err);
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return ( err != NO_ERROR);
|
|||
|
|
|||
|
} // PerformSetService()
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
static BOOL
|
|||
|
CreateServiceEntry( IN char * pszServiceName,
|
|||
|
IN char * pszDisplayName,
|
|||
|
IN char * pszPath)
|
|||
|
/*++
|
|||
|
|
|||
|
This function calls the service controller to create a new service.
|
|||
|
|
|||
|
Arguments:
|
|||
|
pszServiceName pointer to service name
|
|||
|
pszDisplayName pointer to Display name
|
|||
|
pszPath pointer to null-terminated string containing the path for
|
|||
|
the service DLL.
|
|||
|
|
|||
|
Returns:
|
|||
|
|
|||
|
TRUE on success and FALSE if there is any failure.
|
|||
|
Use GetLastError() to get further error code on failure.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
BOOL fReturn = FALSE;
|
|||
|
SC_HANDLE hServiceManager;
|
|||
|
|
|||
|
//
|
|||
|
// Create the service.
|
|||
|
//
|
|||
|
|
|||
|
hServiceManager = OpenSCManager( NULL, // machine name
|
|||
|
NULL, // database name
|
|||
|
STANDARD_RIGHTS_REQUIRED
|
|||
|
| SC_MANAGER_CREATE_SERVICE );
|
|||
|
|
|||
|
if ( hServiceManager != NULL) {
|
|||
|
|
|||
|
SC_HANDLE hService;
|
|||
|
|
|||
|
//
|
|||
|
// create the service itself.
|
|||
|
//
|
|||
|
|
|||
|
hService = CreateService( hServiceManager,
|
|||
|
pszServiceName,
|
|||
|
pszDisplayName,
|
|||
|
GENERIC_READ | GENERIC_WRITE,
|
|||
|
SERVICE_WIN32_SHARE_PROCESS,
|
|||
|
SERVICE_DEMAND_START,
|
|||
|
SERVICE_ERROR_NORMAL,
|
|||
|
pszPath,
|
|||
|
NULL, // lpszLoadOrderGroup
|
|||
|
NULL, // lpdwTagId
|
|||
|
NULL, // lpszDependencies
|
|||
|
NULL, // lpszStartUserName
|
|||
|
NULL ); // lpszPassword
|
|||
|
|
|||
|
|
|||
|
if( hService != NULL ) {
|
|||
|
|
|||
|
fReturn = TRUE;
|
|||
|
CloseServiceHandle( hService);
|
|||
|
}
|
|||
|
|
|||
|
CloseServiceHandle( hServiceManager);
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
fprintf( stderr, "OpenSCManager failed: %ld\n", GetLastError() );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
fprintf( stderr, " %s created with path %s. Return %d ( Error = %ld)\n",
|
|||
|
pszServiceName, pszPath,
|
|||
|
fReturn, ( fReturn) ? NO_ERROR : GetLastError());
|
|||
|
|
|||
|
|
|||
|
return ( fReturn);
|
|||
|
} // CreateServiceEntry()
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
# define EVENT_LOG_REG_KEY \
|
|||
|
"System\\CurrentControlSet\\Services\\EventLog\\System"
|
|||
|
|
|||
|
# define LEN_EVENT_LOG_REG_KEY ( sizeof( EVENT_LOG_REG_KEY))
|
|||
|
|
|||
|
|
|||
|
|
|||
|
static BOOL
|
|||
|
CreateEventLogEntry( IN char * pszServiceName,
|
|||
|
IN char * pszServicePath
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
This function creates an entry for a service in the Eventlog registry
|
|||
|
so that the messages of the service may be decoded.
|
|||
|
|
|||
|
Arguments:
|
|||
|
pszServiceName pointer to string containing the service name.
|
|||
|
pszServicePath pointer to string containing the path for the service
|
|||
|
dll with the embedded messages.
|
|||
|
|
|||
|
Returns:
|
|||
|
TRUE on success and FALSE if there are any errors. Use GetLastError()
|
|||
|
to get detailed error message.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
char rgchKeyName[ LEN_EVENT_LOG_REG_KEY + 100];
|
|||
|
HKEY hkeyReg;
|
|||
|
LONG err;
|
|||
|
DWORD Disposition;
|
|||
|
|
|||
|
|
|||
|
if ( strlen( pszServiceName) >= 100) {
|
|||
|
|
|||
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY);
|
|||
|
return ( FALSE);
|
|||
|
}
|
|||
|
|
|||
|
sprintf( rgchKeyName, "%s\\%s", EVENT_LOG_REG_KEY, pszServiceName);
|
|||
|
|
|||
|
//
|
|||
|
// Add the data to the EventLog's registry key so that the
|
|||
|
// log insertion strings may be found by the Event Viewer.
|
|||
|
//
|
|||
|
|
|||
|
err = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
|
|||
|
rgchKeyName,
|
|||
|
0,
|
|||
|
NULL,
|
|||
|
REG_OPTION_NON_VOLATILE,
|
|||
|
KEY_WRITE,
|
|||
|
NULL,
|
|||
|
&hkeyReg,
|
|||
|
&Disposition );
|
|||
|
|
|||
|
if( err != 0 ) {
|
|||
|
|
|||
|
fprintf( stderr, "RegCreateKeyEx failed: %ld\n", err );
|
|||
|
|
|||
|
SetLastError( err);
|
|||
|
return ( FALSE);
|
|||
|
}
|
|||
|
|
|||
|
err = RegSetValueEx( hkeyReg,
|
|||
|
"EventMessageFile",
|
|||
|
0,
|
|||
|
REG_EXPAND_SZ,
|
|||
|
pszServicePath,
|
|||
|
strlen( pszServicePath ) + 1 );
|
|||
|
|
|||
|
if( err == 0 ) {
|
|||
|
|
|||
|
DWORD Value;
|
|||
|
|
|||
|
Value = ( EVENTLOG_ERROR_TYPE |
|
|||
|
EVENTLOG_WARNING_TYPE |
|
|||
|
EVENTLOG_INFORMATION_TYPE
|
|||
|
);
|
|||
|
|
|||
|
err = RegSetValueEx( hkeyReg,
|
|||
|
"TypesSupported",
|
|||
|
0,
|
|||
|
REG_DWORD,
|
|||
|
(CONST BYTE *)&Value,
|
|||
|
sizeof(Value) );
|
|||
|
}
|
|||
|
|
|||
|
RegCloseKey( hkeyReg );
|
|||
|
|
|||
|
if( err != 0 ) {
|
|||
|
|
|||
|
fprintf( stderr, "RegSetValueEx failed: %ld\n", err );
|
|||
|
SetLastError( err);
|
|||
|
}
|
|||
|
|
|||
|
return ( err == 0);
|
|||
|
|
|||
|
} // CreateEventLogEntry()
|
|||
|
|
|||
|
DWORD
|
|||
|
SetSecret(
|
|||
|
IN LPWSTR Server,
|
|||
|
IN LPWSTR SecretName,
|
|||
|
IN LPWSTR pSecret,
|
|||
|
IN DWORD cbSecret
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Description
|
|||
|
|
|||
|
Sets the specified LSA secret
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Server - Server name (or NULL) secret lives on
|
|||
|
SecretName - Name of the LSA secret
|
|||
|
pSecret - Pointer to secret memory
|
|||
|
cbSecret - Size of pSecret memory block
|
|||
|
|
|||
|
Note:
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
LSA_HANDLE hPolicy;
|
|||
|
UNICODE_STRING unicodePassword;
|
|||
|
UNICODE_STRING unicodeServer;
|
|||
|
NTSTATUS ntStatus;
|
|||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|||
|
LSA_HANDLE hSecret;
|
|||
|
UNICODE_STRING unicodeSecret;
|
|||
|
|
|||
|
|
|||
|
RtlInitUnicodeString( &unicodeServer,
|
|||
|
Server );
|
|||
|
|
|||
|
//
|
|||
|
// Initialize the unicode string by hand so we can handle '\0' in the
|
|||
|
// string
|
|||
|
//
|
|||
|
|
|||
|
unicodePassword.Buffer = pSecret;
|
|||
|
unicodePassword.Length = (USHORT) cbSecret;
|
|||
|
unicodePassword.MaximumLength = (USHORT) cbSecret;
|
|||
|
|
|||
|
//
|
|||
|
// Open a policy to the remote LSA
|
|||
|
//
|
|||
|
|
|||
|
InitializeObjectAttributes( &ObjectAttributes,
|
|||
|
NULL,
|
|||
|
0L,
|
|||
|
NULL,
|
|||
|
NULL );
|
|||
|
|
|||
|
ntStatus = LsaOpenPolicy( &unicodeServer,
|
|||
|
&ObjectAttributes,
|
|||
|
POLICY_ALL_ACCESS,
|
|||
|
&hPolicy );
|
|||
|
|
|||
|
if ( !NT_SUCCESS( ntStatus ) )
|
|||
|
{
|
|||
|
SetLastError( RtlNtStatusToDosError( ntStatus ) );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Create or open the LSA secret
|
|||
|
//
|
|||
|
|
|||
|
RtlInitUnicodeString( &unicodeSecret,
|
|||
|
SecretName );
|
|||
|
|
|||
|
ntStatus = LsaCreateSecret( hPolicy,
|
|||
|
&unicodeSecret,
|
|||
|
SECRET_ALL_ACCESS,
|
|||
|
&hSecret );
|
|||
|
|
|||
|
if ( !NT_SUCCESS( ntStatus ))
|
|||
|
{
|
|||
|
|
|||
|
//
|
|||
|
// If the secret already exists, then we just need to open it
|
|||
|
//
|
|||
|
|
|||
|
if ( ntStatus == STATUS_OBJECT_NAME_COLLISION )
|
|||
|
{
|
|||
|
ntStatus = LsaOpenSecret( hPolicy,
|
|||
|
&unicodeSecret,
|
|||
|
SECRET_ALL_ACCESS,
|
|||
|
&hSecret );
|
|||
|
}
|
|||
|
|
|||
|
if ( !NT_SUCCESS( ntStatus ))
|
|||
|
{
|
|||
|
LsaClose( hPolicy );
|
|||
|
SetLastError( RtlNtStatusToDosError( ntStatus ) );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Set the secret value
|
|||
|
//
|
|||
|
|
|||
|
ntStatus = LsaSetSecret( hSecret,
|
|||
|
&unicodePassword,
|
|||
|
&unicodePassword );
|
|||
|
|
|||
|
LsaClose( hSecret );
|
|||
|
LsaClose( hPolicy );
|
|||
|
|
|||
|
if ( !NT_SUCCESS( ntStatus ))
|
|||
|
{
|
|||
|
return RtlNtStatusToDosError( ntStatus );
|
|||
|
}
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/************************ End of File ***********************/
|