mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
733 lines
12 KiB
733 lines
12 KiB
/*++
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ws2setup
|
|
|
|
Abstract:
|
|
|
|
This module contains a simple setup application for NT WinSock 2.0.
|
|
This application migrates the existing WinSock 1.1 information stored
|
|
in the registry to WinSock 2.0.
|
|
|
|
Author:
|
|
|
|
Keith Moore (keithmo) 9-Oct-1995
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
#include "precomp.h"
|
|
|
|
|
|
//
|
|
// Private constants.
|
|
//
|
|
|
|
#define MAX_REGISTRY_NAME 256
|
|
|
|
#define SERVICES_KEY "System\\CurrentControlSet\\Services"
|
|
|
|
#define WINSOCK_SUBKEY "WinSock"
|
|
#define MIGRATION_SUBKEY "Setup Migration"
|
|
#define WINSOCK2_SUBKEY "WinSock2"
|
|
#define WINSOCK2_PARAM_SUBKEY "WinSock2\\Parameters"
|
|
|
|
#define MAX_CATALOG_NAME_LENGTH 32 // stolen from dll\include\wsautil.h
|
|
|
|
|
|
//
|
|
// Private prototypes.
|
|
//
|
|
|
|
BOOL
|
|
CALLBACK
|
|
MigrationCallback(
|
|
WSA_SETUP_OPCODE Opcode,
|
|
LPVOID Parameter,
|
|
DWORD Context
|
|
);
|
|
|
|
DWORD
|
|
CleanWinsock2Tree(
|
|
VOID
|
|
);
|
|
|
|
DWORD
|
|
OpenServicesRoot(
|
|
PHKEY ServicesKey
|
|
);
|
|
|
|
DWORD
|
|
OpenWinsockRoot(
|
|
HKEY ServicesKey,
|
|
PHKEY WinsockKey
|
|
);
|
|
|
|
DWORD
|
|
OpenWinsock2ParametersRoot(
|
|
HKEY ServicesKey,
|
|
PHKEY Winsock2ParametersKey
|
|
);
|
|
|
|
DWORD
|
|
RecursivelyDeleteRegistryTree(
|
|
HKEY RootKey,
|
|
LPSTR TargetKeyName
|
|
);
|
|
|
|
|
|
//
|
|
// Public functions.
|
|
//
|
|
|
|
INT
|
|
_CRTAPI1
|
|
main(
|
|
INT argc,
|
|
CHAR * argv[]
|
|
)
|
|
{
|
|
|
|
DWORD error;
|
|
WSA_SETUP_DISPOSITION disposition;
|
|
BOOL cleanFirst;
|
|
HMODULE winsockDllHandle;
|
|
LPFN_MIGRATE_WINSOCK_CONFIGURATION migrateWinsockConfiguration;
|
|
|
|
//
|
|
// Interpret the command line arguments.
|
|
//
|
|
|
|
cleanFirst = FALSE;
|
|
|
|
if( argc != 1 ) {
|
|
|
|
if( argc == 2 &&
|
|
_stricmp( argv[1], "clean" ) == 0 ) {
|
|
|
|
cleanFirst = TRUE;
|
|
|
|
} else {
|
|
|
|
printf( "Use: ws2setup [clean]\n" );
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// If necessary, blow away the old WinSock 2.0 tree before continuing.
|
|
// If this fails, tell the user but press on regardless.
|
|
//
|
|
|
|
if( cleanFirst ) {
|
|
|
|
printf( "Cleaning WinSock 2.0 Protocol Catalog..." );
|
|
|
|
error = CleanWinsock2Tree();
|
|
|
|
if( error == NO_ERROR ) {
|
|
|
|
printf( "done\n" );
|
|
|
|
} else {
|
|
|
|
printf( "error %lu\n", error );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Load WSOCK32.DLL. Note that we must dynamically load it; otherwise,
|
|
// it will cache registry data that we may want to delete.
|
|
//
|
|
|
|
winsockDllHandle = LoadLibrary( "WSOCK32.DLL" );
|
|
|
|
if( winsockDllHandle == NULL ) {
|
|
|
|
error = GetLastError();
|
|
|
|
printf( "Cannot load WSOCK32.DLL, error %lu\n", error );
|
|
return 1;
|
|
|
|
}
|
|
|
|
migrateWinsockConfiguration = (PVOID)GetProcAddress(
|
|
winsockDllHandle,
|
|
"MigrateWinsockConfiguration"
|
|
);
|
|
|
|
if( migrateWinsockConfiguration == NULL ) {
|
|
|
|
error = GetLastError();
|
|
|
|
printf( "Cannot find MigrateWinsockConfiguration(), error %lu\n", error );
|
|
return 1;
|
|
|
|
}
|
|
|
|
//
|
|
// Do it.
|
|
//
|
|
|
|
printf( "Updating configuration info...\n" );
|
|
|
|
error = migrateWinsockConfiguration(
|
|
&disposition,
|
|
&MigrationCallback,
|
|
0 );
|
|
|
|
if( error != 0 ) {
|
|
|
|
printf( "MigrateWinsockConfiguration() failed, error %lu\n", error );
|
|
return 1;
|
|
|
|
}
|
|
|
|
switch( disposition ) {
|
|
|
|
case WsaSetupNoChangesMade:
|
|
printf( "No configuration changes necessary\n" );
|
|
break;
|
|
|
|
case WsaSetupChangesMadeRebootNotNecessary:
|
|
case WsaSetupChangesMadeRebootRequired:
|
|
printf( "Configuration changes made successfully\n" );
|
|
break;
|
|
|
|
default:
|
|
printf(
|
|
"MigrateWinsockConfiguration() returned invalid disposition %d\n",
|
|
disposition
|
|
);
|
|
break;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
} // main
|
|
|
|
|
|
//
|
|
// Private functions.
|
|
//
|
|
|
|
BOOL
|
|
CALLBACK
|
|
MigrationCallback(
|
|
WSA_SETUP_OPCODE Opcode,
|
|
LPVOID Parameter,
|
|
DWORD Context
|
|
)
|
|
{
|
|
|
|
switch( Opcode ) {
|
|
|
|
case WsaSetupInstallingProvider :
|
|
printf( " Installing %ls\n", Parameter );
|
|
break;
|
|
|
|
case WsaSetupRemovingProvider :
|
|
printf( " Removing %ls\n", Parameter );
|
|
break;
|
|
|
|
case WsaSetupValidatingProvider :
|
|
printf( " Validating %ls\n", Parameter );
|
|
break;
|
|
|
|
case WsaSetupUpdatingProvider :
|
|
printf( " Updating %ls\n", Parameter );
|
|
break;
|
|
|
|
default :
|
|
printf( "MigrationCallback(): unknown opcode %d\n", Opcode );
|
|
break;
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
} // MigrationCallback
|
|
|
|
|
|
DWORD
|
|
CleanWinsock2Tree(
|
|
VOID
|
|
)
|
|
{
|
|
|
|
DWORD error;
|
|
HKEY servicesKey;
|
|
HKEY winsockKey;
|
|
HKEY winsock2ParametersKey;
|
|
DWORD valueType;
|
|
DWORD valueLength;
|
|
CHAR currentProtocolCatalog[MAX_CATALOG_NAME_LENGTH];
|
|
|
|
//
|
|
// Setup locals so we know how to cleanup on exit.
|
|
//
|
|
|
|
servicesKey = NULL;
|
|
winsockKey = NULL;
|
|
winsock2ParametersKey = NULL;
|
|
|
|
//
|
|
// Open the services registry key.
|
|
//
|
|
|
|
error = OpenServicesRoot(
|
|
&servicesKey
|
|
);
|
|
|
|
if( error != NO_ERROR ) {
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
//
|
|
// Open the winsock registry key.
|
|
//
|
|
|
|
error = OpenWinsockRoot(
|
|
servicesKey,
|
|
&winsockKey
|
|
);
|
|
|
|
if( error != NO_ERROR ) {
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
//
|
|
// Open the winsock2 parameters registry key.
|
|
//
|
|
|
|
error = OpenWinsock2ParametersRoot(
|
|
servicesKey,
|
|
&winsock2ParametersKey
|
|
);
|
|
|
|
if( error != NO_ERROR ) {
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
//
|
|
// Determine the current protocol catalog key name.
|
|
//
|
|
|
|
valueLength = sizeof(currentProtocolCatalog);
|
|
|
|
error = RegQueryValueEx(
|
|
winsock2ParametersKey,
|
|
WINSOCK_CURRENT_PROTOCOL_CATALOG_NAME,
|
|
NULL,
|
|
&valueType,
|
|
currentProtocolCatalog,
|
|
&valueLength
|
|
);
|
|
|
|
if( error == NO_ERROR ) {
|
|
|
|
//
|
|
// Delete the WinSock 2.0 protocol catalog key.
|
|
//
|
|
|
|
error = RecursivelyDeleteRegistryTree(
|
|
winsock2ParametersKey,
|
|
currentProtocolCatalog
|
|
);
|
|
|
|
if( error != NO_ERROR ) {
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// This system's registry does not have the "current catalog"
|
|
// value, so try all catalog names used prior to the introduction
|
|
// of this value.
|
|
//
|
|
// Note that, since we're not taking the trouble to find out
|
|
// exactly which registry key is being used for the protocol
|
|
// catalog, we'll ignore any errors generated by these operations.
|
|
//
|
|
|
|
(VOID)RecursivelyDeleteRegistryTree(
|
|
winsock2ParametersKey,
|
|
"Protocol_Catalog"
|
|
);
|
|
|
|
(VOID)RecursivelyDeleteRegistryTree(
|
|
winsock2ParametersKey,
|
|
"Protocol_Catalog0"
|
|
);
|
|
|
|
(VOID)RecursivelyDeleteRegistryTree(
|
|
winsock2ParametersKey,
|
|
"Protocol_Catalog4"
|
|
);
|
|
|
|
(VOID)RecursivelyDeleteRegistryTree(
|
|
winsock2ParametersKey,
|
|
"Protocol_Catalog5"
|
|
);
|
|
|
|
error = NO_ERROR;
|
|
|
|
}
|
|
|
|
//
|
|
// Delete the setup migration key.
|
|
//
|
|
|
|
error = RecursivelyDeleteRegistryTree(
|
|
winsockKey,
|
|
MIGRATION_SUBKEY
|
|
);
|
|
|
|
if( error != NO_ERROR ) {
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
//
|
|
// Success!
|
|
//
|
|
|
|
exit:
|
|
|
|
if( servicesKey != NULL ) {
|
|
|
|
(VOID)RegCloseKey( servicesKey );
|
|
|
|
}
|
|
|
|
if( winsockKey != NULL ) {
|
|
|
|
(VOID)RegCloseKey( winsockKey );
|
|
|
|
}
|
|
|
|
if( winsock2ParametersKey != NULL ) {
|
|
|
|
(VOID)RegCloseKey( winsock2ParametersKey );
|
|
|
|
}
|
|
|
|
return error;
|
|
|
|
} // CleanWinsock2Tree
|
|
|
|
|
|
DWORD
|
|
OpenServicesRoot(
|
|
PHKEY ServicesKey
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Opens the HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services
|
|
registry key.
|
|
|
|
Arguments:
|
|
|
|
ServicesKey - Will receive a handle to the registry key if successful.
|
|
|
|
Return Value:
|
|
|
|
DWORD - A Win32 status code, 0 if successful, !0 otherwise.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
DWORD error;
|
|
|
|
//
|
|
// Open the key.
|
|
//
|
|
|
|
error = RegOpenKeyEx(
|
|
HKEY_LOCAL_MACHINE,
|
|
SERVICES_KEY,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
ServicesKey
|
|
);
|
|
|
|
return error;
|
|
|
|
} // OpenServicesRoot
|
|
|
|
|
|
DWORD
|
|
OpenWinsockRoot(
|
|
HKEY ServicesKey,
|
|
PHKEY WinsockKey
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Opens the HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\WinSock
|
|
registry key.
|
|
|
|
Arguments:
|
|
|
|
ServicesKey - The handle to the ...\Services key.
|
|
|
|
WinsockKey - Will receive a handle to the WinSock key if successful.
|
|
|
|
Return Value:
|
|
|
|
DWORD - A Win32 status code, 0 if successful, !0 otherwise.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
DWORD error;
|
|
|
|
//
|
|
// Open the WinSock key.
|
|
//
|
|
|
|
error = RegOpenKeyEx(
|
|
ServicesKey,
|
|
WINSOCK_SUBKEY,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
WinsockKey
|
|
);
|
|
|
|
return error;
|
|
|
|
} // OpenWinsockRoot
|
|
|
|
|
|
DWORD
|
|
OpenWinsock2ParametersRoot(
|
|
HKEY ServicesKey,
|
|
PHKEY Winsock2ParametersKey
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Opens the HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\...
|
|
...\WinSock2\Parameters registry key.
|
|
|
|
Arguments:
|
|
|
|
ServicesKey - The handle to the ...\Services key.
|
|
|
|
Winsock2ParametersKey - Will receive a handle to the WinSock2
|
|
parameters key if successful.
|
|
|
|
Return Value:
|
|
|
|
DWORD - A Win32 status code, 0 if successful, !0 otherwise.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
DWORD error;
|
|
|
|
//
|
|
// Open the WinSock2 parameters key.
|
|
//
|
|
|
|
error = RegOpenKeyEx(
|
|
ServicesKey,
|
|
WINSOCK2_PARAM_SUBKEY,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
Winsock2ParametersKey
|
|
);
|
|
|
|
return error;
|
|
|
|
} // OpenWinsock2ParametersRoot
|
|
|
|
|
|
DWORD
|
|
RecursivelyDeleteRegistryTree(
|
|
HKEY RootKey,
|
|
LPSTR TargetKeyName
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Deletes the specified registry key and all subkeys.
|
|
|
|
Arguments:
|
|
|
|
RootKey - A handle to the registry key containing the key to delete.
|
|
|
|
TargetKeyName - The name of the key to delete.
|
|
|
|
Return Value:
|
|
|
|
DWORD - A Win32 status code, 0 if successful, !0 otherwise.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
DWORD error;
|
|
HKEY targetKey;
|
|
FILETIME lastWriteTime;
|
|
DWORD subkeyIndex;
|
|
DWORD subkeyNameLength;
|
|
CHAR subkeyName[MAX_REGISTRY_NAME];
|
|
|
|
//
|
|
// Setup locals so we know how to cleanup on exit.
|
|
//
|
|
|
|
targetKey = NULL;
|
|
|
|
//
|
|
// Open the target key.
|
|
//
|
|
|
|
error = RegOpenKeyEx(
|
|
RootKey,
|
|
TargetKeyName,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
&targetKey
|
|
);
|
|
|
|
if( error == ERROR_FILE_NOT_FOUND ) {
|
|
|
|
error = NO_ERROR;
|
|
goto exit;
|
|
|
|
} else if( error != NO_ERROR ) {
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
//
|
|
// Enumerate & recursively delete the subkeys.
|
|
//
|
|
|
|
subkeyIndex = 0;
|
|
|
|
for( ; ; ) {
|
|
|
|
subkeyNameLength = sizeof(subkeyName);
|
|
|
|
error = RegEnumKeyEx(
|
|
targetKey,
|
|
subkeyIndex,
|
|
subkeyName,
|
|
&subkeyNameLength,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&lastWriteTime
|
|
);
|
|
|
|
if( error != NO_ERROR ) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
error = RecursivelyDeleteRegistryTree(
|
|
targetKey,
|
|
subkeyName
|
|
);
|
|
|
|
if( error != NO_ERROR ) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
//
|
|
// Note that since we just totally blew away the current subkey
|
|
// in the enumeration, we do not want to increment the subkey
|
|
// index.
|
|
//
|
|
|
|
}
|
|
|
|
if( error != ERROR_NO_MORE_ITEMS ) {
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
//
|
|
// Close the target key.
|
|
//
|
|
|
|
error = RegCloseKey( targetKey );
|
|
|
|
targetKey = NULL;
|
|
|
|
if( error != NO_ERROR ) {
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
//
|
|
// Delete the target key.
|
|
//
|
|
|
|
error = RegDeleteKey(
|
|
RootKey,
|
|
TargetKeyName
|
|
);
|
|
|
|
if( error != NO_ERROR ) {
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
//
|
|
// Success!
|
|
//
|
|
|
|
exit:
|
|
|
|
if( targetKey != NULL ) {
|
|
|
|
(VOID)RegCloseKey( targetKey );
|
|
|
|
}
|
|
|
|
return error;
|
|
|
|
} // RecursivelyDeleteRegistryTree
|
|
|