Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

1188 lines
31 KiB

/*++
Copyright (c) 1993 Microsoft Corporation
Module Name:
strngtab.c
Abstract:
String table functions for Windows NT Setup API dll
A string table is a block of memory that contains a bunch of strings.
Hashing is used, and each hash table entry points to a linked list
of strings within the string table. Strings within each linked list
are sorted in ascending order. A node in the linked list consists of
a pointer to the next node, followed by the string itself. Nodes
are manually aligned to start on DWORD boundaries so we don't have to
resort to using unaligned pointers.
Author:
Ted Miller (tedm) 11-Jan-1995
Revision History:
--*/
#include "setupntp.h"
#pragma hdrstop
//
// Values used for the initial and growth size
// of the string table data area
//
// (We start out with 6K, but remember that this includes the hash buckets.
// After you subtract their part of the buffer, you're left with ~4K bytes.)
//
#define STRING_TABLE_INITIAL_SIZE 6144
#define STRING_TABLE_GROWTH_SIZE 2048
#include "pshpack1.h"
typedef struct _STRING_NODE {
//
// This is stored as an offset instead of a pointer
// because the table can move as it's built
// The offset is from the beginning of the table
//
LONG NextOffset;
//
// This field must be last
//
TCHAR String[ANYSIZE_ARRAY];
} STRING_NODE, *PSTRING_NODE;
#include "poppack.h"
typedef struct _STRING_TABLE {
PUCHAR Data; // First HASH_BUCKET_COUNT DWORDS are StringNodeOffset array.
DWORD DataSize;
DWORD BufferSize;
MYLOCK Lock;
} STRING_TABLE, *PSTRING_TABLE;
#define LockTable(table) BeginSynchronizedAccess(&((table)->Lock))
#define UnlockTable(table) EndSynchronizedAccess(&((table)->Lock))
VOID
pStringTableComputeHashValue(
IN PTSTR String,
OUT PDWORD StringLength,
IN DWORD Flags,
OUT PDWORD HashValue
)
/*++
Routine Description:
Compute a hash value for a given string.
The algorithm simply adds up the unicode values for each
character in the string and then takes the result mod the
number of hash buckets.
Arguments:
String - supplies the string for which a hash value is desired.
StringLength - receives the number of characters in the string,
not including the terminating nul.
Flags - supplies flags controlling how the hashing is to be done. May be
a combination of the following values (all other bits ignored):
STRTAB_BUFFER_WRITEABLE - The caller-supplied buffer may be written to during
the string look-up. Specifying this flag improves the
performance of this API for case-insensitive string
additions. This flag is ignored for case-sensitive
string additions.
STRTAB_ALREADY_LOWERCASE - The supplied string has already been converted to
all lower-case (e.g., by calling CharLower), and
therefore doesn't need to be lower-cased in the
hashing routine. If this flag is supplied, then
STRTAB_BUFFER_WRITEABLE is ignored, since modifying
the caller's buffer is not required.
HashValue - receives the hash value.
Return Value:
None.
--*/
{
DWORD d, Length, Value;
if((Flags & (STRTAB_BUFFER_WRITEABLE | STRTAB_ALREADY_LOWERCASE)) == STRTAB_BUFFER_WRITEABLE) {
//
// Then the buffer is writeable, but isn't yet lower-case. Take care of that right now.
//
CharLower(String);
Flags |= STRTAB_ALREADY_LOWERCASE;
}
//
// Define a macro to ensure we don't get sign-extension when adding up character values.
//
#ifdef UNICODE
#define DWORD_FROM_TCHAR(x) ((DWORD)((WCHAR)(x)))
#else
#define DWORD_FROM_TCHAR(x) ((DWORD)((UCHAR)(x)))
#endif
if(Flags & STRTAB_ALREADY_LOWERCASE) {
for(Value=0,Length=lstrlen(String),d=0;
d < Length;
Value += DWORD_FROM_TCHAR(String[d++]));
} else {
//
// Make sure we don't get sign-extension on extended chars
// in String -- otherwise we get values like 0xffffffe4 passed
// to CharLower(), which thinks it's a pointer and faults.
//
for(Value=0,Length=lstrlen(String),d=0;
d < Length;
Value += DWORD_FROM_TCHAR(CharLower((PTSTR)(UCHAR)String[d++])));
}
*HashValue = Value % HASH_BUCKET_COUNT;
*StringLength = Length;
}
LONG
pStringTableLookUpString(
IN PVOID StringTable,
IN OUT PTSTR String,
OUT PDWORD StringLength,
OUT PDWORD HashValue, OPTIONAL
OUT PVOID *FindContext, OPTIONAL
IN DWORD Flags
)
/*++
Routine Description:
Locates a string in the string table, if present.
If the string is not present, this routine may optionally tell its
caller where the search stopped. This is useful for maintaining a
sorted order for the strings.
Arguments:
StringTable - supplies handle to string table to be searched
for the string
String - supplies the string to be looked up
StringLength - receives number of characters in the string, not
including the terminating nul.
HashValue - Optionally, receives hash value for the string. If this
parameter is specified, then FindContext must be specified as well.
FinalNode - Optionally, receives the context at which the search was
terminated. If HashValue is not specified, then this parameter
is ignored.
(NOTE: This is actually a PSTRING_NODE pointer, that is used
during new string addition. Since this routine has wider exposure
than just internal string table usage, this parameter is made into
a PVOID, so no one else has to have access to string table-internal
structures.
On return, this variable receives a pointer to the string node of
the node where the search stopped. If the string was found, then
this is a pointer to the string's node. If the string was not found,
then this is a pointer to the last string node whose string is
'less' (based on lstrcmpi) than the string we're looking for.
Note that this value may be NULL.)
Flags - supplies flags controlling how the string is to be located. May be
a combination of the following values:
STRTAB_CASE_INSENSITIVE - Search for the string case-insensitively.
STRTAB_CASE_SENSITIVE - Search for the string case-sensitively. This flag
overrides the STRTAB_CASE_INSENSITIVE flag.
STRTAB_BUFFER_WRITEABLE - The caller-supplied buffer may be written to during
the string look-up. Specifying this flag improves the
performance of this API for case-insensitive string
additions. This flag is ignored for case-sensitive
string additions.
In addition to the above public flags, the following private flag is also
allowed:
STRTAB_ALREADY_LOWERCASE - The supplied string has already been converted to
all lower-case (e.g., by calling CharLower), and
therefore doesn't need to be lower-cased in the
hashing routine. If this flag is supplied, then
STRTAB_BUFFER_WRITEABLE is ignored, since modifying
the caller's buffer is not required.
Return Value:
The return value is a value that uniquely identifies the string
within the string table, namely the offset of the string node
within the string table.
If the string could not be found the value is -1.
--*/
{
PSTRING_NODE node,prev;
int i;
PSTRING_TABLE stringTable = StringTable;
DWORD hashValue;
PSTRING_NODE FinalNode;
LONG rc = -1;
//
// If this is a case-sensitive lookup, then we want to reset the STRTAB_BUFFER_WRITEABLE
// flag, if present, since otherwise the string will get replaced with its all-lowercase
// counterpart.
//
if(Flags & STRTAB_CASE_SENSITIVE) {
Flags &= ~STRTAB_BUFFER_WRITEABLE;
}
//
// Compute hash value
//
pStringTableComputeHashValue(String,StringLength,Flags,&hashValue);
if(((PLONG)(stringTable->Data))[hashValue] == -1) {
//
// The string table contains no strings at the computed hash value.
//
FinalNode = NULL;
goto clean0;
}
//
// We know there's at least one string in the table with the computed
// hash value, so go find it. There's no previous node yet.
//
node = (PSTRING_NODE)(stringTable->Data + ((PLONG)(stringTable->Data))[hashValue]);
prev = NULL;
//
// Go looking through the string nodes for that hash value,
// looking through the string.
//
while(1) {
i = (Flags & STRTAB_CASE_SENSITIVE)
? lstrcmp(String,node->String)
: lstrcmpi(String,node->String);
if(i == 0) {
FinalNode = node;
rc = (PUCHAR)node - stringTable->Data;
break;
}
//
// If the string we are looking for is 'less' than the current
// string, we're done looking, because the strings are kept in
// a sorted order.
//
if(i < 0) {
FinalNode = prev;
break;
}
//
// The string we are looking for is 'greater' than the current string.
// Keep looking, unless we've reached the end of the table.
//
if(node->NextOffset == -1) {
FinalNode = node;
break;
} else {
prev = node;
node = (PSTRING_NODE)(stringTable->Data + node->NextOffset);
}
}
clean0:
if(HashValue) {
*HashValue = hashValue;
*FindContext = FinalNode;
}
return rc;
}
LONG
StringTableLookUpString(
IN PVOID StringTable,
IN OUT PTSTR String,
IN DWORD Flags
)
/*++
Routine Description:
Locates a string in the string table, if present.
Arguments:
StringTable - supplies handle to string table to be searched
for the string
String - supplies the string to be looked up. If STRTAB_BUFFER_WRITEABLE is
specified and a case-insensitive lookup is requested, then this buffer
will be all lower-case upon return.
Flags - supplies flags controlling how the string is to be located. May be
a combination of the following values:
STRTAB_CASE_INSENSITIVE - Search for the string case-insensitively.
STRTAB_CASE_SENSITIVE - Search for the string case-sensitively. This flag
overrides the STRTAB_CASE_INSENSITIVE flag.
STRTAB_BUFFER_WRITEABLE - The caller-supplied buffer may be written to during
the string look-up. Specifying this flag improves the
performance of this API for case-insensitive string
additions. This flag is ignored for case-sensitive
string additions.
In addition to the above public flags, the following private flag is also
allowed:
STRTAB_ALREADY_LOWERCASE - The supplied string has already been converted to
all lower-case (e.g., by calling CharLower), and
therefore doesn't need to be lower-cased in the
hashing routine. If this flag is supplied, then
STRTAB_BUFFER_WRITEABLE is ignored, since modifying
the caller's buffer is not required.
Return Value:
The return value is a value that uniquely identifies the string
within the string table.
If the string could not be found the value is -1.
--*/
{
DWORD StringLength, PrivateFlags, AlreadyLcFlag;
LONG rc;
if(!LockTable((PSTRING_TABLE)StringTable)) {
return(-1);
}
switch(Flags & ~STRTAB_ALREADY_LOWERCASE) { // ignore the 'already lower-case' flag here.
case STRTAB_CASE_INSENSITIVE :
case STRTAB_CASE_INSENSITIVE | STRTAB_BUFFER_WRITEABLE :
PrivateFlags = Flags;
break;
default :
PrivateFlags = STRTAB_CASE_SENSITIVE | (Flags & STRTAB_ALREADY_LOWERCASE);
}
rc = pStringTableLookUpString(
StringTable,
String,
&StringLength,
NULL,
NULL,
PrivateFlags
);
UnlockTable((PSTRING_TABLE)StringTable);
return(rc);
}
LONG
pStringTableAddString(
IN PVOID StringTable,
IN PTSTR String,
IN DWORD Flags
)
/*++
Routine Description:
Adds a string to the string table if the string is not already
in the string table. (Does not do locking!)
If the string is to be added case-insensitively, then it is
lower-cased, and added case-sensitively. Since lower-case characters
are 'less than' lower case ones (according to lstrcmp), this ensures that
a case-insensitive string will always appear in front of any of its
case-sensitive counterparts. This ensures that we always find the correct
string ID for things like section names.
Arguments:
StringTable - supplies handle to string table to be searched
for the string
String - supplies the string to be added
Flags - supplies flags controlling how the string is to be added, and
whether the caller-supplied buffer may be modified. May be a combination
of the following values:
STRTAB_CASE_INSENSITIVE - Add the string case-insensitively. The
specified string will be added to the string
table as all lower-case. This flag is overridden
if STRTAB_CASE_SENSITIVE is specified.
STRTAB_CASE_SENSITIVE - Add the string case-sensitively. This flag
overrides the STRTAB_CASE_INSENSITIVE flag.
STRTAB_BUFFER_WRITEABLE - The caller-supplied buffer may be written to during
the string-addition process. Specifying this flag
improves the performance of this API for case-
insensitive string additions. This flag is ignored
for case-sensitive string additions.
In addition to the above public flags, the following private flag is also
allowed:
STRTAB_ALREADY_LOWERCASE - The supplied string has already been converted to
all lower-case (e.g., by calling CharLower), and
therefore doesn't need to be lower-cased in the
hashing routine. If this flag is supplied, then
STRTAB_BUFFER_WRITEABLE is ignored, since modifying
the caller's buffer is not required.
Return Value:
The return value uniquely identifes the string within the string table.
It is -1 if the string was not in the string table but could not be added
(out of memory).
--*/
{
LONG rc;
PSTRING_TABLE stringTable = StringTable;
DWORD StringLength;
DWORD HashValue;
PSTRING_NODE PreviousNode,NewNode;
DWORD SpaceRequired;
PTSTR TempString = String;
BOOL FreeTempString = FALSE;
if(!(Flags & STRTAB_CASE_SENSITIVE)) {
if(!(Flags & STRTAB_ALREADY_LOWERCASE)) {
if(Flags == STRTAB_CASE_INSENSITIVE) {
//
// Then the string is to be added case-insensitively, but the caller
// doesn't want us to write to their buffer. Allocate one of our own.
//
if(TempString = DuplicateString(String)) {
FreeTempString = TRUE;
} else {
//
// We couldn't allocate space for our duplicated string. Since we'll
// only consider exact matches (where the strings are all lower-case),
// we're stuck, since we can't lower-case the buffer in place.
//
return -1;
}
}
//
// Lower-case the buffer.
//
CharLower(TempString);
}
Flags = STRTAB_CASE_SENSITIVE | STRTAB_ALREADY_LOWERCASE;
}
try {
//
// The string might already be in there.
//
rc = pStringTableLookUpString(
StringTable,
TempString,
&StringLength,
&HashValue,
&PreviousNode,
Flags
);
if(rc != -1) {
return(rc);
}
//
// Figure out how much space is required to hold this entry.
// This is the size of a STRING_NODE plus the length of the string.
//
SpaceRequired = sizeof(STRING_NODE) + ((StringLength+1-ANYSIZE_ARRAY)*sizeof(TCHAR));
//
// Make sure things stay aligned within the table
//
if(SpaceRequired % sizeof(DWORD)) {
SpaceRequired += sizeof(DWORD) - (SpaceRequired % sizeof(DWORD));
}
//
// See if there is currently enough room to add the string to the table.
//
if(stringTable->DataSize + SpaceRequired > stringTable->BufferSize) {
//
// Grow the string table.
//
PVOID p;
p = MyRealloc(stringTable->Data,stringTable->BufferSize+STRING_TABLE_GROWTH_SIZE);
if(!p) {
return(-1);
}
//
// Adjust previous node pointer.
//
if(PreviousNode) {
PreviousNode = (PSTRING_NODE)((PUCHAR)p + ((PUCHAR)PreviousNode-(PUCHAR)stringTable->Data));
}
stringTable->Data = p;
stringTable->BufferSize += STRING_TABLE_GROWTH_SIZE;
}
//
// Stick the string in the string table buffer.
//
NewNode = (PSTRING_NODE)(stringTable->Data + stringTable->DataSize);
if(PreviousNode) {
NewNode->NextOffset = PreviousNode->NextOffset;
PreviousNode->NextOffset = (LONG)NewNode - (LONG)stringTable->Data;
} else {
NewNode->NextOffset = ((PLONG)(stringTable->Data))[HashValue];
((PLONG)(stringTable->Data))[HashValue] = (LONG)NewNode - (LONG)stringTable->Data;
}
lstrcpy(NewNode->String,TempString);
stringTable->DataSize += SpaceRequired;
rc = (LONG)NewNode - (LONG)stringTable->Data;
} except(EXCEPTION_EXECUTE_HANDLER) {
rc = -1;
}
if(FreeTempString) {
MyFree(TempString);
}
return rc;
}
LONG
StringTableAddString(
IN PVOID StringTable,
IN PTSTR String,
IN DWORD Flags
)
/*++
Routine Description:
Adds a string to the string table if the string is not already
in the string table.
Arguments:
StringTable - supplies handle to string table to be searched
for the string
String - supplies the string to be added
Flags - supplies flags controlling how the string is to be added, and
whether the caller-supplied buffer may be modified. May be a combination
of the following values:
STRTAB_CASE_INSENSITIVE - Add the string case-insensitively. The
specified string will be added to the string
table as all lower-case. This flag is overridden
if STRTAB_CASE_SENSITIVE is specified.
STRTAB_CASE_SENSITIVE - Add the string case-sensitively. This flag
overrides the STRTAB_CASE_INSENSITIVE flag.
STRTAB_BUFFER_WRITEABLE - The caller-supplied buffer may be written to during
the string-addition process. Specifying this flag
improves the performance of this API for case-
insensitive string additions. This flag is ignored
for case-sensitive string additions.
In addition to the above public flags, the following private flag is also
allowed:
STRTAB_ALREADY_LOWERCASE - The supplied string has already been converted to
all lower-case (e.g., by calling CharLower), and
therefore doesn't need to be lower-cased in the
hashing routine. If this flag is supplied, then
STRTAB_BUFFER_WRITEABLE is ignored, since modifying
the caller's buffer is not required.
Return Value:
The return value uniquely identifes the string within the string table.
It is -1 if the string was not in the string table but could not be added
(out of memory).
--*/
{
LONG rc;
DWORD PrivateFlags;
if(!LockTable((PSTRING_TABLE)StringTable)) {
return(-1);
}
switch(Flags & ~STRTAB_ALREADY_LOWERCASE) {
case STRTAB_CASE_INSENSITIVE :
case STRTAB_CASE_INSENSITIVE | STRTAB_BUFFER_WRITEABLE :
PrivateFlags = Flags;
break;
default :
PrivateFlags = STRTAB_CASE_SENSITIVE | (Flags & STRTAB_ALREADY_LOWERCASE);
}
rc = pStringTableAddString(StringTable, String, PrivateFlags);
UnlockTable((PSTRING_TABLE)StringTable);
return(rc);
}
PTSTR
pStringTableStringFromId(
IN PVOID StringTable,
IN LONG StringId
)
/*++
Routine Description:
Given a string ID returned when a string was added or looked up,
return a pointer to the actual string. (This is exactly the same
as StringTableStringFromId, except that it doesn't do locking.)
Arguments:
StringTable - supplies a pointer to the string table containing the
string to be retrieved.
StringId - supplies a string id returned from StringTableAddString
or StringTableLookUpString.
Return Value:
Pointer to string data. The caller must not write into or otherwise
alter the string.
--*/
{
return ((PSTRING_NODE)(((PSTRING_TABLE)StringTable)->Data + StringId))->String;
}
PTSTR
StringTableStringFromId(
IN PVOID StringTable,
IN LONG StringId
)
/*++
Routine Description:
Given a string ID returned when a string was added or looked up,
return a pointer to the actual string.
Arguments:
StringTable - supplies a pointer to the string table containing the
string to be retrieved.
StringId - supplies a string id returned from StringTableAddString
or StringTableLookUpString.
Return Value:
Pointer to string data. The caller must not write into or otherwise
alter the string.
--*/
{
PTSTR p;
if(!LockTable((PSTRING_TABLE)StringTable)) {
return(NULL);
}
p = ((PSTRING_NODE)(((PSTRING_TABLE)StringTable)->Data + StringId))->String;
UnlockTable((PSTRING_TABLE)StringTable);
return(p);
}
VOID
StringTableTrim(
IN PVOID StringTable
)
/*++
Routine Description:
Free any memory currently allocated for the string table
but not currently used.
This is useful after all strings have been added to a string table
because the string table grows by a fixed block size as it's being built.
Arguments:
StringTable - supplies a string table handle returned from
a call to StringTableInitialize().
Return Value:
None.
--*/
{
if(!LockTable((PSTRING_TABLE)StringTable)) {
return;
}
pStringTableTrim(StringTable);
UnlockTable((PSTRING_TABLE)StringTable);
}
VOID
pStringTableTrim(
IN PVOID StringTable
)
/*++
Routine Description:
Free any memory currently allocated for the string table
but not currently used.
This is useful after all strings have been added to a string table
because the string table grows by a fixed block size as it's being built.
THIS ROUTINE DOES NOT DO LOCKING!
Arguments:
StringTable - supplies a string table handle returned from
a call to StringTableInitialize().
Return Value:
None.
--*/
{
PSTRING_TABLE stringTable = StringTable;
PVOID p;
//
// If the realloc failed the original block is not freed,
// so we don't really care.
//
if(p = MyRealloc(stringTable->Data, stringTable->DataSize)) {
stringTable->Data = p;
stringTable->BufferSize = stringTable->DataSize;
}
}
PVOID
StringTableInitialize(
VOID
)
/*++
Routine Description:
Create and initialize a string table.
Arguments:
None.
Return Value:
NULL if the string table could not be created (out of memory).
Otherwise returns an opaque value that references the string
table in other StringTable calls.
Remarks:
This routine returns a string table with synchronization locks
required by all public StringTable APIs. If the string table
is to be enclosed in a structure that has its own locking
(e.g., HINF, HDEVINFO), then the private version of this API
may be called, which will not create locks for the string table.
--*/
{
PSTRING_TABLE StringTable;
if(StringTable = (PSTRING_TABLE)pStringTableInitialize()) {
if(InitializeSynchronizedAccess(&StringTable->Lock)) {
return StringTable;
}
pStringTableDestroy(StringTable);
}
return NULL;
}
PVOID
pStringTableInitialize(
VOID
)
/*++
Routine Description:
Create and initialize a string table.
THIS ROUTINE DOES NOT INITIALIZE STRING TABLE SYNCHRONIZATION LOCKS!
Arguments:
None.
Return Value:
NULL if the string table could not be created (out of memory).
Otherwise returns an opaque value that references the string
table in other StringTable calls.
Remarks:
The string table returned from this API may not be used as-is with the
public StringTable APIs--it must have its synchronization locks initialized
by the public form of this API.
--*/
{
UINT u;
PSTRING_TABLE stringTable;
//
// Allocate a string table
//
if(stringTable = MyMalloc(sizeof(STRING_TABLE))) {
ZeroMemory(stringTable,sizeof(STRING_TABLE));
//
// Allocate space for the string table data.
//
if(stringTable->Data = MyMalloc(STRING_TABLE_INITIAL_SIZE)) {
stringTable->BufferSize = STRING_TABLE_INITIAL_SIZE;
//
// Initialize the hash table
//
for(u=0; u<HASH_BUCKET_COUNT; u++) {
((PLONG)(stringTable->Data))[u] = -1;
}
//
// Set the DataSize to the size of the StringNodeOffset list, so
// we'll start adding new strings after it.
//
stringTable->DataSize = HASH_BUCKET_COUNT * sizeof(LONG);
return(stringTable);
}
MyFree(stringTable);
}
return(NULL);
}
VOID
StringTableDestroy(
IN PVOID StringTable
)
/*++
Routine Description:
Destroy a string table, freeing all resources it uses.
Arguments:
StringTable - supplies a string table handle returned from
a call to StringTableInitialize().
Return Value:
None.
--*/
{
if(!LockTable((PSTRING_TABLE)StringTable)) {
return;
}
DestroySynchronizedAccess(&(((PSTRING_TABLE)StringTable)->Lock));
pStringTableDestroy(StringTable);
}
VOID
pStringTableDestroy(
IN PVOID StringTable
)
/*++
Routine Description:
Destroy a string table, freeing all resources it uses.
THIS ROUTINE DOES NOT DO LOCKING!
Arguments:
StringTable - supplies a string table handle returned from
a call to StringTableInitialize().
Return Value:
None.
--*/
{
MyFree(((PSTRING_TABLE)StringTable)->Data);
MyFree(StringTable);
}
PVOID
StringTableDuplicate(
IN PVOID StringTable
)
/*++
Routine Description:
Create an independent dupplicate of a string table.
Arguments:
StringTable - supplies a string table handle of string table to duplicate.
Return Value:
Handle for new string table, NULL if out of memory.
--*/
{
PSTRING_TABLE New;
if(!LockTable((PSTRING_TABLE)StringTable)) {
return(NULL);
}
if(New = (PSTRING_TABLE)pStringTableDuplicate(StringTable)) {
if(!InitializeSynchronizedAccess(&New->Lock)) {
pStringTableDestroy(New);
New = NULL;
}
}
UnlockTable((PSTRING_TABLE)StringTable);
return New;
}
PVOID
pStringTableDuplicate(
IN PVOID StringTable
)
/*++
Routine Description:
Create an independent duplicate of a string table.
THIS ROUTINE DOES NOT DO LOCKING!
Arguments:
StringTable - supplies a string table handle of string table to duplicate.
Return Value:
Handle for new string table, NULL if out of memory or buffer copy failure.
Remarks:
This routine does not initialize synchronization locks for the duplicate--these
fields are initialized to NULL.
--*/
{
PSTRING_TABLE New;
PSTRING_TABLE stringTable = StringTable;
BOOL Success;
if(New = MyMalloc(sizeof(STRING_TABLE))) {
CopyMemory(New,StringTable,sizeof(STRING_TABLE));
//
// Allocate space for the string table data.
//
if(New->Data = MyMalloc(stringTable->DataSize)) {
//
// Surround memory copy in try/except, since we may be dealing with
// a string table contained in a PNF, in which case the buffer is
// in a memory-mapped file.
//
Success = TRUE; // assume success unless we get an inpage error...
try {
CopyMemory(New->Data, stringTable->Data, stringTable->DataSize);
} except(EXCEPTION_EXECUTE_HANDLER) {
Success = FALSE;
}
if(Success) {
New->BufferSize = New->DataSize;
ZeroMemory(&New->Lock, sizeof(MYLOCK));
return New;
}
MyFree(New->Data);
}
MyFree(New);
}
return NULL;
}
PVOID
InitializeStringTableFromPNF(
IN PPNF_HEADER PnfHeader
)
{
PSTRING_TABLE StringTable;
BOOL WasLoaded = TRUE;
//
// Allocate a string table
//
if(!(StringTable = MyMalloc(sizeof(STRING_TABLE)))) {
return NULL;
}
try {
StringTable->Data = (PUCHAR)PnfHeader + PnfHeader->StringTableBlockOffset;
StringTable->DataSize = StringTable->BufferSize = PnfHeader->StringTableBlockSize;
//
// Clear the Lock structure, because PNF string tables can only be accessed
// internally, via their associated INF.
//
StringTable->Lock.Handles[0] = StringTable->Lock.Handles[1] = NULL;
} except(EXCEPTION_EXECUTE_HANDLER) {
WasLoaded = FALSE;
}
if(WasLoaded) {
return StringTable;
} else {
MyFree(StringTable);
return NULL;
}
}
DWORD
pStringTableGetDataBlock(
IN PVOID StringTable,
OUT PVOID *StringTableBlock
)
{
*StringTableBlock = (PVOID)(((PSTRING_TABLE)StringTable)->Data);
return ((PSTRING_TABLE)StringTable)->DataSize;
}