//+---------------------------------------------------------------------------- // // 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; } }