2020-09-30 17:12:29 +02:00

686 lines
15 KiB
C++
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
String.cxx
Abstract:
Methods of construction of various kinds of DUALSTRINGARRAYs.
Author:
Mario Goertzel [MarioGo]
Revision History:
MarioGo 04-01-95 Bits 'n pieces
MarioGO 01-??-96 STIRNGARRYs replaced by DUALSTRINGARRAYs
--*/
#include <or.hxx>
#include <dcomss.h> // GetProtseq et al
static CONST WCHAR aCallbackSecurity[] = L"Security=Identification Static True";
static CONST DWORD dwCallbackSecurityLength = sizeof(aCallbackSecurity)/sizeof(WCHAR);
RPC_BINDING_HANDLE
GetBinding(
IN PWSTR pCompressedBinding
)
{
ASSERT(pCompressedBinding);
PWSTR pwstrStringBinding;
PWSTR pwstrProtseq = GetProtseq(*pCompressedBinding);
PWSTR pwstrT;
RPC_STATUS Status;
RPC_BINDING_HANDLE bhReturn;
BOOL fLocal = FALSE;
if (!pwstrProtseq)
{
return(0);
}
int size = OrStringLen(pwstrProtseq) + OrStringLen(pCompressedBinding);
if (*pCompressedBinding == ID_LPC || *pCompressedBinding == ID_WMSG)
{
fLocal = TRUE;
size += dwCallbackSecurityLength + 1; // +1 for ','
}
pwstrStringBinding = (PWSTR) new WCHAR[size];
if (!pwstrStringBinding)
{
return(0);
}
OrStringCopy(pwstrStringBinding, pwstrProtseq);
pwstrT = OrStringSearch(pwstrStringBinding, 0);
*pwstrT = L':';
pwstrT++;
*pwstrT = 0;
OrStringCopy(pwstrT, pCompressedBinding + 1);
if (fLocal)
{
// We assume we have an endpoint.
pwstrT = OrStringSearch(pwstrT, 0);
pwstrT--;
if (*pwstrT != L']')
{
OrDbgPrint(("OR: Local string binding missing endpoint %S\n",
pwstrStringBinding));
ASSERT(0);
return(0);
}
*pwstrT = L',';
pwstrT++;
OrStringCopy(pwstrT, aCallbackSecurity);
pwstrT = OrStringSearch(pwstrT, 0);
*pwstrT = L']';
*(pwstrT + 1) = 0;
}
Status =
RpcBindingFromStringBinding( pwstrStringBinding,
&bhReturn);
#if DBG
if (Status != RPC_S_OK)
{
OrDbgPrint(("OR: Unable to create binding for %S = %d\n",
pwstrStringBinding,
Status));
}
#endif
return(bhReturn);
}
RPC_BINDING_HANDLE
GetBindingToOr(
IN PWSTR pwstrCompressedBinding
)
/*++
Routine Description:
Gets an RPC binding to a remote object resolver given
a compressed string binding to the remote object resolver.
Arguments:
pwstrCompressedBinding - a compressed string binding without an endpoint.
Return Value:
0 - failed to allocate memory or RpcBindingFromStringBinding failed.
non-NULL - completed okay
--*/
{
PWSTR protseq, endpoint;
PWSTR strbinding;
USHORT len;
RPC_BINDING_HANDLE bh = 0;
ASSERT(pwstrCompressedBinding);
ASSERT(*pwstrCompressedBinding != 0);
protseq = GetProtseq(*pwstrCompressedBinding);
endpoint = GetEndpoint(*pwstrCompressedBinding);
if (0 == protseq || 0 == endpoint)
{
ASSERT(0);
return(0);
}
len = 4; // ':' '[' ']' and '\0'
len += OrStringLen(protseq);
len += OrStringLen(endpoint);
len += OrStringLen(&pwstrCompressedBinding[1]);
strbinding = new USHORT[len];
if (strbinding)
{
PWSTR pwstrT;
OrStringCopy(strbinding, protseq); // protseq
pwstrT = OrStringSearch(strbinding, 0); // :
*pwstrT = L':';
pwstrT++;
*pwstrT = 0;
OrStringCat(strbinding, &pwstrCompressedBinding[1]); // network address
pwstrT = OrStringSearch(strbinding, 0); // [
*pwstrT = L'[';
pwstrT++;
*pwstrT = 0;
OrStringCat(strbinding, endpoint); // endpoint
pwstrT = OrStringSearch(strbinding, 0); // ]
*pwstrT = L']';
pwstrT++;
*pwstrT = 0;
RPC_STATUS status = RpcBindingFromStringBinding(strbinding, &bh);
ASSERT(bh == 0 || status == RPC_S_OK);
delete strbinding;
}
if (bh == 0)
{
OrDbgDetailPrint(("OR: Unable to bind to %S\n", pwstrCompressedBinding + 1));
}
return(bh);
}
DUALSTRINGARRAY *
GetStringBinding(
IN PWSTR pwstrCompressed,
IN PWSTR pwstrSecurityBindings
)
/*++
Routine Description:
Converts the compressed string binding into an expanded
string binding. An enpoint maybe optionally specified.
Arguments:
pwstrCompressed - a compressed string binding
pwstrSecurityBindings - optional security bindings
too be tacked onto the end of the expanded string binding.
Terminated by two nulls.
Return Value:
NULL - out of memory
non-NULL - a string binding.
--*/
{
DUALSTRINGARRAY *pT;
PWSTR protseq;
USHORT seccount;
PWSTR t = pwstrSecurityBindings;
if (t && *t)
{
seccount = 0;
do
{
seccount++;
t++;
if (*t == 0)
{
seccount++;
t++;
}
}
while(*t);
seccount++; // final NULL
}
else
{
// Two nulls only.
seccount = 2;
}
protseq = GetProtseq(*pwstrCompressed);
int l = OrStringLen(pwstrCompressed) + OrStringLen(protseq) + seccount + 1 + 1;
pT =(DUALSTRINGARRAY *)midl_user_allocate(sizeof(DUALSTRINGARRAY) + l * sizeof(WCHAR));
if (!pT)
{
return (0);
}
pT->wNumEntries = l;
OrStringCopy(pT->aStringArray, protseq);
OrStringCat(pT->aStringArray, L":");
OrStringCat(pT->aStringArray, pwstrCompressed + 1);
if (pwstrSecurityBindings)
{
PWSTR t = pT->aStringArray;
t = OrStringSearch(t, 0);
t++;
*t = 0; // Second NULL on string bindings.
t++;
OrMemoryCopy(t, pwstrSecurityBindings, seccount*sizeof(WCHAR));
}
else
{
// Add three NULLs, total of four.
PWSTR t = pT->aStringArray;
t = OrStringSearch(t, 0);
t[1] = 0;
t[2] = 0;
t[3] = 0;
}
pT->wSecurityOffset = pT->wNumEntries - seccount;
ASSERT(dsaValid(pT));
return(pT);
}
ORSTATUS
ConvertToRemote(
IN DUALSTRINGARRAY *pdsaLocal,
OUT DUALSTRINGARRAY **ppdsaRemote
)
/* ++
Parameters:
pdsaLocal - An array of string bindings with compressed protseqs.
ppdsaRemote - Will contain only those string bindings in pdsaLocal
which are not "IsLocal()".
Note: *ppdsaRemote maybe used as a flag, don't set it to non-NULL
until it is valid.
-- */
{
int iTotalSize;
int iSize;
USHORT *p1, *p2;
DUALSTRINGARRAY *pdsaT;
// Size remote array
// Final null terminator
iSize = 1;
p1 = pdsaLocal->aStringArray;
while(*p1)
{
if (! IsLocal(*p1) )
{
iSize += OrStringLen(p1) + 1;
}
p1 = OrStringSearch(p1, 0) + 1;
}
if (iSize == 1)
{
iSize = 2; // No non-local strings, need two terminators.
}
iTotalSize = iSize + (pdsaLocal->wNumEntries - pdsaLocal->wSecurityOffset);
pdsaT = new(iTotalSize * sizeof(WCHAR)) DUALSTRINGARRAY;
if (!pdsaT)
{
return(OR_NOMEM);
}
pdsaT->wNumEntries = iTotalSize;
pdsaT->wSecurityOffset = iSize;
p2 = pdsaT->aStringArray;
// Copy security bindings
OrMemoryCopy(p2 + iSize,
pdsaLocal->aStringArray + pdsaLocal->wSecurityOffset,
(iTotalSize - iSize) * sizeof(WCHAR));
if (iSize == 2)
{
// No non-local strings, fill in terminators and return.
*p2 = 0;
*(p2 + 1) = 0;
*ppdsaRemote = pdsaT;
ASSERT(dsaValid(pdsaT));
return(OR_OK);
}
p1 = pdsaLocal->aStringArray;
while(*p1)
{
if ( ! IsLocal(*p1) )
{
OrStringCopy(p2, p1);
p2 = OrStringSearch(p2, 0) + 1;
}
p1 = OrStringSearch(p1, 0) + 1;
}
*p2 = 0; // Second terminator.
*ppdsaRemote = pdsaT;
ASSERT(dsaValid(pdsaT));
return(OR_OK);
}
DUALSTRINGARRAY *
CompressStringArray(
IN DUALSTRINGARRAY *pdsaExpanded,
IN BOOL fSharedMem
)
/*++
Routine Description:
Converts a stringarray of regular string bindings into a
compressed (protseq's replaced with WORD id's) array of
string bindings.
Arguments:
pdsaExpanded - the string array to compress.
Security information is copied.
Return Value:
0 - failed to allocate memory.
non-0 - compressed string array.
--*/
{
int i, size;
USHORT *p1, *p2, *p3;
PWSTR pwstr;
DUALSTRINGARRAY *pdsaCompressed;
// Compute size of result.
p1 = pdsaExpanded->aStringArray;
size = pdsaExpanded->wNumEntries - pdsaExpanded->wSecurityOffset;
if (*p1 == 0)
{
size += 2; // two null terminators ONLY.
}
else
{
size += 1; // last null terminator
}
while(*p1)
{
int sizeT = OrStringLen(p1);
p2 = OrStringSearch(p1, L':'); // ':' is not valid in protseq.
if (p2)
{
size += sizeT + 1 - (p2 - p1); // proseq len (p2 - p1) become 1 for Id.
}
else
{
ASSERT(p2);
}
p1 = OrStringSearch(p1, 0) + 1;
}
if (fSharedMem)
{
pdsaCompressed = (DUALSTRINGARRAY*)
OrMemAlloc(sizeof(DUALSTRINGARRAY) + size * sizeof(WCHAR));
}
else
{
pdsaCompressed = (DUALSTRINGARRAY*)
midl_user_allocate(sizeof(DUALSTRINGARRAY) + size * sizeof(WCHAR));
}
if (0 == pdsaCompressed)
{
return(0);
}
pdsaCompressed->wNumEntries = size;
pdsaCompressed->wSecurityOffset = size - (pdsaExpanded->wNumEntries - pdsaExpanded->wSecurityOffset);
p3 = pdsaCompressed->aStringArray;
*p3 = 0;
p1 = pdsaExpanded->aStringArray;
if (*p1 == 0)
{
// Two null terminators only.
*(p3 + 1) = 0;
}
while(*p1)
{
p2 = OrStringSearch(p1, L':');
if (p2)
{
*p2 = 0;
*p3 = GetProtseqId(p1);
*p2 = L':';
if (*p3 != 0)
{
p3++;
p1 = p2 + 1; // Just after ':'
OrStringCopy(p3, p1);
// Move p3 to start of next string if any.
p3 = OrStringSearch(p3, 0) + 1;
}
}
// Move p1 to start of next string if any.
p1 = OrStringSearch(p1, 0) + 1;
}
// Second terminator, p3 already points to it.
*p3 = 0;
// Copy security bindings
OrMemoryCopy(p3 + 1,
pdsaExpanded->aStringArray + pdsaExpanded->wSecurityOffset,
(pdsaExpanded->wNumEntries - pdsaExpanded->wSecurityOffset) * sizeof(WCHAR));
ASSERT(dsaValid(pdsaCompressed));
return(pdsaCompressed);
}
PWSTR
FindMatchingProtseq(
IN USHORT cClientProtseqs,
IN USHORT aClientProtseqs[],
IN PWSTR pwstrServerBindings
)
/*++
Routine Description:
Finds the first protseq id in aClientProtseqs which appears in any of
the server bindings.
Arguments:
cClientProtseqs - the number of entries in aClientProtseqs.
aClientProtseqs - Protseq tower id's support by the client.
pwstrServerBindings - compressed array of bindings supported by the server
terminated by two NULLs.
Return Value:
0 - no match found.
non-0 - a pointer into the pwstrCompressedBindings.
--*/
// Called by server oxid's and processes when checking for lazy use protseq.
{
ULONG i;
if (0 == cClientProtseqs)
{
return(0);
}
while(*pwstrServerBindings)
{
for(i = 0; i < cClientProtseqs; i++)
{
if (aClientProtseqs[i] == *pwstrServerBindings)
{
return(pwstrServerBindings);
}
}
pwstrServerBindings = OrStringSearch(pwstrServerBindings, 0) + 1;
}
return(NULL);
}
PWSTR
FindMatchingProtseq(
IN USHORT protseq,
IN PWSTR pwstrCompressedBindings
)
/*++
Routine Description:
Searches a compressed string array for an entry which
matches a particular protseq.
Arguments:
protseq - The protseq to search for.
pwstrCompressedBindings - The bindings to search.
Return Value:
0 - not found
non-0 - a pointer into the pwstrCompressedBindings
--*/
{
ASSERT(pwstrCompressedBindings);
while(*pwstrCompressedBindings)
{
if (*pwstrCompressedBindings == protseq)
{
return(pwstrCompressedBindings);
}
pwstrCompressedBindings = OrStringSearch(pwstrCompressedBindings, 0) + 1;
}
return(0);
}
ORSTATUS
MergeBindings(
IN DUALSTRINGARRAY *pdsaStringBindings,
IN DUALSTRINGARRAY *pdsaSecurityBindings,
OUT DUALSTRINGARRAY **ppdsaMergedBindings
)
/*++
Routine Description:
Merges the string bindings from the first param with the security
bindings from the second param to create a new dualstring array.
Arguments:
pdsaStringBindings -- The string bindings supplier
pdsaSecurityBindings -- The security bindings supplier
ppdsaMergedBindings -- the merged result
Return Value:
OR_OK (0) - success
OR_NOMEM - memory allocation failed
--*/
{
ASSERT(dsaValid(pdsaStringBindings));
ASSERT(dsaValid(pdsaSecurityBindings));
USHORT wBindingsSize = pdsaStringBindings->wSecurityOffset;
USHORT wSecuritySize = pdsaSecurityBindings->wNumEntries -
pdsaSecurityBindings->wSecurityOffset;
USHORT wNumEntries = wBindingsSize + wSecuritySize;
DUALSTRINGARRAY *pdsa = (DUALSTRINGARRAY *)
new char[
sizeof(DUALSTRINGARRAY) +
(wNumEntries - 1) * sizeof(WCHAR)
];
if (!pdsa)
{
return OR_NOMEM;
}
*ppdsaMergedBindings = pdsa;
pdsa->wNumEntries = wNumEntries;
pdsa->wSecurityOffset = wBindingsSize;
memcpy(
pdsa->aStringArray,
pdsaStringBindings->aStringArray,
wBindingsSize * sizeof(WCHAR)
);
memcpy(
pdsa->aStringArray + pdsa->wSecurityOffset,
pdsaSecurityBindings->aStringArray + pdsaSecurityBindings->wSecurityOffset,
sizeof(WCHAR) * wSecuritySize
);
return OR_OK;
}