Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1182 lines
31 KiB

/*++
Copyright (c) 1998, Microsoft Corporation
Module Name:
sainfo.c
Abstract:
This module contains code for managing shared access settings.
Shared Access Settings are stored in a file and consist of a list
of sections which correspond either to 'applications' or 'servers',
and content indices which list all applications and servers in the file.
E.g.
[Contents.Application]
<key>=1 ; Enabled
[Contents.Server]
<key>=1 ; Enabled
An 'application' entry specifies parameters for a dynamic ticket
which will allow the application to work through the NAT,
by dynamically allowing an inbound secondary session.
E.g.
[Application.<key>]
Title=DirectPlay
Protocol=TCP
Port=47624
TcpResponseList=2300-2400
UdpResponseList=2300-2400
BuiltIn=1 ; optional flag, defaults to 0
A 'server' entry specifies parameters for a static port mapping
which will direct all sessions for a particular protocol and port
to a particular internal machine.
E.g.
[Server.<key>]
Title=WWW
Protocol=TCP
Port=80
InternalName=MACHINENAME
InternalPort=8080
ReservedAddress=192.168.0.200
BuiltIn=0 ; optional flag, defaults to 0
Author:
Abolade Gbadegesin (aboladeg) 17-Oct-1998
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
#include <pbk.h>
#include <tchar.h>
#include <limits.h>
#define LSTRLEN(s) ((sizeof(s) / sizeof(TCHAR)) - 1)
#define HTONS(s) ((UCHAR)((s) >> 8) | ((UCHAR)(s) << 8))
#define HTONL(l) ((HTONS(l) << 16) | HTONS((l) >> 16))
#define NTOHS(s) HTONS(s)
#define NTOHL(l) HTONL(l)
#if 0
const TCHAR c_szApplication[] = TEXT("Application");
const TCHAR c_szBuiltIn[] = TEXT("BuiltIn");
const TCHAR c_szContents[] = TEXT("Contents");
const TCHAR c_szInternalName[] = TEXT("InternalName");
const TCHAR c_szInternalPort[] = TEXT("InternalPort");
const TCHAR c_szKeyFormat[] = TEXT("%08X");
#endif
const TCHAR c_szMaxResponseEntry[] = TEXT("65535-65535,");
#if 0
const TCHAR c_szPort[] = TEXT("Port");
const TCHAR c_szProtocol[] = TEXT("Protocol");
const TCHAR c_szReservedAddress[] = TEXT("ReservedAddress");
#endif
const TCHAR c_szResponseFormat1[] = TEXT("%d");
const TCHAR c_szResponseFormat2[] = TEXT("%d-%d");
#if 0
const TCHAR c_szSectionFormat[] = TEXT("%s.%s");
const TCHAR c_szServer[] = TEXT("Server");
const TCHAR c_szSharedAccessIni[] = TEXT("SharedAccess.ini");
const TCHAR c_szTagBuiltIn[] = TEXT("BuiltIn=");
const TCHAR c_szTagInternalName[] = TEXT("InternalName=");
const TCHAR c_szTagInternalPort[] = TEXT("InternalPort=");
const TCHAR c_szTagPort[] = TEXT("Port=");
const TCHAR c_szTagProtocol[] = TEXT("Protocol=");
const TCHAR c_szTagReservedAddress[] = TEXT("ReservedAddress=");
const TCHAR c_szTagTcpResponseList[] = TEXT("TcpResponseList=");
const TCHAR c_szTagTitle[] = TEXT("Title=");
const TCHAR c_szTagUdpResponseList[] = TEXT("UdpResponseList=");
const TCHAR c_szTCP[] = TEXT("TCP");
const TCHAR c_szTcpResponseList[] = TEXT("TcpResponseList");
const TCHAR c_szTitle[] = TEXT("Title");
const TCHAR c_szUDP[] = TEXT("UDP");
const TCHAR c_szUdpResponseList[] = TEXT("UdpResponseList");
//
// FORWARD DECLARATIONS
//
SAAPPLICATION*
LoadApplication(
ULONG KeyValue,
BOOL Enabled,
const TCHAR* Path
);
TCHAR*
LoadEntryList(
const TCHAR* Path,
const TCHAR* Section
);
TCHAR*
LoadPath(
VOID
);
SASERVER*
LoadServer(
ULONG KeyValue,
BOOL Enabled,
const TCHAR* Path
);
LONG
Lstrcmpni(
const TCHAR* String1,
const TCHAR* String2,
LONG Length
);
TCHAR*
QueryEntryList(
const TCHAR* EntryList,
const TCHAR* Tag
);
BOOL
SaveApplication(
SAAPPLICATION* Application,
const TCHAR* Path
);
BOOL
SaveServer(
SAINFO* Info,
SASERVER* Server,
const TCHAR* Path
);
BOOL
WritePrivateProfileStringUTF8(
const TCHAR* Section,
const TCHAR* Key,
const TCHAR* Value,
const TCHAR* Path
);
VOID APIENTRY
RasFreeSharedAccessSettings(
IN SAINFO* Info
)
/*++
Routine Description:
Frees memory allocated for the contents of 'Info'.
Arguments:
Info - the settings to be freed
Return Value:
none.
--*/
{
SAAPPLICATION* Application;
PLIST_ENTRY Link;
SASERVER* Server;
TRACE("RasFreeSharedAccessSettings");
while (!IsListEmpty(&Info->ApplicationList)) {
Link = RemoveHeadList(&Info->ApplicationList);
Application = CONTAINING_RECORD(Link, SAAPPLICATION, Link);
FreeSharedAccessApplication(Application);
}
while (!IsListEmpty(&Info->ServerList)) {
Link = RemoveHeadList(&Info->ServerList);
Server = CONTAINING_RECORD(Link, SASERVER, Link);
FreeSharedAccessServer(Server);
}
Free(Info);
} // RasFreeSharedAccessSettings
SAINFO* APIENTRY
RasLoadSharedAccessSettings(
BOOL EnabledOnly
)
/*++
Routine Description:
Reads in the local shared access settings, returning an allocated
'SAINFO' containing the settings retrieved.
Arguments:
EnabledOnly - if TRUE, only the application-entries which are enabled
are retrieved.
Return Value:
SAINFO* - the settings retrieved
--*/
{
SAAPPLICATION* Application;
BOOL Enabled;
SAINFO* Info;
TCHAR* Key;
TCHAR* KeyEnd;
TCHAR* KeyList;
ULONG KeyValue;
TCHAR* Path;
TCHAR SectionName[32];
SASERVER* Server;
TRACE("RasLoadSharedAccessSettings");
//
// Allocate and initialize the settings-structure
//
Info = (SAINFO*)Malloc(sizeof(SAINFO));
if (!Info) { return NULL; }
InitializeListHead(&Info->ApplicationList);
InitializeListHead(&Info->ServerList);
//
// Read scope information from the registry
//
CsQueryScopeInformation(NULL, &Info->ScopeAddress, &Info->ScopeMask);
//
// Construct the path to the shared access information file,
// and read the index of 'application' sections.
// Each section should contain a valid application-description,
// for which we construct a corresponding 'SAAPPLICATION' entry
// in the application-list.
//
if (!(Path = LoadPath())) {
RasFreeSharedAccessSettings(Info);
return NULL;
}
wsprintf(SectionName, c_szSectionFormat, c_szContents, c_szApplication);
if (KeyList = LoadEntryList(SectionName, Path)) {
for (Key = KeyList; *Key; Key += lstrlen(Key) + 1) {
//
// Ensure the key is a valid hexadecimal integer,
// and read the 'Enabled' setting which is its value.
// N.B. if the entry is disabled and the caller only wants
// enabled entries, exclude this one.
//
KeyValue = _tcstoul(Key, &KeyEnd, 16);
if (*KeyEnd++ != TEXT('=')) {
continue;
} else if (!(Enabled = !!_ttol(KeyEnd)) && EnabledOnly) {
continue;
}
//
// Read in the corresponding 'Application.<key>' section.
//
Application = LoadApplication(KeyValue, Enabled, Path);
if (Application) {
InsertTailList(&Info->ApplicationList, &Application->Link);
}
}
Free(KeyList);
}
//
// Finally, read the index of 'server' sections, and read each section.
// Each section contains a server-description for which we construct
// a corresponding 'SASERVER' entry in the server-list.
//
wsprintf(SectionName, c_szSectionFormat, c_szContents, c_szServer);
if (KeyList = LoadEntryList(SectionName, Path)) {
for (Key = KeyList; *Key; Key += lstrlen(Key) + 1) {
//
// Ensure the key is a valid hexadecimal integer,
// and read the 'Enabled' setting which is its value.
// N.B. if the entry is disabled and the caller only wants
// enabled entries, exclude this one.
//
KeyValue = _tcstoul(Key, &KeyEnd, 16);
if (*KeyEnd++ != TEXT('=')) {
continue;
} else if (!(Enabled = !!_ttol(KeyEnd)) && EnabledOnly) {
continue;
}
//
// Read in the corresponding 'Server.<key>' section.
//
Server = LoadServer(KeyValue, Enabled, Path);
if (Server) {
InsertTailList(&Info->ServerList, &Server->Link);
}
}
Free(KeyList);
}
return Info;
} // RasLoadSharedAccessSettings
BOOL APIENTRY
RasSaveSharedAccessSettings(
IN SAINFO* Info
)
/*++
Routine Description:
Stores the shared access settings in 'Info' back into the local registry
from where the settings were read.
N.B. If 'Info' was loaded with the 'EnableOnly' flag, saving it back
will erase all disabled entries.
Arguments:
Info - supplies the settings to be saved
Return Value:
BOOL - TRUE if successful, FALSE otherwise.
--*/
{
SAAPPLICATION* Application;
TCHAR Buffer[10];
PLIST_ENTRY Link;
TCHAR Key[10];
TCHAR* Path;
TCHAR SectionName[32];
SASERVER* Server;
TRACE("RasSaveSharedAccessSettings");
//
// First erase the existing file.
//
if (!(Path = LoadPath()) || CreateDirectoriesOnPath(Path, NULL)) {
Free0(Path);
return FALSE;
}
DeleteFile(Path);
//
// Now we reconstruct the file.
// We begin by saving each application entry, in the process building
// a content index of all the saved entries.
//
wsprintf(SectionName, c_szSectionFormat, c_szContents, c_szApplication);
for (Link = Info->ApplicationList.Flink; Link != &Info->ApplicationList;
Link = Link->Flink) {
Application = CONTAINING_RECORD(Link, SAAPPLICATION, Link);
if (SaveApplication(Application, Path)) {
wsprintf(Key, c_szKeyFormat, Application->Key);
_ltot(!!Application->Enabled, Buffer, 10);
WritePrivateProfileStringUTF8(
SectionName,
Key,
Buffer,
Path
);
}
}
//
// Similarly, save each server entry, in the process building
// a content index of all the saved entries.
//
wsprintf(SectionName, c_szSectionFormat, c_szContents, c_szServer);
for (Link = Info->ServerList.Flink; Link != &Info->ServerList;
Link = Link->Flink) {
Server = CONTAINING_RECORD(Link, SASERVER, Link);
if (SaveServer(Info, Server, Path)) {
wsprintf(Key, c_szKeyFormat, Server->Key);
_ltot(!!Server->Enabled, Buffer, 10);
WritePrivateProfileStringUTF8(
SectionName,
Key,
Buffer,
Path
);
}
}
Free(Path);
CsControlService(IPNATHLP_CONTROL_UPDATE_SETTINGS);
return TRUE;
} // RasSaveSharedAccessSettings
VOID APIENTRY
FreeSharedAccessApplication(
SAAPPLICATION* Application
)
{
PLIST_ENTRY Link;
SARESPONSE* Response;
while (!IsListEmpty(&Application->ResponseList)) {
Link = RemoveHeadList(&Application->ResponseList);
Response = CONTAINING_RECORD(Link, SARESPONSE, Link);
Free(Response);
}
Free0(Application->Title);
Free(Application);
}
VOID APIENTRY
FreeSharedAccessServer(
SASERVER* Server
)
{
Free0(Server->Title);
Free0(Server->InternalName);
Free(Server);
}
SAAPPLICATION*
LoadApplication(
ULONG KeyValue,
BOOL Enabled,
const TCHAR* Path
)
{
SAAPPLICATION* Application;
TCHAR* EntryList;
TCHAR Key[10];
TCHAR SectionName[32];
TCHAR* Value;
wsprintf(Key, c_szKeyFormat, KeyValue);
wsprintf(SectionName, c_szSectionFormat, c_szApplication, Key);
if (!(EntryList = LoadEntryList(SectionName, Path))) { return NULL; }
do {
//
// Allocate and initialize an 'application' entry.
//
Application = (SAAPPLICATION*)Malloc(sizeof(SAAPPLICATION));
if (!Application) { break; }
ZeroMemory(Application, sizeof(*Application));
InitializeListHead(&Application->ResponseList);
Application->Key = KeyValue;
Application->Enabled = Enabled;
//
// Read each required '<tag>=<value>' entry in the section.
// The tags required for an application are
// 'Title='
// 'Protocol='
// 'Port='
// The optional tags, at least one of which must be present, are
// 'TcpResponseList='
// 'UdpResponseList='
// The optional tags which may be absent are
// 'BuiltIn='
//
Value = QueryEntryList(EntryList, c_szTagTitle);
if (!Value) { break; }
Application->Title = StrDup(Value);
Value = QueryEntryList(EntryList, c_szTagProtocol);
if (!Value) { break; }
if (!Lstrcmpni(Value, c_szTCP, LSTRLEN(c_szTCP))) {
Application->Protocol = NAT_PROTOCOL_TCP;
} else if (!Lstrcmpni(Value, c_szUDP, LSTRLEN(c_szTCP))) {
Application->Protocol = NAT_PROTOCOL_UDP;
} else {
break;
}
Value = QueryEntryList(EntryList, c_szTagPort);
if (!Value || !(Application->Port = (USHORT)_ttol(Value))) { break; }
Application->Port = HTONS(Application->Port);
Value = QueryEntryList(EntryList, c_szTagTcpResponseList);
if (Value) {
SharedAccessResponseStringToList(
NAT_PROTOCOL_TCP,
Value,
&Application->ResponseList
);
}
Value = QueryEntryList(EntryList, c_szTagUdpResponseList);
if (Value) {
SharedAccessResponseStringToList(
NAT_PROTOCOL_UDP,
Value,
&Application->ResponseList
);
}
if (IsListEmpty(&Application->ResponseList)) { break; }
Value = QueryEntryList(EntryList, c_szTagBuiltIn);
if (Value) {
Application->BuiltIn = _ttol(Value) ? TRUE : FALSE;
} else {
Application->BuiltIn = FALSE;
}
//
// The entry was loaded successfully.
//
Free(EntryList);
return Application;
} while (FALSE);
//
// Something went wrong.
//
if (Application) { FreeSharedAccessApplication(Application); }
Free(EntryList);
return NULL;
}
TCHAR*
LoadEntryList(
const TCHAR* Section,
const TCHAR* Path
)
{
CHAR* BufferA = NULL;
ULONG Length;
CHAR* PathA = NULL;
CHAR* SectionA = NULL;
ULONG Size;
CHAR* Source;
TCHAR* Target;
TCHAR* BufferW = NULL;
if (!(SectionA = StrDupAFromT(Section))) {
return NULL;
}
if (!(PathA = StrDupAFromTAnsi(Path))) {
Free(SectionA);
return NULL;
}
for (BufferA = NULL, Size = MAX_PATH; ; Size += MAX_PATH, Free(BufferA)) {
BufferA = (CHAR*)Malloc(Size);
if (!BufferA) {
break;
}
if (GetPrivateProfileSectionA(SectionA, BufferA, Size, PathA)
== Size-2) {
continue;
}
//
// Convert each string in the buffer from UTF8 format to Unicode.
// The conversion will result in at most 'Size' Unicode characters,
// and fewer if 2- or 3-byte UTF8 sequences are present in the
// source buffer.
//
BufferW = (TCHAR*)Malloc(Size * sizeof(TCHAR));
if (!BufferW) {
break;
}
Target = BufferW;
for (Source = BufferA; *Source; Source += lstrlenA(Source) + 1) {
if (StrCpyWFromA(Target, Source, Size) != NO_ERROR) {
break;
}
Length = lstrlen(Target) + 1;
Target += Length;
Size -= Length;
}
if (*Source) { break; }
Free(BufferA);
Free(PathA);
Free(SectionA);
return BufferW;
}
Free0(BufferW);
Free0(BufferA);
Free0(PathA);
Free0(SectionA);
return NULL;
}
TCHAR*
LoadPath(
VOID
)
{
TCHAR* Path;
Path =
(TCHAR*)Malloc(
(MAX_PATH + lstrlen(c_szSharedAccessIni) + 1) * sizeof(TCHAR)
);
if (!Path || !GetPhonebookDirectory(PBM_System, Path)) {
Free0(Path);
return NULL;
}
lstrcat(Path, c_szSharedAccessIni);
return Path;
}
SASERVER*
LoadServer(
ULONG KeyValue,
BOOL Enabled,
const TCHAR* Path
)
{
SASERVER* Server;
TCHAR* EntryList;
TCHAR Key[10];
TCHAR SectionName[32];
TCHAR* Value;
wsprintf(Key, c_szKeyFormat, KeyValue);
wsprintf(SectionName, c_szSectionFormat, c_szServer, Key);
if (!(EntryList = LoadEntryList(SectionName, Path))) { return NULL; }
do {
//
// Allocate and initialize a 'server' entry.
//
Server = (SASERVER*)Malloc(sizeof(SASERVER));
if (!Server) { break; }
ZeroMemory(Server, sizeof(*Server));
Server->Key = KeyValue;
Server->Enabled = Enabled;
//
// Read each required '<tag>=<value>' entry in the section.
// The tags required for a server are
// 'Title='
// 'Protocol='
// 'Port='
// 'InternalPort='
// The optional tags which may be absent are
// 'BuiltIn='
// 'InternalName='
// 'ReservedAddress='
// The 'InternalName=' and 'ReservedAddress=' tags may only be absent
// if 'BuiltIn' is set, in which case the entry is disabled.
//
Value = QueryEntryList(EntryList, c_szTagTitle);
if (!Value) { break; }
Server->Title = StrDup(Value);
Value = QueryEntryList(EntryList, c_szTagProtocol);
if (!Value) { break; }
if (!Lstrcmpni(Value, c_szTCP, LSTRLEN(c_szTCP))) {
Server->Protocol = NAT_PROTOCOL_TCP;
} else if (!Lstrcmpni(Value, c_szUDP, LSTRLEN(c_szTCP))) {
Server->Protocol = NAT_PROTOCOL_UDP;
} else {
break;
}
Value = QueryEntryList(EntryList, c_szTagPort);
if (!Value || !(Server->Port = (USHORT)_ttol(Value))) { break; }
Server->Port = HTONS(Server->Port);
Value = QueryEntryList(EntryList, c_szTagInternalPort);
if (!Value || !(Server->InternalPort = (USHORT)_ttol(Value))) { break; }
Server->InternalPort = HTONS(Server->InternalPort);
Value = QueryEntryList(EntryList, c_szTagBuiltIn);
if (Value) {
Server->BuiltIn = _ttol(Value) ? TRUE : FALSE;
} else {
Server->BuiltIn = FALSE;
}
Value = QueryEntryList(EntryList, c_szTagInternalName);
if (!Value || !lstrlen(Value)) {
if (!Server->BuiltIn) {
break;
} else {
Server->InternalName = NULL;
Server->Enabled = FALSE;
}
} else {
Server->InternalName = StrDup(Value);
}
Value = QueryEntryList(EntryList, c_szTagReservedAddress);
if (!Value || !lstrlen(Value)) {
if (!Server->BuiltIn) {
break;
} else {
Server->ReservedAddress = INADDR_NONE;
Server->Enabled = FALSE;
}
} else {
Server->ReservedAddress = IpPszToHostAddr(Value);
if (Server->ReservedAddress == INADDR_NONE && !Server->BuiltIn) {
break;
}
Server->ReservedAddress = HTONL(Server->ReservedAddress);
}
//
// The entry was loaded successfully.
//
Free(EntryList);
return Server;
} while (FALSE);
//
// Something went wrong.
//
if (Server) { FreeSharedAccessServer(Server); }
Free(EntryList);
return NULL;
}
LONG
Lstrcmpni(
const TCHAR* String1,
const TCHAR* String2,
LONG Length
)
{
return
CSTR_EQUAL -
CompareString(
LOCALE_SYSTEM_DEFAULT,
NORM_IGNORECASE,
String1,
Length,
String2,
Length
);
}
TCHAR*
QueryEntryList(
const TCHAR* EntryList,
const TCHAR* Tag
)
{
TCHAR* Entry;
ULONG TagLength = lstrlen(Tag);
for (Entry = (TCHAR*)EntryList; *Entry; Entry += lstrlen(Entry) + 1) {
if (Entry[0] == Tag[0] && !Lstrcmpni(Tag, Entry, TagLength)) {
return Entry + TagLength;
}
}
return NULL;
}
BOOL
SaveApplication(
SAAPPLICATION* Application,
const TCHAR* Path
)
{
TCHAR Buffer[32];
ULONG Length;
PLIST_ENTRY Link;
SARESPONSE* Response;
TCHAR SectionName[32];
TCHAR* Value;
wsprintf(Buffer, c_szKeyFormat, Application->Key);
wsprintf(SectionName, c_szSectionFormat, c_szApplication, Buffer);
WritePrivateProfileStringUTF8(
SectionName,
c_szTitle,
Application->Title,
Path
);
if (Application->Protocol == NAT_PROTOCOL_TCP) {
Value = (TCHAR*)c_szTCP;
} else if (Application->Protocol == NAT_PROTOCOL_UDP) {
Value = (TCHAR*)c_szUDP;
} else {
return FALSE;
}
WritePrivateProfileStringUTF8(
SectionName,
c_szProtocol,
Value,
Path
);
_ltot(NTOHS(Application->Port), Buffer, 10);
WritePrivateProfileStringUTF8(
SectionName,
c_szPort,
Buffer,
Path
);
Value = SharedAccessResponseListToString(&Application->ResponseList, NAT_PROTOCOL_TCP);
if (Value) {
WritePrivateProfileStringUTF8(
SectionName,
c_szTcpResponseList,
Value,
Path
);
Free(Value);
}
Value = SharedAccessResponseListToString(&Application->ResponseList, NAT_PROTOCOL_UDP);
if (Value) {
WritePrivateProfileStringUTF8(
SectionName,
c_szUdpResponseList,
Value,
Path
);
Free(Value);
}
_ltot(Application->BuiltIn, Buffer, 10);
WritePrivateProfileStringUTF8(
SectionName,
c_szBuiltIn,
Buffer,
Path
);
return TRUE;
}
BOOL
SaveServer(
SAINFO* Info,
SASERVER* Server,
const TCHAR* Path
)
{
TCHAR Buffer[32];
ULONG ReservedAddress;
TCHAR SectionName[32];
TCHAR* Value;
wsprintf(Buffer, c_szKeyFormat, Server->Key);
wsprintf(SectionName, c_szSectionFormat, c_szServer, Buffer);
WritePrivateProfileStringUTF8(
SectionName,
c_szTitle,
Server->Title,
Path
);
if (Server->Protocol == NAT_PROTOCOL_TCP) {
Value = (TCHAR*)c_szTCP;
} else if (Server->Protocol == NAT_PROTOCOL_UDP) {
Value = (TCHAR*)c_szUDP;
} else {
return FALSE;
}
WritePrivateProfileStringUTF8(
SectionName,
c_szProtocol,
Value,
Path
);
_ltot(NTOHS(Server->Port), Buffer, 10);
WritePrivateProfileStringUTF8(
SectionName,
c_szPort,
Buffer,
Path
);
WritePrivateProfileStringUTF8(
SectionName,
c_szInternalName,
Server->InternalName,
Path
);
_ltot(NTOHS(Server->InternalPort), Buffer, 10);
WritePrivateProfileStringUTF8(
SectionName,
c_szInternalPort,
Buffer,
Path
);
if (Server->InternalName && lstrlen(Server->InternalName)) {
ReservedAddress = IpPszToHostAddr(Server->InternalName);
if (ReservedAddress != INADDR_NONE) {
Server->ReservedAddress = HTONL(ReservedAddress);
}
if (Server->ReservedAddress == INADDR_NONE) {
SASERVER* Entry;
ULONG Index;
PLIST_ENTRY Link;
ULONG ScopeLength;
for (Link = Info->ServerList.Flink; Link != &Info->ServerList;
Link = Link->Flink) {
Entry = CONTAINING_RECORD(Link, SASERVER, Link);
if (Entry != Server &&
Entry->ReservedAddress &&
Entry->ReservedAddress != INADDR_NONE &&
lstrcmpi(Entry->InternalName, Server->InternalName) == 0) {
Server->ReservedAddress = Entry->ReservedAddress;
break;
}
}
if (Server->ReservedAddress == INADDR_NONE) {
ScopeLength = NTOHL(~Info->ScopeMask);
for (Index = 1; Index < ScopeLength - 1; Index++) {
ReservedAddress =
(Info->ScopeAddress & Info->ScopeMask) | HTONL(Index);
if (ReservedAddress == Info->ScopeAddress) { continue; }
for (Link = Info->ServerList.Flink;
Link != &Info->ServerList; Link = Link->Flink) {
Entry = CONTAINING_RECORD(Link, SASERVER, Link);
if (Entry->ReservedAddress == ReservedAddress) {
break;
}
}
if (Link == &Info->ServerList) { break; }
}
if (Index > ScopeLength) { return FALSE; }
Server->ReservedAddress = ReservedAddress;
}
}
IpHostAddrToPsz(NTOHL(Server->ReservedAddress), Buffer);
WritePrivateProfileStringUTF8(
SectionName,
c_szReservedAddress,
Buffer,
Path
);
}
_ltot(Server->BuiltIn, Buffer, 10);
WritePrivateProfileStringUTF8(
SectionName,
c_szBuiltIn,
Buffer,
Path
);
return TRUE;
}
#endif
TCHAR* APIENTRY
SharedAccessResponseListToString(
PLIST_ENTRY ResponseList,
UCHAR Protocol
)
{
TCHAR Buffer[LSTRLEN(c_szMaxResponseEntry)];
ULONG Length;
PLIST_ENTRY Link;
SARESPONSE* Response;
TCHAR* Value;
Length = 2;
for (Link = ResponseList->Flink;
Link != ResponseList; Link = Link->Flink) {
Response = CONTAINING_RECORD(Link, SARESPONSE, Link);
if (Response->Protocol != Protocol) { continue; }
Length += LSTRLEN(c_szMaxResponseEntry);
}
if (Length == 2) { return NULL; }
Value = (TCHAR*)Malloc(Length * sizeof(TCHAR));
if (!Value) { return NULL; }
Value[0] = TEXT('\0');
for (Link = ResponseList->Flink;
Link != ResponseList; Link = Link->Flink) {
Response = CONTAINING_RECORD(Link, SARESPONSE, Link);
if (Response->Protocol != Protocol) { continue; }
if (Value[0] != TEXT('\0')) {
lstrcat(Value, TEXT(","));
}
if (Response->StartPort == Response->EndPort) {
wsprintf(
Buffer,
c_szResponseFormat1,
NTOHS(Response->StartPort)
);
} else {
wsprintf(
Buffer,
c_szResponseFormat2,
NTOHS(Response->StartPort),
NTOHS(Response->EndPort)
);
}
lstrcat(Value, Buffer);
}
return Value;
}
BOOL APIENTRY
SharedAccessResponseStringToList(
UCHAR Protocol,
TCHAR* Value,
PLIST_ENTRY ListHead
)
{
TCHAR* Endp;
ULONG EndPort;
LONG Length;
SARESPONSE* Response;
ULONG StartPort;
while (*Value) {
//
// Read either a single port or a range of ports.
//
if (!(StartPort = _tcstoul(Value, &Endp, 10))) {
return FALSE;
} else if (StartPort > USHRT_MAX) {
return FALSE;
}
while(*Endp == ' ') Endp++; // consume whitespace
if (!*Endp || *Endp == ',') {
EndPort = StartPort;
Value = (!*Endp ? Endp : Endp + 1);
} else if (*Endp != '-') {
return FALSE;
} else if (!(EndPort = _tcstoul(++Endp, &Value, 10))) {
return FALSE;
} else if (EndPort > USHRT_MAX) {
return FALSE;
} else if (EndPort < StartPort) {
return FALSE;
} else if (*Value && *Value++ != ',') {
return FALSE;
}
//
// Allocate and append another response entry
//
Response = (SARESPONSE*)Malloc(sizeof(SARESPONSE));
if (!Response) { return FALSE; }
Response->Protocol = Protocol;
Response->StartPort = HTONS((USHORT)StartPort);
Response->EndPort = HTONS((USHORT)EndPort);
InsertTailList(ListHead, &Response->Link);
}
return TRUE;
}
#if 0
BOOL
WritePrivateProfileStringUTF8(
const TCHAR* Section,
const TCHAR* Key,
const TCHAR* Value,
const TCHAR* Path
)
{
CHAR* KeyA;
CHAR* PathA;
CHAR* SectionA;
BOOL Succeeded;
CHAR* ValueA = NULL;
if (!(SectionA = StrDupAFromT(Section))) {
Succeeded = FALSE;
} else {
if (!(KeyA = StrDupAFromT(Key))) {
Succeeded = FALSE;
} else {
if (Value && !(ValueA = StrDupAFromT(Value))) {
Succeeded = FALSE;
} else {
if (!(PathA = StrDupAFromTAnsi(Path))) {
Succeeded = FALSE;
} else {
Succeeded =
WritePrivateProfileStringA(
SectionA,
KeyA,
ValueA,
PathA
);
Free(PathA);
}
Free0(ValueA);
}
Free(KeyA);
}
Free(SectionA);
}
return Succeeded;
}
#endif