Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

611 lines
13 KiB

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
hookproc.c
Abstract:
This module contains hooker management code for the Winsock 2 to
Winsock 1.1 Mapper Service Provider.
Author:
Keith Moore (keithmo) 29-May-1996
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
PHOOKER_INFORMATION
SockFindAndReferenceHooker(
IN LPGUID ProviderId
)
/*++
Routine Description:
This routine maps the given provider GUID to the corresponding
HOOKER_INFORMATION structure. If the specified hooker has already
been loaded (and therefore has an entry in the global list) its
structure pointer is simply returned. Otherwise, an attempt is made
to load the necessary information from the registry.
Arguments:
ProviderId - A pointer to the GUID identifying a hooker.
Return Value:
PHOOKER_INFORMATION - Pointer to the hooker structure if successful,
NULL otherwise.
--*/
{
PLIST_ENTRY listEntry;
PHOOKER_INFORMATION hookerInfo;
RPC_STATUS status;
UCHAR * str;
LONG err;
DWORD type;
DWORD length;
HINSTANCE dllHandle;
CHAR dllPath[MAX_PATH];
CHAR expandedDllPath[MAX_PATH];
WSADATA wsaData;
INT result;
//
// Sanity check.
//
SOCK_ASSERT( ProviderId != NULL );
//
// Setup locals so we know how to cleanup on exit.
//
str = NULL;
dllHandle = NULL;
//
// Scan the in-memory hooker list.
//
SockAcquireGlobalLock();
for( listEntry = SockHookerListHead.Flink ;
listEntry != &SockHookerListHead ;
listEntry = listEntry->Flink ) {
hookerInfo = CONTAINING_RECORD(
listEntry,
HOOKER_INFORMATION,
HookerListEntry
);
if( GUIDS_ARE_EQUAL( ProviderId, &hookerInfo->ProviderId ) ) {
if( hookerInfo->Initialized ) {
hookerInfo->ReferenceCount++;
} else {
hookerInfo = NULL;
}
goto complete;
}
}
//
// Not found in memory, try to load it from the registry.
//
//
// Prepare for early exit.
//
hookerInfo = NULL;
//
// Open the registry key if not already open.
//
if( SockHookerRegistryKey == NULL ) {
err = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
SOCK_HOOKER_GUID_MAPPER_KEY,
0,
KEY_READ,
&SockHookerRegistryKey
);
if( err != NO_ERROR ) {
SOCK_PRINT((
"SockFindAndReferenceHooker: cannot open %s, error %ld\n",
SOCK_HOOKER_GUID_MAPPER_KEY,
err
));
goto complete;
}
}
//
// Map the GUID to a string.
//
status = UuidToString( ProviderId, &str );
if( status != RPC_S_OK ) {
SOCK_PRINT((
"SockFindAndReferenceHooker: cannot map GUID to string, error %d\n",
status
));
goto complete;
}
//
// Try to load the DLL path from the registry.
//
length = sizeof(dllPath);
err = RegQueryValueEx(
SockHookerRegistryKey,
str,
NULL,
&type,
(LPBYTE)dllPath,
&length
);
if( err != NO_ERROR ) {
SOCK_PRINT((
"SockFindAndReferenceHooker: cannot query %s, error %ld\n",
str,
err
));
goto complete;
}
//
// Expand any embedded environment strings.
//
length = ExpandEnvironmentStrings(
dllPath,
expandedDllPath,
sizeof(expandedDllPath)
);
if( length == 0 ) {
err = GetLastError();
SOCK_PRINT((
"SockFindAndReferenceHooker: cannot expand %s, error %ld\n",
dllPath,
err
));
goto complete;
}
//
// Load the DLL.
//
dllHandle = LoadLibrary( expandedDllPath );
if( dllHandle == NULL ) {
err = GetLastError();
SOCK_PRINT((
"SockFindAndReferenceHooker: cannot load %s, error %ld\n",
expandedDllPath,
err
));
goto complete;
}
//
// Allocate a new hooker.
//
hookerInfo = SOCK_ALLOCATE_HEAP( sizeof(*hookerInfo) );
if( hookerInfo == NULL ) {
goto complete;
}
ZeroMemory(
hookerInfo,
sizeof(*hookerInfo)
);
//
// Find the entrypoints.
//
hookerInfo->accept = (PVOID)GetProcAddress( dllHandle, "accept" );
hookerInfo->bind = (PVOID)GetProcAddress( dllHandle, "bind" );
hookerInfo->closesocket = (PVOID)GetProcAddress( dllHandle, "closesocket" );
hookerInfo->connect = (PVOID)GetProcAddress( dllHandle, "connect" );
hookerInfo->ioctlsocket = (PVOID)GetProcAddress( dllHandle, "ioctlsocket" );
hookerInfo->getpeername = (PVOID)GetProcAddress( dllHandle, "getpeername" );
hookerInfo->getsockname = (PVOID)GetProcAddress( dllHandle, "getsockname" );
hookerInfo->getsockopt = (PVOID)GetProcAddress( dllHandle, "getsockopt" );
hookerInfo->listen = (PVOID)GetProcAddress( dllHandle, "listen" );
hookerInfo->recv = (PVOID)GetProcAddress( dllHandle, "recv" );
hookerInfo->recvfrom = (PVOID)GetProcAddress( dllHandle, "recvfrom" );
hookerInfo->select = (PVOID)GetProcAddress( dllHandle, "select" );
hookerInfo->send = (PVOID)GetProcAddress( dllHandle, "send" );
hookerInfo->sendto = (PVOID)GetProcAddress( dllHandle, "sendto" );
hookerInfo->setsockopt = (PVOID)GetProcAddress( dllHandle, "setsockopt" );
hookerInfo->shutdown = (PVOID)GetProcAddress( dllHandle, "shutdown" );
hookerInfo->socket = (PVOID)GetProcAddress( dllHandle, "socket" );
hookerInfo->WSAStartup = (PVOID)GetProcAddress( dllHandle, "WSAStartup" );
hookerInfo->WSACleanup = (PVOID)GetProcAddress( dllHandle, "WSACleanup" );
hookerInfo->WSAGetLastError = (PVOID)GetProcAddress( dllHandle, "WSAGetLastError" );
hookerInfo->WSAIsBlocking = (PVOID)GetProcAddress( dllHandle, "WSAIsBlocking" );
hookerInfo->WSAUnhookBlockingHook = (PVOID)GetProcAddress( dllHandle, "WSAUnhookBlockingHook" );
hookerInfo->WSASetBlockingHook = (PVOID)GetProcAddress( dllHandle, "WSASetBlockingHook" );
hookerInfo->WSACancelBlockingCall = (PVOID)GetProcAddress( dllHandle, "WSACancelBlockingCall" );
hookerInfo->WSAAsyncSelect = (PVOID)GetProcAddress( dllHandle, "WSAAsyncSelect" );
hookerInfo->gethostname = (PVOID)GetProcAddress( dllHandle, "gethostname" );
hookerInfo->gethostbyname = (PVOID)GetProcAddress( dllHandle, "gethostbyname" );
hookerInfo->gethostbyaddr = (PVOID)GetProcAddress( dllHandle, "gethostbyaddr" );
hookerInfo->getservbyname = (PVOID)GetProcAddress( dllHandle, "getservbyname" );
hookerInfo->getservbyport = (PVOID)GetProcAddress( dllHandle, "getservbyport" );
if( hookerInfo->accept == NULL ||
hookerInfo->bind == NULL ||
hookerInfo->closesocket == NULL ||
hookerInfo->connect == NULL ||
hookerInfo->ioctlsocket == NULL ||
hookerInfo->getpeername == NULL ||
hookerInfo->getsockname == NULL ||
hookerInfo->getsockopt == NULL ||
hookerInfo->listen == NULL ||
hookerInfo->recv == NULL ||
hookerInfo->recvfrom == NULL ||
hookerInfo->select == NULL ||
hookerInfo->send == NULL ||
hookerInfo->sendto == NULL ||
hookerInfo->setsockopt == NULL ||
hookerInfo->shutdown == NULL ||
hookerInfo->socket == NULL ||
hookerInfo->WSAStartup == NULL ||
hookerInfo->WSACleanup == NULL ||
hookerInfo->WSAGetLastError == NULL ||
hookerInfo->WSAIsBlocking == NULL ||
hookerInfo->WSAUnhookBlockingHook == NULL ||
hookerInfo->WSASetBlockingHook == NULL ||
hookerInfo->WSACancelBlockingCall == NULL ||
hookerInfo->WSAAsyncSelect == NULL ||
hookerInfo->gethostname == NULL ||
hookerInfo->gethostbyname == NULL ||
hookerInfo->gethostbyaddr == NULL ||
hookerInfo->getservbyname == NULL ||
hookerInfo->getservbyname == NULL
) {
SOCK_PRINT((
"SockFindAndReferenceHooker: cannot find entrypoints in %s\n",
expandedDllPath
));
SOCK_FREE_HEAP( hookerInfo );
hookerInfo = NULL;
goto complete;
}
//
// Go ahead and put it on the global list, but with the "Initialized"
// flag set to FALSE. We don't set this to TRUE until after we've
// completed the hooker's WSAStartup().
//
hookerInfo->ProviderId = *ProviderId;
SOCK_ASSERT( !hookerInfo->Initialized );
InsertHeadList(
&SockHookerListHead,
&hookerInfo->HookerListEntry
);
//
// Initialize it.
//
// Note that the hooker starts out with a reference count of two;
// one for the "active" reference, and one for the reference added
// by this routine.
//
SockPreApiCallout();
result = hookerInfo->WSAStartup( 0x0101, &wsaData );
SockPostApiCallout();
if( result != NO_ERROR ) {
SOCK_PRINT((
"SockFindAndReferenceHooker: %s:WSAStartup() failed, error %d\n",
expandedDllPath,
result
));
RemoveEntryList(
&hookerInfo->HookerListEntry
);
SOCK_FREE_HEAP( hookerInfo );
hookerInfo = NULL;
goto complete;
}
//
// Finish initializing the hooker.
//
hookerInfo->DllHandle = dllHandle;
hookerInfo->ReferenceCount = 2;
hookerInfo->Initialized = TRUE;
//
// Success!
//
IF_DEBUG(HOOKER) {
SOCK_PRINT((
"SockFindAndReferenceHooker: loaded %s [%s] @ %08lx\n",
str,
dllPath,
hookerInfo
));
}
complete:
SockReleaseGlobalLock();
if( str != NULL ) {
RpcStringFree( &str );
}
if( hookerInfo == NULL && dllHandle != NULL ) {
FreeLibrary( dllHandle );
}
return hookerInfo;
} // SockFindAndReferenceHooker
VOID
SockDereferenceHooker(
IN PHOOKER_INFORMATION HookerInfo
)
/*++
Routine Description:
This routine dereferences the given HOOKER_INFORMATION structure.
If the reference count drops to zero, all resources associated with
the structure are released.
Arguments:
HookerInfo - A pointer to the HOOKER_INFORMATION structure to
dereference.
--*/
{
INT result;
INT err;
//
// Sanity check.
//
SOCK_ASSERT( HookerInfo != NULL );
//
// Dereference the hooker, protected by a lock.
//
SockAcquireGlobalLock();
if( HookerInfo->ReferenceCount-- == 0 ) {
//
// Shut 'er down, Scotty.
//
result = HookerInfo->WSACleanup();
if( result == SOCKET_ERROR ) {
err = HookerInfo->WSAGetLastError();
SOCK_PRINT((
"SockDereferenceHooker: WSACleanup() failed, error %d\n",
err
));
//
// Press on regardless...
//
}
//
// Free the hooker's DLL.
//
FreeLibrary( HookerInfo->DllHandle );
//
// Remove the hooker from the global list.
//
RemoveEntryList( &HookerInfo->HookerListEntry );
//
// Free the hooker itself.
//
SOCK_FREE_HEAP( HookerInfo );
}
SockReleaseGlobalLock();
} // SockDereferenceHooker
VOID
SockReferenceHooker(
IN PHOOKER_INFORMATION HookerInfo
)
/*++
Routine Description:
This routine references the given HOOKER_INFORMATION structure.
Arguments:
HookerInfo - A pointer to the HOOKER_INFORMATION structure to
reference.
--*/
{
//
// Sanity check.
//
SOCK_ASSERT( HookerInfo != NULL );
//
// Reference the hooker, protected by a lock.
//
SockAcquireGlobalLock();
HookerInfo->ReferenceCount++;
SOCK_ASSERT( HookerInfo->ReferenceCount != 0 );
SockReleaseGlobalLock();
} // SockReferenceHooker
VOID
SockFreeAllHookers(
VOID
)
/*++
Routine Description:
This routine frees all allocated HOOKER_INFORMATION structures
and closes the hooker registry key.
--*/
{
PLIST_ENTRY listEntry;
PHOOKER_INFORMATION hookerInfo;
//
// Scan the in-memory hooker list and free 'em.
//
SockAcquireGlobalLock();
for( listEntry = SockHookerListHead.Flink ;
listEntry != &SockHookerListHead ; ) {
hookerInfo = CONTAINING_RECORD(
listEntry,
HOOKER_INFORMATION,
HookerListEntry
);
//
// Dereference the hooker.
//
SockDereferenceHooker( hookerInfo );
}
//
// Close the registry key if necessary.
//
if( SockHookerRegistryKey != NULL ) {
RegCloseKey( SockHookerRegistryKey );
SockHookerRegistryKey = NULL;
}
SockReleaseGlobalLock();
} // SockFreeAllHookers