686 lines
15 KiB
C++
686 lines
15 KiB
C++
|
/*++
|
|||
|
|
|||
|
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;
|
|||
|
}
|