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.
763 lines
22 KiB
763 lines
22 KiB
/*++
|
|
|
|
Copyright (c) 1991 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
brconfig.c
|
|
|
|
Abstract:
|
|
|
|
This module contains the Browser service configuration routines.
|
|
|
|
Author:
|
|
|
|
Rita Wong (ritaw) 22-May-1991
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
#include <strsafe.h>
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------//
|
|
// //
|
|
// Global variables //
|
|
// //
|
|
//-------------------------------------------------------------------//
|
|
|
|
//
|
|
// Browser configuration information structure which holds the
|
|
// computername, primary domain, browser config buffer, and a resource
|
|
// to serialize access to the whole thing.
|
|
//
|
|
BRCONFIGURATION_INFO BrInfo = {0};
|
|
|
|
BR_BROWSER_FIELDS BrFields[] = {
|
|
|
|
{WKSTA_KEYWORD_MAINTAINSRVLST, (LPDWORD) &BrInfo.MaintainServerList,
|
|
1,(DWORD)-1, 0, TriValueType, 0, NULL},
|
|
|
|
{BROWSER_CONFIG_BACKUP_RECOVERY_TIME, &BrInfo.BackupBrowserRecoveryTime,
|
|
BACKUP_BROWSER_RECOVERY_TIME, 0, 0xffffffff, DWordType, 0, NULL},
|
|
|
|
{L"CacheHitLimit", &BrInfo.CacheHitLimit,
|
|
// {BROWSER_CONFIG_CACHE_HIT_LIMIT, &BrInfo.CacheHitLimit,
|
|
CACHED_BROWSE_RESPONSE_HIT_LIMIT, 0, 0x100, DWordType, 0, NULL },
|
|
|
|
{L"CacheResponseSize", &BrInfo.NumberOfCachedResponses,
|
|
// {BROWSER_CONFIG_CACHE_HIT_LIMIT, &BrInfo.CacheHitLimit,
|
|
CACHED_BROWSE_RESPONSE_LIMIT, 0, MAXULONG, DWordType, 0, NULL },
|
|
|
|
{L"QueryDriverFrequency", &BrInfo.DriverQueryFrequency,
|
|
BROWSER_QUERY_DRIVER_FREQUENCY, 0, 15*60, DWordType, 0, NULL },
|
|
|
|
{L"DirectHostBinding", (LPDWORD)&BrInfo.DirectHostBinding,
|
|
0, 0, 0, MultiSzType, 0, BrChangeDirectHostBinding },
|
|
|
|
{L"UnboundBindings", (LPDWORD)&BrInfo.UnboundBindings,
|
|
0, 0, 0, MultiSzType, 0, NULL },
|
|
|
|
{L"MasterPeriodicity", (LPDWORD)&BrInfo.MasterPeriodicity,
|
|
MASTER_PERIODICITY, 5*60, 0x7fffffff/1000, DWordType, 0, BrChangeMasterPeriodicity },
|
|
|
|
{L"BackupPeriodicity", (LPDWORD)&BrInfo.BackupPeriodicity,
|
|
BACKUP_PERIODICITY, 5*60, 0x7fffffff/1000, DWordType, 0, NULL },
|
|
|
|
{L"BrowserDebug", (LPDWORD) &BrInfo.BrowserDebug,
|
|
0, 0, 0xffffffff,DWordType, 0, NULL},
|
|
{L"BrowserDebugLimit", (LPDWORD) &BrInfo.BrowserDebugFileLimit,
|
|
10000*1024, 0, 0xffffffff,DWordType, 0, NULL},
|
|
|
|
{NULL, NULL, 0, 0, 0, BooleanType, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
ULONG
|
|
NumberOfServerEnumerations = {0};
|
|
|
|
ULONG
|
|
NumberOfDomainEnumerations = {0};
|
|
|
|
ULONG
|
|
NumberOfOtherEnumerations = {0};
|
|
|
|
ULONG
|
|
NumberOfMissedGetBrowserListRequests = {0};
|
|
|
|
CRITICAL_SECTION
|
|
BrowserStatisticsLock = {0};
|
|
|
|
|
|
|
|
NET_API_STATUS
|
|
BrGetBrowserConfiguration(
|
|
VOID
|
|
)
|
|
{
|
|
NET_API_STATUS status;
|
|
NT_PRODUCT_TYPE NtProductType;
|
|
|
|
try {
|
|
//
|
|
// Initialize the resource for serializing access to configuration
|
|
// information.
|
|
//
|
|
try{
|
|
InitializeCriticalSection(&BrInfo.ConfigCritSect);
|
|
}
|
|
except ( EXCEPTION_EXECUTE_HANDLER ){
|
|
return NERR_NoNetworkResource;
|
|
}
|
|
|
|
//
|
|
// Lock config information structure for write access since we are
|
|
// initializing the data in the structure.
|
|
//
|
|
EnterCriticalSection( &BrInfo.ConfigCritSect );
|
|
|
|
//
|
|
// Set pointer to configuration fields structure
|
|
//
|
|
BrInfo.BrConfigFields = BrFields;
|
|
|
|
//
|
|
// Determine our product type.
|
|
//
|
|
|
|
RtlGetNtProductType(&NtProductType);
|
|
|
|
BrInfo.IsLanmanNt = (NtProductType == NtProductLanManNt);
|
|
|
|
|
|
//
|
|
// Read from the config file the browser configuration fields
|
|
//
|
|
|
|
status = BrReadBrowserConfigFields( TRUE );
|
|
|
|
if (status != NERR_Success) {
|
|
try_return ( status );
|
|
}
|
|
|
|
if (BrInfo.IsLanmanNt) {
|
|
BrInfo.MaintainServerList = 1;
|
|
}
|
|
|
|
|
|
#ifdef ENABLE_PSEUDO_BROWSER
|
|
BrInfo.PseudoServerLevel = GetBrowserPseudoServerLevel();
|
|
#endif
|
|
//
|
|
// Don't let the user define define an incompatible master/backup periodicity.
|
|
//
|
|
|
|
if ( BrInfo.MasterPeriodicity > BrInfo.BackupPeriodicity ) {
|
|
BrInfo.BackupPeriodicity = BrInfo.MasterPeriodicity;
|
|
}
|
|
|
|
|
|
try_exit:NOTHING;
|
|
} finally {
|
|
|
|
// else
|
|
// Leave config file open because we need to read transport names from it.
|
|
//
|
|
|
|
LeaveCriticalSection(&BrInfo.ConfigCritSect);
|
|
}
|
|
return status;
|
|
}
|
|
|
|
#define REPORT_KEYWORD_IGNORED( lptstrKeyword ) \
|
|
{ \
|
|
LPWSTR SubString[1]; \
|
|
SubString[0] = lptstrKeyword; \
|
|
BrLogEvent(EVENT_BROWSER_ILLEGAL_CONFIG, NERR_Success, 1, SubString); \
|
|
NetpKdPrint(( \
|
|
"[Browser] *ERROR* Tried to set keyword '" FORMAT_LPTSTR \
|
|
"' with invalid value.\n" \
|
|
"This error is ignored.\n", \
|
|
lptstrKeyword )); \
|
|
}
|
|
|
|
|
|
NET_API_STATUS
|
|
BrReadBrowserConfigFields(
|
|
IN BOOL InitialCall
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function assigns each browser/redir configuration field to the default
|
|
value if it is not specified in the configuration file or if the value
|
|
specified in the configuration file is invalid. Otherwise it overrides
|
|
the default value with the value found in the configuration file.
|
|
|
|
Arguments:
|
|
|
|
|
|
InitialCall - True if this call was made during initialization
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
NET_API_STATUS status;
|
|
LPNET_CONFIG_HANDLE BrowserSection;
|
|
DWORD i;
|
|
|
|
LPTSTR KeywordValueBuffer;
|
|
DWORD KeywordValueStringLength;
|
|
DWORD KeywordValue;
|
|
DWORD OldKeywordValue;
|
|
|
|
//
|
|
// Open config file and get handle to the [LanmanBrowser] section
|
|
//
|
|
|
|
if ((status = NetpOpenConfigData(
|
|
&BrowserSection,
|
|
NULL, // Local
|
|
SECT_NT_BROWSER,
|
|
TRUE // want read-only access
|
|
)) != NERR_Success) {
|
|
return status;
|
|
}
|
|
|
|
for (i = 0; BrInfo.BrConfigFields[i].Keyword != NULL; i++) {
|
|
BOOL ParameterChanged = FALSE;
|
|
|
|
//
|
|
// Skip this parameter if it can't change dynamically and
|
|
// this isn't the initial call.
|
|
//
|
|
|
|
if ( !InitialCall && BrInfo.BrConfigFields[i].DynamicChangeRoutine == NULL ) {
|
|
continue;
|
|
}
|
|
|
|
switch (BrInfo.BrConfigFields[i].DataType) {
|
|
|
|
case MultiSzType:
|
|
status = NetpGetConfigTStrArray(
|
|
BrowserSection,
|
|
BrInfo.BrConfigFields[i].Keyword,
|
|
(LPTSTR_ARRAY *)(BrInfo.BrConfigFields[i].FieldPtr));
|
|
if ((status != NO_ERROR) && (status != NERR_CfgParamNotFound)) {
|
|
REPORT_KEYWORD_IGNORED( BrInfo.BrConfigFields[i].Keyword );
|
|
}
|
|
break;
|
|
|
|
case BooleanType:
|
|
|
|
status = NetpGetConfigBool(
|
|
BrowserSection,
|
|
BrInfo.BrConfigFields[i].Keyword,
|
|
BrInfo.BrConfigFields[i].Default,
|
|
(LPBOOL)(BrInfo.BrConfigFields[i].FieldPtr)
|
|
);
|
|
|
|
if ((status != NO_ERROR) && (status != NERR_CfgParamNotFound)) {
|
|
|
|
REPORT_KEYWORD_IGNORED( BrInfo.BrConfigFields[i].Keyword );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TriValueType:
|
|
|
|
//
|
|
// Assign default configuration value
|
|
//
|
|
|
|
*(BrInfo.BrConfigFields[i].FieldPtr) = BrInfo.BrConfigFields[i].Default;
|
|
|
|
if (NetpGetConfigValue(
|
|
BrowserSection,
|
|
BrInfo.BrConfigFields[i].Keyword,
|
|
&KeywordValueBuffer
|
|
) != NERR_Success) {
|
|
continue;
|
|
}
|
|
|
|
KeywordValueStringLength = STRLEN(KeywordValueBuffer);
|
|
|
|
if (STRICMP(KeywordValueBuffer, KEYWORD_YES) == 0) {
|
|
*(BrInfo.BrConfigFields[i].FieldPtr) = 1;
|
|
} else if (STRICMP(KeywordValueBuffer, KEYWORD_TRUE) == 0) {
|
|
*(BrInfo.BrConfigFields[i].FieldPtr) = 1;
|
|
} else if (STRICMP(KeywordValueBuffer, KEYWORD_NO) == 0) {
|
|
*(BrInfo.BrConfigFields[i].FieldPtr) = (DWORD) -1;
|
|
} else if (STRICMP(KeywordValueBuffer, KEYWORD_FALSE) == 0) {
|
|
*(BrInfo.BrConfigFields[i].FieldPtr) = (DWORD) -1;
|
|
} else if (STRICMP(KeywordValueBuffer, TEXT("AUTO")) == 0) {
|
|
*(BrInfo.BrConfigFields[i].FieldPtr) = 0;
|
|
}
|
|
else {
|
|
REPORT_KEYWORD_IGNORED( BrInfo.BrConfigFields[i].Keyword );
|
|
}
|
|
|
|
NetApiBufferFree(KeywordValueBuffer);
|
|
|
|
break;
|
|
|
|
|
|
case DWordType:
|
|
|
|
OldKeywordValue = *(LPDWORD)BrInfo.BrConfigFields[i].FieldPtr;
|
|
if (NetpGetConfigDword(
|
|
BrowserSection,
|
|
BrInfo.BrConfigFields[i].Keyword,
|
|
BrInfo.BrConfigFields[i].Default,
|
|
(LPDWORD)(BrInfo.BrConfigFields[i].FieldPtr)
|
|
) != NERR_Success) {
|
|
continue;
|
|
}
|
|
|
|
KeywordValue = *(LPDWORD)BrInfo.BrConfigFields[i].FieldPtr;
|
|
|
|
//
|
|
// Don't allow too large or small a value.
|
|
//
|
|
|
|
if (KeywordValue < BrInfo.BrConfigFields[i].Minimum) {
|
|
BrPrint(( BR_CRITICAL, "%ws value out of range %lu (%lu-%lu)\n",
|
|
BrInfo.BrConfigFields[i].Keyword, KeywordValue,
|
|
BrInfo.BrConfigFields[i].Minimum,
|
|
BrInfo.BrConfigFields[i].Maximum
|
|
));
|
|
KeywordValue =
|
|
*(LPDWORD)BrInfo.BrConfigFields[i].FieldPtr =
|
|
BrInfo.BrConfigFields[i].Minimum;
|
|
}
|
|
|
|
if (KeywordValue > BrInfo.BrConfigFields[i].Maximum) {
|
|
BrPrint(( BR_CRITICAL, "%ws value out of range %lu (%lu-%lu)\n",
|
|
BrInfo.BrConfigFields[i].Keyword, KeywordValue,
|
|
BrInfo.BrConfigFields[i].Minimum,
|
|
BrInfo.BrConfigFields[i].Maximum
|
|
));
|
|
KeywordValue =
|
|
*(LPDWORD)BrInfo.BrConfigFields[i].FieldPtr =
|
|
BrInfo.BrConfigFields[i].Maximum;
|
|
}
|
|
|
|
//
|
|
// Test if the parameter has actually changed
|
|
//
|
|
|
|
if ( OldKeywordValue != KeywordValue ) {
|
|
ParameterChanged = TRUE;
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
NetpAssert(FALSE);
|
|
|
|
}
|
|
|
|
//
|
|
// If this is a dynamic parameter change,
|
|
// and this isn't the initial call.
|
|
// notify that this parameter changed.
|
|
//
|
|
|
|
if ( !InitialCall && ParameterChanged ) {
|
|
BrInfo.BrConfigFields[i].DynamicChangeRoutine();
|
|
}
|
|
}
|
|
|
|
status = NetpCloseConfigData(BrowserSection);
|
|
|
|
if (BrInfo.DirectHostBinding != NULL &&
|
|
!NetpIsTStrArrayEmpty(BrInfo.DirectHostBinding)) {
|
|
BrPrint(( BR_INIT,"DirectHostBinding length: %ld\n",NetpTStrArrayEntryCount(BrInfo.DirectHostBinding)));
|
|
|
|
if (NetpTStrArrayEntryCount(BrInfo.DirectHostBinding) % 2 != 0) {
|
|
status = ERROR_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
VOID
|
|
BrDeleteConfiguration (
|
|
DWORD BrInitState
|
|
)
|
|
{
|
|
|
|
if (BrInfo.DirectHostBinding != NULL) {
|
|
NetApiBufferFree(BrInfo.DirectHostBinding);
|
|
}
|
|
|
|
if (BrInfo.UnboundBindings != NULL) {
|
|
NetApiBufferFree(BrInfo.UnboundBindings);
|
|
}
|
|
|
|
DeleteCriticalSection(&BrInfo.ConfigCritSect);
|
|
|
|
UNREFERENCED_PARAMETER(BrInitState);
|
|
}
|
|
|
|
|
|
NET_API_STATUS
|
|
BrChangeDirectHostBinding(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description (BrChnageDirectHostBinding):
|
|
|
|
Handle a change in DirectHostBinding entry in the registry based on
|
|
Registry notification.
|
|
This is used so that when NwLnkNb transport is created via PnP, we should
|
|
also create NwLnkIpx (current usage).
|
|
The binding is refreshed in BrReadBrowserConfigFields above.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
NET_API_STATUS NetStatus = NERR_Success;
|
|
|
|
|
|
NetStatus = BrChangeConfigValue(
|
|
L"DirectHostBinding",
|
|
MultiSzType,
|
|
NULL,
|
|
&(BrInfo.DirectHostBinding),
|
|
TRUE );
|
|
|
|
if ( NetStatus == NERR_Success ) {
|
|
|
|
//
|
|
// DirectHostBinding sepcified. Verify consistency
|
|
//
|
|
|
|
EnterCriticalSection ( &BrInfo.ConfigCritSect );
|
|
if (BrInfo.DirectHostBinding != NULL &&
|
|
!NetpIsTStrArrayEmpty(BrInfo.DirectHostBinding)) {
|
|
BrPrint(( BR_INIT,"DirectHostBinding length: %ld\n",NetpTStrArrayEntryCount(BrInfo.DirectHostBinding)));
|
|
|
|
if (NetpTStrArrayEntryCount(BrInfo.DirectHostBinding) % 2 != 0) {
|
|
NetApiBufferFree(BrInfo.DirectHostBinding);
|
|
BrInfo.DirectHostBinding = NULL;
|
|
// we fail on invalid specifications
|
|
NetStatus = ERROR_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
LeaveCriticalSection ( &BrInfo.ConfigCritSect );
|
|
}
|
|
|
|
return NetStatus;
|
|
}
|
|
|
|
|
|
NET_API_STATUS
|
|
BrChangeConfigValue(
|
|
LPWSTR pszKeyword IN,
|
|
DATATYPE dataType IN,
|
|
PVOID pDefault IN,
|
|
PVOID *ppData OUT,
|
|
BOOL bFree IN
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Reads in the registry value for browser registry Entry
|
|
|
|
Arguments:
|
|
|
|
pszKeyword -- keyword relative to browser param section
|
|
dataType -- the type of the data to get from netapi lib.
|
|
pDefault -- Default value (to pass to reg calls).
|
|
pData -- data read from the registry.
|
|
Return Value:
|
|
|
|
Net api error code
|
|
|
|
|
|
--*/
|
|
{
|
|
NET_API_STATUS status = STATUS_SUCCESS;
|
|
|
|
LPNET_CONFIG_HANDLE BrowserSection = NULL;
|
|
LPTSTR KeywordValueBuffer;
|
|
DWORD KeywordValueStringLength;
|
|
PVOID pData = NULL;
|
|
|
|
ASSERT ( ppData );
|
|
|
|
|
|
EnterCriticalSection ( &BrInfo.ConfigCritSect );
|
|
|
|
//
|
|
// Open config file and get handle to the [LanmanBrowser] section
|
|
//
|
|
|
|
if ((status = NetpOpenConfigData(
|
|
&BrowserSection,
|
|
NULL, // Local
|
|
SECT_NT_BROWSER,
|
|
TRUE // want read-only access
|
|
)) != NERR_Success) {
|
|
goto Cleanup;
|
|
}
|
|
|
|
|
|
switch (dataType) {
|
|
|
|
case MultiSzType:
|
|
|
|
{
|
|
LPTSTR_ARRAY lpValues = NULL;
|
|
|
|
status = NetpGetConfigTStrArray(
|
|
BrowserSection,
|
|
pszKeyword,
|
|
(LPTSTR_ARRAY *)(&lpValues));
|
|
if ((status != NO_ERROR) && (status != NERR_CfgParamNotFound)) {
|
|
REPORT_KEYWORD_IGNORED( pszKeyword );
|
|
}
|
|
else {
|
|
pData = (PVOID)lpValues;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case BooleanType:
|
|
|
|
{
|
|
//
|
|
// Note : This case is unused at the moment.
|
|
//
|
|
|
|
BOOL bData;
|
|
status = NetpGetConfigBool(
|
|
BrowserSection,
|
|
pszKeyword,
|
|
*(LPBOOL)pDefault,
|
|
&bData
|
|
);
|
|
|
|
if ((status != NO_ERROR) && (status != NERR_CfgParamNotFound)) {
|
|
REPORT_KEYWORD_IGNORED( pszKeyword );
|
|
}
|
|
else
|
|
{
|
|
// store bool value in ptr.
|
|
// caller is responsible for consistent semantics translation.
|
|
pData = IntToPtr((int)bData);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case TriValueType:
|
|
|
|
{
|
|
//
|
|
// Assign default configuration value
|
|
//
|
|
if (NetpGetConfigValue(
|
|
BrowserSection,
|
|
pszKeyword,
|
|
&KeywordValueBuffer
|
|
) != NERR_Success) {
|
|
REPORT_KEYWORD_IGNORED( pszKeyword );
|
|
}
|
|
|
|
KeywordValueStringLength = STRLEN(KeywordValueBuffer);
|
|
|
|
if (STRICMP(KeywordValueBuffer, KEYWORD_YES) == 0) {
|
|
pData = (LPVOID)1;
|
|
} else if (STRICMP(KeywordValueBuffer, KEYWORD_TRUE) == 0) {
|
|
pData = (LPVOID)1;
|
|
} else if (STRICMP(KeywordValueBuffer, KEYWORD_NO) == 0) {
|
|
pData = (LPVOID) -1;
|
|
} else if (STRICMP(KeywordValueBuffer, KEYWORD_FALSE) == 0) {
|
|
pData = (LPVOID) -1;
|
|
} else if (STRICMP(KeywordValueBuffer, TEXT("AUTO")) == 0) {
|
|
pData = (LPVOID)0;
|
|
}
|
|
else {
|
|
// assign the value pointed by pDefault to pData
|
|
pData = ULongToPtr((*(LPDWORD)pDefault));
|
|
REPORT_KEYWORD_IGNORED( pszKeyword );
|
|
}
|
|
|
|
NetApiBufferFree(KeywordValueBuffer);
|
|
|
|
break;
|
|
}
|
|
|
|
|
|
|
|
case DWordType:
|
|
|
|
{
|
|
DWORD dwTmp;
|
|
|
|
if (NetpGetConfigDword(
|
|
BrowserSection,
|
|
pszKeyword,
|
|
*(LPDWORD)pDefault,
|
|
&dwTmp
|
|
) != NERR_Success) {
|
|
REPORT_KEYWORD_IGNORED( pszKeyword );
|
|
}
|
|
else {
|
|
pData = ULongToPtr(dwTmp);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
NetpAssert(FALSE);
|
|
}
|
|
|
|
|
|
Cleanup:
|
|
|
|
// Close config, & leave CS
|
|
NetpCloseConfigData(BrowserSection);
|
|
|
|
// optionaly free data & set return buffer
|
|
if ( status == STATUS_SUCCESS )
|
|
{
|
|
if ( bFree && *ppData )
|
|
{
|
|
NetApiBufferFree( *ppData );
|
|
}
|
|
*ppData = pData;
|
|
}
|
|
LeaveCriticalSection ( &BrInfo.ConfigCritSect );
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
|
|
#if DBG
|
|
NET_API_STATUS
|
|
BrUpdateDebugInformation(
|
|
IN LPWSTR SystemKeyName,
|
|
IN LPWSTR ValueName,
|
|
IN LPTSTR TransportName,
|
|
IN LPTSTR ServerName OPTIONAL,
|
|
IN DWORD ServiceStatus
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine will stick debug information in the registry about the last
|
|
time the browser retrieved information from the remote server.
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
WCHAR TotalKeyName[MAX_PATH];
|
|
ULONG Disposition;
|
|
HKEY Key;
|
|
ULONG Status;
|
|
SYSTEMTIME LocalTime;
|
|
WCHAR LastUpdateTime[100];
|
|
ULONG AvailableLen, NextLen;
|
|
|
|
//
|
|
// Build the key name:
|
|
//
|
|
// HKEY_LOCAL_MACHINE:System\CurrentControlSet\Services\Browser\Debug\<Transport>\SystemKeyName
|
|
//
|
|
|
|
AvailableLen = sizeof(TotalKeyName) / sizeof(WCHAR);
|
|
wcsncpy(TotalKeyName, L"System\\CurrentControlSet\\Services\\Browser\\Debug", AvailableLen);
|
|
AvailableLen -= wcslen(TotalKeyName);
|
|
|
|
NextLen = wcslen(TransportName);
|
|
wcsncat(TotalKeyName, TransportName, AvailableLen);
|
|
AvailableLen -= NextLen;
|
|
|
|
NextLen = wcslen(L"\\");
|
|
wcsncat(TotalKeyName, L"\\", AvailableLen);
|
|
AvailableLen -= NextLen;
|
|
|
|
wcsncat(TotalKeyName, SystemKeyName, AvailableLen);
|
|
|
|
if ((Status = RegCreateKeyEx(HKEY_LOCAL_MACHINE, TotalKeyName, 0,
|
|
L"BrowserDebugInformation",
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_WRITE,
|
|
NULL,
|
|
&Key,
|
|
&Disposition)) != ERROR_SUCCESS) {
|
|
BrPrint(( BR_CRITICAL,"Unable to create key to log debug information: %lx\n", Status));
|
|
Status;
|
|
}
|
|
|
|
if (ARGUMENT_PRESENT(ServerName)) {
|
|
if ((Status = RegSetValueEx(Key, ValueName, 0, REG_SZ, (LPBYTE)ServerName, (wcslen(ServerName)+1) * sizeof(WCHAR))) != ERROR_SUCCESS) {
|
|
BrPrint(( BR_CRITICAL,
|
|
"Unable to set value of ServerName value to %ws: %lx\n",
|
|
ServerName, Status));
|
|
RegCloseKey(Key);
|
|
return Status;
|
|
}
|
|
} else {
|
|
if ((Status = RegSetValueEx(Key, ValueName, 0, REG_DWORD, (LPBYTE)&ServiceStatus, sizeof(ULONG))) != ERROR_SUCCESS) {
|
|
BrPrint(( BR_CRITICAL,"Unable to set value of ServerName value to %ws: %lx\n", ServerName, Status));
|
|
RegCloseKey(Key);
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
|
|
GetLocalTime(&LocalTime);
|
|
|
|
StringCbPrintfW(LastUpdateTime, sizeof(LastUpdateTime), L"%d/%d/%d %d:%d:%d:%d", LocalTime.wDay,
|
|
LocalTime.wMonth,
|
|
LocalTime.wYear,
|
|
LocalTime.wHour,
|
|
LocalTime.wMinute,
|
|
LocalTime.wSecond,
|
|
LocalTime.wMilliseconds);
|
|
|
|
if ((Status = RegSetValueEx(Key, L"LastUpdateTime", 0, REG_SZ, (LPBYTE)&LastUpdateTime, (wcslen(LastUpdateTime) + 1)*sizeof(WCHAR))) != ERROR_SUCCESS) {
|
|
BrPrint(( BR_CRITICAL,"Unable to set value of LastUpdateTime value to %s: %lx\n", LastUpdateTime, Status));
|
|
}
|
|
|
|
RegCloseKey(Key);
|
|
return Status;
|
|
}
|
|
|
|
#endif
|