NT4/private/net/portuas/portmap.c
2020-09-30 17:12:29 +02:00

490 lines
12 KiB
C

/*++
Copyright (c) 1992-1993 Microsoft Corporation
Module Name:
PortMap.C
Abstract:
PortUAS name mapping layer.
Author:
John Rogers (JohnRo) 29-Oct-1992
Revision History:
29-Oct-1992 JohnRo
Created for RAID 9020 ("prompt on conflicts" version).
26-Jan-1993 JohnRo
RAID 8683: PortUAS should set primary group from Mac parms.
--*/
// These must be included first:
#include <nt.h> // Needed by <portuasp.h>
#include <windef.h>
#include <lmcons.h>
// These may be included in any order:
#include <lmapibuf.h>
#include <netdebug.h> // DBGSTATIC, NetpAssert(), etc.
#include <netlib.h> // NetpSetOptionalArg().
#include <portuasp.h> // WARNING_MSG(), Verbose, my prototypes, etc.
#include <string.h> // memcpy().
#include <tstring.h> // NetpAllocWStrFromWStr(), WCSSIZE().
#include <wchar.h> // _wcsicmp().
#include <winerror.h> // NO_ERROR, ERROR_ equates.
#include "nlstxt.h" // NLS message ID's
DBGSTATIC BOOL IgnoreAllNamesInError = FALSE;
// Array of map table entries.
DBGSTATIC LPMAP_ENTRY MapTableStart = NULL;
DBGSTATIC DWORD MapTableEntryCount = 0;
NET_API_STATUS
PortUasMapTableInit(
VOID
)
{
MapTableStart = NULL;
MapTableEntryCount = 0;
IgnoreAllNamesInError = FALSE;
if (Verbose) {
NetpKdPrint(( PREFIX_PORTUAS "Initial map table:\n" ));
PortUasDbgDisplayMapTable( );
}
return (NO_ERROR);
} // PortUasMapTableInit
// Return NO_ERROR and *MapEntry=NULL if not found.
NET_API_STATUS
PortUasFindMapEntry(
IN LPWSTR NameToFind,
OUT BOOL * IgnoreThis OPTIONAL,
OUT LPMAP_ENTRY * MapEntry // Do NOT free this!
)
{
DWORD EntriesLeft;
LPMAP_ENTRY TableEntry;
NetpAssert( NameToFind != NULL );
NetpAssert( (*NameToFind) != NULLC );
NetpAssert( MapEntry != NULL );
if (MapTableEntryCount == 0) {
NetpAssert( MapTableStart == NULL );
// Not found (table empty).
NetpSetOptionalArg( IgnoreThis, FALSE );
*MapEntry = NULL;
return (NO_ERROR);
}
TableEntry = MapTableStart;
for (EntriesLeft=MapTableEntryCount; EntriesLeft > 0; --EntriesLeft) {
if (_wcsicmp( NameToFind, TableEntry->OldName ) == 0 ) {
// Found.
if ( (TableEntry->NewName) == NULL ) {
NetpSetOptionalArg( IgnoreThis, TRUE );
} else {
NetpSetOptionalArg( IgnoreThis, FALSE );
}
*MapEntry = TableEntry;
return (NO_ERROR);
}
++TableEntry;
}
// Not found (in non-empty table).
NetpSetOptionalArg( IgnoreThis, FALSE );
*MapEntry = NULL;
return (NO_ERROR);
} // PortUasFindMapEntry
// This sets globals MapTableStart and MapTableEntryCount.
DBGSTATIC NET_API_STATUS
PortUasReallocateMapTable(
IN DWORD NewEntryCount
)
{
NET_API_STATUS ApiStatus;
if (NewEntryCount==0) {
//
// Handle worst case: no entries left.
//
if (MapTableStart != NULL) {
(VOID) NetApiBufferFree( MapTableStart );
MapTableStart = NULL;
MapTableEntryCount = 0;
} else {
NetpAssert( MapTableEntryCount == 0 );
}
} else if (MapTableStart == NULL) {
//
// Another strange case: just allocate it the first time around.
//
NetpAssert( NewEntryCount == 1 );
ApiStatus = NetApiBufferAllocate(
sizeof( MAP_ENTRY ) * NewEntryCount,
(LPVOID *) (LPVOID) & MapTableStart ); // alloc and set ptr
if (ApiStatus != NO_ERROR) {
UNEXPECTED_MSG( "NetApiBufferAllocate(map tbl)", ApiStatus );
goto Cleanup;
}
NetpAssert( MapTableStart != NULL );
} else {
//
// Reallocate the map table to make room for one more structure.
//
ApiStatus = NetApiBufferReallocate(
MapTableStart, // old buffer
sizeof( MAP_ENTRY ) * NewEntryCount,
(LPVOID *) (LPVOID) & MapTableStart ); // alloc and set ptr
if (ApiStatus != NO_ERROR) {
UNEXPECTED_MSG( "NetApiBufferReallocate(map table)", ApiStatus );
goto Cleanup;
}
NetpAssert( MapTableStart != NULL );
}
//
// Update was OK.
//
MapTableEntryCount = NewEntryCount;
ApiStatus = NO_ERROR;
Cleanup:
if (ApiStatus != NO_ERROR) {
NetpKdPrint(( PREFIX_PORTUAS "PortUasReallocateMapTable: "
" returning " FORMAT_API_STATUS ".\n", ApiStatus ));
}
if (Verbose) {
NetpKdPrint(( PREFIX_PORTUAS "PortUasReallocateMapTable: "
" exiting with table at " FORMAT_LPVOID ", " FORMAT_DWORD
" entries.\n", (LPVOID) MapTableStart, MapTableEntryCount ));
}
return (ApiStatus);
} // PortUasReallocateMapTable
NET_API_STATUS
PortUasFindOrCreateMapEntry(
IN LPWSTR OldName,
IN BOOL ThisIsUserName, // TRUE for user name, FALSE for group name.
IN DWORD Reason, // REASON_ equates from PortUAS.h
OUT BOOL * IgnoreThis,
OUT LPMAP_ENTRY * MapEntryOut // Do NOT free this!
)
{
NET_API_STATUS ApiStatus;
LPWSTR NewName = NULL;
LPWSTR OldNameCopy = NULL;
LPMAP_ENTRY TableEntry = NULL;
NetpAssert( OldName != NULL );
NetpAssert( (*OldName) != NULLC );
NetpAssert( MapEntryOut != NULL );
if (IgnoreAllNamesInError) {
*IgnoreThis = TRUE;
*MapEntryOut = NULL;
return (NO_ERROR);
}
//
// Find existing entry (if any).
// Note that PortUasFindMapEntry returns NO_ERROR and sets *MapEntry=NULL
// if not found.
//
ApiStatus = PortUasFindMapEntry(
OldName, // name to find
IgnoreThis,
MapEntryOut ); // Set map entry ptr - do NOT free this!
if (ApiStatus != NO_ERROR) {
return (ApiStatus);
}
if (*MapEntryOut != NULL) {
if ( (*MapEntryOut)->NewName != NULL ) {
*IgnoreThis = FALSE;
} else {
*IgnoreThis = TRUE;
}
return (NO_ERROR);
}
//
// Prompt for new name.
//
ApiStatus = PortUasDefaultPromptForNewName(
OldName,
ThisIsUserName, // TRUE for user name, FALSE for group name
Reason, // REASON_ equates.
& NewName, // alloc w/ NetApiBufferAllocate().
IgnoreThis,
& IgnoreAllNamesInError );
if (ApiStatus != NO_ERROR) {
UNEXPECTED_MSG( "PortUasDefaultPromptForNewName", ApiStatus );
goto Cleanup;
}
//
// Allocate copy of old name.
//
OldNameCopy = NetpAllocWStrFromWStr( OldName );
if (OldNameCopy == NULL) {
ApiStatus = ERROR_NOT_ENOUGH_MEMORY;
UNEXPECTED_MSG( "NetpAllocWStrFromWStr", ApiStatus );
goto Cleanup;
}
//
// Reallocate the map table to make room for one more structure.
// (Or, just allocate it the first time around.)
// This sets globals MapTableStart and MapTableEntryCount.
//
ApiStatus = PortUasReallocateMapTable( MapTableEntryCount+1 );
if (ApiStatus != NO_ERROR) {
UNEXPECTED_MSG( "PortUasReallocateMapTable(create)", ApiStatus );
goto Cleanup;
}
NetpAssert( MapTableStart != NULL );
NetpAssert( MapTableEntryCount != 0 );
//
// Create the new entry.
//
TableEntry = & MapTableStart[MapTableEntryCount-1];
if (*IgnoreThis) {
TableEntry->NewName = NULL;
} else {
TableEntry->NewName = NewName;
}
TableEntry->OldName = OldNameCopy;
//
// If we made it this far, then everything is valid.
//
*MapEntryOut = TableEntry;
if (Verbose) {
NetpKdPrint(( PREFIX_PORTUAS "Updated map table:\n" ));
PortUasDbgDisplayMapTable( );
}
ApiStatus = NO_ERROR;
Cleanup:
if (ApiStatus != NO_ERROR) {
*MapEntryOut = NULL;
if ( (ApiStatus != NO_ERROR) && (NewName !=NULL ) ) {
(VOID) NetApiBufferFree( NewName );
}
if ( (ApiStatus != NO_ERROR) && (OldNameCopy !=NULL ) ) {
(VOID) NetApiBufferFree( OldNameCopy );
}
}
return (ApiStatus);
} // PortUasFindOrCreateMapEntry
DBGSTATIC VOID
PortUasFreeStringsForMapEntry(
IN LPMAP_ENTRY TableEntry
)
{
NetpAssert( TableEntry != NULL );
NetpAssert( TableEntry->OldName != NULL );
(VOID) NetApiBufferFree( TableEntry->OldName );
if (TableEntry->NewName != NULL) {
(VOID) NetApiBufferFree( TableEntry->NewName );
}
} // PortUasFreeStringsForMapEntry
NET_API_STATUS
PortUasDeleteBadMapEntry(
IN LPMAP_ENTRY EntryToDelete
)
{
NET_API_STATUS ApiStatus;
DWORD EntriesLeft;
LPMAP_ENTRY TableEntry;
if (EntryToDelete == NULL ) {
ApiStatus = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
if (MapTableEntryCount == 0) {
NetpAssert( MapTableStart == NULL );
// Not found (table empty).
ApiStatus = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
TableEntry = MapTableStart;
NetpAssert( MapTableStart != NULL );
for (EntriesLeft=MapTableEntryCount; EntriesLeft > 0; --EntriesLeft) {
if (EntryToDelete == TableEntry) {
// Found it!
// Free string(s) pointed-to by this entry.
PortUasFreeStringsForMapEntry( EntryToDelete );
// Compress this entry out of table.
if (EntriesLeft > 1) { // Any entries after this?
(VOID) memcpy(
EntryToDelete, // dest: entry to be wiped-out
EntryToDelete + (EntriesLeft-1), // src: last entry
sizeof(MAP_ENTRY) ); // byte count
}
// Realloc area for structures and set globals.
ApiStatus = PortUasReallocateMapTable(
MapTableEntryCount-1 ); // new entry count
if (ApiStatus != NO_ERROR) {
UNEXPECTED_MSG( "PortUasReallocateMapTable(del)", ApiStatus );
goto Cleanup;
}
ApiStatus = NO_ERROR;
goto Cleanup;
}
++TableEntry;
}
// Not found (in non-empty table).
ApiStatus = ERROR_INVALID_PARAMETER;
Cleanup:
if (ApiStatus != NO_ERROR) {
NetpKdPrint(( PREFIX_PORTUAS "PortUasDeleteBadMapTableEntry: "
" returning " FORMAT_API_STATUS ".\n", ApiStatus ));
}
if (Verbose) {
NetpKdPrint(( PREFIX_PORTUAS "Map table (after entry delete):\n" ));
PortUasDbgDisplayMapTable( );
}
return (ApiStatus);
} // PortUasDeleteBadMapEntry
NET_API_STATUS
PortUasFreeMapTable(
VOID
)
{
DWORD EntriesLeft;
LPMAP_ENTRY TableEntry;
if (MapTableStart != NULL) {
NetpAssert( MapTableEntryCount != 0 );
if (Verbose) {
NetpKdPrint(( PREFIX_PORTUAS "Final map table (before free):\n" ));
PortUasDbgDisplayMapTable( );
}
//
// Free name strings in each table entry.
//
TableEntry = MapTableStart;
for (EntriesLeft=MapTableEntryCount; EntriesLeft > 0; --EntriesLeft) {
PortUasFreeStringsForMapEntry( TableEntry );
++TableEntry;
}
//
// Free array of structures.
//
(VOID) NetApiBufferFree( MapTableStart );
MapTableStart = NULL;
MapTableEntryCount = 0;
} else {
NetpAssert( MapTableEntryCount == 0 );
}
if (Verbose) {
NetpKdPrint(( PREFIX_PORTUAS "Final map table (after free):\n" ));
PortUasDbgDisplayMapTable( );
}
return (NO_ERROR);
} // PortUasFreeMapTable
VOID
PortUasDbgDisplayMapTable(
VOID
)
{
DWORD EntriesLeft;
LPMAP_ENTRY TableEntry;
NetpKdPrint(( PREFIX_PORTUAS "Map table: (" FORMAT_DWORD " entries)...\n",
MapTableEntryCount ));
if (MapTableEntryCount == 0) {
NetpAssert( MapTableStart == NULL );
return;
}
TableEntry = MapTableStart;
for (EntriesLeft=MapTableEntryCount; EntriesLeft > 0; --EntriesLeft) {
PortUasDbgDisplayMapEntry( TableEntry );
++TableEntry;
}
}
VOID
PortUasDbgDisplayMapEntry(
IN LPMAP_ENTRY Entry
)
{
NetpAssert( Entry != NULL );
NetpAssert( (Entry->OldName) != NULL );
NetpKdPrint(( " map entry at " FORMAT_LPVOID ":\n", (LPVOID) Entry ));
NetpKdPrint(( " old name : " FORMAT_LPWSTR "\n", Entry->OldName ));
NetpKdPrint(( " new name : " FORMAT_LPWSTR "\n",
(Entry->NewName) ? (Entry->NewName) : L"(**IGNORE**)" ));
}