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.
693 lines
14 KiB
693 lines
14 KiB
/*++
|
|
|
|
Copyright (c) 1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
growbuf.c
|
|
|
|
Abstract:
|
|
|
|
Simple buffer management functions that allow variable blocks to
|
|
be added as an array. (Initially used to build a SID array, where
|
|
each SID can be a different size.)
|
|
|
|
Author:
|
|
|
|
Jim Schmidt (jimschm) 05-Feb-1997
|
|
|
|
Revision History:
|
|
|
|
jimschm 11-Aug-1998 Added GrowBufAppendString
|
|
calinn 15-Jan-1998 modified MultiSzAppend
|
|
|
|
|
|
--*/
|
|
|
|
#include "pch.h"
|
|
#include "migutilp.h"
|
|
|
|
#define DEFAULT_GROW_SIZE 8192
|
|
|
|
PBYTE
|
|
RealGrowBuffer (
|
|
IN OUT PGROWBUFFER GrowBuf,
|
|
IN DWORD SpaceNeeded
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
GrowBuffer makes sure there is enough bytes in the buffer
|
|
to accomodate SpaceNeeded. It allocates an initial buffer
|
|
when no buffer is allocated, and it reallocates the buffer
|
|
in increments of GrowBuf->Size (or DEFAULT_GROW_SIZE) when
|
|
needed.
|
|
|
|
Arguments:
|
|
|
|
GrowBuf - A pointer to a GROWBUFFER structure.
|
|
Initialize this structure to zero for
|
|
the first call to GrowBuffer.
|
|
|
|
SpaceNeeded - The number of free bytes needed in the buffer
|
|
|
|
|
|
Return Value:
|
|
|
|
A pointer to the SpaceNeeded bytes, or NULL if a memory allocation
|
|
error occurred.
|
|
|
|
--*/
|
|
|
|
{
|
|
PBYTE NewBuffer;
|
|
DWORD TotalSpaceNeeded;
|
|
DWORD GrowTo;
|
|
|
|
MYASSERT(SpaceNeeded);
|
|
MYASSERT(GrowBuf);
|
|
|
|
if (!GrowBuf->Buf) {
|
|
GrowBuf->Size = 0;
|
|
GrowBuf->End = 0;
|
|
}
|
|
|
|
if (!GrowBuf->GrowSize) {
|
|
GrowBuf->GrowSize = DEFAULT_GROW_SIZE;
|
|
}
|
|
|
|
TotalSpaceNeeded = GrowBuf->End + SpaceNeeded;
|
|
if (TotalSpaceNeeded > GrowBuf->Size) {
|
|
GrowTo = (TotalSpaceNeeded + GrowBuf->GrowSize) - (TotalSpaceNeeded % GrowBuf->GrowSize);
|
|
} else {
|
|
GrowTo = 0;
|
|
}
|
|
|
|
if (!GrowBuf->Buf) {
|
|
GrowBuf->Buf = (PBYTE) MemAlloc (g_hHeap, 0, GrowTo);
|
|
if (!GrowBuf->Buf) {
|
|
DEBUGMSG ((DBG_ERROR, "GrowBuffer: Initial alloc failed"));
|
|
return NULL;
|
|
}
|
|
|
|
GrowBuf->Size = GrowTo;
|
|
} else if (GrowTo) {
|
|
NewBuffer = MemReAlloc (g_hHeap, 0, GrowBuf->Buf, GrowTo);
|
|
if (!NewBuffer) {
|
|
DEBUGMSG ((DBG_ERROR, "GrowBuffer: Realloc failed"));
|
|
return NULL;
|
|
}
|
|
|
|
GrowBuf->Size = GrowTo;
|
|
GrowBuf->Buf = NewBuffer;
|
|
}
|
|
|
|
NewBuffer = GrowBuf->Buf + GrowBuf->End;
|
|
GrowBuf->End += SpaceNeeded;
|
|
|
|
return NewBuffer;
|
|
}
|
|
|
|
|
|
PBYTE
|
|
RealGrowBufferReserve (
|
|
IN PGROWBUFFER GrowBuf,
|
|
IN DWORD BytesToReserve
|
|
)
|
|
{
|
|
DWORD end;
|
|
PBYTE result;
|
|
|
|
MYASSERT(GrowBuf);
|
|
MYASSERT(BytesToReserve);
|
|
|
|
end = GrowBuf->End;
|
|
result = GrowBuffer (GrowBuf, BytesToReserve);
|
|
GrowBuf->End = end;
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
VOID
|
|
FreeGrowBuffer (
|
|
IN PGROWBUFFER GrowBuf
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
FreeGrowBuffer frees a buffer allocated by GrowBuffer.
|
|
|
|
Arguments:
|
|
|
|
GrowBuf - A pointer to the same structure passed to GrowBuffer
|
|
|
|
Return Value:
|
|
|
|
none
|
|
|
|
--*/
|
|
|
|
|
|
{
|
|
MYASSERT(GrowBuf);
|
|
|
|
if (GrowBuf->Buf) {
|
|
MemFree (g_hHeap, 0, GrowBuf->Buf);
|
|
ZeroMemory (GrowBuf, sizeof (GROWBUFFER));
|
|
}
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
Routine Descriptions:
|
|
|
|
MultiSzAppend
|
|
This function is a general-purpose function to append a string
|
|
to a grow buffer.
|
|
|
|
MultiSzAppendVal
|
|
This function adds a key=decimal_val string, where key is a
|
|
specified string, and decimal_val is a specified DWORD.
|
|
|
|
MultiSzAppendString
|
|
This function adds key=string to the grow buffer, where key
|
|
is a specified string, and string is a specified string value.
|
|
|
|
Arguments:
|
|
|
|
GrowBuf - The buffer to append the string or key/value pair
|
|
Key - The key part of the key=val pair
|
|
Val - The val part of the key=val pair
|
|
|
|
Return Value:
|
|
|
|
TRUE if the function succeeded, or FALSE if a memory allocation
|
|
failure occurred.
|
|
|
|
--*/
|
|
|
|
|
|
BOOL
|
|
RealMultiSzAppendA (
|
|
PGROWBUFFER GrowBuf,
|
|
PCSTR String
|
|
)
|
|
{
|
|
PSTR p;
|
|
|
|
if(!GrowBuf || !String){
|
|
MYASSERT(GrowBuf);
|
|
MYASSERT(String);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
p = (PSTR) GrowBuffer (GrowBuf, SizeOfStringA (String) + sizeof(CHAR));
|
|
if (!p) {
|
|
return FALSE;
|
|
}
|
|
|
|
StringCopyA (p, String);
|
|
GrowBuf->End -= sizeof (CHAR);
|
|
GrowBuf->Buf[GrowBuf->End] = 0;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
RealMultiSzAppendValA (
|
|
PGROWBUFFER GrowBuf,
|
|
PCSTR Key,
|
|
DWORD Val
|
|
)
|
|
{
|
|
CHAR KeyValPair[256];
|
|
|
|
MYASSERT(GrowBuf);
|
|
MYASSERT(Key);
|
|
/*
|
|
//BUGBUG: Decided to leave it as it was, because we know callers.
|
|
if(!GrowBuf || !Key){
|
|
MYASSERT(GrowBuf);
|
|
MYASSERT(Key);
|
|
return FALSE;
|
|
}
|
|
|
|
if(_snprintf(KeyValPair, ARRAYSIZE(KeyValPair), "%s=%u", Key, Val) < 0){
|
|
DEBUGMSG((DBG_ERROR, "RealMultiSzAppendValA: Key was truncated, function fails."));
|
|
//KeyValPair[ARRAYSIZE(KeyValPair) - 1] = '\0';
|
|
return FALSE;//Continue with truncated string or return FALSE;
|
|
}
|
|
*/
|
|
|
|
wsprintfA (KeyValPair, "%s=%u", Key, Val);
|
|
return MultiSzAppendA (GrowBuf, KeyValPair);
|
|
}
|
|
|
|
BOOL
|
|
RealMultiSzAppendStringA (
|
|
PGROWBUFFER GrowBuf,
|
|
PCSTR Key,
|
|
PCSTR Val
|
|
)
|
|
{
|
|
CHAR KeyValPair[1024];
|
|
|
|
MYASSERT(GrowBuf);
|
|
MYASSERT(Key);
|
|
MYASSERT(Val);
|
|
/*
|
|
//BUGBUG: Decided to leave it as it was, because we know callers.
|
|
if(!GrowBuf || !Key || !Val){
|
|
MYASSERT(GrowBuf);
|
|
MYASSERT(Key);
|
|
MYASSERT(Val);
|
|
return FALSE;
|
|
}
|
|
|
|
if(_snprintf(KeyValPair, ARRAYSIZE(KeyValPair), "%s=%s", Key, Val) < 0){
|
|
DEBUGMSG((DBG_ERROR, "RealMultiSzAppendStringA: Key was truncated, function fails."));
|
|
//KeyValPair[ARRAYSIZE(KeyValPair) - 1] = '\0';
|
|
return FALSE;//BUGBUG: Continue with truncated string or return FALSE;
|
|
}
|
|
*/
|
|
|
|
wsprintfA (KeyValPair, "%s=%s", Key, Val);
|
|
return MultiSzAppendA (GrowBuf, KeyValPair);
|
|
}
|
|
|
|
|
|
BOOL
|
|
RealMultiSzAppendW (
|
|
PGROWBUFFER GrowBuf,
|
|
PCWSTR String
|
|
)
|
|
{
|
|
PWSTR p;
|
|
|
|
if(!GrowBuf || !String){
|
|
MYASSERT(GrowBuf);
|
|
MYASSERT(String);
|
|
return FALSE;
|
|
}
|
|
|
|
p = (PWSTR) GrowBuffer (GrowBuf, SizeOfStringW (String) + sizeof(WCHAR));
|
|
if (!p) {
|
|
return FALSE;
|
|
}
|
|
|
|
StringCopyW (p, String);
|
|
GrowBuf->End -= sizeof (WCHAR);
|
|
*((PWCHAR) (GrowBuf->Buf + GrowBuf->End)) = 0;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
RealMultiSzAppendValW (
|
|
PGROWBUFFER GrowBuf,
|
|
PCWSTR Key,
|
|
DWORD Val
|
|
)
|
|
{
|
|
WCHAR KeyValPair[256];
|
|
|
|
MYASSERT(GrowBuf);
|
|
MYASSERT(Key);
|
|
|
|
/*
|
|
//BUGBUG: Decided to leave it as it was, because we know callers.
|
|
if(!GrowBuf || !Key){
|
|
MYASSERT(GrowBuf);
|
|
MYASSERT(Key);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if(_snwprintf(KeyValPair, ARRAYSIZE(KeyValPair), L"%s=%u", Key, Val) < 0){
|
|
DEBUGMSG((DBG_ERROR, "RealMultiSzAppendValW: Key was truncated, function fails."));
|
|
//KeyValPair[ARRAYSIZE(KeyValPair) - 1] = '\0';
|
|
return FALSE;//BUGBUG: Continue with truncated string or return FALSE;
|
|
}
|
|
*/
|
|
|
|
wsprintfW (KeyValPair, L"%s=%u", Key, Val);
|
|
return MultiSzAppendW (GrowBuf, KeyValPair);
|
|
}
|
|
|
|
BOOL
|
|
RealMultiSzAppendStringW (
|
|
PGROWBUFFER GrowBuf,
|
|
PCWSTR Key,
|
|
PCWSTR Val
|
|
)
|
|
{
|
|
WCHAR KeyValPair[1024];
|
|
|
|
MYASSERT(GrowBuf);
|
|
MYASSERT(Key);
|
|
MYASSERT(Val);
|
|
/*
|
|
//BUGBUG: Decided to leave it as it was, because we know callers.
|
|
if(!GrowBuf || !Key || !Val){
|
|
MYASSERT(GrowBuf);
|
|
MYASSERT(Key);
|
|
MYASSERT(Val);
|
|
return FALSE;
|
|
}
|
|
|
|
if(_snwprintf(KeyValPair, ARRAYSIZE(KeyValPair), L"%s=%s", Key, Val) < 0){
|
|
DEBUGMSG((DBG_ERROR, "RealMultiSzAppendStringW: Key was truncated, function fails."));
|
|
//KeyValPair[ARRAYSIZE(KeyValPair) - 1] = '\0';
|
|
return FALSE;//BUGBUG: Continue with truncated string or return FALSE;
|
|
}
|
|
*/
|
|
|
|
wsprintfW (KeyValPair, L"%s=%s", Key, Val);
|
|
return MultiSzAppendW (GrowBuf, KeyValPair);
|
|
}
|
|
|
|
|
|
BOOL
|
|
RealGrowBufAppendDword (
|
|
PGROWBUFFER GrowBuf,
|
|
DWORD d
|
|
)
|
|
{
|
|
PDWORD p;
|
|
|
|
if(!GrowBuf){
|
|
MYASSERT(GrowBuf);
|
|
return FALSE;
|
|
}
|
|
|
|
p = (PDWORD) GrowBuffer (GrowBuf, sizeof (DWORD));
|
|
if (!p) {
|
|
return FALSE;
|
|
}
|
|
|
|
*p = d;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
RealGrowBufAppendUintPtr (
|
|
PGROWBUFFER GrowBuf,
|
|
UINT_PTR d
|
|
)
|
|
{
|
|
PUINT_PTR p;
|
|
|
|
if(!GrowBuf){
|
|
MYASSERT(GrowBuf);
|
|
return FALSE;
|
|
}
|
|
|
|
p = (PUINT_PTR) GrowBuffer (GrowBuf, sizeof (UINT_PTR));
|
|
if (!p) {
|
|
return FALSE;
|
|
}
|
|
|
|
*p = d;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
GrowBufAppendString copies the specified string to the end of the grow
|
|
buffer. This is the equivalent of strcat. The grow buffer is
|
|
automatically expanded as necessary.
|
|
|
|
Arguments:
|
|
|
|
GrowBuf - Specifies the destination grow buffer
|
|
String - Specifies the string to append
|
|
|
|
Return Value:
|
|
|
|
Always TRUE.
|
|
|
|
--*/
|
|
|
|
BOOL
|
|
RealGrowBufAppendStringA (
|
|
IN OUT PGROWBUFFER GrowBuf,
|
|
IN PCSTR String
|
|
)
|
|
|
|
{
|
|
UINT OldEnd;
|
|
PSTR p;
|
|
UINT Bytes;
|
|
|
|
if(!GrowBuf){
|
|
MYASSERT(GrowBuf);
|
|
return FALSE;
|
|
}
|
|
|
|
if (String) {
|
|
Bytes = SizeOfStringA (String);
|
|
|
|
OldEnd = GrowBuf->End;
|
|
if (OldEnd) {
|
|
p = (PSTR) (GrowBuf->Buf + OldEnd - sizeof (CHAR));
|
|
if (*p == 0) {
|
|
OldEnd -= sizeof (CHAR);
|
|
}
|
|
}
|
|
|
|
RealGrowBuffer (GrowBuf, Bytes);
|
|
|
|
p = (PSTR) (GrowBuf->Buf + OldEnd);
|
|
StringCopyA (p, String);
|
|
GrowBuf->End = OldEnd + Bytes;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
RealGrowBufAppendStringW (
|
|
IN OUT PGROWBUFFER GrowBuf,
|
|
IN PCWSTR String
|
|
)
|
|
{
|
|
UINT OldEnd;
|
|
PWSTR p;
|
|
UINT Bytes;
|
|
|
|
if(!GrowBuf){
|
|
MYASSERT(GrowBuf);
|
|
return FALSE;
|
|
}
|
|
|
|
if (String) {
|
|
Bytes = SizeOfStringW (String);
|
|
|
|
OldEnd = GrowBuf->End;
|
|
if (OldEnd) {
|
|
p = (PWSTR) (GrowBuf->Buf + OldEnd - sizeof (WCHAR));
|
|
if (*p == 0) {
|
|
OldEnd -= sizeof (WCHAR);
|
|
}
|
|
}
|
|
|
|
RealGrowBuffer (GrowBuf, Bytes);
|
|
|
|
p = (PWSTR) (GrowBuf->Buf + OldEnd);
|
|
StringCopyW (p, String);
|
|
GrowBuf->End = OldEnd + Bytes;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
GrowBufAppendStringAB copies the specified string range to the
|
|
end of the grow buffer. This concatenates the string to the
|
|
existing buffer contents, and keeps the buffer terminated.
|
|
|
|
Arguments:
|
|
|
|
GrowBuf - Specifies the destination grow buffer
|
|
Start - Specifies the start of string to append
|
|
EndPlusOne - Specifies one logical character beyond the end of
|
|
the string, and can point to a nul.
|
|
|
|
Return Value:
|
|
|
|
Always TRUE.
|
|
|
|
--*/
|
|
|
|
BOOL
|
|
RealGrowBufAppendStringABA (
|
|
IN OUT PGROWBUFFER GrowBuf,
|
|
IN PCSTR Start,
|
|
IN PCSTR EndPlusOne
|
|
)
|
|
|
|
{
|
|
UINT OldEnd;
|
|
PSTR p;
|
|
UINT Bytes;
|
|
|
|
if(!GrowBuf){
|
|
MYASSERT(GrowBuf);
|
|
return FALSE;
|
|
}
|
|
|
|
if (Start && Start < EndPlusOne) {
|
|
Bytes = (UINT) (UINT_PTR) ((PBYTE) EndPlusOne - (PBYTE) Start);
|
|
|
|
OldEnd = GrowBuf->End;
|
|
if (OldEnd) {
|
|
p = (PSTR) (GrowBuf->Buf + OldEnd - sizeof (CHAR));
|
|
if (*p == 0) {
|
|
OldEnd -= sizeof (CHAR);
|
|
}
|
|
}
|
|
|
|
RealGrowBuffer (GrowBuf, Bytes + sizeof (CHAR));
|
|
|
|
p = (PSTR) (GrowBuf->Buf + OldEnd);
|
|
CopyMemory (p, Start, Bytes);
|
|
p = (PSTR) ((PBYTE) p + Bytes);
|
|
*p = 0;
|
|
|
|
GrowBuf->End = OldEnd + Bytes + sizeof (CHAR);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
RealGrowBufAppendStringABW (
|
|
IN OUT PGROWBUFFER GrowBuf,
|
|
IN PCWSTR Start,
|
|
IN PCWSTR EndPlusOne
|
|
)
|
|
{
|
|
UINT OldEnd;
|
|
PWSTR p;
|
|
UINT Bytes;
|
|
|
|
if(!GrowBuf){
|
|
MYASSERT(GrowBuf);
|
|
return FALSE;
|
|
}
|
|
|
|
if (Start && Start < EndPlusOne) {
|
|
Bytes = (UINT) (UINT_PTR) ((PBYTE) EndPlusOne - (PBYTE) Start);
|
|
|
|
OldEnd = GrowBuf->End;
|
|
if (OldEnd > sizeof (WCHAR)) {
|
|
p = (PWSTR) (GrowBuf->Buf + OldEnd - sizeof (WCHAR));
|
|
if (*p == 0) {
|
|
OldEnd -= sizeof (WCHAR);
|
|
}
|
|
}
|
|
|
|
RealGrowBuffer (GrowBuf, Bytes + sizeof (WCHAR));
|
|
|
|
p = (PWSTR) (GrowBuf->Buf + OldEnd);
|
|
CopyMemory (p, Start, Bytes);
|
|
p = (PWSTR) ((PBYTE) p + Bytes);
|
|
*p = 0;
|
|
|
|
GrowBuf->End = OldEnd + Bytes + sizeof (WCHAR);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
GrowBufCopyString copies the specified string to the end of the grow buffer.
|
|
|
|
Arguments:
|
|
|
|
GrowBuf - Specifies the grow buffer to add to, receives the updated buffer
|
|
|
|
String - Specifies the string to add to GrowBuf
|
|
|
|
Return Value:
|
|
|
|
|
|
|
|
--*/
|
|
|
|
BOOL
|
|
RealGrowBufCopyStringA (
|
|
IN OUT PGROWBUFFER GrowBuf,
|
|
IN PCSTR String
|
|
)
|
|
{
|
|
PBYTE Buf;
|
|
UINT Size;
|
|
|
|
if(!GrowBuf || !String){
|
|
MYASSERT(GrowBuf);
|
|
MYASSERT(String);
|
|
return FALSE;
|
|
}
|
|
|
|
Size = SizeOfStringA (String);
|
|
|
|
Buf = RealGrowBuffer (GrowBuf, Size);
|
|
if (!Buf) {
|
|
return FALSE;
|
|
}
|
|
|
|
CopyMemory (Buf, String, Size);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
RealGrowBufCopyStringW (
|
|
IN OUT PGROWBUFFER GrowBuf,
|
|
IN PCWSTR String
|
|
)
|
|
{
|
|
PBYTE Buf;
|
|
UINT Size;
|
|
|
|
if(!GrowBuf || !String){
|
|
MYASSERT(GrowBuf);
|
|
MYASSERT(String);
|
|
return FALSE;
|
|
}
|
|
|
|
Size = SizeOfStringW (String);
|
|
|
|
Buf = RealGrowBuffer (GrowBuf, Size);
|
|
if (!Buf) {
|
|
return FALSE;
|
|
}
|
|
|
|
CopyMemory (Buf, String, Size);
|
|
return TRUE;
|
|
}
|