mirror of https://github.com/lianthony/NT4.0
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.
734 lines
21 KiB
734 lines
21 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
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------//
|
|
// //
|
|
// 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};
|
|
|
|
STATIC BR_BROWSER_FIELDS BrFields[] = {
|
|
|
|
{WKSTA_KEYWORD_MAINTAINSRVLST, (LPDWORD) &BrInfo.MaintainServerList,
|
|
1,(DWORD)-1, 0, TriValueType, 0, NULL},
|
|
|
|
{WKSTA_KEYWORD_ISDOMAINMASTER, (LPDWORD) &BrInfo.IsDomainMasterBrowser,
|
|
0, 0, 1, BooleanType, 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, NULL },
|
|
|
|
{L"UnboundBindings", (LPDWORD)&BrInfo.UnboundBindings,
|
|
0, 0, 0, MultiSzType, 0, NULL },
|
|
|
|
{L"MasterPeriodicity", (LPDWORD)&BrInfo.MasterPeriodicity,
|
|
MASTER_PERIODICITY, 5*60, 0xffffffff, DWordType, 0, BrChangeMasterPeriodicity },
|
|
|
|
{L"BackupPeriodicity", (LPDWORD)&BrInfo.BackupPeriodicity,
|
|
BACKUP_PERIODICITY, 5*60, 0xffffffff, DWordType, 0, NULL },
|
|
|
|
|
|
#if DBG
|
|
{L"BrowserDebug", (LPDWORD) &BrInfo.BrowserDebug,
|
|
0, 0, 0xffffffff,DWordType, 0, NULL},
|
|
{L"BrowserDebugLimit", (LPDWORD) &BrInfo.BrowserDebugFileLimit,
|
|
10000*1024, 0, 0xffffffff,DWordType, 0, NULL},
|
|
#endif
|
|
|
|
{NULL, NULL, 0, 0, BooleanType}
|
|
|
|
};
|
|
|
|
|
|
ULONG
|
|
NumberOfServerEnumerations = {0};
|
|
|
|
ULONG
|
|
NumberOfDomainEnumerations = {0};
|
|
|
|
ULONG
|
|
NumberOfOtherEnumerations = {0};
|
|
|
|
ULONG
|
|
NumberOfMissedGetBrowserListRequests = {0};
|
|
|
|
CRITICAL_SECTION
|
|
BrowserStatisticsLock = {0};
|
|
|
|
|
|
DWORD
|
|
BrInAWorkgroup(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function determines whether we are a member of a domain, or of
|
|
a workgroup. First it checks to make sure we're running on a Windows NT
|
|
system (otherwise we're obviously in a domain) and if so, queries LSA
|
|
to get the Primary domain SID, if this is NULL, we're in a workgroup.
|
|
|
|
If we fail for some random unexpected reason, we'll pretend we're in a
|
|
domain (it's more restrictive).
|
|
|
|
Arguments:
|
|
None
|
|
|
|
Return Value:
|
|
|
|
TRUE - We're in a workgroup
|
|
FALSE - We're in a domain
|
|
|
|
--*/
|
|
{
|
|
NT_PRODUCT_TYPE ProductType;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
LSA_HANDLE Handle;
|
|
NTSTATUS Status;
|
|
PPOLICY_PRIMARY_DOMAIN_INFO PolicyPrimaryDomainInfo = NULL;
|
|
DWORD Result = FALSE;
|
|
|
|
|
|
Status = RtlGetNtProductType(&ProductType);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (ProductType == NtProductLanManNt) {
|
|
return(FALSE);
|
|
}
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes, NULL, 0, 0, NULL);
|
|
|
|
Status = LsaOpenPolicy(NULL,
|
|
&ObjectAttributes,
|
|
POLICY_VIEW_LOCAL_INFORMATION,
|
|
&Handle);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
return FALSE;
|
|
}
|
|
|
|
Status = LsaQueryInformationPolicy(Handle, PolicyPrimaryDomainInformation,
|
|
(PVOID *) &PolicyPrimaryDomainInfo);
|
|
|
|
if (NT_SUCCESS(Status)) {
|
|
|
|
if (PolicyPrimaryDomainInfo->Sid == NULL) {
|
|
Result = TRUE;
|
|
}
|
|
else {
|
|
Result = FALSE;
|
|
}
|
|
}
|
|
|
|
if (PolicyPrimaryDomainInfo) {
|
|
LsaFreeMemory((PVOID)PolicyPrimaryDomainInfo);
|
|
}
|
|
LsaClose(Handle);
|
|
|
|
return(Result);
|
|
}
|
|
|
|
|
|
NET_API_STATUS
|
|
BrGetBrowserConfiguration(
|
|
VOID
|
|
)
|
|
{
|
|
NET_API_STATUS status;
|
|
LPTSTR ComputerName;
|
|
NT_PRODUCT_TYPE NtProductType;
|
|
|
|
//
|
|
// Initialize the resource for serializing access to configuration
|
|
// information.
|
|
//
|
|
RtlInitializeResource(&BrInfo.ConfigResource);
|
|
|
|
//
|
|
// Lock config information structure for write access since we are
|
|
// initializing the data in the structure.
|
|
//
|
|
if (! RtlAcquireResourceExclusive(&BrInfo.ConfigResource, TRUE)) {
|
|
return NERR_InternalError;
|
|
}
|
|
|
|
//
|
|
// Set pointer to configuration fields structure
|
|
//
|
|
BrInfo.BrConfigFields = BrFields;
|
|
|
|
//
|
|
// Get the configured computer name. NetpGetComputerName allocates
|
|
// the memory to hold the computername string using LocalAlloc.
|
|
//
|
|
if ((status = NetpGetComputerName(
|
|
&ComputerName
|
|
)) != NERR_Success) {
|
|
RtlReleaseResource(&BrInfo.ConfigResource);
|
|
return status;
|
|
}
|
|
|
|
if ((status = I_NetNameCanonicalize(
|
|
NULL,
|
|
ComputerName,
|
|
BrInfo.BrComputerName,
|
|
(CNLEN + 1) * sizeof(TCHAR),
|
|
NAMETYPE_COMPUTER,
|
|
0
|
|
)) != NERR_Success) {
|
|
|
|
KdPrint(("[Browser] ComputerName specified is invalid\n"));
|
|
|
|
(void) LocalFree(ComputerName);
|
|
RtlReleaseResource(&BrInfo.ConfigResource);
|
|
return status;
|
|
}
|
|
|
|
//
|
|
// Free memory allocated by NetpGetComputerName.
|
|
//
|
|
(void) LocalFree(ComputerName);
|
|
|
|
BrInfo.BrComputerNameLength = STRLEN(BrInfo.BrComputerName);
|
|
|
|
dprintf(CONFIG, ("[Browser] ComputerName %ws, length %lu\n",
|
|
BrInfo.BrComputerName, BrInfo.BrComputerNameLength));
|
|
|
|
|
|
//
|
|
// Get the primary domain name from the configuration file
|
|
//
|
|
|
|
{
|
|
LPTSTR DomainNameT;
|
|
if ((status = NetpGetDomainName(
|
|
& DomainNameT
|
|
)) != NERR_Success) {
|
|
goto CloseConfigFile;
|
|
}
|
|
NetpAssert( DomainNameT != NULL );
|
|
(void) STRCPY( BrInfo.BrPrimaryDomainName, DomainNameT );
|
|
BrInfo.BrPrimaryDomainNameLength = STRLEN( DomainNameT );
|
|
(void) NetApiBufferFree( DomainNameT );
|
|
}
|
|
|
|
if ((status = I_NetNameCanonicalize(
|
|
NULL,
|
|
BrInfo.BrPrimaryDomainName,
|
|
BrInfo.BrPrimaryDomainName,
|
|
(DNLEN + 1) * sizeof(TCHAR),
|
|
BrInAWorkgroup() ? NAMETYPE_WORKGROUP : NAMETYPE_DOMAIN,
|
|
0
|
|
)) != NERR_Success) {
|
|
|
|
KdPrint(("[Browser] Primary domain name specified is invalid\n"));
|
|
goto CloseConfigFile;
|
|
}
|
|
|
|
//
|
|
// Determine our product type.
|
|
//
|
|
|
|
RtlGetNtProductType(&NtProductType);
|
|
|
|
BrInfo.IsLanmanNt = (NtProductType == NtProductLanManNt);
|
|
|
|
//
|
|
// Now determine the primary domain controller for our domain.
|
|
//
|
|
|
|
{
|
|
if (NtProductType == NtProductLanManNt) {
|
|
LSA_HANDLE LsaHandle;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
NTSTATUS Status;
|
|
PPOLICY_LSA_SERVER_ROLE_INFO ServerRole;
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
|
|
|
|
Status = LsaOpenPolicy(NULL, &ObjectAttributes,
|
|
POLICY_VIEW_LOCAL_INFORMATION,
|
|
&LsaHandle);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
RtlReleaseResource(&BrInfo.ConfigResource);
|
|
|
|
return(BrMapStatus(Status));
|
|
}
|
|
|
|
Status = LsaQueryInformationPolicy(LsaHandle,
|
|
PolicyLsaServerRoleInformation,
|
|
(PVOID)&ServerRole
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
LsaClose(LsaHandle);
|
|
|
|
RtlReleaseResource(&BrInfo.ConfigResource);
|
|
|
|
return(BrMapStatus(Status));
|
|
}
|
|
|
|
LsaClose(LsaHandle);
|
|
|
|
//
|
|
// If we're running on the primary DC, then set that information
|
|
// up, otherwise ask the DC for its name.
|
|
//
|
|
|
|
if (ServerRole->LsaServerRole == PolicyServerRolePrimary) {
|
|
BrInfo.IsPrimaryDomainController = TRUE;
|
|
} else {
|
|
BrInfo.IsPrimaryDomainController = FALSE;
|
|
}
|
|
|
|
LsaFreeMemory( ServerRole );
|
|
|
|
} else {
|
|
LSA_HANDLE LsaHandle;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
NTSTATUS Status;
|
|
PPOLICY_PRIMARY_DOMAIN_INFO PrimaryDomain;
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
|
|
|
|
Status = LsaOpenPolicy(NULL, &ObjectAttributes,
|
|
POLICY_VIEW_LOCAL_INFORMATION,
|
|
&LsaHandle);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
RtlReleaseResource(&BrInfo.ConfigResource);
|
|
|
|
return(BrMapStatus(Status));
|
|
}
|
|
|
|
Status = LsaQueryInformationPolicy(LsaHandle,
|
|
PolicyPrimaryDomainInformation,
|
|
(PVOID)&PrimaryDomain
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
LsaClose(LsaHandle);
|
|
|
|
RtlReleaseResource(&BrInfo.ConfigResource);
|
|
|
|
return(BrMapStatus(Status));
|
|
}
|
|
|
|
LsaClose(LsaHandle);
|
|
|
|
if (PrimaryDomain->Sid == NULL) {
|
|
BrInfo.IsDomainMember = FALSE;
|
|
} else {
|
|
BrInfo.IsDomainMember = TRUE;
|
|
}
|
|
|
|
LsaFreeMemory( PrimaryDomain );
|
|
|
|
//
|
|
// We're not NTAS, so we cannot be the domain controller.
|
|
//
|
|
|
|
BrInfo.IsPrimaryDomainController = FALSE;
|
|
|
|
}
|
|
}
|
|
|
|
//
|
|
// Read from the config file the browser configuration fields
|
|
//
|
|
|
|
status = BrReadBrowserConfigFields( TRUE );
|
|
|
|
if (status != NERR_Success) {
|
|
goto CloseConfigFile;
|
|
}
|
|
|
|
//
|
|
// Leave config file open because we need to read transport names from it.
|
|
//
|
|
RtlReleaseResource(&BrInfo.ConfigResource);
|
|
|
|
return NERR_Success;
|
|
|
|
|
|
CloseConfigFile:
|
|
|
|
BrShutdownDgReceiver();
|
|
|
|
RtlReleaseResource(&BrInfo.ConfigResource);
|
|
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;
|
|
|
|
//
|
|
// Convert unicode strings back to ANSI so that we can use
|
|
// isdigit() and atol().
|
|
//
|
|
|
|
if (KeywordValue < BrInfo.BrConfigFields[i].Minimum ||
|
|
KeywordValue > BrInfo.BrConfigFields[i].Maximum) {
|
|
KdPrint(("[Browser] %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].Default;
|
|
}
|
|
|
|
//
|
|
// 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)) {
|
|
KdPrint(("Browser: 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);
|
|
}
|
|
|
|
RtlDeleteResource(&BrInfo.ConfigResource);
|
|
|
|
UNREFERENCED_PARAMETER(BrInitState);
|
|
}
|
|
|
|
#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];
|
|
|
|
//
|
|
// Build the key name:
|
|
//
|
|
// HKEY_LOCAL_MACHINE:System\CurrentControlSet\Services\Browser\Debug\<Transport>\SystemKeyName
|
|
//
|
|
|
|
wcscpy(TotalKeyName, L"System\\CurrentControlSet\\Services\\Browser\\Debug");
|
|
|
|
wcscat(TotalKeyName, TransportName);
|
|
|
|
wcscat(TotalKeyName, L"\\");
|
|
|
|
wcscat(TotalKeyName, SystemKeyName);
|
|
|
|
if ((Status = RegCreateKeyEx(HKEY_LOCAL_MACHINE, TotalKeyName, 0,
|
|
L"BrowserDebugInformation",
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_WRITE,
|
|
NULL,
|
|
&Key,
|
|
&Disposition)) != ERROR_SUCCESS) {
|
|
KdPrint(("[BROWSER] Unable to create key to log debug information: %lx\n", Status));
|
|
return Status;
|
|
}
|
|
|
|
if (ARGUMENT_PRESENT(ServerName)) {
|
|
if ((Status = RegSetValueEx(Key, ValueName, 0, REG_SZ, (LPBYTE)ServerName, (wcslen(ServerName)+1) * sizeof(WCHAR))) != ERROR_SUCCESS) {
|
|
KdPrint(("[BROWSER] 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) {
|
|
KdPrint(("[BROWSER] Unable to set value of ServerName value to %ws: %lx\n", ServerName, Status));
|
|
RegCloseKey(Key);
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
|
|
GetLocalTime(&LocalTime);
|
|
|
|
swprintf(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) {
|
|
KdPrint(("[BROWSER] Unable to set value of LastUpdateTime value to %s: %lx\n", LastUpdateTime, Status));
|
|
RegCloseKey(Key);
|
|
return Status;
|
|
}
|
|
|
|
RegCloseKey(Key);
|
|
}
|
|
|
|
#endif
|