windows-nt/Source/XPSP1/NT/net/qos/tools/tsinstl/main.c
2020-09-26 16:20:57 +08:00

911 lines
26 KiB
C

//
// Popup choices and install Timestamp driver.
//
// ShreeM (January 31, 1999)
//
// This command line based installation program does the following -
// 1. TcEnumerateInterfaces.
// 2. Display these interfaces to the user.
// 3. Based on the user input - Plumb the registry.
// 4. Ask the user if the service needs to be AUTO or MANUAL.
//
#define UNICODE
#define INITGUID
#include <windows.h>
#include <stdio.h>
#include <objbase.h>
#include <wmium.h>
#include <ntddndis.h>
#include <qos.h>
#include <qossp.h>
#include <wtypes.h>
#include <traffic.h>
#include <tcerror.h>
#include <tcguid.h>
#include <winsock2.h>
#include <ndisguid.h>
#include <tlhelp32.h>
#include <ntddpsch.h>
#define LAST_COMPATIBLE_OS_VERSION 2050
HANDLE hClient = NULL;
ULONG ClientContext = 12;
BOOLEAN WANlink = FALSE;
#define REGKEY_SERVICES TEXT("System\\CurrentControlSet\\Services")
#define REGKEY_PSCHED TEXT("System\\CurrentControlSet\\Services\\Psched")
#define REGKEY_PSCHED_PARAMS TEXT("System\\CurrentControlSet\\Services\\Psched\\Parameters")
#define REGKEY_PSCHED_PARAMS_ADAPTERS TEXT("System\\CurrentControlSet\\Services\\Psched\\Parameters\\Adapters")
#define REGKEY_TIMESTMP TEXT("System\\CurrentControlSet\\Services\\TimeStmp")
TCHAR Profiles[] = TEXT("LANTEST");
TCHAR Lantest[] = TEXT("TokenBucketConformer\0TrafficShaper\0DRRSequencer\0TimeStmp");
//
// Function prototype
//
VOID ShutdownNT();
VOID _stdcall NotifyHandler(
HANDLE ClRegCtx,
HANDLE ClIfcCtx,
ULONG Event,
HANDLE SubCode,
ULONG BufSize,
PVOID Buffer)
{
//
// This function may get executed in a new thread, so we can't fire the events directly (because
// it breaks some clients, like VB and IE.) To get around this, we'll fire off an APC in the origina
// thread, which will handle the actual event firing.
//
OutputDebugString(TEXT("Notify called\n"));
}
//
// Delete the service and cleanup Psched regkeys
//
BOOLEAN
DeleteTimeStamp(PTC_IFC_DESCRIPTOR pIf);
// Just delete the service (no psched stuff)
VOID RemoveTimeStampService();
void _cdecl main(
INT argc,
CHAR *argv[]
)
{
TCI_CLIENT_FUNC_LIST ClientHandlerList;
ULONG err;
TCHAR SzBuf[MAX_PATH], *TBuffer, *KeyBuffer;
ULONG i = 0, len = 0, j = 0, cb = 0, Number = 0, size = 0, interfaceid = 0;
WCHAR servicetype, response;
BYTE *Buffer;
TC_IFC_DESCRIPTOR *pIf, WanIf;
DWORD ret, Disposition, starttype, choice, InstallFlag = -1;
HKEY hConfigKey, TimeStampKey;
SC_HANDLE schService;
SC_HANDLE schSCManager;
BOOLEAN Success = FALSE;
OSVERSIONINFO osversion;
ClientHandlerList.ClNotifyHandler = NotifyHandler;
ClientHandlerList.ClAddFlowCompleteHandler = NULL;
ClientHandlerList.ClModifyFlowCompleteHandler = NULL;
ClientHandlerList.ClDeleteFlowCompleteHandler = NULL;
wprintf(TEXT("Installer for Time Stamp module 1.0 for Windows NT (c) Microsoft Corp.\n\n"));
// check if the psched versions will be compatible before doing anything here.
osversion.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
osversion.dwBuildNumber = 0;
GetVersionEx(&osversion);
if (osversion.dwBuildNumber < LAST_COMPATIBLE_OS_VERSION) {
wprintf(TEXT("Install ERROR!\nYour current Windows 2000 OS build number is %d.\n"), osversion.dwBuildNumber);
wprintf(TEXT("To use the version of TIMESTMP in the QoS Tools CD, you will be required to upgrade \nto an OS build number of atleast 2050 or later.\n"));
return;
}
wprintf(TEXT("Running this program will (un)install this module on one Interface at a time.\n"));
wprintf(TEXT("You will the prompted for basic choices in the installation process.\n"));
j = 0;
get_again:
wprintf(TEXT("[1] Install\n[2] Uninstall\n[3] Exit\n Your Choice:"));
fflush(stdin);
wscanf(TEXT("%d"), &choice);
if (1 == choice) {
InstallFlag = 1;
} else if (2 == choice) {
InstallFlag = 0;
} else if (3 == choice) {
return;
} else if (j < 3) {
j++;
goto get_again;
} else {
return;
}
err = TcRegisterClient(
CURRENT_TCI_VERSION,
(HANDLE)UlongToPtr(ClientContext),
&ClientHandlerList,
&hClient
);
if (NO_ERROR != err) {
hClient = NULL;
wsprintf(SzBuf, TEXT("Error registering Client: %d - %d\n"), err, GetLastError());
OutputDebugString(SzBuf);
wprintf(TEXT("INSTALLER: QoS is not installed on this machine\n\n"));
//
// However, if it should be ok to Uninstall the Timestmp service using this easily.
//
if (0 == InstallFlag) {
RemoveTimeStampService();
}
return;
} else {
OutputDebugString(TEXT("Registered Client:\n"));
}
size = 0;
// Query Buffer Size required.
err = TcEnumerateInterfaces(
hClient,
&size,
(TC_IFC_DESCRIPTOR *)NULL
);
if (NO_ERROR != err) {
wsprintf(SzBuf, TEXT("Error Enumerating Interfaces: %d - (size reqd. %d) \n"), err, size);
OutputDebugString(SzBuf);
} else {
wsprintf(SzBuf, TEXT("Enumerating Interfaces works??? : %d - ITS OK!\n"), size);
OutputDebugString(SzBuf);
wprintf(TEXT("INSTALLER: QoS is either not installed on this machine\n\t OR \n"));
wprintf(TEXT("None of the adapters are enabled for QoS\n"));
//
// However, if it should be ok to Uninstall the Timestmp service using this easily.
//
if (0 == InstallFlag) {
RemoveTimeStampService();
}
wprintf(TEXT("Exiting...\n"));
goto cleanup_no_free;
}
// if there are no interfaces (qos is not installed on this machine), get out.
//
if (!size) {
wprintf(TEXT("INSTALLER: QoS is either not installed on this machine\n\t OR \n"));
wprintf(TEXT("None of the adapters are enabled for QoS\n"));
//
// However, if it should be ok to Uninstall the Timestmp service using this easily.
//
if (0 == InstallFlag) {
RemoveTimeStampService();
}
wprintf(TEXT("Exiting...\n"));
goto cleanup_no_free;
}
// query the interfaces
Buffer = malloc (size);
err = TcEnumerateInterfaces(
hClient,
&size,
(TC_IFC_DESCRIPTOR *)Buffer
);
if (NO_ERROR != err) {
wsprintf(SzBuf, TEXT("Error Enumerating Interfaces: %d (size:%d)!\n"), err, size);
OutputDebugString(SzBuf);
//
// However, if it should be ok to Uninstall the Timestmp service using this easily.
//
if (0 == InstallFlag) {
RemoveTimeStampService();
}
wprintf(TEXT("Exiting...\n"));
goto cleanup;
} else {
OutputDebugString(TEXT("OK, so we got the interfaces.\n"));
}
// Display the interfaces for the user.
wprintf(TEXT("\nThe interfaces available for (un)installing time stamp module are - \n"));
len = 0;
for (i = 1; len < size ; i++) {
pIf = (PTC_IFC_DESCRIPTOR)(Buffer + len);
wprintf(TEXT("[%d]:%ws\n\t%ws\n"), i, pIf->pInterfaceName, pIf->pInterfaceID);
// Move to next interface
len += pIf->Length;
if (NULL != wcsstr(pIf->pInterfaceName, L"WAN")) {
wprintf(TEXT("Please disconnect WAN links before installing Timestmp\n"));
goto cleanup;
}
}
wprintf(TEXT("[%d]:NDISWANIP (the WAN Interface)\n"), i);
// Try to get the interface ID thrice...
j = 0;
get_interfaceid:
wprintf(TEXT("\nYour choice:"));
fflush(stdin);
wscanf(TEXT("%d"), &interfaceid);
if (interfaceid < 1 || (interfaceid > i)) {
j++;
if (j > 2) {
wprintf(TEXT("Invalid Choice - Exiting...\n"));
goto cleanup;
} else {
wprintf(TEXT("Invalid choice - pick again\n"));
goto get_interfaceid;
}
}
// Get to the interface ID for the Interface selected.
pIf = NULL;
len = 0;
if (i == interfaceid) {
wprintf(TEXT("\nInterface selected for (un)installing Time Stamp - \nNdisWanIp\n\n\n"));
WANlink = TRUE;
pIf = NULL;
} else {
for (i = 1; i <= interfaceid ; i++) {
pIf = (PTC_IFC_DESCRIPTOR)(Buffer + len);
wprintf(TEXT("[%d]:%ws\n\t%ws\n"), i, pIf->pInterfaceName, pIf->pInterfaceID);
if (i == interfaceid) {
break;
}
// Move to next interface
len += pIf->Length;
}
wprintf(TEXT("\nInterface selected for (un)installing Time Stamp - \n%ws\n\n\n"), pIf->pInterfaceName);
}
//
// Branch here for Uninstall/Install.
//
if (InstallFlag == FALSE) {
if (!DeleteTimeStamp(pIf)) {
wprintf(TEXT("Delete TimeStamp Failed!\n"));
}
return;
}
//
// This is the regular install path.
//
j = 0;
get_servicetype:
wprintf(TEXT("\nWould you like this service to be- [A]UTO, [M]ANUAL, [D]ISABLED:"));
fflush(stdin);
wscanf(TEXT("%[a-z]"), &servicetype);
switch (towupper(servicetype)) {
case TEXT('A'):
wprintf(TEXT("\nYou have chosen AUTO start up option\n"));
starttype = SERVICE_AUTO_START;
break;
case TEXT('D'):
wprintf(TEXT("\nYou have chosen DISABLED start up option\n"));
starttype = SERVICE_DISABLED;
break;
case TEXT('M'):
wprintf(TEXT("\nYou have chosen MANUAL start up option"));
starttype = SERVICE_DEMAND_START;
break;
default:
if (j > 2) {
wprintf(TEXT("\nIncorrect choice. Exiting...\n"));
goto cleanup;
} else {
j++;
wprintf(TEXT("\nInvalid - Choose again.\n"));
goto get_servicetype;
}
break;
}
wprintf(TEXT("\n\n\n"));
//
// We have enough info to muck with the registry now.
//
// 1.1 open psched regkey and add profile
ret = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
REGKEY_PSCHED_PARAMS,
0,
KEY_ALL_ACCESS,
&hConfigKey);
if (ret !=ERROR_SUCCESS){
wprintf(TEXT("Cant OPEN key\n"));
goto cleanup;
}
ret = RegSetValueEx(
hConfigKey,
TEXT("Profiles"),
0,
REG_MULTI_SZ,
(LPBYTE)Profiles,
sizeof(Profiles)
);
if (ret !=ERROR_SUCCESS){
wprintf(TEXT("Cant SET Value:Profiles\n"));
RegCloseKey(hConfigKey);
goto cleanup;
}
ret = RegSetValueEx(
hConfigKey,
TEXT("LANTEST"),
0,
REG_MULTI_SZ,
(LPBYTE)Lantest,
sizeof(Lantest)
);
if (ret !=ERROR_SUCCESS){
wprintf(TEXT("Cant SET Value:LANTEST\n"));
RegCloseKey(hConfigKey);
goto cleanup;
}
RegCloseKey(hConfigKey);
// 1.2 Open the adapters section and add the profile
if (!WANlink) {
KeyBuffer = malloc(sizeof(TCHAR) * (wcslen(pIf->pInterfaceID) + wcslen(REGKEY_PSCHED_PARAMS_ADAPTERS)));
} else {
KeyBuffer = malloc(sizeof(TCHAR) * (wcslen(TEXT("NdisWanIp")) + wcslen(REGKEY_PSCHED_PARAMS_ADAPTERS)));
}
wcscpy(KeyBuffer, REGKEY_PSCHED_PARAMS_ADAPTERS);
wcscat(KeyBuffer, TEXT("\\"));
if (!WANlink) {
wcscat(KeyBuffer, pIf->pInterfaceID);
} else {
wcscat(KeyBuffer, TEXT("NdisWanIp"));
}
ret = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
KeyBuffer,
0,
KEY_ALL_ACCESS,
&hConfigKey);
if (ret != ERROR_SUCCESS) {
wprintf(TEXT("INSTALLER: Couldn't open Regkey for Adapter specific info\n"));
free(KeyBuffer);
RegCloseKey(hConfigKey);
goto cleanup;
}
ret = RegSetValueEx(
hConfigKey,
TEXT("Profile"),
0,
REG_SZ,
(LPBYTE)Profiles,
sizeof(Profiles)
);
if (ret !=ERROR_SUCCESS){
wprintf(TEXT("Cant SET Value:LANTEST under PARAMETERS\\ADAPTERS\n"));
free(KeyBuffer);
RegCloseKey(hConfigKey);
goto cleanup;
}
free(KeyBuffer);
RegCloseKey(hConfigKey);
// 2. throw in time stamp into the registry
ret = RegCreateKeyEx(
HKEY_LOCAL_MACHINE, // handle of an open key
REGKEY_TIMESTMP, // address of subkey name
0, // reserved
TEXT(""), // address of class string
REG_OPTION_NON_VOLATILE, // special options flag
KEY_ALL_ACCESS, // desired security access
NULL, // address of key security structure
&TimeStampKey, // address of buffer for opened handle
&Disposition // address of disposition value buffer
);
if (ret != ERROR_SUCCESS) {
wprintf(TEXT("Couldn't open Regkey to plumb time stamp module\n"));
RegCloseKey(hConfigKey);
goto cleanup;
}
if (Disposition == REG_OPENED_EXISTING_KEY) {
wprintf(TEXT("Time Stamp module is already installed.\n\n\n\n"));
RegCloseKey(hConfigKey);
goto cleanup;
}
RegCloseKey(hConfigKey);
// 3. Create the service...
schSCManager = OpenSCManager(
NULL, // machine (NULL == local)
NULL, // database (NULL == default)
SC_MANAGER_ALL_ACCESS // access required
);
if ( schSCManager ) {
schService = CreateService(
schSCManager, // SCManager database
TEXT("TimeStmp"), // name of service
TEXT("TimeStmp"), // name to display
SERVICE_ALL_ACCESS, // desired access
SERVICE_KERNEL_DRIVER, // service type
starttype, // start type
SERVICE_ERROR_NORMAL, // error control type
TEXT("System32\\Drivers\\timestmp.sys"), // service's binary
NULL, // no load ordering group
NULL, // no tag identifier
NULL, // BUGBUG: no depend upon PNP_TDI??
NULL, // LocalSystem account
NULL); // no password
if (!schService) {
// couldn't create it.
wprintf(TEXT("Could NOT create Time Stamp service - %d"), GetLastError());
goto cleanup;
} else {
wprintf(TEXT("\nThe service will start on reboot.\n"));
Success = TRUE;
}
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
} else {
wprintf(TEXT("\nINSTALLER: Couldn't open Service Control Manager - Do you have access?\n"));
}
wprintf(TEXT("The Time Stamp module installation is complete.\n"));
wprintf(TEXT("Please ensure that a copy of timestmp.sys exists in your\n"));
wprintf(TEXT("\\system32\\drivers directory before you reboot.\n"));
cleanup:
// cleanup before getting out
free(Buffer);
cleanup_no_free:
// deregister before bailing...
err = TcDeregisterClient(hClient);
if (NO_ERROR != err) {
hClient = NULL;
wsprintf(SzBuf, TEXT("Error DEregistering Client: %d - %d\n"), err, GetLastError());
OutputDebugString(SzBuf);
return;
}
if (Success) {
ShutdownNT();
}
}
//
// Delete the service and cleanup Psched regkeys
//
BOOLEAN
DeleteTimeStamp(PTC_IFC_DESCRIPTOR pIf)
{
SC_HANDLE schService;
SC_HANDLE schSCManager;
TCHAR *KBuffer;
DWORD err;
HKEY hKey;
//
// 1. Delete Timestamp service.
//
schSCManager = OpenSCManager(
NULL, // machine (NULL == local)
NULL, // database (NULL == default)
SC_MANAGER_ALL_ACCESS // access required
);
if ( schSCManager ) {
schService = OpenService(
schSCManager, // handle to service control manager
TEXT("TimeStmp"), // pointer to name of service to start
SERVICE_ALL_ACCESS // type of access to service
);
if (!schService) {
// couldn't open it.
wprintf(TEXT("Could NOT open Time Stamp service - %d\n"), GetLastError());
wprintf(TEXT("Deletion of Time Stamp Service was UNSUCCESSFUL\n"));
//return FALSE;
} else {
if (!DeleteService(schService)) {
wprintf(TEXT("\nThe deletion of Timestamp service has failed - error (%d).\n"), GetLastError());
} else {
wprintf(TEXT("\nThe service will NOT start on reboot.\n"));
}
}
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
} else {
wprintf(TEXT("\nINSTALLER: Couldn't open Service Control Manager - Do you have access?\n"));
}
//
// 2. Clean up psched registry.
//
err = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
REGKEY_PSCHED_PARAMS,
0,
KEY_ALL_ACCESS,
&hKey);
if (err !=ERROR_SUCCESS){
wprintf(TEXT("Cant OPEN key\n"));
return FALSE;
}
err = RegDeleteValue(
hKey,
TEXT("Profiles")
);
if (err !=ERROR_SUCCESS){
wprintf(TEXT("Cant Delete Value:Profiles\n"));
RegCloseKey(hKey);
return FALSE;
}
err = RegDeleteValue(
hKey,
TEXT("LANTEST")
);
if (err != ERROR_SUCCESS){
wprintf(TEXT("Cant Delete Value:LANTEST\n"));
RegCloseKey(hKey);
return FALSE;
}
RegCloseKey(hKey);
// 2.2 Clean up the adapter specific registry
if (!WANlink) {
KBuffer = malloc(sizeof(TCHAR) * (wcslen(pIf->pInterfaceID) + wcslen(REGKEY_PSCHED_PARAMS_ADAPTERS)));
} else {
KBuffer = malloc(sizeof(TCHAR) * (wcslen(TEXT("NdisWanIp")) + wcslen(REGKEY_PSCHED_PARAMS_ADAPTERS)));
}
wcscpy(KBuffer, REGKEY_PSCHED_PARAMS_ADAPTERS);
wcscat(KBuffer, TEXT("\\"));
if (!WANlink) {
wcscat(KBuffer, pIf->pInterfaceID);
} else {
wcscat(KBuffer, TEXT("NdisWanIp"));
}
err = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
KBuffer,
0,
KEY_ALL_ACCESS,
&hKey);
if (err != ERROR_SUCCESS) {
wprintf(TEXT("INSTALLER: Couldn't open Regkey for Adapter specific info\n"));
wprintf(TEXT("INSTALLER: CLEAN UP is partial\n"));
free(KBuffer);
return FALSE;
}
err = RegDeleteValue(
hKey,
TEXT("Profile")
);
if (err !=ERROR_SUCCESS){
wprintf(TEXT("Cant Delete Value:LANTEST under PARAMETERS\\ADAPTERS\n"));
wprintf(TEXT("INSTALLER: CLEAN UP is partial\n"));
free(KBuffer);
RegCloseKey(hKey);
return FALSE;
}
free(KBuffer);
RegCloseKey(hKey);
wprintf(TEXT("The Time Stamp service is successfully deleted\n"));
wprintf(TEXT("You need to reboot for the changes to take effect\n"));
return TRUE;
}
// Just delete the service (no psched stuff)
VOID RemoveTimeStampService(
)
{
SC_HANDLE schService;
SC_HANDLE schSCManager;
TCHAR *KBuffer;
DWORD err;
HKEY hKey;
//
// 1. Delete Timestamp service.
//
schSCManager = OpenSCManager(
NULL, // machine (NULL == local)
NULL, // database (NULL == default)
SC_MANAGER_ALL_ACCESS // access required
);
if ( schSCManager ) {
schService = OpenService(
schSCManager, // handle to service control manager
TEXT("TimeStmp"), // pointer to name of service to start
SERVICE_ALL_ACCESS // type of access to service
);
if (!schService) {
// couldn't open it.
wprintf(TEXT("Could NOT open Time Stamp service - %d\n"), GetLastError());
wprintf(TEXT("Deletion of Time Stamp Service was UNSUCCESSFUL\n"));
return;
} else {
if (!DeleteService(schService)) {
wprintf(TEXT("\nThe deletion of Timestamp service has failed - error (%d).\n"), GetLastError());
} else {
wprintf(TEXT("\nThe service will NOT start on reboot.\n"));
}
}
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
} else {
wprintf(TEXT("\nINSTALLER: Couldn't open Service Control Manager - Do you have access?\n"));
}
wprintf(TEXT("The Time Stamp service is successfully deleted\n"));
wprintf(TEXT("You need to reboot for the changes to take effect\n"));
return;
}
VOID ShutdownNT()
{
HANDLE hToken; // handle to process token
TOKEN_PRIVILEGES tkp; // ptr. to token structure
TCHAR SzBuf[MAX_PATH];
BOOL fResult; // system shutdown flag
INT nRet = IDYES;
// Get the curren process token handle
// so we can get shutdown privilege.
if (!OpenProcessToken (GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
wsprintf(SzBuf, TEXT("OpenProcessToken failed (%d)\n"), GetLastError());
OutputDebugString(SzBuf);
return;
}
// Get the LUID for shutdown privilege
LookupPrivilegeValue (NULL, SE_SHUTDOWN_NAME,
&tkp.Privileges[0].Luid);
tkp.PrivilegeCount = 1; // one privilege to set
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
// Get shutdown privileges for this process
AdjustTokenPrivileges (hToken,
FALSE,
&tkp,
0,
(PTOKEN_PRIVILEGES) NULL,
0);
// Cannot test the return value of AdjustTokenPrivileges
if (GetLastError() != ERROR_SUCCESS) {
wsprintf(SzBuf, TEXT("AdjustTokenPriviledges failed (%d)\n"), GetLastError());
OutputDebugString(SzBuf);
CloseHandle(hToken);
return;
}
CloseHandle(hToken);
/*if (!InitiateSystemShutdownEx(
NULL,
,
0xffffff00,
FALSE, //BOOL bForceAppsClosed,
TRUE, //BOOL bRebootAfterShutdown,
0 //DWORD dwReason
)) {*/
//
// OK, so how about a popup?
//
nRet = MessageBox (
NULL,//hwndParent,
TEXT("A reboot is required for TimeStamp Driver to get loaded. Please ensure that your %windir%\\system32\\driver's directory has a copy of timestmp.sys. Reboot now?"),
TEXT("TIMESTAMP Driver Install Program"),
MB_YESNO | MB_ICONEXCLAMATION
);
if (nRet == IDYES) {
if (!ExitWindowsEx(EWX_REBOOT, 10)) {
wsprintf(SzBuf, TEXT("InitializeShutdownEx failed (%d)\n"), GetLastError());
OutputDebugString(SzBuf);
} else {
return;
}
}
return;
}