Method for updating LSP Protocol chains (Code included)
June 22nd, 2004 - 10:42 am ET by Chet Simpson | Report spam
As I've gotten closer and closer to finishing my LSP I've been doing some
tests concerning the installation and removal of the provider when other
LSP's have been installed onto the system. During the testing I noticed that
several products being used to test compatibility failed miserably during the
removal stage of their own provider. Under Windows XP updating the protocol
chains is a snap as you have the WSCUpdateProvider call. Under Win9x variants
it's not as easy since you have to manage reinstalling the providers while
making sure all of the protocol chains are fixed for the new configuration. I
*think* I've found an easier method of updating the protocol chains for
instances such as this but I wanted to get some additional input.
I examined the protocol catalogs on both Windows XP and Windows 98se and was
somewhat surprised that with the exception of the contents the data layout was
the same for both platforms. From what I can tell each catalog entry contains
256 bytes containing the pathname of the dll, followed by 4 unknown bytes
(possibly unused), followed by the contents of the WSAPROTOCOL_INFOW
structure. Since the WSAPROTOCOL_INFOW data seems to be stored verbatim in the
registry I decided to run a few tests and came up with the code below for
updating only the protocol chains in a catalog entry.
Although this is only a proof of concept implementation I'm betting that if I
stepped into the WSCUpdateProvider call it would look very similar to the code
below. If WSCUpdateProvider does work in a similar fashion and the structure
of the catalog data remains the same across all Win32 platforms I see no
reason why this code (with a bit of additional error checking) couldn't be
used in a production environment.
Anyone have some thoughts on this approach?
[ SNIP CODE HERE ]
struct CATITEM {
char Path[256];
DWORD Unknown;
WSAPROTOCOL_INFOW ProtocolInfo;
};
#define KEY_PACKED_CATALOG_ITEM "PackedCatalogItem"
#define KEY_PROTOCOL_CATALOG \
"System\\CurrentControlSet\\Services\\Winsock2\\Parameters\\Protocol_Catalog9\\Catalog_Entries"
#define KEY_NAME_LENGTH 256
int UpdateProviderChain(const DWORD providerID,
const WSAPROTOCOLCHAIN *chain,
DWORD *lpErrno)
{
LONG retVal;
LONG result;
HKEY hkey;
DWORD index;
// Open the proto catalog in the registry
result = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
KEY_PROTOCOL_CATALOG,
0,
KEY_READ,
&hkey);
if(ERROR_SUCCESS != result) {
*lpErrno = result;
return SOCKET_ERROR;
}
// Set up the default error
retVal = SOCKET_ERROR;
*lpErrno = WSAEINVAL;
// Go do it
index = 0;
while(ERROR_SUCCESS == result) {
char subKeyName[KEY_NAME_LENGTH + 1];
DWORD subKeyLen;
FILETIME lastReadTime;
HKEY subKey;
DWORD type;
DWORD size;
CATITEM item;
LONG status;
subKeyLen = KEY_NAME_LENGTH;
// Enumerate the key index
result = RegEnumKeyEx(hkey,
index,
subKeyName,
&subKeyLen,
0,
NULL,
NULL,
&lastReadTime);
// If there are no more items then assume the catalog ID is incorrect
if(ERROR_NO_MORE_ITEMS == result) {
*lpErrno = WSAEINVAL;
break;
}
// Check for misc other errors
if(ERROR_SUCCESS != result) {
*lpErrno = result;
break;
}
// Open the sub key
subKey = NULL;
result = RegOpenKeyEx(hkey,
subKeyName,
0,
KEY_READ | KEY_WRITE,
&subKey);
if(ERROR_SUCCESS != result) {
*lpErrno = result;
break;
}
/*
** NOTE **
The query of the value does not currently initiate an overall
failure of the update to the catalog chain
*/
// Get the key data
size = sizeof(item);
status = RegQueryValueEx(subKey,
KEY_PACKED_CATALOG_ITEM,
0,
&type,
(BYTE*)&item,
&size);
// Make sure we got the data
if(ERROR_SUCCESS == status && sizeof(CATITEM) == size && REG_BINARY =type) {
// Check the provider ID
if(providerID == item.ProtocolInfo.dwCatalogEntryId) {
// Update the new chain
item.ProtocolInfo.ProtocolChain = *chain;
// Save the data
*lpErrno = RegSetValueEx(subKey,
KEY_PACKED_CATALOG_ITEM,
0,
REG_BINARY,
(BYTE*)&item,
sizeof(item));
if(ERROR_SUCCESS != result) {
retVal = ERROR_SUCCESS;
}
RegCloseKey(subKey);
break;
}
}
// Close the subkey if it was opened
if(ERROR_SUCCESS == status && NULL != subKey) {
RegCloseKey(subKey);
}
index++;
}
RegCloseKey(hkey);
return retVal;
}
-
Chet Simpson
MSDN in one hand. Prozac in the other.
tests concerning the installation and removal of the provider when other
LSP's have been installed onto the system. During the testing I noticed that
several products being used to test compatibility failed miserably during the
removal stage of their own provider. Under Windows XP updating the protocol
chains is a snap as you have the WSCUpdateProvider call. Under Win9x variants
it's not as easy since you have to manage reinstalling the providers while
making sure all of the protocol chains are fixed for the new configuration. I
*think* I've found an easier method of updating the protocol chains for
instances such as this but I wanted to get some additional input.
I examined the protocol catalogs on both Windows XP and Windows 98se and was
somewhat surprised that with the exception of the contents the data layout was
the same for both platforms. From what I can tell each catalog entry contains
256 bytes containing the pathname of the dll, followed by 4 unknown bytes
(possibly unused), followed by the contents of the WSAPROTOCOL_INFOW
structure. Since the WSAPROTOCOL_INFOW data seems to be stored verbatim in the
registry I decided to run a few tests and came up with the code below for
updating only the protocol chains in a catalog entry.
Although this is only a proof of concept implementation I'm betting that if I
stepped into the WSCUpdateProvider call it would look very similar to the code
below. If WSCUpdateProvider does work in a similar fashion and the structure
of the catalog data remains the same across all Win32 platforms I see no
reason why this code (with a bit of additional error checking) couldn't be
used in a production environment.
Anyone have some thoughts on this approach?
[ SNIP CODE HERE ]
struct CATITEM {
char Path[256];
DWORD Unknown;
WSAPROTOCOL_INFOW ProtocolInfo;
};
#define KEY_PACKED_CATALOG_ITEM "PackedCatalogItem"
#define KEY_PROTOCOL_CATALOG \
"System\\CurrentControlSet\\Services\\Winsock2\\Parameters\\Protocol_Catalog9\\Catalog_Entries"
#define KEY_NAME_LENGTH 256
int UpdateProviderChain(const DWORD providerID,
const WSAPROTOCOLCHAIN *chain,
DWORD *lpErrno)
{
LONG retVal;
LONG result;
HKEY hkey;
DWORD index;
// Open the proto catalog in the registry
result = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
KEY_PROTOCOL_CATALOG,
0,
KEY_READ,
&hkey);
if(ERROR_SUCCESS != result) {
*lpErrno = result;
return SOCKET_ERROR;
}
// Set up the default error
retVal = SOCKET_ERROR;
*lpErrno = WSAEINVAL;
// Go do it
index = 0;
while(ERROR_SUCCESS == result) {
char subKeyName[KEY_NAME_LENGTH + 1];
DWORD subKeyLen;
FILETIME lastReadTime;
HKEY subKey;
DWORD type;
DWORD size;
CATITEM item;
LONG status;
subKeyLen = KEY_NAME_LENGTH;
// Enumerate the key index
result = RegEnumKeyEx(hkey,
index,
subKeyName,
&subKeyLen,
0,
NULL,
NULL,
&lastReadTime);
// If there are no more items then assume the catalog ID is incorrect
if(ERROR_NO_MORE_ITEMS == result) {
*lpErrno = WSAEINVAL;
break;
}
// Check for misc other errors
if(ERROR_SUCCESS != result) {
*lpErrno = result;
break;
}
// Open the sub key
subKey = NULL;
result = RegOpenKeyEx(hkey,
subKeyName,
0,
KEY_READ | KEY_WRITE,
&subKey);
if(ERROR_SUCCESS != result) {
*lpErrno = result;
break;
}
/*
** NOTE **
The query of the value does not currently initiate an overall
failure of the update to the catalog chain
*/
// Get the key data
size = sizeof(item);
status = RegQueryValueEx(subKey,
KEY_PACKED_CATALOG_ITEM,
0,
&type,
(BYTE*)&item,
&size);
// Make sure we got the data
if(ERROR_SUCCESS == status && sizeof(CATITEM) == size && REG_BINARY =type) {
// Check the provider ID
if(providerID == item.ProtocolInfo.dwCatalogEntryId) {
// Update the new chain
item.ProtocolInfo.ProtocolChain = *chain;
// Save the data
*lpErrno = RegSetValueEx(subKey,
KEY_PACKED_CATALOG_ITEM,
0,
REG_BINARY,
(BYTE*)&item,
sizeof(item));
if(ERROR_SUCCESS != result) {
retVal = ERROR_SUCCESS;
}
RegCloseKey(subKey);
break;
}
}
// Close the subkey if it was opened
if(ERROR_SUCCESS == status && NULL != subKey) {
RegCloseKey(subKey);
}
index++;
}
RegCloseKey(hkey);
return retVal;
}
-
Chet Simpson
MSDN in one hand. Prozac in the other.
Similar topics
Make your own search
Tags
Create a new topic
Follow the discussion
1 reply
Make a reply
May 21st, 2013 - 4:36 AM ET
Join now


Replies