Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1408 lines
34 KiB

/*++
Copyright (c) 1999 Microsoft Corporation
Module Name:
smbrdr.c
Abstract:
This module implements the functios to load and unload the
smb monolithic minirdr. Also explicit start/stop control is
provided
This module also populates the registry entries for the
driver, and the network provider.
--*/
//#ifndef UNICODE
//#define UNICODE
//#endif
#include <windows.h>
#include <devioctl.h>
#include <stdlib.h>
#include "srfunc.h"
#ifdef DBG
#define DbgP(_x_) DbgPrint _x_
#else
#define DbgP(_x_)
#endif
ULONG _cdecl DbgPrint( LPTSTR Format, ... );
#define TRACE_TAG L"SMBRDR: "
TCHAR* SmbMrxDriverName = TEXT("SmbMRx");
// load action states
ULONG_PTR LoadActionStates[] =
{
RDR_NULL_STATE,
RDR_LOADING,
RDR_NULL_STATE,
RDR_NULL_STATE,
RDR_NULL_STATE,
RDR_NULL_STATE,
RDR_NULL_STATE,
RDR_NULL_STATE,
RDR_NULL_STATE
};
// unload action states
ULONG_PTR UnloadActionStates[] =
{
RDR_NULL_STATE,
RDR_NULL_STATE,
RDR_NULL_STATE,
RDR_NULL_STATE,
RDR_UNLOADING,
RDR_UNLOADING,
RDR_NULL_STATE,
RDR_NULL_STATE,
RDR_NULL_STATE
};
// Start action states
ULONG_PTR StartActionStates[] =
{
RDR_NULL_STATE,
RDR_NULL_STATE,
RDR_NULL_STATE,
RDR_NULL_STATE,
RDR_STARTING,
RDR_STARTING,
RDR_NULL_STATE,
RDR_NULL_STATE,
RDR_NULL_STATE
};
// Stop action states
ULONG_PTR StopActionStates[] =
{
RDR_NULL_STATE,
RDR_NULL_STATE,
RDR_NULL_STATE,
RDR_NULL_STATE,
RDR_NULL_STATE,
RDR_NULL_STATE,
RDR_NULL_STATE,
RDR_NULL_STATE,
RDR_STOPPING
};
ULONG_PTR TransitionActionStates[] =
{
RDR_NULL_STATE,
RDR_NULL_STATE,
RDR_UNLOADED,
RDR_LOADED,
RDR_NULL_STATE,
RDR_NULL_STATE,
RDR_STOPPED,
RDR_STARTED,
RDR_NULL_STATE
};
ULONG_PTR ErrorActionStates[] =
{
RDR_NULL_STATE,
RDR_NULL_STATE,
RDR_LOADED,
RDR_UNLOADED,
RDR_NULL_STATE,
RDR_NULL_STATE,
RDR_STARTED,
RDR_STOPPED,
RDR_NULL_STATE
};
ULONG_PTR NoneActionStates[] =
{
RDR_NULL_STATE,
RDR_UNLOADED,
RDR_UNLOADING,
RDR_LOADING,
RDR_LOADED,
RDR_STOPPED,
RDR_STOPPING,
RDR_STARTING,
RDR_STARTED
};
ULONG_PTR *ActionsStatesArray[] =
{
LoadActionStates,
UnloadActionStates,
StartActionStates,
StopActionStates,
TransitionActionStates,
ErrorActionStates,
NoneActionStates
};
ACTIONVECTOR ActionProcs[] =
{
RdrLoad,
RdrUnload,
RdrStart,
RdrStop,
RdrDoNothing,
RdrDoNothing,
RdrDoNothing
};
typedef enum _INSTALLCHECKS
{
installcheck_start,
installcheck_driverfile,
installcheck_providerfile,
installcheck_serviceentry,
installcheck_providerorder,
installcheck_stop,
installcheck_done
};
ULONG_PTR RdrInstallCheck( void )
{
TCHAR tszTestPath[_MAX_PATH];
ULONG_PTR teststep;
ULONG len = 0;
ULONG_PTR tc = SETUP_COMPLETE;
HANDLE th;
for ( teststep = installcheck_start; teststep < installcheck_done; teststep++ )
{
switch ( teststep )
{
case installcheck_start:
{
len = GetWindowsDirectory( tszTestPath, _MAX_PATH );
}
break;
case installcheck_driverfile:
{
lstrcpyn( &tszTestPath[len], DRIVER_FILE_PATH, _MAX_PATH - len );
th = CreateFile( tszTestPath, 0, 0, NULL, OPEN_EXISTING, 0, NULL );
if ( th == INVALID_HANDLE_VALUE )
{
tc = SETUP_MISSING_FILE;
teststep = installcheck_stop;
}
else
{
CloseHandle( th );
}
}
break;
case installcheck_providerfile:
{
lstrcpyn( &tszTestPath[len], PROVIDER_FILE_PATH, _MAX_PATH - len );
th = CreateFile( tszTestPath, 0, 0, NULL, OPEN_EXISTING, 0, NULL );
if ( th == INVALID_HANDLE_VALUE )
{
tc = SETUP_MISSING_FILE;
teststep = installcheck_stop;
}
else
{
CloseHandle( th );
}
}
break;
case installcheck_serviceentry:
{
HKEY hTestKey;
if ( OpenKey( RDRSERVICE_KEY, &hTestKey ) )
{
RegCloseKey( hTestKey );
}
else
{
tc = SETUP_INCOMPLETE;
teststep = installcheck_stop;
}
}
break;
case installcheck_providerorder:
{
LPTSTR pOrder;
RdrGetProviderOrderString( &pOrder );
if ( pOrder )
{
if ( !RdrFindProviderInOrder( pOrder, PROVIDER_NAME ) )
{
tc = SETUP_INCOMPLETE;
teststep = installcheck_stop;
}
free( pOrder );
}
}
break;
case installcheck_stop:
break;
}
}
return tc;
}
BOOL RdrCompleteSetup( void )
{
return RdrSetupServiceEntry( ) && RdrSetupProviderOrder( );
}
// These handles are retained
HANDLE hSharedMemory;
HANDLE hMutex;
BOOL RdrStart(void)
/*++
Routine Description:
This routine starts the SMB sample mini redirector.
Notes:
The start is distinguished from Load. During this phase the appropriate FSCTL
is issued and the shared memory/mutex data structures required for the Network
provider DLL are initialized.
--*/
{
HANDLE DeviceHandle; // The mini rdr device handle
DWORD BytesRet;
BOOL started = FALSE;
// Grab a handle to the redirector device object
DbgP((TEXT("Opening Rdr Device Object for Start Ioctl\n")));
DeviceHandle = CreateFile( DD_SMBMRX_USERMODE_DEV_NAME,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL );
DbgP((TEXT("returned from rdr device open\n")));
if ( DeviceHandle != INVALID_HANDLE_VALUE )
{
DbgP(( TEXT("Issueing Rdr Start Ioctl\n") ));
started = DeviceIoControl( DeviceHandle,
IOCTL_SMBMRX_START,
NULL,
0,
NULL,
0,
&BytesRet,
NULL );
// Create a section of shared memory to serve as the connection database
if ( started )
{
DWORD Status;
hSharedMemory = CreateFileMapping( INVALID_HANDLE_VALUE,
NULL,
PAGE_READWRITE,
0,
sizeof(SMBMRXNP_SHARED_MEMORY),
SMBMRXNP_SHARED_MEMORY_NAME);
if (hSharedMemory == NULL)
{
Status = GetLastError();
DbgP((TEXT("SMB MRx Net Provider shared memory Creation status %lx\n"),Status));
}
else
{
PSMBMRXNP_SHARED_MEMORY pSharedMemory;
pSharedMemory = MapViewOfFile(hSharedMemory, FILE_MAP_WRITE, 0, 0, 0);
if (pSharedMemory != NULL)
{
pSharedMemory->HighestIndexInUse = -1;
pSharedMemory->NumberOfResourcesInUse = 0;
}
UnmapViewOfFile(pSharedMemory);
}
hMutex = CreateMutex( NULL,
FALSE,
SMBMRXNP_MUTEX_NAME);
if (hMutex == NULL)
{
Status = GetLastError();
DbgP(( TEXT("SMB MRx Net Provider Mutex Creation status %lx\n"), Status));
}
}
else
{
DbgP(( TEXT("The DeviceIoctl for Starting Redirector returned %lx\n"), GetLastError() ));
}
}
else
{
DbgP(( TEXT("The CreateFile for opening device failed with error 0x%lx\n"), GetLastError() ));
DbgP(( TEXT("Device is %s\n"),DD_SMBMRX_USERMODE_DEV_NAME ));
}
//DbgP((TEXT("SMB MRx sample mini redirector start status %lx\n"),ntstatus));
CloseHandle(DeviceHandle);
return started;
}
BOOL RdrStop( void )
/*++
Routine Description:
This routine stops the SMB sample mini redirector.
Notes:
The stop is distinguished from unload. During this phase the appropriate FSCTL
is issued and the shared memory/mutex data structures required for the Network
provider DLL are torn down.
--*/
{
HANDLE DeviceHandle; // The mini rdr device handle
DWORD BytesRet;
BOOL stopped = FALSE;
// Grab a handle to the redirector device object
DeviceHandle = CreateFile( DD_SMBMRX_USERMODE_DEV_NAME,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL );
DbgP((TEXT("Doing Stop DeviceIoControl\n")));
if ( DeviceHandle != INVALID_HANDLE_VALUE )
{
stopped = DeviceIoControl( DeviceHandle,
IOCTL_SMBMRX_STOP,
NULL,
0,
NULL,
0,
&BytesRet,
NULL );
CloseHandle( DeviceHandle );
}
else
{
DbgP(( TEXT("The CreateFile for opening device failed\n") ));
}
CloseHandle(hMutex);
CloseHandle(hSharedMemory);
// DbgP(( TEXT("SMB MRx sample mini redirector start status %lx\n"),ntstatus ));
return stopped;
}
BOOL RdrLoad( void )
{
SC_HANDLE sch, service;
BOOL loaded = FALSE;
DbgP((TEXT("Loading SMB sample minirdr.......\n")));
sch = OpenSCManager( NULL, NULL, GENERIC_EXECUTE );
if ( sch )
{
service = OpenService( sch, RDRSERVICE, GENERIC_EXECUTE );
if ( service )
{
loaded = StartService( service, 0, NULL );
CloseServiceHandle( service );
}
CloseServiceHandle( sch );
}
return loaded;
}
BOOL RdrUnload( void )
{
SC_HANDLE sch, service;
BOOL unloaded = FALSE;
DbgP((TEXT("Unloading SMB sample minirdr.......\n")));
sch = OpenSCManager( NULL, NULL, GENERIC_EXECUTE );
if ( sch )
{
service = OpenService( sch, RDRSERVICE, GENERIC_EXECUTE );
if ( service )
{
SERVICE_STATUS ss;
unloaded = ControlService( service, SERVICE_CONTROL_STOP, &ss );
CloseServiceHandle( service );
}
CloseServiceHandle( sch );
}
return unloaded;
}
BOOL RdrDoNothing( void )
{
return TRUE;
}
BOOL RdrDoAction( ULONG_PTR action )
{
return (*ActionProcs[action])( );
}
ULONG_PTR RdrGetInitialState(void)
{
ULONG_PTR state = RDR_UNLOADED;
SC_HANDLE sch, service;
sch = OpenSCManager( NULL, NULL, GENERIC_READ );
if ( sch )
{
service = OpenService( sch, RDRSERVICE, GENERIC_READ );
if ( service )
{
SERVICE_STATUS ss;
if ( QueryServiceStatus( service, &ss ) )
{
switch ( ss.dwCurrentState )
{
case SERVICE_STOPPED:
state = RDR_UNLOADED;
break;
case SERVICE_START_PENDING:
state = RDR_LOADING;
break;
case SERVICE_STOP_PENDING:
state = RDR_UNLOADING;
break;
case SERVICE_RUNNING:
state = RDR_LOADED;
break;
case SERVICE_CONTINUE_PENDING:
case SERVICE_PAUSE_PENDING:
case SERVICE_PAUSED:
default:
state = RDR_UNLOADED;
break;
}
#if 0 //just check for load/unload state for now
// go check the start/stop state
if ( state == RDR_LOADED )
{
BOOL IsOk;
HANDLE DeviceHandle;
DWORD BytesRet;
ULONG_PTR RdrStateValue;
DeviceHandle = CreateFile( DD_SMBMRX_USERMODE_DEV_NAME,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL );
if ( DeviceHandle != INVALID_HANDLE_VALUE )
{
DbgP((TEXT("Doing Get State DeviceIoControl\n")));
IsOk = DeviceIoControl( DeviceHandle,
IOCTL_SMBMRX_GETSTATE,
NULL,
0,
&RdrStateValue,
sizeof(ULONG),
&BytesRet,
NULL );
CloseHandle( DeviceHandle );
}
if ( IsOk )
{
state = RdrStateValue;
}
}
#endif
}
CloseServiceHandle( service );
}
CloseServiceHandle( sch );
}
return state;
}
ULONG_PTR RdrGetNextState( ULONG_PTR Action, ULONG_PTR CurrentState )
{
return ActionsStatesArray[Action][CurrentState];
}
REGENTRY LinkageKeyValues[] =
{
{ TEXT("Bind"), REG_MULTI_SZ, 0, 0 },
{ TEXT("Export"), REG_MULTI_SZ, 0, 0 },
{ TEXT("Route"), REG_MULTI_SZ, 0, 0 }
};
REGENTRY LinkageDisabledKeyValues[] =
{
{ TEXT("Bind"), REG_MULTI_SZ, 0, 0 },
{ TEXT("Export"), REG_MULTI_SZ, 0, 0 },
{ TEXT("Route"), REG_MULTI_SZ, 0, 0 }
};
REGENTRY NetworkProviderKeyValues[] =
{
{
TEXT("Devicename"),
REG_SZ,
sizeof(SMBMRX_DEVICE_NAME),
SMBMRX_DEVICE_NAME
},
{
TEXT("ProviderPath"),
REG_EXPAND_SZ,
sizeof(PROVIDER_PATH),
PROVIDER_PATH
},
{
TEXT("Name"),
REG_SZ,
sizeof(SMBMRX_PROVIDER_NAME),
SMBMRX_PROVIDER_NAME
}
};
REGENTRY ProviderOrderKeyValues[] =
{
{ TEXT("ProviderOrder"), REG_SZ, 0, 0 }
};
BOOL RdrSetupServiceEntry( void )
/*++
Routine Description:
This routine initializes the registry entries for the smbmrx
minirdr. This only needs to be done once.
Arguments:
None
Return Value:
None
--*/
{
HKEY hCurrentKey;
SC_HANDLE sch, service;
BOOL success = TRUE;
DbgP(( TEXT( "Setting up ") RDRSERVICE TEXT(" registry Entries\n" ) ));
sch = OpenSCManager( NULL, NULL, GENERIC_WRITE );
if ( sch )
{
service = CreateService( sch,
RDRSERVICE,
RDRSERVICE,
SERVICE_ALL_ACCESS,
SERVICE_FILE_SYSTEM_DRIVER,
SERVICE_DEMAND_START,
SERVICE_ERROR_NORMAL,
TEXT("System32\\DRIVERS\\") RDRSERVICE TEXT(".sys"),
TEXT("Network"),
NULL,
NULL,
NULL,
NULL );
if ( service )
{
CloseServiceHandle( service );
}
else if ( GetLastError( ) != ERROR_SERVICE_EXISTS )
{
success = FALSE;
}
CloseServiceHandle( sch );
}
else
{
success = FALSE;
}
// Read the linkage values associated with the Lanman workstation service.
// This contains all the transports and the order in which they need to be used
if ( success && OpenKey( WKSSERVICE_KEY TEXT("\\Linkage"), &hCurrentKey ) )
{
ULONG i;
ReadRegistryKeyValues( hCurrentKey,
sizeof(LinkageKeyValues) / sizeof(REGENTRY),
LinkageKeyValues);
RegCloseKey(hCurrentKey);
// Update the SMB MRx linkage values
if ( CreateKey( RDRSERVICE_KEY TEXT("\\Linkage"), &hCurrentKey ) )
{
WriteRegistryKeyValues( hCurrentKey,
sizeof(LinkageKeyValues) / sizeof(REGENTRY),
LinkageKeyValues);
RegCloseKey(hCurrentKey);
}
else
{
success = FALSE;
}
for ( i = 0; i < ( sizeof(LinkageKeyValues) / sizeof(REGENTRY) ); i++ )
{
if ( LinkageKeyValues[i].pvValue )
{
free( LinkageKeyValues[i].pvValue );
LinkageKeyValues[i].pvValue = NULL;
}
}
}
else
{
success = FALSE;
}
//if ( OpenKey( WKSSERVICE_KEY TEXT("\\Linkage\\Disabled",&hCurrentKey))
//{
// ReadRegistryKeyValues( hCurrentKey,
// sizeof(LinkageDisabledKeyValues) / sizeof(REGENTRY),
// LinkageDisabledKeyValues);
// RegCloseKey(hCurrentKey);
//}
//else
//{
// DbgP(( TEXT("Error Opening Key %s Status %d\n"),WKSSERVICE_KEY TEXT("\\Linkage\\Disabled"),GetLastError() ));
// return;
//}
// Update the SMB MRx linkage disabled values
//if ( CreateKey( RDRSERVICE_KEY TEXT("\\Linkage\\Disabled") ,&hCurrentKey))
//{
// WriteRegistryKeyValues( hCurrentKey,
// sizeof(LinkageDisabledKeyValues)/sizeof(REGENTRY),
// LinkageDisabledKeyValues );
// RegCloseKey(hCurrentKey);
//}
//else
//{
// DbgP(( TEXT("Error Creating Key %s Status %d\n"),RDRSERVICE_KEY TEXT("\\linkage\\disabled",GetLastError() ));
// return;
//}
// Update the SMBmrx network provider section
if ( success && CreateKey( RDRSERVICE_KEY TEXT("\\NetworkProvider"), &hCurrentKey ) )
{
WriteRegistryKeyValues( hCurrentKey,
sizeof(NetworkProviderKeyValues)/sizeof(REGENTRY),
NetworkProviderKeyValues);
RegCloseKey(hCurrentKey);
}
else
{
success = FALSE;
}
if ( success && CreateKey( RDRSERVICE_KEY TEXT("\\Parameters"), &hCurrentKey ) )
{
RegCloseKey( hCurrentKey );
}
else
{
success = FALSE;
}
return success;
}
BOOL RdrSetupProviderOrder( void )
{
LPTSTR pOrderString = NULL;
ULONG_PTR len;
BOOL success = TRUE;
len = RdrGetProviderOrderString( &pOrderString ) * sizeof(TCHAR);
if ( len > 0 && pOrderString )
{
if ( !RdrFindProviderInOrder( pOrderString, PROVIDER_NAME ) )
{
LPTSTR pNewOrderString;
len += sizeof( PROVIDER_NAME ) + (2 * sizeof(TCHAR)); // add 2 for comma delimeter and null
pNewOrderString = malloc( len );
if ( pNewOrderString )
{
lstrcpy( pNewOrderString, pOrderString );
lstrcat( pNewOrderString, TEXT(",") );
lstrcat( pNewOrderString, PROVIDER_NAME );
success = RdrSetProviderOrderString( pNewOrderString );
free( pNewOrderString );
}
}
}
else
{
success = RdrSetProviderOrderString( PROVIDER_NAME );
}
if ( pOrderString )
{
free( pOrderString );
}
return success;
}
ULONG_PTR RdrGetProviderOrderString( LPTSTR *OrderString )
{
HKEY hOrderKey;
ULONG_PTR len = 0;
if ( OpenKey( PROVIDER_ORDER_KEY, &hOrderKey ) )
{
ReadRegistryKeyValues( hOrderKey,
sizeof(ProviderOrderKeyValues) / sizeof(REGENTRY),
ProviderOrderKeyValues);
RegCloseKey(hOrderKey);
len = ProviderOrderKeyValues[0].dwLength / sizeof( TCHAR ) - 1;
*OrderString = (LPTSTR) ProviderOrderKeyValues[0].pvValue;
}
return len;
}
BOOL RdrSetProviderOrderString( LPTSTR OrderString )
{
HKEY hOrderKey;
ULONG len = 0;
BOOL rc = FALSE;
if ( CreateKey( PROVIDER_ORDER_KEY, &hOrderKey ) )
{
ProviderOrderKeyValues[0].dwLength = ( lstrlen( OrderString ) + 1 ) * sizeof( TCHAR );
ProviderOrderKeyValues[0].pvValue = OrderString;
WriteRegistryKeyValues( hOrderKey,
sizeof(ProviderOrderKeyValues) / sizeof(REGENTRY),
ProviderOrderKeyValues);
RegCloseKey(hOrderKey);
rc = TRUE;
}
return rc;
}
BOOL RdrFindProviderInOrder( LPTSTR OrderString, LPTSTR Provider )
{
LPTSTR pCompare;
BOOL match = FALSE;
if ( OrderString && Provider && *Provider )
{
pCompare = Provider;
while ( *OrderString )
{
if ( toupper(*OrderString++) != toupper(*pCompare++) )
{
pCompare = Provider;
}
if ( *pCompare == TEXT('\0') )
{
if ( ( *OrderString == TEXT(',') ) || ( *OrderString == TEXT('\0') ) )
{
match = TRUE;
break;
}
else // hmm, it's a substring of another provider name
{
while ( ( *OrderString != TEXT(',') ) && ( *OrderString != TEXT('\0') ) )
{
OrderString++;
}
pCompare = Provider;
}
}
}
}
return match;
}
void
ReadRegistryKeyValues(
HKEY hCurrentKey,
DWORD NumberOfValues,
PREGENTRY pValues)
/*++
Routine Description:
This routine reads a bunch of values associated with a given key.
Arguments:
hCurrentKey - the key
NumberOfValues - the number of values
pValues - the array of values
Return Value:
None
--*/
{
//
// Iterate through table reading the values along the way
//
DWORD i;
for (i = 0; i < NumberOfValues; i++)
{
DWORD dwType;
LPTSTR pszKey;
dwType = pValues[i].dwType;
pszKey = pValues[i].pszKey;
switch (dwType)
{
case REG_SZ:
GetRegsz(hCurrentKey, pszKey, &pValues[i].pvValue,
&pValues[i].dwLength);
break;
case REG_DWORD:
GetRegdw(hCurrentKey, pszKey, &pValues[i].pvValue,
&pValues[i].dwLength);
break;
case REG_EXPAND_SZ:
GetRegesz(hCurrentKey, pszKey, &pValues[i].pvValue,
&pValues[i].dwLength);
break;
case REG_MULTI_SZ:
GetRegmsz(hCurrentKey, pszKey, &pValues[i].pvValue,
&pValues[i].dwLength);
break;
case REG_BINARY:
DbgP(( TEXT("%s is a REG_BINARY and won't be duplicated\n"), pszKey ));
break;
default:
DbgP(( TEXT("%s is an unknown type; %d (decimal)\n"), pszKey, dwType ));
break;
}
}
}
//
// Get a REG_SZ value and stick it in the table entry, along with the
// length
//
BOOL GetRegsz(HKEY hKey, LPTSTR pszKey, PVOID * ppvValue, DWORD *pdwLength)
{
BYTE achValue[1024];
DWORD dwLength;
LONG Status;
DWORD dwType = REG_SZ;
PBYTE pszValue = NULL;
if ( (NULL == pszKey) || (NULL == ppvValue) ||
(NULL == hKey) || (NULL == pdwLength))
{
return FALSE;
}
#ifdef _DEBUG
FillMemory(achValue, sizeof(achValue), 0xcd);
#endif
dwLength = sizeof(achValue);
Status = RegQueryValueEx( hKey,
pszKey,
NULL,
&dwType,
(PUCHAR) &achValue[0],
&dwLength);
if ((ERROR_SUCCESS != Status) || (REG_SZ != dwType) )
{
return FALSE;
}
pszValue = malloc(dwLength);
if (NULL == pszValue)
{
return FALSE;
}
CopyMemory(pszValue, achValue, dwLength);
*ppvValue = pszValue;
*pdwLength = dwLength;
return TRUE;
}
//
// Get the value of a REG_EXPAND_SZ and its length
//
BOOL GetRegesz(HKEY hKey, LPTSTR pszKey, PVOID * ppvValue, DWORD * pdwLength)
{
BYTE achValue[1024];
DWORD dwLength;
LONG Status;
DWORD dwType = REG_EXPAND_SZ;
PBYTE pszValue = NULL;
if ( (NULL == pszKey) || (NULL == ppvValue) ||
(NULL == hKey) || (NULL == pdwLength))
{
return FALSE;
}
#ifdef _DEBUG
FillMemory(achValue, sizeof(achValue), 0xcd);
#endif
dwLength = sizeof(achValue);
Status = RegQueryValueEx( hKey,
pszKey,
NULL,
&dwType,
(PUCHAR) &achValue[0],
&dwLength);
if ((ERROR_SUCCESS != Status) || (REG_EXPAND_SZ != dwType))
{
return FALSE;
}
pszValue = malloc(dwLength);
if (NULL == pszValue)
{
return FALSE;
}
CopyMemory(pszValue, achValue, dwLength);
*ppvValue = pszValue;
*pdwLength = dwLength;
return TRUE;
}
//
// Get value and length of REG_MULTI_SZ
//
BOOL GetRegmsz(HKEY hKey, LPTSTR pszKey, PVOID * ppvValue, DWORD * pdwLength)
{
//BYTE achValue[1024];
BYTE achValue[2048]; // careful, some of these strings are quite long
DWORD dwLength;
LONG Status;
DWORD dwType = REG_MULTI_SZ;
PBYTE pszValue = NULL;
if ( (NULL == pszKey) || (NULL == ppvValue) ||
(NULL == hKey) || (NULL == pdwLength))
{
return FALSE;
}
#ifdef _DEBUG
FillMemory(achValue, sizeof(achValue), 0xcd);
#endif
dwLength = sizeof(achValue);
Status = RegQueryValueEx( hKey,
pszKey,
NULL,
&dwType,
(PUCHAR) &achValue[0],
&dwLength);
if ((ERROR_SUCCESS != Status) || (REG_MULTI_SZ != dwType))
{
return FALSE;
}
pszValue = malloc(dwLength);
if (NULL == pszValue)
{
return FALSE;
}
CopyMemory(pszValue, achValue, dwLength);
*ppvValue = pszValue;
*pdwLength = dwLength;
return TRUE;
}
//
// Get value and length of REG_DWORD
//
BOOL GetRegdw(HKEY hKey, LPTSTR pszKey, PVOID * ppvValue, DWORD * pdwLength)
{
DWORD dwValue = 0;
DWORD dwLength;
LONG Status;
DWORD dwType = REG_DWORD;
if ( (NULL == pszKey) || (NULL == ppvValue) ||
(NULL == hKey) || (NULL == pdwLength) )
{
return FALSE;
}
dwLength = sizeof(dwValue);
Status = RegQueryValueEx( hKey,
pszKey,
NULL,
&dwType,
(PUCHAR) &dwValue,
&dwLength);
if ((ERROR_SUCCESS != Status) || (REG_DWORD != dwType))
{
return FALSE;
}
*ppvValue = (PVOID) (ULONG_PTR) dwValue;
*pdwLength = dwLength;
return TRUE;
}
void
WriteRegistryKeyValues(
HKEY hCurrentKey,
DWORD NumberOfValues,
PREGENTRY pValues)
/*++
Routine Description:
This routine reads a bunch of values associated with a given key.
Arguments:
hCurrentKey - the key
NumberOfValues - the number of values
pValues - the array of values
Return Value:
None
--*/
{
DWORD i;
for (i = 0; i < NumberOfValues; i++)
{
DWORD dwType;
PVOID pvValue;
DWORD dwLength;
LPTSTR pszKey;
pszKey = pValues[i].pszKey;
dwType = pValues[i].dwType;
dwLength = pValues[i].dwLength;
pvValue = pValues[i].pvValue;
switch (dwType)
{
case REG_SZ:
AddValue(hCurrentKey, pszKey, dwType, dwLength, pvValue);
break;
case REG_DWORD:
AddValue(hCurrentKey, pszKey, dwType, dwLength, &pvValue);
break;
case REG_EXPAND_SZ:
AddValue(hCurrentKey, pszKey, dwType, dwLength, pvValue);
break;
case REG_MULTI_SZ:
AddValue(hCurrentKey, pszKey, dwType, dwLength, pvValue);
break;
case REG_BINARY:
//
// There are no binary values we need to copy. If we did, we'd
// put something here
//
break;
default:
DbgP(( TEXT("%s is an unknown type; %d (decimal)\n"), pszKey, dwType ));
break;
}
}
}
//
// Open a key so we can read the values
//
BOOL OpenKey(
LPTSTR pszKey,
PHKEY phKey)
/*++
Routine Description:
This routine opens a registry key.
Arguments:
pszKey - the name of the key relative to HKEY_LOCAL_MACHINE
phKey - the key handlle
Return Value:
TRUE if successful, otherwise FALSE
--*/
{
HKEY hNewKey = 0;
DWORD Status;
Status = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
pszKey,
0,
KEY_QUERY_VALUE,
&hNewKey);
if (ERROR_SUCCESS != Status)
{
*phKey = NULL;
return FALSE;
}
else
{
*phKey = hNewKey;
return TRUE;
}
}
BOOL CreateKey(LPTSTR pszKey, PHKEY phKey)
/*++
Routine Description:
This routine creates a registry key.
Arguments:
pszKey - the name of the key relative to HKEY_LOCAL_MACHINE
phKey - the key handlle
Return Value:
TRUE if successful, otherwise FALSE
--*/
{
LONG Status;
DWORD Disposition;
Status = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
pszKey,
0,
REG_NONE,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
phKey,
&Disposition);
if ( ERROR_SUCCESS == Status)
{
return TRUE;
}
else
{
DbgP(( TEXT("error creating key %s Status %d\n"), pszKey, Status ));
return FALSE;
}
}
//
// Add a value to the registry
//
BOOL AddValue(HKEY hKey, LPTSTR pszKey, DWORD dwType, DWORD dwLength, PVOID pvValue)
{
BOOL fSuccess = TRUE;
LONG Status = ERROR_SUCCESS;
HANDLE th;
Status = RegSetValueEx( hKey,
pszKey,
0,
dwType,
pvValue,
dwLength);
if (Status != ERROR_SUCCESS)
{
fSuccess = FALSE;
//RegCloseKey(hKey);
}
return fSuccess;
}
int _cdecl _vsnwprintf( wchar_t *buffer, size_t count, wchar_t *format, va_list arg_ptr);
// Format and write debug information to OutputDebugString
ULONG
_cdecl
DbgPrint(
LPTSTR Format,
...
)
{
ULONG rc = 0;
TCHAR szbuffer[256];
va_list marker;
va_start( marker, Format );
{
rc = _vsnwprintf( szbuffer, 254, Format, marker );
szbuffer[255] = (TCHAR)0;
OutputDebugString( TRACE_TAG );
OutputDebugString( szbuffer );
}
return rc;
}