windows-nt/Source/XPSP1/NT/base/fs/dfs/driver/lvolinfo.c
2020-09-26 16:20:57 +08:00

1217 lines
31 KiB
C

//+----------------------------------------------------------------------------
//
// Copyright (C) 1992, Microsoft Corporation
//
// File: lvolinfo.c
//
// Contents: Functions to store and retrieve local volume info in the
// registry.
//
// Classes: None
//
// Functions: DfsStoreLvolInfo
// DfsGetLvolInfo
// DfsDeleteLvolInfo
// DfsChangeLvolInfoServiceType
// DfsChangeLvolInfoEntryPath
// DfsCreateExitPointInfo
// DfsDeleteExitPointInfo
//
// DfspAddSubordinateId
// GuidToString
// StringToGuid
//
//
// History: August 16, 1994 Milans created
//
//-----------------------------------------------------------------------------
#include "dfsprocs.h"
#include "regkeys.h"
#include "registry.h"
#define Dbg DEBUG_TRACE_LOCALVOL
NTSTATUS
DfspAddSubordinateId(
IN PWSTR wszLvolKey,
IN PDFS_PKT_ENTRY_ID pId);
NTSTATUS
DfspReadPrefix(
IN PWSTR wszKey,
IN PWSTR wszValue,
OUT PUNICODE_STRING pustrPrefix);
NTSTATUS
DfspSavePrefix(
IN PWSTR wszKey,
IN PWSTR wszValue,
IN PUNICODE_STRING pustrPrefix);
NTSTATUS
DfspUpgradePrefix(
IN PWSTR wszKey,
IN PWSTR wszValue,
IN USHORT cbComputerName,
IN PULONG pcbPrefix,
IN OUT PWSTR *pwszPrefix);
//+----------------------------------------------------------------------------
//
// Function: DfsStoreLvolInfo
//
// Synopsis: Stores the local volume info in the registry.
//
// Arguments: [pRelationInfo] -- Contains the entry id and exit point info
// for the local volume.
//
// Returns: STATUS_SUCCESS
//
//-----------------------------------------------------------------------------
NTSTATUS
DfsStoreLvolInfo(
IN PDFS_LOCAL_VOLUME_CONFIG pConfigInfo,
IN PUNICODE_STRING pustrStorageId)
{
NTSTATUS Status;
WCHAR wszLvolKey[ 2 * sizeof(GUID) + 1 ];
ULONG i;
DebugTrace(+1, Dbg, "DfsStoreLvolInfo: Entered\n", 0);
//
// Open the local volume section
//
Status = KRegSetRoot(wszLocalVolumesSection);
if (!NT_SUCCESS(Status)) {
DebugTrace(-1, Dbg, "Unable to open Local volumes section!\n", 0);
return( Status );
}
//
// Now, create a key for the local volume. We use the ascii form of the
// volume guid as the key.
//
GuidToString( &pConfigInfo->RelationInfo.EntryId.Uid, wszLvolKey );
DebugTrace(0, Dbg, "Volume Guid (Key) is [%ws]\n", wszLvolKey);
Status = KRegCreateKey( NULL, wszLvolKey );
if (!NT_SUCCESS(Status)) {
goto Cleanup;
}
//
// Now, put the rest of the stuff in the registry for this local volume.
// Entry Path
// 8.3 Entry Path
// Entry Type
// Storage ID
// Share Name
// A separate key for each exit point.
//
DebugTrace(0, Dbg, "Entry path is %wZ\n", &pConfigInfo->RelationInfo.EntryId.Prefix);
Status = DfspSavePrefix(
wszLvolKey,
wszEntryPath,
&pConfigInfo->RelationInfo.EntryId.Prefix);
if (!NT_SUCCESS(Status)) {
DebugTrace(0, Dbg, "Error setting entry path in registry %08lx!\n", ULongToPtr( Status ));
goto Cleanup;
}
DebugTrace(
0, Dbg, "Short Entry path is %wZ\n",
&pConfigInfo->RelationInfo.EntryId.ShortPrefix);
Status = DfspSavePrefix(
wszLvolKey,
wszShortEntryPath,
&pConfigInfo->RelationInfo.EntryId.ShortPrefix);
if (!NT_SUCCESS(Status)) {
DebugTrace(0, Dbg, "Error setting short entry path in registry %08lx!\n", ULongToPtr( Status ));
goto Cleanup;
}
DebugTrace(0, Dbg, "Entry type is %08lx\n", ULongToPtr( pConfigInfo->EntryType ));
Status = KRegSetValue(
wszLvolKey,
wszEntryType,
REG_DWORD,
sizeof(ULONG),
(PBYTE) &pConfigInfo->EntryType);
if (!NT_SUCCESS(Status)) {
DebugTrace(0, Dbg, "Error setting entry type in registry %08lx\n", ULongToPtr( Status ));
goto Cleanup;
}
Status = KRegSetValue(
wszLvolKey,
wszServiceType,
REG_DWORD,
sizeof(ULONG),
(PBYTE) &pConfigInfo->ServiceType);
if (!NT_SUCCESS(Status)) {
DebugTrace(0, Dbg, "Error setting service type in registry %08lx\n", ULongToPtr( Status ));
goto Cleanup;
}
DebugTrace(0, Dbg, "Storage ID is %wZ\n", pustrStorageId);
Status = KRegSetValue(
wszLvolKey,
wszStorageId,
REG_SZ,
pustrStorageId->Length,
(PBYTE) pustrStorageId->Buffer);
if (!NT_SUCCESS(Status)) {
DebugTrace(0, Dbg, "Error setting storage id in registry %08lx\n", ULongToPtr( Status ));
goto Cleanup;
}
DebugTrace(0, Dbg, "Share name is %wZ\n", &pConfigInfo->Share);
Status = KRegSetValue(
wszLvolKey,
wszShareName,
REG_SZ,
pConfigInfo->Share.Length,
(PVOID) pConfigInfo->Share.Buffer);
if (!NT_SUCCESS(Status)) {
DebugTrace(0, Dbg, "Error setting share name in registry %08lx\n", ULongToPtr( Status ));
goto Cleanup;
}
for (i = pConfigInfo->RelationInfo.SubordinateIdCount;
i != 0;
i--) {
Status = DfspAddSubordinateId(
wszLvolKey,
&pConfigInfo->RelationInfo.SubordinateIdList[i-1]);
if (!NT_SUCCESS(Status)) {
DebugTrace(0, Dbg, "Error %08lx adding subordinate info!\n", ULongToPtr( Status ));
goto Cleanup;
}
DebugTrace(0, Dbg, "Successfully added subordinate info\n", 0);
}
Cleanup:
if (!NT_SUCCESS(Status)) {
//
// We have to cleanup all the stuff we did if we failed somewhere.
// This is easy - just delete the key we added for the local volume
//
NTSTATUS CleanupStatus;
DebugTrace(0, Dbg, "Error occured, cleaning up...\n", 0);
CleanupStatus = KRegDeleteKey( wszLvolKey );
if (!NT_SUCCESS(CleanupStatus)) {
//
// We are hosed!
//
DebugTrace(0, Dbg, "Unable to cleanup %08lx!\n", ULongToPtr( CleanupStatus ));
}
}
KRegCloseRoot();
DebugTrace(-1, Dbg, "DfsStoreLvolInfo exited %08lx\n", ULongToPtr( Status ));
return( Status );
}
//+----------------------------------------------------------------------------
//
// Function: DfsGetLvolInfo
//
// Synopsis: Retrieves local volume info from the registry given the key
// identifying the local volume.
//
// Arguments: [pwszGuid] -- the string representation of the guid of the
// volume.
// [pRelationInfo] -- Pointer to relation info which will be
// filled in. Note that the SubordinateIdList will
// be allocated here, and must be freed by the
// caller. Additionally, the buffers in the
// individual prefixes are also allocated and must
// be freed.
//
// Returns: NTSTATUS from reading the registry.
//
//-----------------------------------------------------------------------------
NTSTATUS
DfsGetLvolInfo(
IN PWSTR pwszGuid,
OUT PDFS_LOCAL_VOLUME_CONFIG pConfigInfo,
OUT PUNICODE_STRING pustrStorageId)
{
NTSTATUS Status;
PDFS_PKT_ENTRY_ID pid;
PULONG pulEntryType = NULL;
PULONG pulServiceType = NULL;
ULONG i, cbSize;
APWSTR awstrSubs = NULL;
DebugTrace(+1, Dbg, "DfsGetLvolInfo: Entered for %ws\n", pwszGuid);
//
// First, initialize the pConfigInfo and pustrStorageId to NULL to
// facilitate cleanup.
//
RtlZeroMemory((PVOID) pConfigInfo, sizeof(DFS_LOCAL_VOLUME_CONFIG));
RtlZeroMemory((PVOID) pustrStorageId, sizeof(UNICODE_STRING));
Status = KRegSetRoot(wszLocalVolumesSection);
if (!NT_SUCCESS(Status)) {
DebugTrace(-1, Dbg, "DfsGetLvolInfo: Error setting registry root %08lx!\n", ULongToPtr( Status ));
return( Status );
}
//
// Get the Entry ID - convert the wchar GUID to an actual GUID, and get
// the entry path from the registry.
//
pid = &pConfigInfo->RelationInfo.EntryId;
Status = DfspReadPrefix( pwszGuid, wszEntryPath, &pid->Prefix );
DebugTrace(0, Dbg, "EntryPath is %wZ\n", &pid->Prefix);
Status = DfspReadPrefix( pwszGuid, wszShortEntryPath, &pid->ShortPrefix );
if (!NT_SUCCESS(Status)) {
DebugTrace(-1, Dbg, "DfsGetLvolInfo: Error reading entry path %08lx\n", ULongToPtr( Status ));
KRegCloseRoot();
return( Status );
}
DebugTrace(0, Dbg, "8.3 EntryPath is %wZ\n", &pid->Prefix);
StringToGuid( pwszGuid, &pid->Uid );
//
// Now get the Entry and Service Type
//
Status = KRegGetValue( pwszGuid, wszEntryType, (PBYTE *) &pulEntryType );
if (!NT_SUCCESS(Status)) {
DebugTrace(0, Dbg, "Error %08lx getting entry type\n", ULongToPtr( Status ));
goto Cleanup;
}
pConfigInfo->EntryType = *pulEntryType;
Status = KRegGetValue( pwszGuid, wszServiceType, (PBYTE *) &pulServiceType );
if (!NT_SUCCESS(Status)) {
if (Status == STATUS_OBJECT_NAME_NOT_FOUND) {
pConfigInfo->ServiceType = 0;
} else {
DebugTrace(0, Dbg, "Error %08lx getting service type\n", ULongToPtr( Status ));
goto Cleanup;
}
} else {
pConfigInfo->ServiceType = *pulServiceType;
}
//
// Next, get the Storage ID
//
Status = KRegGetValue( pwszGuid, wszStorageId, (PBYTE *) &pustrStorageId->Buffer);
if (!NT_SUCCESS(Status)) {
DebugTrace(0, Dbg, "Error %08lx getting storage id from registry\n", ULongToPtr( Status ));
goto Cleanup;
}
pustrStorageId->Length = wcslen(pustrStorageId->Buffer) * sizeof(WCHAR);
pustrStorageId->MaximumLength = pustrStorageId->Length + sizeof(WCHAR);
DebugTrace(0, Dbg, "Storage id is %wZ\n", pustrStorageId);
//
// Next, get the share name
//
Status = KRegGetValue( pwszGuid, wszShareName, (PBYTE *) &pConfigInfo->Share.Buffer);
if (!NT_SUCCESS(Status)) {
DebugTrace(0, Dbg, "Error %08lx getting share name from registry\n", ULongToPtr( Status ));
goto Cleanup;
}
pConfigInfo->Share.Length = wcslen(pConfigInfo->Share.Buffer) * sizeof(WCHAR);
pustrStorageId->MaximumLength = pConfigInfo->Share.Length + sizeof(WCHAR);
DebugTrace(0, Dbg, "Share Nameis %wZ\n", &pConfigInfo->Share);
//
// We have the volumes PKT_ENTRY_ID. Now, figure out how many
// subordinates there are, and get them.
//
Status = KRegEnumSubKeySet(
pwszGuid,
&pConfigInfo->RelationInfo.SubordinateIdCount,
&awstrSubs);
if (!NT_SUCCESS(Status)) {
DebugTrace(0, Dbg, "DfsGetLvolInfo: Error getting subkeys %08lx\n", ULongToPtr( Status ));
goto Cleanup;
}
DebugTrace(0, Dbg, "Volume has %d subordinates\n", ULongToPtr( pConfigInfo->RelationInfo.SubordinateIdCount ));
if (pConfigInfo->RelationInfo.SubordinateIdCount == 0) {
DebugTrace(-1, Dbg, "DfsGetLvolInfo: No subordinates! Returning success\n", 0);
Status = STATUS_SUCCESS;
goto Cleanup;
}
cbSize = pConfigInfo->RelationInfo.SubordinateIdCount * sizeof(DFS_PKT_ENTRY_ID);
pConfigInfo->RelationInfo.SubordinateIdList = ExAllocatePoolWithTag(
PagedPool,
cbSize,
' sfD' );
if (pConfigInfo->RelationInfo.SubordinateIdList == NULL) {
DebugTrace(0, Dbg, "DfsGetLvolInfo: Unable to allocate %d bytes!\n", ULongToPtr( cbSize ));
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Cleanup;
}
RtlZeroMemory(pConfigInfo->RelationInfo.SubordinateIdList, cbSize);
//
// Get all the Subordinate information
//
for (i = pConfigInfo->RelationInfo.SubordinateIdCount; i != 0; i--) {
PWSTR pwszSubordinateGuid;
pid = &pConfigInfo->RelationInfo.SubordinateIdList[i-1];
//
// awstrSubs[?] is of the form lvolguid\subordinateguid.
//
pwszSubordinateGuid = &awstrSubs[i-1][2 * sizeof(GUID) + 1];
DebugTrace(0, Dbg, "Subordinate Guid is %ws\n", pwszSubordinateGuid);
StringToGuid( pwszSubordinateGuid, &pid->Uid );
DebugTrace(0, Dbg, "Subkey is %ws\n", awstrSubs[i-1]);
Status = DfspReadPrefix(
awstrSubs[i-1],
wszEntryPath,
&pid->Prefix);
if (!NT_SUCCESS(Status)) {
DebugTrace(0, Dbg, "Error %08lx reading subordinate prefix\n", ULongToPtr( Status ));
goto Cleanup;
}
DebugTrace(0, Dbg, "Retrieved Subordinate Entry %ws\n", awstrSubs[i-1]);
DebugTrace(0, Dbg, "Prefix is %wZ\n", &pid->Prefix);
}
Cleanup:
KRegCloseRoot();
if (pulEntryType) {
ExFreePool( pulEntryType );
}
if (pulServiceType) {
ExFreePool( pulServiceType );
}
if (!NT_SUCCESS(Status)) {
//
// Cleanup whatever relation info we might have built up so far.
//
KRegFreeArray(
pConfigInfo->RelationInfo.SubordinateIdCount,
(APBYTE) awstrSubs);
if (pConfigInfo->RelationInfo.EntryId.Prefix.Buffer != NULL) {
ExFreePool(pConfigInfo->RelationInfo.EntryId.Prefix.Buffer);
}
if (pustrStorageId->Buffer != NULL) {
ExFreePool(pustrStorageId->Buffer);
}
for (i = pConfigInfo->RelationInfo.SubordinateIdCount; i != 0; i--) {
pid = &pConfigInfo->RelationInfo.SubordinateIdList[i-1];
if (pid->Prefix.Buffer != NULL) {
ExFreePool( pid->Prefix.Buffer );
}
}
if (pConfigInfo->RelationInfo.SubordinateIdList != NULL) {
ExFreePool(pConfigInfo->RelationInfo.SubordinateIdList);
}
} else {
KRegFreeArray(
pConfigInfo->RelationInfo.SubordinateIdCount,
(APBYTE) awstrSubs);
}
DebugTrace(-1, Dbg, "DfsGetLvolInfo: Exited - %08lx\n", ULongToPtr( Status ) );
return( Status );
}
//+----------------------------------------------------------------------------
//
// Function: DfsDeleteLvolInfo
//
// Synopsis: Deletes local volume information from the registry.
//
// Arguments: [pguidLvol] -- pointer to guid of local volume to delete.
//
// Returns: NTSTATUS from registry API
//
//-----------------------------------------------------------------------------
NTSTATUS
DfsDeleteLvolInfo(
IN GUID *pguidLvol)
{
NTSTATUS Status;
WCHAR wszLvolKey[ 2 * sizeof(GUID) + 1 ];
DebugTrace(+1, Dbg, "DfsDeleteLvolInfo - Entered\n", 0);
GuidToString(pguidLvol, wszLvolKey);
Status = KRegSetRoot( wszLocalVolumesSection );
if (!NT_SUCCESS(Status)) {
DebugTrace(-1, Dbg, "DfsDeleteLvolInfo - Error %08lx opening local volumes section\n", ULongToPtr( Status ));
return(Status);
}
Status = KRegDeleteKey( wszLvolKey );
if (Status == STATUS_OBJECT_NAME_NOT_FOUND) {
Status = STATUS_SUCCESS;
}
KRegCloseRoot();
DebugTrace(-1, Dbg, "DfsDeleteLvolInfo - Exiting %08lx\n", ULongToPtr( Status ));
return( Status );
}
//+----------------------------------------------------------------------------
//
// Function: DfsChangeLvolInfoServiceType
//
// Synopsis: Changes the service type associated with the local volume in
// the registry.
//
// Arguments: [pguidLvol] -- pointer to guid of local volume.
// [ulServiceType] -- new service type.
//
// Returns: NTSTATUS from registry api.
//
//-----------------------------------------------------------------------------
NTSTATUS
DfsChangeLvolInfoServiceType(
IN GUID *pguidLvol,
IN ULONG ulServiceType)
{
NTSTATUS Status;
WCHAR wszLvolKey[ 2 * sizeof(GUID) + 1 ];
Status = KRegSetRoot( wszLocalVolumesSection );
if (!NT_SUCCESS(Status)) {
return( Status );
}
GuidToString(pguidLvol, wszLvolKey);
Status = KRegSetValue(
wszLvolKey,
wszServiceType,
REG_DWORD,
sizeof(ULONG),
(PBYTE) &ulServiceType);
KRegCloseRoot();
return( Status );
}
//+----------------------------------------------------------------------------
//
// Function: DfsChangeLvolInfoEntryPath
//
// Synopsis: Changes the entry path associated with the local volume in the
// registry.
//
// Arguments: [pguidLvol] -- pointer to guid of local volume.
// [pustrEntryPath] -- new entry path.
//
// Returns: NTSTATUS from registry api.
//
//-----------------------------------------------------------------------------
NTSTATUS
DfsChangeLvolInfoEntryPath(
IN GUID *pguidLvol,
IN PUNICODE_STRING pustrEntryPath)
{
NTSTATUS Status;
WCHAR wszLvolKey[ 2 * sizeof(GUID) + 1 ];
Status = KRegSetRoot( wszLocalVolumesSection );
if (!NT_SUCCESS(Status)) {
return( Status );
}
GuidToString(pguidLvol, wszLvolKey);
Status = DfspSavePrefix(
wszLvolKey,
wszEntryPath,
pustrEntryPath);
KRegCloseRoot();
return( Status );
}
//+----------------------------------------------------------------------------
//
// Function: DfsCreateExitPointInfo
//
// Synopsis: Adds a single exit point to the local volume information in
// the registry.
//
// Arguments: [pguidLvol] -- pointer to guid of local volume.
// [pidExitPoint] -- pointer to PKT_ENTRY_ID of exit point.
//
// Returns: NTSTATUS from registry manipulation.
//
//-----------------------------------------------------------------------------
NTSTATUS
DfsCreateExitPointInfo(
IN GUID *pguidLvol,
IN PDFS_PKT_ENTRY_ID pidExitPoint)
{
NTSTATUS Status = STATUS_SUCCESS;
WCHAR wszLvolKey[ 2 * sizeof(GUID) + 1 ];
DebugTrace(+1, Dbg, "DfsCreateExitPointInfo - Entered\n", 0);
//
// Stop storing exit point information in the SYSTEM part of
// the registry. (380845).
//
#if 0
Status = KRegSetRoot( wszLocalVolumesSection );
if (!NT_SUCCESS(Status)) {
DebugTrace(-1, Dbg, "DfsCreateExitPointInfo - exiting %08lx\n", Status);
return(Status);
}
GuidToString( pguidLvol, wszLvolKey );
Status = DfspAddSubordinateId( wszLvolKey, pidExitPoint );
KRegCloseRoot();
#endif
DebugTrace(-1, Dbg, "DfsCreateExitPointInfo - Exited %08lx\n", ULongToPtr( Status ));
return( Status );
}
//+----------------------------------------------------------------------------
//
// Function: DfsDeleteExitPointInfo
//
// Synopsis: Deletes an exit point info from the registry.
//
// Arguments: [pguidLvol] -- pointer to guid of local volume.
// [pguidExitPoint] -- pointer to guid of exit point.
//
// Returns: NTSTATUS from registry api.
//
//-----------------------------------------------------------------------------
NTSTATUS
DfsDeleteExitPointInfo(
IN GUID *pguidLvol,
IN GUID *pguidExitPoint)
{
NTSTATUS Status = STATUS_SUCCESS;
WCHAR wszExitPointKey[ 2 * sizeof(GUID) + // for Local volume guid
1 + // for UNICODE_PATH_SEP
2 * sizeof(GUID) + // for exit point guid
1 ]; // for UNICODE_NULL
DebugTrace(+1, Dbg, "DfsDeleteExitPointInfo: Entered\n", 0);
//
// Stop storing exit point information in the SYSTEM part of
// the registry. (380845).
//
#if 0
Status = KRegSetRoot( wszLocalVolumesSection );
if (!NT_SUCCESS(Status)) {
DebugTrace(-1, Dbg, "DfsDeleteExitPointInfo: Exiting %08lx\n", Status);
return( Status );
}
GuidToString( pguidLvol, wszExitPointKey );
wszExitPointKey[ 2 * sizeof(GUID) ] = UNICODE_PATH_SEP;
GuidToString( pguidExitPoint, &wszExitPointKey[2*sizeof(GUID) + 1] );
DebugTrace(0, Dbg, "Attempting to delete subkey %ws\n", wszExitPointKey);
Status = KRegDeleteKey( wszExitPointKey );
KRegCloseRoot();
if (Status == STATUS_OBJECT_NAME_NOT_FOUND) {
Status = STATUS_SUCCESS;
}
#endif
DebugTrace(-1, Dbg, "DfsDeleteExitPointInfo: Exiting %08lx\n", ULongToPtr( Status ));
return( Status );
}
//+----------------------------------------------------------------------------
//
// Function: DfspAddSubordinateId
//
// Synopsis: Adds a single exit point info to a local volume entry in the
// registry.
//
// Arguments: [wszLvolKey] -- The local volume key under which to add info.
// [pId] -- The info to add.
//
// Returns: NT Status from adding the info.
//
//-----------------------------------------------------------------------------
NTSTATUS
DfspAddSubordinateId(
IN PWSTR wszLvolKey,
IN PDFS_PKT_ENTRY_ID pId)
{
NTSTATUS Status;
WCHAR wszExitPoint[ 2 * sizeof(GUID) + 1 ];
WCHAR wszExitPointKey[ 2 * sizeof(GUID) +
sizeof(UNICODE_PATH_SEP_STR) +
2 * sizeof(GUID) +
sizeof(UNICODE_NULL) ];
GuidToString( &pId->Uid, wszExitPoint );
DebugTrace(0, Dbg, "Adding exit point key %ws\n", wszExitPoint);
Status = KRegCreateKey(wszLvolKey, wszExitPoint);
if (!NT_SUCCESS(Status)) {
DebugTrace(0, Dbg, "Error adding exit pt key %08lx\n", ULongToPtr( Status ));
return(Status);
}
//
// Now, add the entry path for the exit point as a value to the
// new key.
//
wcscpy(wszExitPointKey, wszLvolKey);
wcscat(wszExitPointKey, UNICODE_PATH_SEP_STR);
wcscat(wszExitPointKey, wszExitPoint);
DebugTrace(0, Dbg, "Subkey name is %ws\n", wszExitPointKey);
DebugTrace(0, Dbg, "Prefix is %wZ\n", &pId->Prefix);
Status = DfspSavePrefix(
wszExitPointKey,
wszEntryPath,
&pId->Prefix);
if (!NT_SUCCESS(Status)) {
KRegDeleteKey(wszExitPointKey);
}
return(Status);
}
//+----------------------------------------------------------------------------
//
// Function: DfspReadPrefix
//
// Synopsis: Reads a prefix from the registry, given the registry key and
// value name. To handle machine renames, the first component
// of the prefix is matched against the current computer name.
// If the two are different, indicating a computer name change,
// the prefix is updated.
//
// Arguments: [wszKey] -- Name of key (relative to current root)
// [wszValue] -- Name of value to read prefix from
// [pustrPrefix] -- On successful return, the prefix is returned
// here.
//
// Returns: [STATUS_SUCCESS] -- If successfully retrieved prefix.
//
// [STATUS_INSUFFICIENT_RESOURCES] -- Unable to allocate memory
//
// [STATUS_INTERNAL_DB_CORRUPTION] -- The retrieved value did
// not look like a prefix.
//
// Status from reading the registry value
//
//-----------------------------------------------------------------------------
NTSTATUS
DfspReadPrefix(
IN PWSTR wszKey,
IN PWSTR wszValue,
OUT PUNICODE_STRING pustrPrefix)
{
NTSTATUS Status;
PWSTR wszCurrentPrefix = NULL;
ULONG cbPrefix, cwCurrentPrefix, i;
UNICODE_STRING ustrComputerName;
Status = KRegGetValue(
wszKey,
wszValue,
(LPBYTE *)&wszCurrentPrefix );
//
// If successfully read in the prefix, do some elementary syntax checking
//
if (NT_SUCCESS(Status)) {
cwCurrentPrefix = wcslen(wszCurrentPrefix);
cbPrefix = cwCurrentPrefix * sizeof(WCHAR);
//
// Must be atleast \a\b
//
if ((cwCurrentPrefix < 4) ||
(wszCurrentPrefix[0] != UNICODE_PATH_SEP)) {
Status = STATUS_INTERNAL_DB_CORRUPTION;
}
}
//
// Compute the first component of the prefix
//
if (NT_SUCCESS(Status)) {
ustrComputerName.Buffer = &wszCurrentPrefix[1];
for (i = 1;
(i < cwCurrentPrefix) &&
(wszCurrentPrefix[i] != UNICODE_PATH_SEP);
i++) {
NOTHING;
}
if (i != cwCurrentPrefix) {
ustrComputerName.Length = (USHORT) ((i-1) * sizeof(WCHAR));
ustrComputerName.MaximumLength = ustrComputerName.Length;
} else {
Status = STATUS_INTERNAL_DB_CORRUPTION;
}
}
if (NT_SUCCESS(Status)) {
pustrPrefix->Buffer = wszCurrentPrefix;
pustrPrefix->Length = (USHORT) cbPrefix;
pustrPrefix->MaximumLength = (USHORT)cbPrefix + sizeof(UNICODE_NULL);
} else {
if (wszCurrentPrefix != NULL)
kreg_free( wszCurrentPrefix );
}
return( Status );
}
//+----------------------------------------------------------------------------
//
// Function: DfspSavePrefix
//
// Synopsis: Saves a prefix to the registry.
//
// Arguments: [wszKey] -- Name of key (relative to current root)
// [wszValue] -- Name of value to save prefix to.
// [pustrPrefix] -- The prefix to store.
//
// Returns: Status from registry operation
//
//-----------------------------------------------------------------------------
NTSTATUS
DfspSavePrefix(
IN PWSTR wszKey,
IN PWSTR wszValue,
IN PUNICODE_STRING pustrPrefix)
{
NTSTATUS Status;
Status = KRegSetValue(
wszKey,
wszValue,
REG_SZ,
pustrPrefix->Length,
(LPBYTE) pustrPrefix->Buffer);
return( Status );
}
//+----------------------------------------------------------------------------
//
// Function: DfspUpgradePrefix
//
// Synopsis: If a machine rename has occured since the last time a prefix
// was updated, this routine will upgrade the first component
// of the prefix to match the computer name.
//
// Arguments: [wszKey] -- Name of key (relative to current root)
// [wszValue] -- Name of value to save updated prefix to.
// [cbComputerName] -- size, in bytes, of the first component of
// the input prefix.
// [pcbPrefix] -- On entry, size in bytes of the input prefix.
// On return, size in bytes of the new prefix. Neither
// sizes includes the terminating NULL.
// [pwszPrefix] -- On entry, the prefix as it currently exists in
// the registry. On return, points to a new block of
// memory that has the new prefix.
//
// Returns: [STATUS_SUCCESS] -- Successfully updated prefix.
//
// [STATUS_INSUFFICIENT_RESOURCES] -- Out of memory condition
//
//-----------------------------------------------------------------------------
NTSTATUS
DfspUpgradePrefix(
IN PWSTR wszKey,
IN PWSTR wszValue,
IN USHORT cbComputerName,
IN PULONG pcbPrefix,
IN OUT PWSTR *pwszPrefix)
{
NTSTATUS Status;
ULONG cbPrefix;
PWSTR wszCurrentPrefix, wszNewPrefix;
wszCurrentPrefix = *pwszPrefix;
cbPrefix = (*pcbPrefix) -
cbComputerName +
DfsData.NetBIOSName.Length;
wszNewPrefix = (PWSTR) kreg_alloc( cbPrefix + sizeof(UNICODE_NULL) );
if (wszNewPrefix != NULL) {
wszNewPrefix[0] = UNICODE_PATH_SEP;
RtlCopyMemory(
&wszNewPrefix[1],
DfsData.NetBIOSName.Buffer,
DfsData.NetBIOSName.Length);
RtlCopyMemory(
&wszNewPrefix[ DfsData.NetBIOSName.Length/sizeof(WCHAR) + 1],
&wszCurrentPrefix[ cbComputerName/sizeof(WCHAR) + 1 ],
(*pcbPrefix) - cbComputerName);
*pcbPrefix = cbPrefix;
*pwszPrefix = wszNewPrefix;
kreg_free( wszCurrentPrefix );
//
// We try to update the prefix in the registry. Failure to do so is
// ok, we'll just try again next time we try to read it.
//
(VOID) KRegSetValue(
wszKey,
wszValue,
REG_SZ,
cbPrefix,
(LPBYTE) wszNewPrefix);
Status = STATUS_SUCCESS;
} else {
Status = STATUS_INSUFFICIENT_RESOURCES;
}
return( Status );
}
//+----------------------------------------------------------------------------
//
// Function: GuidToString
//
// Synopsis: Converts a GUID to a 32 char wchar null terminated string.
//
// Arguments: [pGuid] -- Pointer to Guid structure.
// [pwszGuid] -- wchar buffer into which to put the string
// representation of the GUID. Must be atleast
// 2 * sizeof(GUID) + 1 long.
//
// Returns: Nothing
//
//-----------------------------------------------------------------------------
const WCHAR rgwchHexDigits[] = L"0123456789ABCDEF";
VOID GuidToString(
IN GUID *pGuid,
OUT PWSTR pwszGuid)
{
PBYTE pbBuffer = (PBYTE) pGuid;
USHORT i;
for(i = 0; i < sizeof(GUID); i++) {
pwszGuid[2 * i] = rgwchHexDigits[(pbBuffer[i] >> 4) & 0xF];
pwszGuid[2 * i + 1] = rgwchHexDigits[pbBuffer[i] & 0xF];
}
pwszGuid[2 * i] = UNICODE_NULL;
}
//+----------------------------------------------------------------------------
//
// Function: StringToGuid
//
// Synopsis: Converts a 32 wchar null terminated string to a GUID.
//
// Arguments: [pwszGuid] -- the string to convert
// [pGuid] -- Pointer to destination GUID.
//
// Returns: Nothing
//
//-----------------------------------------------------------------------------
#define HEX_DIGIT_TO_INT(d, i) \
ASSERT(((d) >= L'0' && (d) <= L'9') || \
((d) >= L'A' && (d) <= L'F')); \
if ((d) <= L'9') { \
i = (d) - L'0'; \
} else { \
i = (d) - L'A' + 10; \
}
VOID StringToGuid(
IN PWSTR pwszGuid,
OUT GUID *pGuid)
{
PBYTE pbBuffer = (PBYTE) pGuid;
USHORT i, n;
for (i = 0; i < sizeof(GUID); i++) {
HEX_DIGIT_TO_INT(pwszGuid[2 * i], n);
pbBuffer[i] = n << 4;
HEX_DIGIT_TO_INT(pwszGuid[2 * i + 1], n);
pbBuffer[i] |= n;
}
}