824 lines
14 KiB
C
824 lines
14 KiB
C
/*++
|
||
|
||
Copyright (c) 1999-1999 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
dtsetup.c
|
||
|
||
Abstract:
|
||
|
||
Simple Duct-Tape setup.
|
||
|
||
Author:
|
||
|
||
Keith Moore (keithmo) 02-Sep-1999
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
|
||
#include "precomp.h"
|
||
#pragma hdrstop
|
||
|
||
|
||
//
|
||
// Configuration data.
|
||
//
|
||
|
||
#define UL_SERVICE_NAME L"UL"
|
||
#define UL_DISPLAY_NAME L"UL"
|
||
#define UL_DRIVER_NAME L"UL.SYS"
|
||
#define UL_DEPENDENCIES NULL
|
||
|
||
#define WAS_SERVICE_NAME L"IISW3ADM"
|
||
#define WAS_DISPLAY_NAME L"IIS Web Admin Service"
|
||
#define WAS_DLL_NAME L"iisw3adm.dll"
|
||
#define WAS_DEPENDENCIES L"UL"
|
||
#define WAS_COMMAND_LINE L"%SystemRoot%\\System32\\svchost.exe -k iissvcs"
|
||
#define WAS_PARAM_KEY L"System\\CurrentControlSet\\Services\\iisw3adm\\Parameters"
|
||
#define WAS_EVENT_KEY L"System\\CurrentControlSet\\Services\\EventLog\\System\\WAS"
|
||
#define WAS_SVCHOST_KEY L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Svchost"
|
||
|
||
#define SERVICE_DLL_VALUE L"ServiceDll"
|
||
#define EVENT_MESSAGE_VALUE L"EventMessageFile"
|
||
#define SVCHOST_VALUE L"iissvcs"
|
||
|
||
#define CATALOG_DLL_NAME L"catalog.dll"
|
||
#define CATALOG_KEY L"Software\\Microsoft\\Catalog42"
|
||
#define CATALOG_URT_VALUE L"URT"
|
||
|
||
|
||
//
|
||
// Our command table.
|
||
//
|
||
|
||
typedef
|
||
VOID
|
||
(* PFN_COMMAND)(
|
||
IN INT argc,
|
||
IN PWSTR argv[]
|
||
);
|
||
|
||
typedef struct _COMMAND_ENTRY
|
||
{
|
||
PWSTR pCommandName;
|
||
PWSTR pUsageHelp;
|
||
PFN_COMMAND pCommandHandler;
|
||
|
||
} COMMAND_ENTRY, *PCOMMAND_ENTRY;
|
||
|
||
|
||
//
|
||
// Private prototypes.
|
||
//
|
||
|
||
VOID
|
||
Usage(
|
||
VOID
|
||
);
|
||
|
||
PCOMMAND_ENTRY
|
||
FindCommandByName(
|
||
IN PWSTR pCommand
|
||
);
|
||
|
||
VOID
|
||
DoInstall(
|
||
IN INT argc,
|
||
IN PWSTR argv[]
|
||
);
|
||
|
||
VOID
|
||
DoRemove(
|
||
IN INT argc,
|
||
IN PWSTR argv[]
|
||
);
|
||
|
||
DWORD
|
||
InstallUL(
|
||
IN PWSTR pBaseDirectory
|
||
);
|
||
|
||
DWORD
|
||
InstallWAS(
|
||
IN PWSTR pBaseDirectory
|
||
);
|
||
|
||
DWORD
|
||
InstallCatalog(
|
||
IN PWSTR pBaseDirectory
|
||
);
|
||
|
||
VOID
|
||
RemoveCatalog(
|
||
VOID
|
||
);
|
||
|
||
VOID
|
||
RemoveWAS(
|
||
VOID
|
||
);
|
||
|
||
VOID
|
||
RemoveUL(
|
||
VOID
|
||
);
|
||
|
||
DWORD
|
||
InstallService(
|
||
IN PWSTR pServiceName,
|
||
IN PWSTR pDisplayName OPTIONAL,
|
||
IN PWSTR pBinPath,
|
||
IN PWSTR pDependencies OPTIONAL,
|
||
IN DWORD ServiceType,
|
||
IN DWORD StartType,
|
||
IN DWORD ErrorControl
|
||
);
|
||
|
||
DWORD
|
||
RemoveService(
|
||
IN PWSTR pServiceName
|
||
);
|
||
|
||
DWORD
|
||
WriteRegValue(
|
||
IN PWSTR pKeyName,
|
||
IN PWSTR pValueName,
|
||
IN PWSTR pValue
|
||
);
|
||
|
||
DWORD
|
||
DeleteRegKey(
|
||
IN PWSTR pKeyName
|
||
);
|
||
|
||
|
||
//
|
||
// Private globals.
|
||
//
|
||
|
||
COMMAND_ENTRY CommandTable[] =
|
||
{
|
||
{
|
||
L"install",
|
||
L"install UL and WAS",
|
||
&DoInstall
|
||
},
|
||
|
||
{
|
||
L"remove",
|
||
L"remove UL and WAS",
|
||
&DoRemove
|
||
}
|
||
|
||
};
|
||
|
||
#define NUM_COMMAND_ENTRIES (sizeof(CommandTable) / sizeof(CommandTable[0]))
|
||
|
||
|
||
//
|
||
// Public functions.
|
||
//
|
||
|
||
|
||
INT
|
||
__cdecl
|
||
wmain(
|
||
INT argc,
|
||
PWSTR argv[]
|
||
)
|
||
{
|
||
PCOMMAND_ENTRY pEntry;
|
||
|
||
//
|
||
// Find the command handler.
|
||
//
|
||
|
||
if (argc == 1)
|
||
{
|
||
pEntry = NULL;
|
||
}
|
||
else
|
||
{
|
||
pEntry = FindCommandByName( argv[1] );
|
||
}
|
||
|
||
if (pEntry == NULL)
|
||
{
|
||
Usage();
|
||
return 1;
|
||
}
|
||
|
||
//
|
||
// Call the handler.
|
||
//
|
||
|
||
argc--;
|
||
argv++;
|
||
|
||
(pEntry->pCommandHandler)( argc, argv );
|
||
|
||
return 0;
|
||
|
||
} // wmain
|
||
|
||
|
||
//
|
||
// Private functions.
|
||
//
|
||
|
||
PCOMMAND_ENTRY
|
||
FindCommandByName(
|
||
IN PWSTR pCommand
|
||
)
|
||
{
|
||
PCOMMAND_ENTRY pEntry;
|
||
INT i;
|
||
|
||
for (i = NUM_COMMAND_ENTRIES, pEntry = &CommandTable[0] ;
|
||
i > 0 ;
|
||
i--, pEntry++)
|
||
{
|
||
if (_wcsicmp( pCommand, pEntry->pCommandName ) == 0)
|
||
{
|
||
return pEntry;
|
||
}
|
||
}
|
||
|
||
return NULL;
|
||
|
||
} // FindCommandByName
|
||
|
||
|
||
VOID
|
||
Usage(
|
||
VOID
|
||
)
|
||
{
|
||
PCOMMAND_ENTRY pEntry;
|
||
INT i;
|
||
INT maxLength;
|
||
INT len;
|
||
|
||
//
|
||
// Scan the command table, searching for the longest command name.
|
||
// (This makes the output much prettier...)
|
||
//
|
||
|
||
maxLength = 0;
|
||
|
||
for (i = NUM_COMMAND_ENTRIES, pEntry = &CommandTable[0] ;
|
||
i > 0 ;
|
||
i--, pEntry++)
|
||
{
|
||
len = wcslen( pEntry->pCommandName );
|
||
|
||
if (len > maxLength)
|
||
{
|
||
maxLength = len;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Now display the usage information.
|
||
//
|
||
|
||
wprintf(
|
||
L"use: dtsetup action [options]\n"
|
||
L"\n"
|
||
L"valid actions are:\n"
|
||
L"\n"
|
||
);
|
||
|
||
for (i = NUM_COMMAND_ENTRIES, pEntry = &CommandTable[0] ;
|
||
i > 0 ;
|
||
i--, pEntry++)
|
||
{
|
||
wprintf(
|
||
L" %-*s - %s\n",
|
||
maxLength,
|
||
pEntry->pCommandName,
|
||
pEntry->pUsageHelp
|
||
);
|
||
}
|
||
|
||
} // Usage
|
||
|
||
|
||
VOID
|
||
DoInstall(
|
||
IN INT argc,
|
||
IN PWSTR argv[]
|
||
)
|
||
{
|
||
PWSTR pBaseDirectory;
|
||
DWORD err;
|
||
|
||
//
|
||
// Validate the arguments.
|
||
//
|
||
|
||
if (argc != 2)
|
||
{
|
||
wprintf( L"use: dtsetup install directory\n" );
|
||
return;
|
||
}
|
||
|
||
//
|
||
// Install 'em.
|
||
//
|
||
|
||
wprintf( L"installing UL..." );
|
||
err = InstallUL( argv[1] );
|
||
|
||
if (err != NO_ERROR)
|
||
{
|
||
wprintf( L"error %lu\n", err );
|
||
return;
|
||
}
|
||
|
||
wprintf( L"done\n" );
|
||
|
||
wprintf( L"installing WAS..." );
|
||
err = InstallWAS( argv[1] );
|
||
|
||
if (err != NO_ERROR)
|
||
{
|
||
wprintf( L"error %lu\n", err );
|
||
RemoveUL();
|
||
return;
|
||
}
|
||
|
||
wprintf( L"done\n" );
|
||
|
||
wprintf( L"installing Catalog..." );
|
||
err = InstallCatalog( argv[1] );
|
||
|
||
if (err != NO_ERROR)
|
||
{
|
||
wprintf( L"error %lu\n", err );
|
||
RemoveWAS();
|
||
RemoveUL();
|
||
return;
|
||
}
|
||
|
||
wprintf( L"done\n" );
|
||
|
||
//
|
||
// Success!
|
||
//
|
||
|
||
} // DoInstall
|
||
|
||
|
||
VOID
|
||
DoRemove(
|
||
IN INT argc,
|
||
IN PWSTR argv[]
|
||
)
|
||
{
|
||
//
|
||
// Validate the arguments.
|
||
//
|
||
|
||
if (argc != 1)
|
||
{
|
||
wprintf( L"use: dtsetup remove\n" );
|
||
return;
|
||
}
|
||
|
||
//
|
||
// Remove 'em.
|
||
//
|
||
|
||
wprintf( L"removing Catalog..." );
|
||
RemoveCatalog();
|
||
wprintf( L"done\n" );
|
||
|
||
wprintf( L"removing WAS..." );
|
||
RemoveWAS();
|
||
wprintf( L"done\n" );
|
||
|
||
wprintf( L"removing UL..." );
|
||
RemoveUL();
|
||
wprintf( L"done\n" );
|
||
|
||
} // DoRemove
|
||
|
||
|
||
DWORD
|
||
InstallUL(
|
||
IN PWSTR pBaseDirectory
|
||
)
|
||
{
|
||
DWORD err;
|
||
WCHAR binPath[MAX_PATH];
|
||
|
||
//
|
||
// Build the path to the driver.
|
||
//
|
||
|
||
wcscpy( binPath, pBaseDirectory );
|
||
|
||
if (binPath[wcslen(binPath) - 1] != L'\\')
|
||
{
|
||
wcscat( binPath, L"\\" );
|
||
}
|
||
|
||
wcscat( binPath, UL_DRIVER_NAME );
|
||
|
||
//
|
||
// Install it.
|
||
//
|
||
|
||
err = InstallService(
|
||
UL_SERVICE_NAME, // pServiceName
|
||
UL_DISPLAY_NAME, // pDisplayName
|
||
binPath, // pBinPath
|
||
UL_DEPENDENCIES, // pDependencies
|
||
SERVICE_KERNEL_DRIVER, // ServiceType
|
||
SERVICE_DEMAND_START, // StartType
|
||
SERVICE_ERROR_NORMAL // ErrorControl
|
||
);
|
||
|
||
return err;
|
||
|
||
} // InstallUL
|
||
|
||
|
||
DWORD
|
||
InstallWAS(
|
||
IN PWSTR pBaseDirectory
|
||
)
|
||
{
|
||
DWORD err;
|
||
WCHAR binPath[MAX_PATH];
|
||
|
||
//
|
||
// Build the path to the service.
|
||
//
|
||
|
||
wcscpy( binPath, pBaseDirectory );
|
||
|
||
if (binPath[wcslen(binPath) - 1] != L'\\')
|
||
{
|
||
wcscat( binPath, L"\\" );
|
||
}
|
||
|
||
wcscat( binPath, WAS_DLL_NAME );
|
||
|
||
//
|
||
// Install it.
|
||
//
|
||
|
||
err = InstallService(
|
||
WAS_SERVICE_NAME, // pServiceName
|
||
WAS_DISPLAY_NAME, // pDisplayName
|
||
WAS_COMMAND_LINE, // pBinPath
|
||
WAS_DEPENDENCIES, // pDependencies
|
||
SERVICE_WIN32_SHARE_PROCESS | // ServiceType
|
||
SERVICE_INTERACTIVE_PROCESS,
|
||
SERVICE_DEMAND_START, // StartType
|
||
SERVICE_ERROR_NORMAL // ErrorControl
|
||
);
|
||
|
||
if (err == NO_ERROR)
|
||
{
|
||
err = WriteRegValue(
|
||
WAS_PARAM_KEY, // pKeyName
|
||
SERVICE_DLL_VALUE, // pValueName
|
||
binPath // pValue
|
||
);
|
||
}
|
||
|
||
if (err == NO_ERROR)
|
||
{
|
||
err = WriteRegValue(
|
||
WAS_EVENT_KEY, // pKeyName
|
||
EVENT_MESSAGE_VALUE, // pValueName
|
||
binPath // pValue
|
||
);
|
||
}
|
||
|
||
if (err == NO_ERROR)
|
||
{
|
||
err = WriteRegValue(
|
||
WAS_SVCHOST_KEY, // pKeyName
|
||
SVCHOST_VALUE, // pValueName
|
||
WAS_SERVICE_NAME // pValue
|
||
);
|
||
}
|
||
|
||
return err;
|
||
|
||
} // InstallWAS
|
||
|
||
|
||
DWORD
|
||
InstallCatalog(
|
||
IN PWSTR pBaseDirectory
|
||
)
|
||
{
|
||
DWORD err;
|
||
WCHAR binPath[MAX_PATH];
|
||
|
||
//
|
||
// Build the path to the service.
|
||
//
|
||
|
||
wcscpy( binPath, pBaseDirectory );
|
||
|
||
if (binPath[wcslen(binPath) - 1] != L'\\')
|
||
{
|
||
wcscat( binPath, L"\\" );
|
||
}
|
||
|
||
wcscat( binPath, CATALOG_DLL_NAME );
|
||
|
||
//
|
||
// Install it.
|
||
//
|
||
|
||
err = WriteRegValue(
|
||
CATALOG_KEY, // pKeyName
|
||
CATALOG_URT_VALUE, // pValueName
|
||
binPath // pValue
|
||
);
|
||
|
||
return err;
|
||
|
||
} // InstallCatalog
|
||
|
||
|
||
VOID
|
||
RemoveCatalog(
|
||
VOID
|
||
)
|
||
{
|
||
(VOID)DeleteRegKey( CATALOG_KEY );
|
||
|
||
} // RemoveCatalog
|
||
|
||
|
||
VOID
|
||
RemoveWAS(
|
||
VOID
|
||
)
|
||
{
|
||
(VOID)RemoveService( WAS_SERVICE_NAME );
|
||
(VOID)DeleteRegKey( WAS_EVENT_KEY );
|
||
|
||
} // RemoveWAS
|
||
|
||
|
||
VOID
|
||
RemoveUL(
|
||
VOID
|
||
)
|
||
{
|
||
(VOID)RemoveService( UL_SERVICE_NAME );
|
||
|
||
} // RemoveUL
|
||
|
||
|
||
DWORD
|
||
InstallService(
|
||
IN PWSTR pServiceName,
|
||
IN PWSTR pDisplayName OPTIONAL,
|
||
IN PWSTR pBinPath,
|
||
IN PWSTR pDependencies OPTIONAL,
|
||
IN DWORD ServiceType,
|
||
IN DWORD StartType,
|
||
IN DWORD ErrorControl
|
||
)
|
||
{
|
||
SC_HANDLE scHandle;
|
||
SC_HANDLE svcHandle;
|
||
DWORD err;
|
||
|
||
//
|
||
// Setup locals so we know how to cleanup on exit.
|
||
//
|
||
|
||
scHandle = NULL;
|
||
svcHandle = NULL;
|
||
|
||
//
|
||
// If no display name specified, just use the service name.
|
||
//
|
||
|
||
if (pDisplayName == NULL)
|
||
{
|
||
pDisplayName = pServiceName;
|
||
}
|
||
|
||
//
|
||
// Open the service controller.
|
||
//
|
||
|
||
scHandle = OpenSCManagerW(
|
||
NULL, // lpMachineName
|
||
NULL, // lpDatabaseName
|
||
SC_MANAGER_ALL_ACCESS // dwDesiredAccess
|
||
);
|
||
|
||
if (scHandle == NULL)
|
||
{
|
||
err = GetLastError();
|
||
goto cleanup;
|
||
}
|
||
|
||
//
|
||
// Create the service.
|
||
//
|
||
|
||
svcHandle = CreateServiceW(
|
||
scHandle, // hSCManager
|
||
pServiceName, // lpServiceName
|
||
pDisplayName, // lpDisplayName
|
||
SERVICE_ALL_ACCESS, // dwDesiredAccess
|
||
ServiceType, // dwServiceType
|
||
StartType, // dwStartType
|
||
ErrorControl, // dwErrorControl
|
||
pBinPath, // lpBinaryPathName
|
||
NULL, // lpLoadOrderGroup
|
||
NULL, // lpdwTagId
|
||
pDependencies, // lpDependencies
|
||
NULL, // lpServiceStartName
|
||
NULL // lpPassword
|
||
);
|
||
|
||
if (svcHandle == NULL)
|
||
{
|
||
err = GetLastError();
|
||
goto cleanup;
|
||
}
|
||
|
||
//
|
||
// Success!
|
||
//
|
||
|
||
err = 0;
|
||
|
||
cleanup:
|
||
|
||
if (svcHandle != NULL)
|
||
{
|
||
CloseServiceHandle( svcHandle );
|
||
}
|
||
|
||
if (scHandle != NULL)
|
||
{
|
||
CloseServiceHandle( scHandle );
|
||
}
|
||
|
||
return err;
|
||
|
||
} // InstallService
|
||
|
||
|
||
DWORD
|
||
RemoveService(
|
||
IN PWSTR pServiceName
|
||
)
|
||
{
|
||
SC_HANDLE scHandle;
|
||
SC_HANDLE svcHandle;
|
||
DWORD err;
|
||
|
||
//
|
||
// Setup locals so we know how to cleanup on exit.
|
||
//
|
||
|
||
scHandle = NULL;
|
||
svcHandle = NULL;
|
||
|
||
//
|
||
// Open the service controller.
|
||
//
|
||
|
||
scHandle = OpenSCManagerW(
|
||
NULL, // lpMachineName
|
||
NULL, // lpDatabaseName
|
||
SC_MANAGER_ALL_ACCESS // dwDesiredAccess
|
||
);
|
||
|
||
if (scHandle == NULL)
|
||
{
|
||
err = GetLastError();
|
||
goto cleanup;
|
||
}
|
||
|
||
//
|
||
// Open the service.
|
||
//
|
||
|
||
svcHandle = OpenServiceW(
|
||
scHandle, // hSCManager
|
||
pServiceName, // lpServiceName
|
||
SERVICE_ALL_ACCESS // dwDesiredAccess
|
||
);
|
||
|
||
if (svcHandle == NULL)
|
||
{
|
||
err = GetLastError();
|
||
goto cleanup;
|
||
}
|
||
|
||
//
|
||
// Delete it.
|
||
//
|
||
|
||
if (!DeleteService( svcHandle ))
|
||
{
|
||
err = GetLastError();
|
||
goto cleanup;
|
||
}
|
||
|
||
//
|
||
// Success!
|
||
//
|
||
|
||
err = 0;
|
||
|
||
cleanup:
|
||
|
||
if (svcHandle != NULL)
|
||
{
|
||
CloseServiceHandle( svcHandle );
|
||
}
|
||
|
||
if (scHandle != NULL)
|
||
{
|
||
CloseServiceHandle( scHandle );
|
||
}
|
||
|
||
return err;
|
||
|
||
} // RemoveService
|
||
|
||
|
||
DWORD
|
||
WriteRegValue(
|
||
IN PWSTR pKeyName,
|
||
IN PWSTR pValueName,
|
||
IN PWSTR pValue
|
||
)
|
||
{
|
||
DWORD err;
|
||
HKEY key;
|
||
DWORD disposition;
|
||
DWORD length;
|
||
|
||
err = RegCreateKeyExW(
|
||
HKEY_LOCAL_MACHINE, // hKey
|
||
pKeyName, // lpSubKey
|
||
0, // Reserved
|
||
NULL, // lpClass
|
||
REG_OPTION_NON_VOLATILE, // dwOptions
|
||
KEY_ALL_ACCESS, // samDesired
|
||
NULL, // lpSecurityAttributes,
|
||
&key, // phkResult
|
||
&disposition // lpdwDisposition
|
||
);
|
||
|
||
if (err == NO_ERROR)
|
||
{
|
||
length = (wcslen(pValue) + 1) * sizeof(pValue[0]);
|
||
|
||
err = RegSetValueExW(
|
||
key, // hKey
|
||
pValueName, // lpValueName
|
||
0, // Reserved
|
||
REG_EXPAND_SZ, // dwType
|
||
(CONST BYTE *)pValue, // lpData
|
||
length // cbData
|
||
);
|
||
|
||
RegCloseKey( key );
|
||
}
|
||
|
||
return err;
|
||
|
||
} // WriteRegValue
|
||
|
||
|
||
DWORD
|
||
DeleteRegKey(
|
||
IN PWSTR pKeyName
|
||
)
|
||
{
|
||
DWORD err;
|
||
|
||
err = RegDeleteKeyW(
|
||
HKEY_LOCAL_MACHINE,
|
||
pKeyName
|
||
);
|
||
|
||
return err;
|
||
|
||
} // DeleteRegKey
|
||
|