1457 lines
48 KiB
C++
1457 lines
48 KiB
C++
//
|
|
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
|
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
|
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
|
// PARTICULAR PURPOSE.
|
|
//
|
|
// Copyright (C) 2004 Microsoft Corporation. All Rights Reserved.
|
|
//
|
|
// Module Name: lspadd.cpp
|
|
//
|
|
// Description:
|
|
//
|
|
// This file contains the routines used in installing an LSP into the Winsock
|
|
// catalog. This file also contains routines for changing the Winsock provider
|
|
// order since the catalog is typically reordered upon LSP installation.
|
|
// See instlsp.cpp for more information on running this code.
|
|
//
|
|
#include "instlsp.h"
|
|
|
|
//
|
|
// Function: InstallLsp
|
|
//
|
|
// Description:
|
|
// This function installs the LSP over each of the catalog IDs supplied in
|
|
// the pdwCatalogIdArray into the given Winsock catalog (since there are
|
|
// two catalogs on WIN64 platforms). This routine first installs the layered
|
|
// protocol entry (the dummy hidden provider) followed by installing the
|
|
// layered protocol chains.
|
|
//
|
|
int
|
|
InstallLsp(
|
|
WINSOCK_CATALOG eCatalog, // Which catalog to install LSP into
|
|
__in_z char *lpszLspName, // String name of LSP
|
|
__in_z char *lpszLspPathAndFile, // Location of 64-bit LSP dll and dll name
|
|
__in_z char *lpszLspPathAndFile32, // Location of 32-bit LSP dll and dll name
|
|
DWORD dwCatalogIdArrayCount, // Number of entries in pdwCatalogIdArray
|
|
DWORD *pdwCatalogIdArray, // Array of IDs to install over
|
|
BOOL IfsProvider,
|
|
BOOL InstallOverAll
|
|
)
|
|
{
|
|
OSVERSIONINFOEX osv = {0};
|
|
WSAPROTOCOL_INFOW *pProtocolInfo = NULL,
|
|
*pDummyEntry = NULL,
|
|
*pLayeredEntries = NULL;
|
|
WCHAR wszLspName[ WSAPROTOCOL_LEN ],
|
|
wszFullProviderPath[ MAX_PATH+1 ],
|
|
wszFullProviderPath32[ MAX_PATH+1 ];
|
|
GUID ProviderBaseGuid;
|
|
INT rc = SOCKET_ERROR;
|
|
|
|
//
|
|
// Install the LSP over the given entries. If selected to install over all
|
|
// entries, then enumerate the catalog to obtain all the available providers.
|
|
//
|
|
|
|
if ( NULL == lpszLspName )
|
|
{
|
|
lpszLspName = DEFAULT_LSP_NAME;
|
|
}
|
|
|
|
// Convert the LSP name to UNICODE since the Winsock catalog is all UNICODE
|
|
rc = MultiByteToWideChar(
|
|
CP_ACP,
|
|
0,
|
|
lpszLspName,
|
|
(int) strlen( lpszLspName ) + 1,
|
|
wszLspName,
|
|
WSAPROTOCOL_LEN
|
|
);
|
|
if (rc == 0)
|
|
{
|
|
fprintf(stderr, "InstallLsp: MultiByteToWideChar failed to convert '%s'; Error = %d\n",
|
|
lpszLspName, GetLastError());
|
|
goto cleanup;
|
|
}
|
|
|
|
rc = MultiByteToWideChar(
|
|
CP_ACP,
|
|
0,
|
|
lpszLspPathAndFile,
|
|
(int) strlen( lpszLspPathAndFile ) + 1,
|
|
wszFullProviderPath,
|
|
MAX_PATH
|
|
);
|
|
if ( 0 == rc )
|
|
{
|
|
fprintf( stderr, "InstallLsp: MultiByteToWidechar failed to convert '%s': Error = %d\n",
|
|
lpszLspPathAndFile, GetLastError() );
|
|
goto cleanup;
|
|
}
|
|
|
|
if (lpszLspPathAndFile32)
|
|
{
|
|
rc = MultiByteToWideChar(
|
|
CP_ACP,
|
|
0,
|
|
lpszLspPathAndFile32,
|
|
(int) strlen( lpszLspPathAndFile32 ) + 1,
|
|
wszFullProviderPath32,
|
|
MAX_PATH
|
|
);
|
|
if ( 0 == rc )
|
|
{
|
|
fprintf( stderr, "InstallLsp: MultiByteToWidechar failed to convert '%s': Error = %d\n",
|
|
lpszLspPathAndFile32, GetLastError() );
|
|
goto cleanup;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
wszFullProviderPath32[0] = '\0';
|
|
}
|
|
|
|
// Verify there's at least one entry to layer over
|
|
if ( 0 == dwCatalogIdArrayCount )
|
|
{
|
|
fprintf(stderr, "InstallLsp: Error! Must specify at least one provider to layer over!\n\n");
|
|
goto cleanup;
|
|
}
|
|
|
|
printf("LSP name is '%S'\n", wszLspName);
|
|
|
|
// Retrieve the GUID under which the LSP is to be installed
|
|
RetrieveLspGuid( lpszLspPathAndFile, &ProviderBaseGuid );
|
|
|
|
osv.dwOSVersionInfoSize = sizeof(osv);
|
|
GetVersionEx( (LPOSVERSIONINFO) &osv );
|
|
|
|
if ( osv.dwMajorVersion >= 6 )
|
|
{
|
|
// On Windows Vista, use the new LSP install API
|
|
|
|
rc = InstallProviderVista(
|
|
eCatalog,
|
|
wszLspName,
|
|
wszFullProviderPath,
|
|
wszFullProviderPath32,
|
|
&ProviderBaseGuid,
|
|
dwCatalogIdArrayCount,
|
|
pdwCatalogIdArray,
|
|
IfsProvider,
|
|
InstallOverAll
|
|
);
|
|
if ( SOCKET_ERROR == rc )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// This isn't Vista so install the LSP the old way
|
|
//
|
|
|
|
// Create the 'dummy' protocol entry
|
|
pDummyEntry = CreateDummyEntry( eCatalog, pdwCatalogIdArray[ 0 ], wszLspName, IfsProvider );
|
|
if (pDummyEntry == NULL)
|
|
{
|
|
fprintf(stderr, "InstallLsp: CreateDummyEntry failed!\n");
|
|
goto cleanup;
|
|
}
|
|
|
|
// Install the 'dummy' protocol entry for the LSP
|
|
rc = InstallProvider(
|
|
eCatalog,
|
|
&ProviderBaseGuid,
|
|
wszFullProviderPath,
|
|
pDummyEntry,
|
|
1
|
|
);
|
|
if ( NO_ERROR != rc )
|
|
{
|
|
fprintf(stderr, "InstallLsp: Unable to install the dummy LSP entry!\n");
|
|
goto cleanup;
|
|
}
|
|
|
|
// Don't need this struture any more
|
|
LspFree( pDummyEntry );
|
|
pDummyEntry = NULL;
|
|
|
|
if ( FALSE == IfsProvider )
|
|
{
|
|
rc = InstallNonIfsLspProtocolChains( eCatalog, &ProviderBaseGuid, wszLspName,
|
|
wszFullProviderPath, pdwCatalogIdArray, dwCatalogIdArrayCount );
|
|
|
|
}
|
|
else
|
|
{
|
|
rc = InstallIfsLspProtocolChains( eCatalog, &ProviderBaseGuid, wszLspName,
|
|
wszFullProviderPath, pdwCatalogIdArray, dwCatalogIdArrayCount );
|
|
}
|
|
|
|
if ( SOCKET_ERROR == rc )
|
|
{
|
|
// An error occured installing the chains so remove the dummy entry
|
|
DeinstallProvider( eCatalog, &ProviderBaseGuid );
|
|
}
|
|
|
|
}
|
|
|
|
cleanup:
|
|
|
|
if ( NULL != pProtocolInfo )
|
|
FreeProviders( pProtocolInfo );
|
|
|
|
if ( NULL != pDummyEntry )
|
|
LspFree( pDummyEntry );
|
|
|
|
if ( NULL != pLayeredEntries )
|
|
LspFree( pLayeredEntries );
|
|
|
|
return rc;
|
|
}
|
|
|
|
//
|
|
// Function: InstallProvider
|
|
//
|
|
// Description:
|
|
// This is a wrapper for the WSCInstallProvider function. Depending on
|
|
// which catalog is specified, this routine calls the correct install
|
|
// routine.
|
|
//
|
|
int
|
|
InstallProvider(
|
|
WINSOCK_CATALOG Catalog, // Which catalog are we operating on
|
|
GUID *Guid, // GUID under which provider will be installed
|
|
WCHAR *lpwszLspPath, // Path to LSP's DLL
|
|
WSAPROTOCOL_INFOW *pProvider, // Array of provider structures to install
|
|
INT iProviderCount // Number of providers in array
|
|
)
|
|
{
|
|
WSAPROTOCOL_INFOW *pEnumProviders = NULL,
|
|
*pEntry = NULL;
|
|
INT iEnumProviderCount,
|
|
ErrorCode,
|
|
rc = SOCKET_ERROR;
|
|
|
|
#ifdef _WIN64
|
|
if ( LspCatalog32Only == Catalog )
|
|
{
|
|
// Can't install only in 32-bit catalog from 64-bit
|
|
fprintf( stderr, "InstallProvider: Error! It is not possible to install only "
|
|
"in 32-bit catalog from 64-bit process!\n\n"
|
|
);
|
|
goto cleanup;
|
|
}
|
|
else if ( LspCatalog64Only == Catalog )
|
|
{
|
|
// Just need to call WSCInstallProvider
|
|
rc = WSCInstallProvider(
|
|
Guid,
|
|
lpwszLspPath,
|
|
pProvider,
|
|
iProviderCount,
|
|
&ErrorCode
|
|
);
|
|
}
|
|
else
|
|
{
|
|
// To install in both we must call WSCInstallProviderPath64_32
|
|
rc = WSCInstallProvider64_32(
|
|
Guid,
|
|
lpwszLspPath,
|
|
pProvider,
|
|
iProviderCount,
|
|
&ErrorCode
|
|
);
|
|
}
|
|
#else
|
|
if ( LspCatalog32Only == Catalog )
|
|
{
|
|
// From a 32-bit process we can only install into 32-bit catalog
|
|
rc = WSCInstallProvider(
|
|
Guid,
|
|
lpwszLspPath,
|
|
pProvider,
|
|
iProviderCount,
|
|
&ErrorCode
|
|
);
|
|
}
|
|
else
|
|
{
|
|
// From a 32-bit process, we can't touch the 64-bit catalog at all
|
|
fprintf( stderr, "InstallProvider: Error! It is not possible to install into "
|
|
"the 64-bit catalog from a 32-bit process!\n\n"
|
|
);
|
|
goto cleanup;
|
|
}
|
|
#endif
|
|
if ( SOCKET_ERROR == rc )
|
|
{
|
|
fprintf( stderr, "InstallProvider: WSCInstallProvider* failed: %d\n", ErrorCode );
|
|
goto cleanup;
|
|
}
|
|
|
|
// Go back and enumerate what we just installed
|
|
pEnumProviders = EnumerateProviders( Catalog, &iEnumProviderCount );
|
|
if ( NULL == pEnumProviders )
|
|
{
|
|
fprintf( stderr, "InstallProvider: EnumerateProviders failed!\n" );
|
|
goto cleanup;
|
|
}
|
|
|
|
// Make sure our entry is in the catalog
|
|
pEntry = FindProviderByGuid( Guid, pEnumProviders, iEnumProviderCount );
|
|
if ( pEntry )
|
|
{
|
|
printf( "Installed: [%4d] %S\n",
|
|
pEntry->dwCatalogEntryId,
|
|
pEntry->szProtocol
|
|
);
|
|
}
|
|
|
|
cleanup:
|
|
|
|
if ( NULL != pEnumProviders )
|
|
FreeProviders( pEnumProviders );
|
|
|
|
return rc;
|
|
}
|
|
|
|
//
|
|
// Function: CreateDummyEntry
|
|
//
|
|
// Description:
|
|
// This creates a single WSAPROTOCOL_INFOW structure which describes the
|
|
// hidden "dummy" entry for an LSP. This is required since the layered
|
|
// chain entries must reference the catalog ID of the LSP and a catalog ID
|
|
// cannot be obtained until an entry is installed.
|
|
//
|
|
WSAPROTOCOL_INFOW *
|
|
CreateDummyEntry(
|
|
WINSOCK_CATALOG Catalog,
|
|
INT CatalogId,
|
|
WCHAR *lpwszLspName,
|
|
BOOL IfsProvider
|
|
)
|
|
{
|
|
WSAPROTOCOL_INFOW *pProtocolInfo = NULL,
|
|
*pDummyEntry = NULL,
|
|
*pEntry = NULL;
|
|
INT iProtocolCount = 0;
|
|
int err;
|
|
|
|
// Enumerate the catalog
|
|
pProtocolInfo = EnumerateProviders( Catalog, &iProtocolCount );
|
|
if ( NULL == pProtocolInfo )
|
|
{
|
|
fprintf(stderr, "CreateDummyEntry: EnumerateProviders failed!\n");
|
|
goto cleanup;
|
|
}
|
|
|
|
// Find one of the providers we are layering over
|
|
pEntry = FindProviderById( CatalogId, pProtocolInfo, iProtocolCount );
|
|
if ( pEntry )
|
|
{
|
|
// Allocate space and copy the provider structure
|
|
pDummyEntry = (WSAPROTOCOL_INFOW *) LspAlloc(
|
|
sizeof( WSAPROTOCOL_INFOW ),
|
|
&err
|
|
);
|
|
if ( NULL == pDummyEntry )
|
|
{
|
|
fprintf( stderr, "CreateDummyEntry: LspAlloc failed: %d\n", err );
|
|
goto cleanup;
|
|
}
|
|
|
|
// Copy the entry as a basis for the dummy entry
|
|
memcpy( pDummyEntry, pEntry, sizeof( WSAPROTOCOL_INFOW ) );
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr, "CreateDummyEntry: Error! Unable to find provider with ID of %d\n\n",
|
|
CatalogId
|
|
);
|
|
goto cleanup;
|
|
}
|
|
|
|
// Remove the IFS provider flag if the LSP doesn't support it
|
|
if ( FALSE == IfsProvider )
|
|
pDummyEntry->dwServiceFlags1 &= (~XP1_IFS_HANDLES);
|
|
|
|
// Set the flags indicating this is a hidden ("dummy") entry
|
|
pDummyEntry->iSocketType = 0;
|
|
pDummyEntry->iProtocol = 0;
|
|
pDummyEntry->dwProviderFlags |= PFL_HIDDEN;
|
|
pDummyEntry->dwProviderFlags &= (~PFL_MATCHES_PROTOCOL_ZERO);
|
|
pDummyEntry->ProtocolChain.ChainLen = LAYERED_PROTOCOL;
|
|
|
|
// Copy the LSP name
|
|
wcsncpy_s( pDummyEntry->szProtocol, lpwszLspName, WSAPROTOCOL_LEN );
|
|
|
|
cleanup:
|
|
|
|
if ( NULL != pProtocolInfo )
|
|
FreeProviders( pProtocolInfo );
|
|
|
|
return pDummyEntry;
|
|
}
|
|
|
|
//
|
|
// Function: InstallIfsLspProtocolChains
|
|
//
|
|
// Description:
|
|
// This routine installs the layered protocol chains for an IFS based LSP. It
|
|
// assumes the LSP dummy entry is already installed. This function first enumerates
|
|
// the catalog to find the ID of the dummy entry. It then builds the protocol
|
|
// entries for the IFS layered protocols. Note that an IFS entry must be installed
|
|
// such that no non-IFS providers are layered beneath it. This means if the user
|
|
// chooses to install the IFS LSP over a provider which includes non-IFS layers, it
|
|
// must insert itself into the chain such that it is below all non-IFS providers.
|
|
// This means that existing entries need to be modified in order to reflect this
|
|
// ordering. Also in the event that the IFS LSP is inserted into an existing chain
|
|
// this installer still builds a series of standalone entries (i.e. entries that
|
|
// would have existed of the LSPs layered over the IFS LSP were installed after
|
|
// the IFS LSP was).
|
|
//
|
|
int
|
|
InstallIfsLspProtocolChains(
|
|
WINSOCK_CATALOG eCatalog,
|
|
GUID *Guid,
|
|
WCHAR *lpszLspName,
|
|
WCHAR *lpszLspFullPathAndFile,
|
|
DWORD *pdwCatalogIdArray,
|
|
DWORD dwCatalogIdArrayCount
|
|
)
|
|
{
|
|
WSAPROTOCOL_INFOW *pProvider = NULL,
|
|
*pProviderNew = NULL,
|
|
*pLayeredEntries = NULL,
|
|
*pEntry = NULL,
|
|
TempEntry = {0};
|
|
DWORD *pProviderOrder = NULL,
|
|
dwDummyLspId;
|
|
WCHAR wszLspDll[ MAX_PATH ];
|
|
BOOL bLayeredOverNonIfs = FALSE,
|
|
bContainsNonIfs = FALSE;
|
|
HRESULT hr;
|
|
int ProviderPathLen = MAX_PATH-1,
|
|
iProviderCount,
|
|
iProviderCountNew,
|
|
LayerIdx,
|
|
retval = SOCKET_ERROR,
|
|
err,
|
|
idx,
|
|
rc,
|
|
i, j, k;
|
|
|
|
// Enumerate the catalog
|
|
pProvider = EnumerateProviders( eCatalog, &iProviderCount );
|
|
if ( NULL == pProvider )
|
|
{
|
|
fprintf( stderr, "InstallIfsLspProtocolChains: Unable to enumerate catalog\n" );
|
|
goto cleanup;
|
|
}
|
|
|
|
// Find the dummy, hidden entry of our new LSP
|
|
dwDummyLspId = GetCatalogIdForProviderGuid( Guid, pProvider, iProviderCount );
|
|
|
|
ASSERT( dwDummyLspId != 0 );
|
|
|
|
// Allocate space for the protocol chains of the new LSP
|
|
pLayeredEntries = (WSAPROTOCOL_INFOW *) LspAlloc( sizeof(WSAPROTOCOL_INFOW) *
|
|
dwCatalogIdArrayCount, &err );
|
|
if ( NULL == pLayeredEntries )
|
|
{
|
|
fprintf( stderr, "InstallIfsLspProtocolChains: LspAlloc failed: %d\n", err );
|
|
goto cleanup;
|
|
}
|
|
|
|
LayerIdx = 0;
|
|
|
|
// Build the layered protocol entries as well as a list of those providers which
|
|
// require modification. Whenever an LSP is installed, a number of protocol entries
|
|
// are installed where the first entry in the chain array is the LSP's dummy entry.
|
|
// Addtionally, if we're installing an IFS LSP over an provider whose protocol chain
|
|
// includes non-IFS LSPs, the IFS LSP must be placed in the chain such that no
|
|
// non-IFS LSPs are positioned after it in the chain.
|
|
|
|
// Loop through each ID we're layering over
|
|
for(i=0; i < (int)dwCatalogIdArrayCount ;i++)
|
|
{
|
|
for(j=0; j < iProviderCount ;j++)
|
|
{
|
|
printf("Matching selected ID %d to catalog %d\n",
|
|
pdwCatalogIdArray[ i ], pProvider[ j ].dwCatalogEntryId );
|
|
|
|
if ( pdwCatalogIdArray[ i ] == pProvider[ j ].dwCatalogEntryId )
|
|
{
|
|
// Verify the entry has room enough to be layered over
|
|
if ( pProvider[ j ].ProtocolChain.ChainLen >= ( MAX_PROTOCOL_CHAIN - 1 ) )
|
|
{
|
|
fprintf( stderr, "InstallIfsLspProtocolChain: Too many LSPs installed!\n");
|
|
goto cleanup;
|
|
}
|
|
|
|
// Save off the entry which we're layering over
|
|
memcpy( &pLayeredEntries[ LayerIdx ], &pProvider[ j ],
|
|
sizeof( pLayeredEntries[ 0 ] ) );
|
|
|
|
memcpy( &TempEntry, &pProvider[ j ], sizeof( TempEntry ) );
|
|
|
|
// Fill in the new LSP entry's name
|
|
hr = StringCchPrintfW( pLayeredEntries[ LayerIdx ].szProtocol, WSAPROTOCOL_LEN,
|
|
L"%s over [%s]",
|
|
lpszLspName,
|
|
pProvider[ j ].szProtocol
|
|
);
|
|
if ( FAILED( hr ) )
|
|
{
|
|
fprintf( stderr, "InstallIfsLspProtocolChains: StringCchPrintfW failed: 0x%x\n", hr );
|
|
goto cleanup;
|
|
}
|
|
|
|
// Check whether the selected entry contains non IFS LSPs in its chain
|
|
if ( pProvider[ j ].ProtocolChain.ChainLen >= 2 )
|
|
{
|
|
for(k=pProvider[ j ].ProtocolChain.ChainLen-2 ; k >= 0 ;k--)
|
|
{
|
|
bContainsNonIfs = IsNonIfsProvider( pProvider, iProviderCount,
|
|
pProvider[ j ].ProtocolChain.ChainEntries[ k ] );
|
|
|
|
if ( TRUE == bContainsNonIfs )
|
|
{
|
|
// Need to modify the pProvider entry to reference the
|
|
// added LSP entry within its chain
|
|
|
|
// In the 'modified' array make a space at location after 'k'
|
|
InsertIdIntoProtocolChain( &pProvider[ j ], k+1, UPDATE_LSP_ENTRY );
|
|
|
|
// Save the index to the layer which corresponds to this entry
|
|
pProvider[ j ].dwProviderReserved = LayerIdx + 1;
|
|
|
|
// Need to fix the 'pLayeredEntry' as well
|
|
BuildSubsetLspChain( &pLayeredEntries[ LayerIdx ], k+1, dwDummyLspId );
|
|
|
|
pLayeredEntries[ LayerIdx ].dwServiceFlags1 |= XP1_IFS_HANDLES;
|
|
|
|
bLayeredOverNonIfs = TRUE;
|
|
|
|
// Need to insert the IFS provider in all LSPs that are layered
|
|
// above the location where the IFS provider was just inserted
|
|
InsertIfsLspIntoAllChains( &TempEntry, pProvider, iProviderCount,
|
|
LayerIdx + 1, k );
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Need to setup the protocol chain in the pLayeredEntry if we haven't
|
|
// already done so above
|
|
if ( TRUE != bContainsNonIfs )
|
|
{
|
|
InsertIdIntoProtocolChain( &pLayeredEntries[ LayerIdx ], 0, dwDummyLspId );
|
|
|
|
// The second entry is always the ID of the current pProvider[i]
|
|
// In case of multiple LSPs then if we didn't do this the [1] index
|
|
// would contain the ID of that LSP's dummy entry and not the entry
|
|
// itself.
|
|
pLayeredEntries[ LayerIdx ].ProtocolChain.ChainEntries[ 1 ] =
|
|
TempEntry.dwCatalogEntryId;
|
|
|
|
pLayeredEntries[ LayerIdx ].dwServiceFlags1 |= XP1_IFS_HANDLES;
|
|
}
|
|
|
|
LayerIdx++;
|
|
}
|
|
}
|
|
}
|
|
|
|
ASSERT( LayerIdx == (int)dwCatalogIdArrayCount );
|
|
|
|
// Create a unique GUID for each provider to install and install it
|
|
for(i=0;i < (int)dwCatalogIdArrayCount ;i++)
|
|
{
|
|
if ( RPC_S_OK != UuidCreate( &pLayeredEntries[ i ].ProviderId ) )
|
|
{
|
|
fprintf(stderr, "InstallIfsLspProtocolChains: UuidCreate failed: %d\n", GetLastError());
|
|
goto cleanup;
|
|
}
|
|
|
|
rc = InstallProvider( eCatalog, &pLayeredEntries[ i ].ProviderId,
|
|
lpszLspFullPathAndFile, &pLayeredEntries[ i ], 1 );
|
|
if ( NO_ERROR != rc )
|
|
{
|
|
fprintf(stderr, "InstallIfsLspProtocolChains: Unable to install the dummy LSP entry!\n");
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
if ( TRUE == bLayeredOverNonIfs )
|
|
{
|
|
// Enumerate the catalog again so we can find the catalog IDs
|
|
|
|
pProviderNew = EnumerateProviders( eCatalog, &iProviderCountNew );
|
|
if ( NULL == pProviderNew )
|
|
{
|
|
fprintf( stderr, "InstallIfsLspProtocolChains: Unable to enumerate catalog\n" );
|
|
goto cleanup;
|
|
}
|
|
|
|
for(i=0; i < (int)dwCatalogIdArrayCount ;i++)
|
|
{
|
|
pLayeredEntries[ i ].dwCatalogEntryId = GetCatalogIdForProviderGuid(
|
|
&pLayeredEntries[ i ].ProviderId,
|
|
pProviderNew,
|
|
iProviderCountNew
|
|
);
|
|
|
|
ASSERT( pLayeredEntries[ i ].dwCatalogEntryId != 0 );
|
|
}
|
|
|
|
// Update the protocol chains of the modified entries to point to the just
|
|
// installed providers
|
|
for(i=0; i < iProviderCount ;i++)
|
|
{
|
|
if ( pProvider[ i ].dwProviderReserved == 0 )
|
|
continue;
|
|
|
|
for(j=0; j < pProvider[ i ].ProtocolChain.ChainLen ;j++)
|
|
{
|
|
if ( UPDATE_LSP_ENTRY == pProvider[ i ].ProtocolChain.ChainEntries[ j ] )
|
|
{
|
|
pProvider[ i ].ProtocolChain.ChainEntries[ j ] =
|
|
pLayeredEntries[ pProvider[ i ].dwProviderReserved - 1 ].dwCatalogEntryId;
|
|
|
|
pProvider[ i ].dwProviderReserved = 0;
|
|
}
|
|
}
|
|
|
|
// Get the DLL path
|
|
ProviderPathLen = MAX_PATH-1;
|
|
rc = WSCGetProviderPath(
|
|
&pProvider[ i ].ProviderId,
|
|
wszLspDll,
|
|
&ProviderPathLen,
|
|
&err
|
|
);
|
|
if ( SOCKET_ERROR == rc )
|
|
{
|
|
fprintf( stderr, "InstallIfsLspProtocolChains: WSCGetProviderPath failed: %d\n", err );
|
|
goto cleanup;
|
|
}
|
|
|
|
// Update the providers which were modified
|
|
rc = UpdateProvider( eCatalog, &pProvider[ i ].ProviderId,
|
|
wszLspDll, &pProvider[ i ], 1, &err );
|
|
if ( SOCKET_ERROR == rc )
|
|
{
|
|
fprintf( stderr, "InstallIfsLspProtocolChains: UpdateProvider failed: %d\n", err );
|
|
goto cleanup;
|
|
}
|
|
|
|
printf("Updated entry ID: %d: %S (chain len = %d)\n",
|
|
pProvider[ i ].dwCatalogEntryId,
|
|
pProvider[ i ].szProtocol,
|
|
pProvider[ i ].ProtocolChain.ChainLen
|
|
);
|
|
}
|
|
|
|
FreeProviders( pProvider );
|
|
pProvider = NULL;
|
|
|
|
FreeProviders( pProviderNew );
|
|
pProviderNew = NULL;
|
|
|
|
|
|
//WSCUpdateProvider doesn't update the process' copy of the winsock catalog.
|
|
//By calling cleanup and startup again, it forces a refresh. Otherwise,
|
|
//the rest of the installer code can't see the changes that were just made.
|
|
{
|
|
WSADATA wsd;
|
|
|
|
WSACleanup();
|
|
|
|
WSAStartup( MAKEWORD(2,2), &wsd );
|
|
}
|
|
|
|
|
|
pProvider = EnumerateProviders( eCatalog, &iProviderCount );
|
|
if ( NULL == pProvider )
|
|
{
|
|
fprintf( stderr, "InstallIfsLspProtocolChains: Unable to enumerate catalog\n" );
|
|
goto cleanup;
|
|
}
|
|
|
|
// Allocate an array of DWORDs to contain the new catalog ordering
|
|
pProviderOrder = (DWORD *)LspAlloc( iProviderCount * sizeof(DWORD), &err );
|
|
if ( NULL == pProviderOrder )
|
|
{
|
|
fprintf( stderr, "InstallIfsLspProtocolChains: Unable to enumerate catalog\n" );
|
|
goto cleanup;
|
|
}
|
|
|
|
// First add the entries we layered over first
|
|
idx = 0;
|
|
for(i=0; i < (int)dwCatalogIdArrayCount ;i++)
|
|
{
|
|
pEntry = FindProviderById( pdwCatalogIdArray[ i ], pProvider, iProviderCount );
|
|
if ( NULL == pEntry )
|
|
{
|
|
fprintf(stderr, "InstallIfsLspProtocolChain: Unable to find entry to reorder catalog!\n");
|
|
goto cleanup;
|
|
}
|
|
|
|
pEntry->dwProviderReserved = 1;
|
|
|
|
pProviderOrder[ idx++ ] = pEntry->dwCatalogEntryId;
|
|
}
|
|
|
|
// Now go through the protocol chain of the entries we layered over and put those
|
|
// LSP entries next in the new order
|
|
for(i=0; i < (int)dwCatalogIdArrayCount ;i++)
|
|
{
|
|
pEntry = FindProviderById( pdwCatalogIdArray[ i ], pProvider, iProviderCount );
|
|
if ( NULL == pEntry )
|
|
{
|
|
fprintf(stderr, "InstallIfsLspProtocolChain: Unable to find entry to reorder catalog!\n");
|
|
goto cleanup;
|
|
}
|
|
|
|
printf("Looping through: %d: %S (chain len = %d)\n",
|
|
pEntry->dwCatalogEntryId,
|
|
pEntry->szProtocol,
|
|
pEntry->ProtocolChain.ChainLen );
|
|
|
|
for(j=1; j < pEntry->ProtocolChain.ChainLen-1 ;j++)
|
|
{
|
|
dwDummyLspId = FindDummyIdFromProtocolChainId(
|
|
pEntry->ProtocolChain.ChainEntries[ j ],
|
|
pProvider,
|
|
iProviderCount
|
|
);
|
|
|
|
printf(" Finding dummy ID for chain entry: %d is %d\n",
|
|
pEntry->ProtocolChain.ChainEntries[ j ],
|
|
dwDummyLspId
|
|
);
|
|
|
|
for(k=0; k < iProviderCount ;k++)
|
|
{
|
|
if ( ( pProvider[ k ].ProtocolChain.ChainLen >= 2 ) &&
|
|
( pProvider[ k ].ProtocolChain.ChainEntries[ 0 ] == dwDummyLspId ) &&
|
|
( pProvider[ k ].dwProviderReserved == 0 )
|
|
)
|
|
{
|
|
pProviderOrder[ idx++ ] = pProvider[ k ].dwCatalogEntryId;
|
|
pProvider[ k ].dwProviderReserved = 1;
|
|
|
|
printf(" Adding: %d\n", pProvider[ k ].dwCatalogEntryId );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Now any catalog entry that wasn't already copied, copy it
|
|
for(i=0; i < iProviderCount ;i++)
|
|
{
|
|
if ( pProvider[ i ].dwProviderReserved == 0 )
|
|
pProviderOrder[ idx++ ] = pProvider[ i ].dwCatalogEntryId;
|
|
}
|
|
|
|
ASSERT( idx == iProviderCount );
|
|
|
|
// Write the new catalog order
|
|
rc = WriteProviderOrder( eCatalog, pProviderOrder, iProviderCount, &err );
|
|
if ( NO_ERROR != rc )
|
|
{
|
|
fprintf( stderr, "InstallIfsLspProtocolChains: WriteProviderOrder failed: %d\n",
|
|
err );
|
|
goto cleanup;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Reorder the winsock catalog so the layered chain entries appear first.
|
|
// Since we didn't have to modify any existing entries, all we need to do is
|
|
// move the added entries to the head of the catalog
|
|
//
|
|
rc = ReorderCatalog( eCatalog, dwDummyLspId );
|
|
if ( NO_ERROR != rc )
|
|
{
|
|
fprintf(stderr, "InstallIfsLspProtocolChains: Unable to reorder Winsock catalog!\n");
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
retval = NO_ERROR;
|
|
|
|
cleanup:
|
|
|
|
if ( NULL != pProvider )
|
|
{
|
|
FreeProviders( pProvider );
|
|
pProvider = NULL;
|
|
}
|
|
|
|
if ( NULL != pProviderNew )
|
|
{
|
|
FreeProviders( pProviderNew );
|
|
pProviderNew = NULL;
|
|
}
|
|
|
|
if ( NULL != pProviderOrder )
|
|
{
|
|
LspFree( pProviderOrder );
|
|
pProviderOrder = NULL;
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
//
|
|
// Function: InstallNonIfsLspProtocolChains
|
|
//
|
|
// Description:
|
|
// This function builds and install the protocol chain entries associated with
|
|
// a non-IFS LSP. The caling routine installs the dummy, hidden entry in the
|
|
// catalog and this routine enumerates the catalog, finds the dummy entry,
|
|
// builds the layered chain entries, and installs them into the catalog.
|
|
//
|
|
int
|
|
InstallNonIfsLspProtocolChains(
|
|
WINSOCK_CATALOG eCatalog,
|
|
GUID *Guid,
|
|
WCHAR *lpszLspName,
|
|
WCHAR *lpszLspFullPathAndFile,
|
|
DWORD *pdwCatalogIdArray,
|
|
DWORD dwCatalogIdArrayCount
|
|
)
|
|
{
|
|
WSAPROTOCOL_INFOW *pProvider = NULL,
|
|
*pLayeredEntries = NULL;
|
|
DWORD dwDummyLspId = 0;
|
|
INT iProviderCount = 0,
|
|
retval = SOCKET_ERROR,
|
|
idx,
|
|
err,
|
|
rc,
|
|
i, j;
|
|
HRESULT hr;
|
|
|
|
// Enumerate the catalog
|
|
pProvider = EnumerateProviders( eCatalog, &iProviderCount );
|
|
if ( NULL == pProvider )
|
|
{
|
|
fprintf( stderr, "InstallNonIfsLspProtocolChain: Unable to enumerate catalog\n" );
|
|
goto cleanup;
|
|
}
|
|
|
|
pLayeredEntries = (WSAPROTOCOL_INFOW *) LspAlloc( sizeof(WSAPROTOCOL_INFOW) *
|
|
dwCatalogIdArrayCount, &err );
|
|
if ( NULL == pLayeredEntries )
|
|
{
|
|
fprintf( stderr, "InstallNonIfsLspProtocolChain: LspAlloc failed: %d\n", err );
|
|
goto cleanup;
|
|
}
|
|
|
|
// Find the dummy entry so we can extract its catalog ID
|
|
dwDummyLspId = GetCatalogIdForProviderGuid( Guid, pProvider, iProviderCount );
|
|
|
|
ASSERT( dwDummyLspId != 0 );
|
|
|
|
// Go through the catalog and build the layered entries
|
|
idx = 0;
|
|
for(i=0; i < iProviderCount ;i++)
|
|
{
|
|
for(j=0; j < (int) dwCatalogIdArrayCount ;j++)
|
|
{
|
|
if ( pProvider[ i ].dwCatalogEntryId == pdwCatalogIdArray[ j ] )
|
|
{
|
|
if ( pProvider[ i ].ProtocolChain.ChainLen >= ( MAX_PROTOCOL_CHAIN - 1 ) )
|
|
{
|
|
fprintf( stderr, "InstallNonIfsLspProtocolchain: Too many LSPs installed!\n");
|
|
goto cleanup;
|
|
}
|
|
|
|
memcpy( &pLayeredEntries[ idx ], &pProvider[ i ], sizeof( WSAPROTOCOL_INFOW ) );
|
|
|
|
// Put our LSP name in the protocol field
|
|
hr = StringCchPrintfW( pLayeredEntries[ idx ].szProtocol, WSAPROTOCOL_LEN,
|
|
L"%s over [%s]",
|
|
lpszLspName,
|
|
pProvider[ i ].szProtocol
|
|
);
|
|
if ( FAILED( hr ) )
|
|
{
|
|
fprintf( stderr, "InstallNonIfsLspProtocolChain: StringCchPrintfW failed: 0x%x\n", hr );
|
|
goto cleanup;
|
|
}
|
|
|
|
// Move all the protocol chain entries down by 1 position and insert
|
|
// the dummy entry id at the head
|
|
InsertIdIntoProtocolChain( &pLayeredEntries[ idx ], 0, dwDummyLspId );
|
|
|
|
// The second entry is always the ID of the current pProvider[i]
|
|
// In case of multiple LSPs then if we didn't do this the [1] index
|
|
// would contain the ID of that LSP's dummy entry and not the entry
|
|
// itself.
|
|
pLayeredEntries[ idx ].ProtocolChain.ChainEntries[ 1 ] =
|
|
pProvider[ i ].dwCatalogEntryId;
|
|
|
|
// Remove the IFS flag
|
|
pLayeredEntries[ idx ].dwServiceFlags1 &= (~XP1_IFS_HANDLES);
|
|
|
|
idx++;
|
|
}
|
|
}
|
|
}
|
|
|
|
for(i=0; i < (int)dwCatalogIdArrayCount ;i++)
|
|
{
|
|
// Create a GUID for the protocol chain entries
|
|
if ( UuidCreate( &pLayeredEntries[ i ].ProviderId ) != RPC_S_OK )
|
|
{
|
|
fprintf(stderr, "InstallNonIfsLspProtocolChains: UuidCreate failed: %d\n", GetLastError());
|
|
goto cleanup;
|
|
}
|
|
|
|
// Install the layered chain providers
|
|
rc = InstallProvider(
|
|
eCatalog,
|
|
&pLayeredEntries[ i ].ProviderId,
|
|
lpszLspFullPathAndFile,
|
|
&pLayeredEntries[ i ],
|
|
1
|
|
);
|
|
if ( NO_ERROR != rc )
|
|
{
|
|
fprintf(stderr, "InstallNonIfsLspProtocolChains: Unable to install layered chain entries!\n");
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
// Reorder the winsock catalog so the layered chain entries appear first
|
|
rc = ReorderCatalog( eCatalog, dwDummyLspId );
|
|
if ( NO_ERROR != rc )
|
|
{
|
|
fprintf(stderr, "InstallNonIfsLspProtocolChains: Unable to reorder Winsock catalog!\n");
|
|
goto cleanup;
|
|
}
|
|
|
|
retval = NO_ERROR;
|
|
|
|
cleanup:
|
|
|
|
if ( NULL != pProvider )
|
|
FreeProviders( pProvider );
|
|
|
|
if ( NULL != pLayeredEntries )
|
|
LspFree( pLayeredEntries );
|
|
|
|
return retval;
|
|
}
|
|
|
|
//
|
|
// Function: InsertIfsLspIntoAllChains
|
|
//
|
|
// Description:
|
|
// This routine takes a Winsock catalog entry where an IFS LSP entry is being
|
|
// inserted in the middle of the chain and the same IFS LSP entry needs to be
|
|
// installed in the individual provider entries for every LSP referenced in the
|
|
// chain above the IFS provider position. This function traverses the protocol
|
|
// chain for all entries above the inserted IFS entry, looks up the provider
|
|
// belonging to that entry, and inserts the IFS LSP into it's chain.
|
|
//
|
|
int
|
|
InsertIfsLspIntoAllChains(
|
|
WSAPROTOCOL_INFOW *OriginalEntry, // Original (unmodified) entry to follow chains
|
|
WSAPROTOCOL_INFOW *Catalog, // Array of catalog entries
|
|
int CatalogCount, // Number of entries in Catalog array
|
|
int IfsEntryIdx, // Index into IFS standalone entry array
|
|
int ChainIdx // Chain index in OriginalEntry to start at
|
|
)
|
|
{
|
|
WSAPROTOCOL_INFOW TempEntry = {0};
|
|
int Idx, i, j, k;
|
|
|
|
for(i=ChainIdx; i > 0 ;i--)
|
|
{
|
|
#ifdef DBG
|
|
printf( "Looking for entry: %d\n", OriginalEntry->ProtocolChain.ChainEntries[ i ] );
|
|
#endif
|
|
|
|
for(j=0; j < CatalogCount ;j++)
|
|
{
|
|
if ( Catalog[ j ].dwCatalogEntryId == OriginalEntry->ProtocolChain.ChainEntries[ i ] )
|
|
{
|
|
printf( "Found match: %ws\n", Catalog[ j ].szProtocol );
|
|
Idx = j;
|
|
|
|
if ( Catalog[ j ].ProtocolChain.ChainLen == LAYERED_PROTOCOL )
|
|
{
|
|
Idx = -1;
|
|
|
|
// Not good. The catalog ID in the chain points to the dummy
|
|
// entry. We'll need to do some other heuristic to find the
|
|
// "right" entry.
|
|
for(k=0; k < CatalogCount ;k++)
|
|
{
|
|
if ( ( OriginalEntry->iAddressFamily == Catalog[ k ].iAddressFamily ) &&
|
|
( OriginalEntry->iSocketType == Catalog[ k ].iSocketType ) &&
|
|
( OriginalEntry->iProtocol == Catalog[ k ].iProtocol ) &&
|
|
( (i+1) == Catalog[ k ].ProtocolChain.ChainLen )
|
|
)
|
|
{
|
|
Idx = k;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( Idx != -1 )
|
|
{
|
|
// Found a match and need to insert the new IFS LSP into the chain
|
|
memcpy( &TempEntry, &Catalog[ Idx ], sizeof( TempEntry ) );
|
|
|
|
if ( Catalog[ Idx ].ProtocolChain.ChainLen >= 2 )
|
|
{
|
|
for(k=Catalog[ Idx ].ProtocolChain.ChainLen-2 ; k >= 0 ;k--)
|
|
{
|
|
if ( TRUE == IsNonIfsProvider( Catalog, CatalogCount,
|
|
Catalog[ Idx ].ProtocolChain.ChainEntries[ k ] ) )
|
|
{
|
|
// K points to first non-IFS provider - insert after
|
|
InsertIdIntoProtocolChain( &Catalog[ Idx ], k+1, UPDATE_LSP_ENTRY );
|
|
|
|
// Save the index to the layer which corresponds to this entry
|
|
Catalog[ Idx ].dwProviderReserved = IfsEntryIdx;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf( "????? Index not found ????\n" );
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// Function: ReorderCatalog
|
|
//
|
|
// Description:
|
|
// This routine reorders the Winsock catalog such that those entries
|
|
// which reference the given catalog ID (dwLayerId) as the first entry
|
|
// in the chain array occur at the head of the catalog. This routine
|
|
// also operates on the specified Winsock catalog.
|
|
//
|
|
int
|
|
ReorderCatalog(
|
|
WINSOCK_CATALOG Catalog,
|
|
DWORD dwLayeredId
|
|
)
|
|
{
|
|
DWORD *pdwProtocolOrder = NULL;
|
|
INT iProviderCount,
|
|
ErrorCode,
|
|
rc = SOCKET_ERROR;
|
|
|
|
#ifdef _WIN64
|
|
if ( ( LspCatalog32Only == Catalog ) || ( LspCatalogBoth == Catalog ) )
|
|
{
|
|
printf("Reordering 32-bit Winsock catalog...\n");
|
|
pdwProtocolOrder = ReorderACatalog(
|
|
LspCatalog32Only,
|
|
dwLayeredId,
|
|
&iProviderCount
|
|
);
|
|
if ( NULL == pdwProtocolOrder )
|
|
{
|
|
fprintf( stderr, "ReorderCatalog: ReorderACatalog failed!\n" );
|
|
goto cleanup;
|
|
}
|
|
|
|
rc = WriteProviderOrder( LspCatalog32Only, pdwProtocolOrder, iProviderCount, &ErrorCode );
|
|
if ( SOCKET_ERROR == rc )
|
|
{
|
|
fprintf( stderr, "ReorderCatalog: Reorder of 32-bit catalog failed: %d\n", rc );
|
|
}
|
|
}
|
|
if ( ( LspCatalog64Only == Catalog ) || ( LspCatalogBoth == Catalog ) )
|
|
{
|
|
printf("Reordering 64-bit Winsock catalog...\n");
|
|
pdwProtocolOrder = ReorderACatalog(
|
|
LspCatalog64Only,
|
|
dwLayeredId,
|
|
&iProviderCount
|
|
);
|
|
if ( NULL == pdwProtocolOrder )
|
|
{
|
|
fprintf(stderr, "ReorderCatalog: ReorderACatalog failed!\n");
|
|
goto cleanup;
|
|
}
|
|
|
|
rc = WriteProviderOrder( LspCatalog64Only, pdwProtocolOrder, iProviderCount, &ErrorCode );
|
|
if ( SOCKET_ERROR == rc )
|
|
{
|
|
fprintf(stderr, "ReorderCatalog: Reorder of 64-bit catalog failed: %d\n", rc);
|
|
}
|
|
}
|
|
#else
|
|
if ( ( LspCatalog32Only == Catalog ) || ( LspCatalogBoth == Catalog ) )
|
|
{
|
|
printf("Reordering 32-bit Winsock catalog...\n");
|
|
pdwProtocolOrder = ReorderACatalog(
|
|
LspCatalog32Only,
|
|
dwLayeredId,
|
|
&iProviderCount
|
|
);
|
|
if ( NULL == pdwProtocolOrder )
|
|
{
|
|
fprintf( stderr, "ReorderCatalog: ReorderACatalog failed!\n" );
|
|
goto cleanup;
|
|
}
|
|
|
|
rc = WriteProviderOrder( LspCatalog32Only, pdwProtocolOrder, iProviderCount, &ErrorCode );
|
|
if ( SOCKET_ERROR == rc )
|
|
{
|
|
fprintf(stderr, "ReorderCatalog: Reorder of 32-bit catalog failed: %d\n", rc);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
cleanup:
|
|
|
|
if ( NULL != pdwProtocolOrder )
|
|
LspFree( pdwProtocolOrder );
|
|
|
|
return rc;
|
|
}
|
|
|
|
//
|
|
// Function: ReorderACatalog
|
|
//
|
|
// Description:
|
|
// This routine enumerates a single catalog (32 or 64 bit) and reorders
|
|
// the catalog according to the supplied catalog ID. That is, any provider
|
|
// with that ID at the head of it's protocol chain is moved to the beginning
|
|
// of the catalog.
|
|
//
|
|
DWORD *
|
|
ReorderACatalog(
|
|
WINSOCK_CATALOG Catalog,
|
|
DWORD dwLayerId,
|
|
INT *dwEntryCount
|
|
)
|
|
{
|
|
WSAPROTOCOL_INFOW *pProvider = NULL;
|
|
DWORD *pdwProtocolOrder = NULL;
|
|
INT iProviderCount = 0,
|
|
idx,
|
|
err,
|
|
i;
|
|
|
|
// Validate parameters
|
|
if ( ( NULL == dwEntryCount ) || ( LspCatalogBoth == Catalog ) )
|
|
return NULL;
|
|
|
|
// Enumerate the catalog
|
|
pProvider = EnumerateProviders( Catalog, &iProviderCount );
|
|
if ( NULL == pProvider )
|
|
{
|
|
fprintf( stderr, "ReorderACatalog: Unable to enumerate Winsock catalog!\n" );
|
|
goto cleanup;
|
|
}
|
|
|
|
// Allocate space for the array of catalog IDs (the catalog order)
|
|
pdwProtocolOrder = (DWORD *) LspAlloc(
|
|
sizeof( DWORD ) * iProviderCount,
|
|
&err
|
|
);
|
|
if ( NULL == pdwProtocolOrder )
|
|
{
|
|
fprintf(stderr, "ReorderACatalog: LspAlloc failed: %d\n", GetLastError());
|
|
goto cleanup;
|
|
}
|
|
|
|
idx = 0;
|
|
|
|
// First put all the layered entries at the head of the catalog
|
|
for(i=0; i < iProviderCount ;i++)
|
|
{
|
|
if ( TRUE == IsIdInChain( &pProvider[ i ], dwLayerId ) )
|
|
{
|
|
pdwProtocolOrder[ idx++ ] = pProvider[ i ].dwCatalogEntryId;
|
|
}
|
|
}
|
|
|
|
// Put the remaining entries after the layered chain entries
|
|
for(i=0; i < iProviderCount ;i++)
|
|
{
|
|
if ( FALSE == IsIdInChain( &pProvider[ i ], dwLayerId ) )
|
|
{
|
|
pdwProtocolOrder[ idx++ ] = pProvider[ i ].dwCatalogEntryId;
|
|
}
|
|
}
|
|
|
|
cleanup:
|
|
|
|
if (pProvider)
|
|
FreeProviders(pProvider);
|
|
|
|
// Update the count
|
|
*dwEntryCount = iProviderCount;
|
|
|
|
|
|
return pdwProtocolOrder;
|
|
}
|
|
|
|
//
|
|
// Function: WriteProviderOrder
|
|
//
|
|
// Description:
|
|
// This function wraps the WSCWriteProviderOrder function and calls the
|
|
// appropriate function depending on the Winsock catalog being modified
|
|
// (the 32-bit and/or 64-bit Winsock catalogs).
|
|
//
|
|
int
|
|
WriteProviderOrder(
|
|
WINSOCK_CATALOG Catalog,
|
|
DWORD *pdwCatalogOrder,
|
|
DWORD dwNumberOfEntries,
|
|
INT *lpErrno
|
|
)
|
|
{
|
|
int rc = NO_ERROR;
|
|
|
|
#ifdef _WIN64
|
|
if ( LspCatalog32Only == Catalog )
|
|
{
|
|
rc = WSCWriteProviderOrder32( pdwCatalogOrder, dwNumberOfEntries );
|
|
}
|
|
else if ( LspCatalog64Only == Catalog )
|
|
{
|
|
rc = WSCWriteProviderOrder( pdwCatalogOrder, dwNumberOfEntries );
|
|
}
|
|
#else
|
|
if ( LspCatalog32Only == Catalog )
|
|
{
|
|
rc = WSCWriteProviderOrder(pdwCatalogOrder, dwNumberOfEntries );
|
|
}
|
|
else
|
|
{
|
|
fprintf( stderr, "WriteProviderOrder: Unable to manipulate 64-bit catalog from "
|
|
"a 32-bit process\n" );
|
|
}
|
|
#endif
|
|
if ( 0 != rc )
|
|
{
|
|
*lpErrno = rc;
|
|
fprintf( stderr, "WriteProviderOrder: WSCWriteProviderOrder failed: %d\n", *lpErrno );
|
|
rc = SOCKET_ERROR;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
//
|
|
// Function: InstallProviderVista
|
|
//
|
|
// Description:
|
|
// On Windows Vista and later there is a new LSP install function
|
|
// (WSCInstallProviderAndChains) that performs all necessary installation
|
|
// steps in a single call (instead of multiple WSCInstallProvider calls).
|
|
// This function dynamically loads the function and invokes it to install
|
|
// the LSP. The function either expects a NULL list of WSAPROTOCOL_INFOW
|
|
// structures in which case it installs the LSP over each unique address
|
|
// family, socket type, and protocol base provider on the system. Otherwise,
|
|
// if the pdwCatalogIdArray specifies exact providers, this function builds
|
|
// a list of those provider structures in which case the install API installs
|
|
// the LSP over each instance of the address family, socket type and protocol
|
|
// specified in the array.
|
|
//
|
|
int
|
|
InstallProviderVista(
|
|
WINSOCK_CATALOG eCatalog, // Which catalog to install LSP into
|
|
__in_z WCHAR *lpszLspName, // String name of LSP
|
|
__in_z WCHAR *lpszLspPathAndFile, // Location of 64-bit LSP dll and dll name
|
|
__in_z WCHAR *lpszLspPathAndFile32, // Location of 32-bit LSP dll and dll name
|
|
LPGUID providerGuid,
|
|
DWORD dwCatalogIdArrayCount, // Number of entries in pdwCatalogIdArray
|
|
DWORD *pdwCatalogIdArray, // Array of IDs to install over
|
|
BOOL IfsProvider,
|
|
BOOL InstallOverAll
|
|
)
|
|
{
|
|
LPWSCINSTALLPROVIDERANDCHAINS lpInstallProviderAndChains;
|
|
WSAPROTOCOL_INFOW *protocolList = NULL;
|
|
WSAPROTOCOL_INFOW *pEnumProviders = NULL;
|
|
HMODULE hMod = NULL;
|
|
DWORD dwEntryCount;
|
|
char *lpInstallFunction = NULL;
|
|
INT iEnumProviderCount;
|
|
int rc, i, j, error;
|
|
|
|
|
|
rc = SOCKET_ERROR;
|
|
|
|
//
|
|
// Dynamically load the function in order for this installer to run properly
|
|
// on downlevel OSes
|
|
//
|
|
hMod = LoadLibrary("ws2_32.dll");
|
|
if ( NULL == hMod )
|
|
{
|
|
fprintf(stderr, "Unable to load ws2_32.dll!\n");
|
|
goto cleanup;
|
|
}
|
|
|
|
#ifdef _WIN64
|
|
if ( ( eCatalog == LspCatalog32Only ) || ( eCatalog == LspCatalog64Only ) )
|
|
{
|
|
fprintf(stderr, "New install API always installs into both catalogs!\n");
|
|
goto cleanup;
|
|
}
|
|
else
|
|
{
|
|
lpInstallFunction = "WSCInstallProviderAndChains64_32";
|
|
}
|
|
#else
|
|
UNREFERENCED_PARAMETER(lpszLspPathAndFile32);
|
|
|
|
if ( ( eCatalog == LspCatalog64Only) || ( eCatalog == LspCatalogBoth ) )
|
|
{
|
|
fprintf(stderr, "Cannot install into 64-bit catalog from 32-bit process\n");
|
|
goto cleanup;
|
|
}
|
|
else
|
|
{
|
|
lpInstallFunction = "WSCInstallProviderAndChains";
|
|
}
|
|
#endif
|
|
|
|
// Load the new install function
|
|
lpInstallProviderAndChains = (LPWSCINSTALLPROVIDERANDCHAINS) GetProcAddress(
|
|
hMod,
|
|
lpInstallFunction
|
|
);
|
|
if ( NULL == lpInstallProviderAndChains )
|
|
{
|
|
fprintf( stderr, "InstallLsp: Unable to load WSCInstallProviderAndChains function!\n");
|
|
rc = SOCKET_ERROR;
|
|
goto cleanup;
|
|
}
|
|
|
|
if ( InstallOverAll )
|
|
{
|
|
//
|
|
// Install over all unique BSPs on the system so pass NULL for the provider list
|
|
//
|
|
|
|
rc = lpInstallProviderAndChains(
|
|
providerGuid,
|
|
lpszLspPathAndFile,
|
|
#ifdef _WIN64
|
|
(lpszLspPathAndFile32[0] == '\0' ? lpszLspPathAndFile : lpszLspPathAndFile32),
|
|
#endif
|
|
lpszLspName,
|
|
( IfsProvider ? XP1_IFS_HANDLES : 0 ),
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&error
|
|
);
|
|
if ( SOCKET_ERROR == rc )
|
|
{
|
|
fprintf(stderr, "InstallProviderVista: %s failed: %d\n",
|
|
lpInstallFunction, error );
|
|
goto cleanup;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// User specified a subset of providers to install over so build a list of
|
|
// the corresponding WSAPROTOCOL_INFOW structures to pass to install call
|
|
//
|
|
|
|
protocolList = (WSAPROTOCOL_INFOW *) LspAlloc( sizeof(WSAPROTOCOL_INFOW) *
|
|
dwCatalogIdArrayCount, &error);
|
|
if ( NULL == protocolList )
|
|
{
|
|
fprintf(stderr, "InstallProviderVista: Out of memory!\n");
|
|
rc = SOCKET_ERROR;
|
|
goto cleanup;
|
|
}
|
|
|
|
pEnumProviders = EnumerateProviders( eCatalog, &iEnumProviderCount );
|
|
if ( NULL == pEnumProviders )
|
|
{
|
|
fprintf(stderr, "InstallProviderVista: Unable to enumerate catalog!\n");
|
|
rc = SOCKET_ERROR;
|
|
goto cleanup;
|
|
}
|
|
|
|
// Build a list of protocol structures to layer over
|
|
dwEntryCount = 0;
|
|
for(i=0; i < (int)dwCatalogIdArrayCount ;i++)
|
|
{
|
|
for(j=0; j < iEnumProviderCount ;j++)
|
|
{
|
|
if ( pdwCatalogIdArray[i] == pEnumProviders[j].dwCatalogEntryId )
|
|
{
|
|
memcpy( &protocolList[dwEntryCount++], &pEnumProviders[j], sizeof(WSAPROTOCOL_INFOW) );
|
|
}
|
|
}
|
|
}
|
|
|
|
rc = lpInstallProviderAndChains(
|
|
providerGuid,
|
|
lpszLspPathAndFile,
|
|
#ifdef _WIN64
|
|
lpszLspPathAndFile,
|
|
#endif
|
|
lpszLspName,
|
|
( IfsProvider ? XP1_IFS_HANDLES : 0 ),
|
|
protocolList,
|
|
dwEntryCount,
|
|
NULL,
|
|
&error
|
|
);
|
|
if ( SOCKET_ERROR == rc )
|
|
{
|
|
fprintf(stderr, "InstallProviderVista: %s failed: %d\n",
|
|
lpInstallFunction, error );
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
rc = NO_ERROR;
|
|
|
|
cleanup:
|
|
|
|
if ( NULL != hMod )
|
|
FreeLibrary( hMod );
|
|
|
|
if ( NULL != pEnumProviders )
|
|
FreeProviders( pEnumProviders );
|
|
|
|
if ( NULL != protocolList )
|
|
LspFree( protocolList );
|
|
|
|
return rc;
|
|
}
|