mirror of https://github.com/tongzx/nt5src
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.
1819 lines
44 KiB
1819 lines
44 KiB
/*++
|
|
|
|
Copyright (c) 1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
objstr.c
|
|
|
|
Abstract:
|
|
|
|
Implements a set of APIs to handle the string representation of nodes/leafs of a tree
|
|
|
|
Author:
|
|
|
|
03-Jan-2000 Ovidiu Temereanca (ovidiut) - File creation.
|
|
|
|
Revision History:
|
|
|
|
<alias> <date> <comments>
|
|
|
|
--*/
|
|
|
|
/*
|
|
+-------+
|
|
| root1 | Level 1
|
|
+-------+
|
|
/ \
|
|
/ \
|
|
+---------+ (-------)
|
|
| node1 | ( leaf1 ) Level 2
|
|
+---------+ (-------)
|
|
/ | \ \__________
|
|
/ | \ \
|
|
+-------+ +-------+ (-------) (-------)
|
|
| node2 | | node3 | ( leaf2 ) ( leaf3 ) Level 3
|
|
+-------+ +-------+ (-------) (-------)
|
|
/ \
|
|
/ \
|
|
+-------+ (-------)
|
|
| node4 | ( leaf4 ) Level 4
|
|
+-------+ (-------)
|
|
/ \
|
|
/ \
|
|
(-------) (-------)
|
|
( leaf5 ) ( leaf6 ) Level 5
|
|
(-------) (-------)
|
|
|
|
|
|
The string representation of some tree elements above:
|
|
|
|
root1
|
|
root1 <leaf1>
|
|
root1\node1
|
|
root1\node1 <leaf2>
|
|
root1\node1 <leaf3>
|
|
|
|
*/
|
|
|
|
#include "pch.h"
|
|
|
|
//
|
|
// Includes
|
|
//
|
|
|
|
// None
|
|
|
|
#define DBG_OBJSTR "ObjStr"
|
|
|
|
//
|
|
// Strings
|
|
//
|
|
|
|
#define S_OBJSTR "ObjStr"
|
|
|
|
//
|
|
// Constants
|
|
//
|
|
|
|
#define OBJSTR_LEAF_HEADA '<'
|
|
#define OBJSTR_LEAF_HEADW L'<'
|
|
|
|
#define OBJSTR_LEAF_TAILA '>'
|
|
#define OBJSTR_LEAF_TAILW L'>'
|
|
|
|
#define OBJSTR_SEPARATORA ' '
|
|
#define OBJSTR_SEPARATORW L' '
|
|
|
|
|
|
//
|
|
// Macros
|
|
//
|
|
|
|
#define pObjStrAllocateMemory(Size) PmGetMemory (g_ObjStrPool, Size)
|
|
|
|
#define pObjStrFreeMemory(Buffer) if (/*lint --e(774)*/Buffer) PmReleaseMemory (g_ObjStrPool, Buffer)
|
|
|
|
//
|
|
// Types
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Globals
|
|
//
|
|
|
|
PMHANDLE g_ObjStrPool;
|
|
|
|
//
|
|
// Macro expansion list
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Private function prototypes
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Macro expansion definition
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Code
|
|
//
|
|
|
|
BOOL
|
|
ObsInitialize (
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
ObsInitialize initializes this library.
|
|
|
|
Arguments:
|
|
|
|
none
|
|
|
|
Return Value:
|
|
|
|
TRUE if the init was successful.
|
|
FALSE if not. GetLastError() returns extended error info.
|
|
|
|
--*/
|
|
|
|
{
|
|
g_ObjStrPool = PmCreateNamedPool (S_OBJSTR);
|
|
return g_ObjStrPool != NULL;
|
|
}
|
|
|
|
|
|
VOID
|
|
ObsTerminate (
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
ObsTerminate is called to free resources used by this lib.
|
|
|
|
Arguments:
|
|
|
|
none
|
|
|
|
Return Value:
|
|
|
|
none
|
|
|
|
--*/
|
|
|
|
{
|
|
if (g_ObjStrPool) {
|
|
PmDestroyPool (g_ObjStrPool);
|
|
g_ObjStrPool = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
pExtractStringAB is a private function that creates a new string in the given pool,
|
|
using a source string and a limit to copy up to.
|
|
|
|
Arguments:
|
|
|
|
Start - Specifies the source string
|
|
End - Specifies the point to copy up to (excluding it), within the same string
|
|
Pool - Specifies the pool to use for allocation
|
|
|
|
Return Value:
|
|
|
|
A pointer to the newly created string
|
|
|
|
--*/
|
|
|
|
PSTR
|
|
pExtractStringABA (
|
|
IN PCSTR Start,
|
|
IN PCSTR End,
|
|
IN PMHANDLE Pool
|
|
)
|
|
{
|
|
PSTR p;
|
|
|
|
p = PmGetMemory (Pool, (DWORD)(End - Start + 1) * DWSIZEOF (CHAR));
|
|
StringCopyABA (p, Start, End);
|
|
return p;
|
|
}
|
|
|
|
|
|
PWSTR
|
|
pExtractStringABW (
|
|
IN PCWSTR Start,
|
|
IN PCWSTR End,
|
|
IN PMHANDLE Pool
|
|
)
|
|
{
|
|
PWSTR p;
|
|
|
|
p = PmGetMemory (Pool, (DWORD)(End - Start + 1) * DWSIZEOF (WCHAR));
|
|
StringCopyABW (p, Start, End);
|
|
return p;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
ObsFree frees the given object from the private pool
|
|
|
|
Arguments:
|
|
|
|
EncodedObject - Specifies the source string
|
|
End - Specifies the point to copy up to (excluding it), within the same string
|
|
Pool - Specifies the pool to use for allocation
|
|
|
|
Return Value:
|
|
|
|
A pointer to the newly created string
|
|
|
|
--*/
|
|
|
|
VOID
|
|
ObsFreeA (
|
|
IN PCSTR EncodedObject
|
|
)
|
|
{
|
|
pObjStrFreeMemory ((PVOID)EncodedObject);
|
|
}
|
|
|
|
|
|
VOID
|
|
ObsFreeW (
|
|
IN PCWSTR EncodedObject
|
|
)
|
|
{
|
|
pObjStrFreeMemory ((PVOID)EncodedObject);
|
|
}
|
|
|
|
BOOL
|
|
ObsEncodeStringA (
|
|
PSTR Destination,
|
|
PCSTR Source
|
|
)
|
|
{
|
|
MBCHAR ch;
|
|
|
|
while (*Source) {
|
|
ch = _mbsnextc (Source);
|
|
if (_mbschr (EscapedCharsA, ch)) {
|
|
*Destination = '^';
|
|
Destination ++;
|
|
}
|
|
// now copy the multibyte character
|
|
if (IsLeadByte (*Source)) {
|
|
*Destination = *Source;
|
|
Destination ++;
|
|
Source ++;
|
|
}
|
|
*Destination = *Source;
|
|
Destination ++;
|
|
Source ++;
|
|
}
|
|
*Destination = 0;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
ObsEncodeStringW (
|
|
PWSTR Destination,
|
|
PCWSTR Source
|
|
)
|
|
{
|
|
while (*Source) {
|
|
if (wcschr (EscapedCharsW, *Source)) {
|
|
*Destination = L'^';
|
|
Destination ++;
|
|
}
|
|
*Destination = *Source;
|
|
Destination ++;
|
|
Source ++;
|
|
}
|
|
*Destination = 0;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
ObsDecodeStringA (
|
|
PSTR Destination,
|
|
PCSTR Source
|
|
)
|
|
{
|
|
BOOL escaping = FALSE;
|
|
|
|
while (*Source) {
|
|
if ((_mbsnextc (Source) == '^') && (!escaping)) {
|
|
escaping = TRUE;
|
|
Source ++;
|
|
} else {
|
|
escaping = FALSE;
|
|
// now copy the multibyte character
|
|
if (IsLeadByte (*Source)) {
|
|
*Destination = *Source;
|
|
Destination ++;
|
|
Source ++;
|
|
}
|
|
*Destination = *Source;
|
|
Destination ++;
|
|
Source ++;
|
|
}
|
|
}
|
|
*Destination = 0;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
ObsDecodeStringW (
|
|
PWSTR Destination,
|
|
PCWSTR Source
|
|
)
|
|
{
|
|
BOOL escaping = FALSE;
|
|
|
|
while (*Source) {
|
|
if ((*Source == L'^') && (!escaping)) {
|
|
escaping = TRUE;
|
|
Source ++;
|
|
} else {
|
|
escaping = FALSE;
|
|
*Destination = *Source;
|
|
Destination ++;
|
|
Source ++;
|
|
}
|
|
}
|
|
*Destination = 0;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
ObsSplitObjectStringEx splits the given encoded object into components: node and
|
|
leaf. Strings are allocated from the given pool
|
|
|
|
Arguments:
|
|
|
|
EncodedObject - Specifies the source object string
|
|
DecodedNode - Receives the decoded node part; optional
|
|
DecodedLeaf - Receives the decoded leaf part; optional
|
|
Pool - Specifies the pool to use for allocation; optional; if not specified,
|
|
the module pool will be used and ObsFree needs to be called for them
|
|
to be freed
|
|
|
|
Return Value:
|
|
|
|
TRUE if the source object has a legal format and it has been split into components
|
|
|
|
--*/
|
|
|
|
BOOL
|
|
ObsSplitObjectStringExA (
|
|
IN PCSTR EncodedObject,
|
|
OUT PSTR* DecodedNode, OPTIONAL
|
|
OUT PSTR* DecodedLeaf, OPTIONAL
|
|
IN PMHANDLE Pool, OPTIONAL
|
|
IN BOOL DecodeStrings
|
|
)
|
|
{
|
|
PCSTR p;
|
|
PCSTR q;
|
|
PCSTR nodeTerm;
|
|
PSTR leaf = NULL;
|
|
PCSTR lastWack = NULL;
|
|
PCSTR lastStar = NULL;
|
|
|
|
MYASSERT (EncodedObject);
|
|
if (!EncodedObject) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (!Pool) {
|
|
Pool = g_ObjStrPool;
|
|
}
|
|
|
|
p = EncodedObject;
|
|
|
|
if (*p == '\\') {
|
|
//
|
|
// must be UNC format; check for syntax
|
|
//
|
|
p++;
|
|
if (*p != '\\') {
|
|
DEBUGMSGA ((
|
|
DBG_OBJSTR,
|
|
"ObsSplitObjectStringExA: relative paths not supported: %s",
|
|
EncodedObject
|
|
));
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
while (*p && *p != OBJSTR_LEAF_HEADA) {
|
|
if (*p == OBJSTR_SEPARATORA) {
|
|
q = p + 1;
|
|
while (*q == OBJSTR_SEPARATORA) {
|
|
q++;
|
|
}
|
|
if (*q == 0 || *q == OBJSTR_LEAF_HEADA) {
|
|
break;
|
|
}
|
|
p = q;
|
|
}
|
|
if (*p == '\\') {
|
|
if ((UBINT)p == (UBINT)lastWack + 1) {
|
|
//
|
|
// two wacks in a row? no way
|
|
//
|
|
DEBUGMSGA ((
|
|
DBG_OBJSTR,
|
|
"ObsSplitObjectStringExA: Bad EncodedObject: %s",
|
|
EncodedObject
|
|
));
|
|
return FALSE;
|
|
}
|
|
lastWack = p;
|
|
} else if (*p == '*') {
|
|
lastStar = p;
|
|
}
|
|
p = CharNextA (p);
|
|
}
|
|
|
|
if (p == EncodedObject) {
|
|
DEBUGMSGA ((
|
|
DBG_OBJSTR,
|
|
"ObsSplitObjectStringExA: Bad EncodedObject: %s",
|
|
EncodedObject
|
|
));
|
|
return FALSE;
|
|
}
|
|
|
|
if (lastWack && lastWack + 1 == p && lastStar && lastStar + 1 != lastWack) {
|
|
nodeTerm = lastWack;
|
|
} else {
|
|
nodeTerm = p;
|
|
}
|
|
|
|
while (*p == OBJSTR_SEPARATORA) {
|
|
//
|
|
// *p is one byte wide
|
|
//
|
|
p++;
|
|
}
|
|
|
|
if (*p) {
|
|
|
|
if (*p != OBJSTR_LEAF_HEADA) {
|
|
//
|
|
// wrong start
|
|
//
|
|
DEBUGMSGA ((
|
|
DBG_OBJSTR,
|
|
"ObsSplitObjectStringExA: Bad EncodedObject: %s",
|
|
EncodedObject
|
|
));
|
|
return FALSE;
|
|
}
|
|
|
|
q = p + 1;
|
|
while (*q != OBJSTR_LEAF_TAILA) {
|
|
if (*q == 0) {
|
|
//
|
|
// incorrectly terminated
|
|
//
|
|
DEBUGMSGA ((
|
|
DBG_OBJSTR,
|
|
"ObsSplitObjectStringExA: Bad EncodedObject: %s",
|
|
EncodedObject
|
|
));
|
|
return FALSE;
|
|
}
|
|
q = CharNextA (q);
|
|
}
|
|
|
|
if (*(q + 1) != 0) {
|
|
//
|
|
// must end after the terminating char
|
|
//
|
|
DEBUGMSGA ((
|
|
DBG_OBJSTR,
|
|
"ObsSplitObjectStringExA: Bad EncodedObject: \"%s\"; chars after the leaf",
|
|
EncodedObject
|
|
));
|
|
return FALSE;
|
|
}
|
|
|
|
if (DecodedLeaf) {
|
|
leaf = pExtractStringABA (p + 1, q, Pool);
|
|
if (DecodeStrings) {
|
|
//
|
|
// decode chars
|
|
//
|
|
ObsDecodeStringA (leaf, leaf);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (DecodedLeaf) {
|
|
*DecodedLeaf = leaf;
|
|
}
|
|
|
|
if (DecodedNode) {
|
|
*DecodedNode = pExtractStringABA (EncodedObject, nodeTerm, Pool);
|
|
if (DecodeStrings) {
|
|
//
|
|
// decode chars
|
|
//
|
|
ObsDecodeStringA (*DecodedNode, *DecodedNode);
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
ObsSplitObjectStringExW (
|
|
IN PCWSTR EncodedObject,
|
|
OUT PWSTR* DecodedNode, OPTIONAL
|
|
OUT PWSTR* DecodedLeaf, OPTIONAL
|
|
IN PMHANDLE Pool, OPTIONAL
|
|
IN BOOL DecodeStrings
|
|
)
|
|
{
|
|
PCWSTR p;
|
|
PCWSTR q;
|
|
PCWSTR nodeTerm;
|
|
PWSTR leaf = NULL;
|
|
PCWSTR lastWack = NULL;
|
|
PCWSTR lastStar = NULL;
|
|
|
|
MYASSERT (EncodedObject);
|
|
if (!EncodedObject) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (!Pool) {
|
|
Pool = g_ObjStrPool;
|
|
}
|
|
|
|
p = EncodedObject;
|
|
|
|
if (*p == L'\\') {
|
|
//
|
|
// must be UNC format; check for syntax
|
|
//
|
|
p++;
|
|
if (*p != L'\\') {
|
|
DEBUGMSGW ((
|
|
DBG_OBJSTR,
|
|
"ObsSplitObjectStringExW: relative paths not supported: %s",
|
|
EncodedObject
|
|
));
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
while (*p && *p != OBJSTR_LEAF_HEADW) {
|
|
if (*p == OBJSTR_SEPARATORW) {
|
|
q = p + 1;
|
|
while (*q == OBJSTR_SEPARATORW) {
|
|
q++;
|
|
}
|
|
if (*q == 0 || *q == OBJSTR_LEAF_HEADW) {
|
|
break;
|
|
}
|
|
p = q;
|
|
}
|
|
if (*p == L'\\') {
|
|
if ((UBINT)p == (UBINT)lastWack + 1) {
|
|
//
|
|
// two wacks in a row? no way
|
|
//
|
|
DEBUGMSGW ((
|
|
DBG_OBJSTR,
|
|
"ObsSplitObjectStringExW: Bad EncodedObject: %s",
|
|
EncodedObject
|
|
));
|
|
return FALSE;
|
|
}
|
|
lastWack = p;
|
|
} else if (*p == L'*') {
|
|
lastStar = p;
|
|
}
|
|
p++;
|
|
}
|
|
|
|
if (p == EncodedObject) {
|
|
DEBUGMSGW ((
|
|
DBG_OBJSTR,
|
|
"ObsSplitObjectStringExW: Bad EncodedObject: %s",
|
|
EncodedObject
|
|
));
|
|
return FALSE;
|
|
}
|
|
|
|
if (lastWack && lastWack + 1 == p && lastStar && lastStar + 1 != lastWack) {
|
|
nodeTerm = lastWack;
|
|
} else {
|
|
nodeTerm = p;
|
|
}
|
|
|
|
while (*p == OBJSTR_SEPARATORW) {
|
|
//
|
|
// *p is one WCHAR wide
|
|
//
|
|
p++;
|
|
}
|
|
|
|
if (*p) {
|
|
|
|
if (*p != OBJSTR_LEAF_HEADW) {
|
|
//
|
|
// wrong start
|
|
//
|
|
DEBUGMSGW ((
|
|
DBG_OBJSTR,
|
|
"ObsSplitObjectStringExW: Bad EncodedObject: %s",
|
|
EncodedObject
|
|
));
|
|
return FALSE;
|
|
}
|
|
|
|
q = p + 1;
|
|
while (*q != OBJSTR_LEAF_TAILW) {
|
|
if (*q == 0) {
|
|
//
|
|
// incorrectly terminated
|
|
//
|
|
DEBUGMSGW ((
|
|
DBG_OBJSTR,
|
|
"ObsSplitObjectStringExW: Bad EncodedObject: %s",
|
|
EncodedObject
|
|
));
|
|
return FALSE;
|
|
}
|
|
q++;
|
|
}
|
|
|
|
if (*(q + 1) != 0) {
|
|
//
|
|
// must end after the terminating char
|
|
//
|
|
DEBUGMSGW ((
|
|
DBG_OBJSTR,
|
|
"ObsSplitObjectStringExW: Bad EncodedObject: \"%s\"; chars after the leaf",
|
|
EncodedObject
|
|
));
|
|
return FALSE;
|
|
}
|
|
|
|
if (DecodedLeaf) {
|
|
leaf = pExtractStringABW (p + 1, q, Pool);
|
|
if (DecodeStrings) {
|
|
//
|
|
// decode chars
|
|
//
|
|
ObsDecodeStringW (leaf, leaf);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (DecodedLeaf) {
|
|
*DecodedLeaf = leaf;
|
|
}
|
|
|
|
if (DecodedNode) {
|
|
*DecodedNode = pExtractStringABW (EncodedObject, nodeTerm, Pool);
|
|
if (DecodeStrings) {
|
|
//
|
|
// decode chars
|
|
//
|
|
ObsDecodeStringW (*DecodedNode, *DecodedNode);
|
|
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
ObsBuildEncodedObjectStringEx builds an encoded object from components: node and
|
|
leaf. The string is allocated from the module's pool
|
|
|
|
Arguments:
|
|
|
|
DecodedNode - Specifies the decoded node part
|
|
DecodedLeaf - Specifies the decoded leaf part; optional
|
|
EncodeObject - Specifies TRUE if the resulting object needs to be encoded using
|
|
encoding rules
|
|
|
|
Return Value:
|
|
|
|
Pointer to the newly created object string
|
|
|
|
--*/
|
|
|
|
PSTR
|
|
ObsBuildEncodedObjectStringExA (
|
|
IN PCSTR DecodedNode,
|
|
IN PCSTR DecodedLeaf, OPTIONAL
|
|
IN BOOL EncodeObject
|
|
)
|
|
{
|
|
PSTR encodedNode;
|
|
PSTR encodedLeaf;
|
|
PSTR encodedString;
|
|
|
|
MYASSERT (DecodedNode);
|
|
if (!DecodedNode) {
|
|
return NULL;
|
|
}
|
|
//
|
|
// at most, one byte char will be expanded to 4 bytes (4 times)
|
|
//
|
|
if (EncodeObject) {
|
|
encodedNode = pObjStrAllocateMemory (4 * ByteCountA (DecodedNode) + DWSIZEOF(CHAR));
|
|
ObsEncodeStringA (encodedNode, DecodedNode);
|
|
} else {
|
|
encodedNode = DuplicateTextExA (g_ObjStrPool, DecodedNode, 0, NULL);
|
|
}
|
|
|
|
if (!DecodedLeaf) {
|
|
return encodedNode;
|
|
}
|
|
|
|
if (EncodeObject) {
|
|
encodedLeaf = pObjStrAllocateMemory (4 * ByteCountA (DecodedLeaf) + DWSIZEOF(CHAR));
|
|
ObsEncodeStringA (encodedLeaf, DecodedLeaf);
|
|
} else {
|
|
encodedLeaf = DuplicateTextExA (g_ObjStrPool, DecodedLeaf, 0, NULL);
|
|
}
|
|
|
|
//
|
|
// preferred format: %1 <%2> %1 - Node, %2 - Leaf
|
|
//
|
|
encodedString = pObjStrAllocateMemory (
|
|
ByteCountA (encodedNode) +
|
|
DWSIZEOF (" <>") +
|
|
ByteCountA (encodedLeaf)
|
|
);
|
|
wsprintfA (
|
|
encodedString,
|
|
"%s %c%s%c",
|
|
encodedNode,
|
|
OBJSTR_LEAF_HEADA,
|
|
encodedLeaf,
|
|
OBJSTR_LEAF_TAILA
|
|
);
|
|
|
|
pObjStrFreeMemory (encodedNode);
|
|
pObjStrFreeMemory (encodedLeaf);
|
|
|
|
return encodedString;
|
|
}
|
|
|
|
|
|
PWSTR
|
|
ObsBuildEncodedObjectStringExW (
|
|
IN PCWSTR DecodedNode,
|
|
IN PCWSTR DecodedLeaf, OPTIONAL
|
|
IN BOOL EncodeObject
|
|
)
|
|
{
|
|
PWSTR encodedNode;
|
|
PWSTR encodedLeaf;
|
|
PWSTR encodedString;
|
|
|
|
MYASSERT (DecodedNode);
|
|
if (!DecodedNode) {
|
|
return NULL;
|
|
}
|
|
//
|
|
// at most, one wide char will be expanded to 4 wide chars (4 times)
|
|
//
|
|
if (EncodeObject) {
|
|
encodedNode = pObjStrAllocateMemory (4 * ByteCountW (DecodedNode) + DWSIZEOF(WCHAR));
|
|
ObsEncodeStringW (encodedNode, DecodedNode);
|
|
} else {
|
|
encodedNode = DuplicateTextExW (g_ObjStrPool, DecodedNode, 0, NULL);
|
|
}
|
|
|
|
if (!DecodedLeaf) {
|
|
return encodedNode;
|
|
}
|
|
|
|
if (EncodeObject) {
|
|
encodedLeaf = pObjStrAllocateMemory (4 * ByteCountW (DecodedLeaf) + DWSIZEOF(WCHAR));
|
|
ObsEncodeStringW (encodedLeaf, DecodedLeaf);
|
|
} else {
|
|
encodedLeaf = DuplicateTextExW (g_ObjStrPool, DecodedLeaf, 0, NULL);
|
|
}
|
|
|
|
//
|
|
// preferred format: %1 <%2> %1 - Node, %2 - Leaf
|
|
//
|
|
encodedString = pObjStrAllocateMemory (
|
|
ByteCountW (encodedNode) +
|
|
DWSIZEOF (L" <>") +
|
|
ByteCountW (encodedLeaf)
|
|
);
|
|
wsprintfW (
|
|
encodedString,
|
|
L"%s %c%s%c",
|
|
encodedNode,
|
|
OBJSTR_LEAF_HEADW,
|
|
encodedLeaf,
|
|
OBJSTR_LEAF_TAILW
|
|
);
|
|
|
|
pObjStrFreeMemory (encodedNode);
|
|
pObjStrFreeMemory (encodedLeaf);
|
|
|
|
return encodedString;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
ObsCreateParsedPatternEx parses the given object into an internal format for quick
|
|
pattern matching
|
|
|
|
Arguments:
|
|
|
|
EncodedObject - Specifies the source object string
|
|
|
|
Return Value:
|
|
|
|
A pointer to the newly created structure or NULL if the object was invalid
|
|
|
|
--*/
|
|
|
|
POBSPARSEDPATTERNA
|
|
ObsCreateParsedPatternExA (
|
|
IN PCSTR EncodedObject,
|
|
IN BOOL MakePrimaryRootEndWithWack
|
|
)
|
|
{
|
|
POBSPARSEDPATTERNA ospp;
|
|
PSTR decodedNode;
|
|
PSTR decodedLeaf;
|
|
PCSTR p;
|
|
PCSTR root;
|
|
|
|
MYASSERT (EncodedObject);
|
|
|
|
if (!ObsSplitObjectStringExA (EncodedObject, &decodedNode, &decodedLeaf, NULL, FALSE)) {
|
|
return NULL;
|
|
}
|
|
|
|
ospp = pObjStrAllocateMemory (DWSIZEOF(OBSPARSEDPATTERNA));
|
|
ZeroMemory (ospp, DWSIZEOF(OBSPARSEDPATTERNA));
|
|
ospp->MaxSubLevel = NODE_LEVEL_MAX;
|
|
|
|
MYASSERT (decodedNode);
|
|
if (!GetNodePatternMinMaxLevelsA (decodedNode, decodedNode, &ospp->MinNodeLevel, &ospp->MaxNodeLevel)) {
|
|
pObjStrFreeMemory (decodedNode);
|
|
pObjStrFreeMemory (decodedLeaf);
|
|
pObjStrFreeMemory (ospp);
|
|
return NULL;
|
|
}
|
|
|
|
MYASSERT (ospp->MinNodeLevel > 0 && ospp->MaxNodeLevel >= ospp->MinNodeLevel);
|
|
if (ospp->MaxNodeLevel != NODE_LEVEL_MAX) {
|
|
ospp->MaxSubLevel = ospp->MaxNodeLevel - ospp->MinNodeLevel;
|
|
}
|
|
|
|
ospp->NodePattern = CreateParsedPatternA (decodedNode);
|
|
if (!ospp->NodePattern) {
|
|
DEBUGMSGA ((
|
|
DBG_OBJSTR,
|
|
"ObsCreateParsedPatternExA: Bad EncodedObject: %s",
|
|
EncodedObject
|
|
));
|
|
pObjStrFreeMemory (decodedNode);
|
|
pObjStrFreeMemory (decodedLeaf);
|
|
pObjStrFreeMemory (ospp);
|
|
return NULL;
|
|
}
|
|
if (ospp->NodePattern->PatternCount > 1) {
|
|
DEBUGMSGA ((
|
|
DBG_OBJSTR,
|
|
"ObsCreateParsedPatternExA: Bad EncodedObject (multiple patterns specified): %s",
|
|
EncodedObject
|
|
));
|
|
DestroyParsedPatternA (ospp->NodePattern);
|
|
pObjStrFreeMemory (decodedNode);
|
|
pObjStrFreeMemory (decodedLeaf);
|
|
pObjStrFreeMemory (ospp);
|
|
return NULL;
|
|
}
|
|
|
|
root = ParsedPatternGetRootA (ospp->NodePattern);
|
|
if (root) {
|
|
//
|
|
// extract the real root part
|
|
//
|
|
if (ParsedPatternIsExactMatchA (ospp->NodePattern)) {
|
|
ospp->Flags |= OBSPF_EXACTNODE;
|
|
ospp->ExactRoot = DuplicateTextExA (g_ObjStrPool, root, 0, NULL);
|
|
ospp->ExactRootBytes = ByteCountA (root);
|
|
ospp->MaxSubLevel = 0;
|
|
} else {
|
|
p = FindLastWackA (root);
|
|
if (p) {
|
|
//
|
|
// exact root specified
|
|
// if the last wack is actually the last character or is followed by star(s),
|
|
// optimize the matching by setting some flags
|
|
//
|
|
if (*(p + 1) == 0) {
|
|
if (ParsedPatternIsRootPlusStarA (ospp->NodePattern)) {
|
|
ospp->Flags |= OBSPF_NODEISROOTPLUSSTAR;
|
|
}
|
|
}
|
|
if (MakePrimaryRootEndWithWack && *root != '\\') {
|
|
//
|
|
// see if this is really the primary root
|
|
//
|
|
if (p == _mbschr (root, '\\')) {
|
|
//
|
|
// include it in the string
|
|
//
|
|
p++;
|
|
}
|
|
}
|
|
ospp->ExactRoot = pExtractStringABA (root, p, g_ObjStrPool);
|
|
ospp->ExactRootBytes = (DWORD)((PBYTE)p - (PBYTE)root);
|
|
}
|
|
}
|
|
} else if (ParsedPatternIsOptionalA (ospp->NodePattern)) {
|
|
ospp->Flags |= OBSPF_OPTIONALNODE;
|
|
}
|
|
|
|
if (decodedLeaf) {
|
|
if (*decodedLeaf) {
|
|
ospp->LeafPattern = CreateParsedPatternA (decodedLeaf);
|
|
if (!ospp->LeafPattern) {
|
|
DEBUGMSGA ((
|
|
DBG_OBJSTR,
|
|
"ObsCreateParsedPatternExA: Bad EncodedObject: %s",
|
|
EncodedObject
|
|
));
|
|
DestroyParsedPatternA (ospp->NodePattern);
|
|
pObjStrFreeMemory (ospp->ExactRoot);
|
|
pObjStrFreeMemory (decodedNode);
|
|
pObjStrFreeMemory (decodedLeaf);
|
|
pObjStrFreeMemory (ospp);
|
|
return NULL;
|
|
}
|
|
if (ospp->LeafPattern->PatternCount > 1) {
|
|
DEBUGMSGA ((
|
|
DBG_OBJSTR,
|
|
"ObsCreateParsedPatternExA: Bad EncodedObject (multiple patterns specified): %s",
|
|
EncodedObject
|
|
));
|
|
DestroyParsedPatternA (ospp->NodePattern);
|
|
DestroyParsedPatternA (ospp->LeafPattern);
|
|
pObjStrFreeMemory (ospp->ExactRoot);
|
|
pObjStrFreeMemory (decodedNode);
|
|
pObjStrFreeMemory (decodedLeaf);
|
|
pObjStrFreeMemory (ospp);
|
|
return NULL;
|
|
}
|
|
|
|
if (ParsedPatternIsOptionalA (ospp->LeafPattern)) {
|
|
ospp->Flags |= OBSPF_OPTIONALLEAF;
|
|
} else if (ParsedPatternIsExactMatchA (ospp->LeafPattern)) {
|
|
ospp->Flags |= OBSPF_EXACTLEAF;
|
|
}
|
|
|
|
} else {
|
|
//
|
|
// accept empty string for leaf
|
|
//
|
|
ospp->Flags |= OBSPF_EXACTLEAF;
|
|
}
|
|
ospp->Leaf = DuplicateTextExA (g_ObjStrPool, decodedLeaf, 0, NULL);
|
|
} else {
|
|
ospp->Flags |= OBSPF_NOLEAF;
|
|
}
|
|
|
|
pObjStrFreeMemory (decodedNode);
|
|
pObjStrFreeMemory (decodedLeaf);
|
|
return ospp;
|
|
}
|
|
|
|
|
|
POBSPARSEDPATTERNW
|
|
ObsCreateParsedPatternExW (
|
|
IN PCWSTR EncodedObject,
|
|
IN BOOL MakePrimaryRootEndWithWack
|
|
)
|
|
{
|
|
POBSPARSEDPATTERNW ospp;
|
|
PWSTR decodedNode;
|
|
PWSTR decodedLeaf;
|
|
PCWSTR p;
|
|
PCWSTR root;
|
|
|
|
MYASSERT (EncodedObject);
|
|
|
|
if (!ObsSplitObjectStringExW (EncodedObject, &decodedNode, &decodedLeaf, NULL, FALSE)) {
|
|
return NULL;
|
|
}
|
|
|
|
ospp = pObjStrAllocateMemory (DWSIZEOF(OBSPARSEDPATTERNW));
|
|
ZeroMemory (ospp, DWSIZEOF(OBSPARSEDPATTERNW));
|
|
ospp->MaxSubLevel = NODE_LEVEL_MAX;
|
|
|
|
MYASSERT (decodedNode);
|
|
if (!GetNodePatternMinMaxLevelsW (decodedNode, decodedNode, &ospp->MinNodeLevel, &ospp->MaxNodeLevel)) {
|
|
pObjStrFreeMemory (decodedNode);
|
|
pObjStrFreeMemory (decodedLeaf);
|
|
pObjStrFreeMemory (ospp);
|
|
return NULL;
|
|
}
|
|
|
|
MYASSERT (ospp->MinNodeLevel > 0 && ospp->MaxNodeLevel >= ospp->MinNodeLevel);
|
|
if (ospp->MaxNodeLevel != NODE_LEVEL_MAX) {
|
|
ospp->MaxSubLevel = ospp->MaxNodeLevel - ospp->MinNodeLevel;
|
|
}
|
|
|
|
ospp->NodePattern = CreateParsedPatternW (decodedNode);
|
|
if (!ospp->NodePattern) {
|
|
DEBUGMSGW ((
|
|
DBG_OBJSTR,
|
|
"ObsCreateParsedPatternExW: Bad EncodedObject: %s",
|
|
EncodedObject
|
|
));
|
|
pObjStrFreeMemory (decodedNode);
|
|
pObjStrFreeMemory (decodedLeaf);
|
|
pObjStrFreeMemory (ospp);
|
|
return NULL;
|
|
}
|
|
if (ospp->NodePattern->PatternCount > 1) {
|
|
DEBUGMSGW ((
|
|
DBG_OBJSTR,
|
|
"ObsCreateParsedPatternExW: Bad EncodedObject (multiple patterns specified): %s",
|
|
EncodedObject
|
|
));
|
|
DestroyParsedPatternW (ospp->NodePattern);
|
|
pObjStrFreeMemory (decodedNode);
|
|
pObjStrFreeMemory (decodedLeaf);
|
|
pObjStrFreeMemory (ospp);
|
|
return NULL;
|
|
}
|
|
|
|
root = ParsedPatternGetRootW (ospp->NodePattern);
|
|
if (root) {
|
|
//
|
|
// extract the real root part
|
|
//
|
|
if (ParsedPatternIsExactMatchW (ospp->NodePattern)) {
|
|
ospp->Flags |= OBSPF_EXACTNODE;
|
|
ospp->ExactRoot = DuplicateTextExW (g_ObjStrPool, root, 0, NULL);
|
|
ospp->ExactRootBytes = ByteCountW (root);
|
|
ospp->MaxSubLevel = 0;
|
|
} else {
|
|
p = FindLastWackW (root);
|
|
if (p) {
|
|
//
|
|
// exact root specified
|
|
// if the last wack is actually the last character or is followed by star(s),
|
|
// optimize the matching by setting some flags
|
|
//
|
|
if (*(p + 1) == 0) {
|
|
if (ParsedPatternIsRootPlusStarW (ospp->NodePattern)) {
|
|
ospp->Flags |= OBSPF_NODEISROOTPLUSSTAR;
|
|
}
|
|
}
|
|
if (MakePrimaryRootEndWithWack && *root != L'\\') {
|
|
//
|
|
// see if this is really the primary root
|
|
//
|
|
if (p == wcschr (root, L'\\')) {
|
|
//
|
|
// include it in the string
|
|
//
|
|
p++;
|
|
}
|
|
}
|
|
ospp->ExactRoot = pExtractStringABW (root, p, g_ObjStrPool);
|
|
ospp->ExactRootBytes = (DWORD)((PBYTE)p - (PBYTE)root);
|
|
}
|
|
}
|
|
} else if (ParsedPatternIsOptionalW (ospp->NodePattern)) {
|
|
ospp->Flags |= OBSPF_OPTIONALNODE;
|
|
}
|
|
|
|
if (decodedLeaf) {
|
|
if (*decodedLeaf) {
|
|
ospp->LeafPattern = CreateParsedPatternW (decodedLeaf);
|
|
if (!ospp->LeafPattern) {
|
|
DEBUGMSGW ((
|
|
DBG_OBJSTR,
|
|
"ObsCreateParsedPatternExW: Bad EncodedObject: %s",
|
|
EncodedObject
|
|
));
|
|
DestroyParsedPatternW (ospp->NodePattern);
|
|
pObjStrFreeMemory (ospp->ExactRoot);
|
|
pObjStrFreeMemory (decodedNode);
|
|
pObjStrFreeMemory (decodedLeaf);
|
|
pObjStrFreeMemory (ospp);
|
|
return NULL;
|
|
}
|
|
if (ospp->LeafPattern->PatternCount > 1) {
|
|
DEBUGMSGW ((
|
|
DBG_OBJSTR,
|
|
"ObsCreateParsedPatternExW: Bad EncodedObject (multiple patterns specified): %s",
|
|
EncodedObject
|
|
));
|
|
DestroyParsedPatternW (ospp->NodePattern);
|
|
DestroyParsedPatternW (ospp->LeafPattern);
|
|
pObjStrFreeMemory (ospp->ExactRoot);
|
|
pObjStrFreeMemory (decodedNode);
|
|
pObjStrFreeMemory (decodedLeaf);
|
|
pObjStrFreeMemory (ospp);
|
|
return NULL;
|
|
}
|
|
|
|
if (ParsedPatternIsOptionalW (ospp->LeafPattern)) {
|
|
ospp->Flags |= OBSPF_OPTIONALLEAF;
|
|
} else if (ParsedPatternIsExactMatchW (ospp->LeafPattern)) {
|
|
ospp->Flags |= OBSPF_EXACTLEAF;
|
|
}
|
|
|
|
} else {
|
|
//
|
|
// accept empty string for leaf
|
|
//
|
|
ospp->Flags |= OBSPF_EXACTLEAF;
|
|
}
|
|
ospp->Leaf = DuplicateTextExW (g_ObjStrPool, decodedLeaf, 0, NULL);
|
|
} else {
|
|
ospp->Flags |= OBSPF_NOLEAF;
|
|
}
|
|
|
|
pObjStrFreeMemory (decodedNode);
|
|
pObjStrFreeMemory (decodedLeaf);
|
|
return ospp;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
ObsDestroyParsedPattern destroys the given structure, freeing resources
|
|
|
|
Arguments:
|
|
|
|
ParsedPattern - Specifies the parsed pattern structure
|
|
|
|
Return Value:
|
|
|
|
none
|
|
|
|
--*/
|
|
|
|
VOID
|
|
ObsDestroyParsedPatternA (
|
|
IN POBSPARSEDPATTERNA ParsedPattern
|
|
)
|
|
{
|
|
if (ParsedPattern) {
|
|
if (ParsedPattern->NodePattern) {
|
|
DestroyParsedPatternA (ParsedPattern->NodePattern);
|
|
}
|
|
if (ParsedPattern->LeafPattern) {
|
|
DestroyParsedPatternA (ParsedPattern->LeafPattern);
|
|
}
|
|
if (ParsedPattern->Leaf) {
|
|
FreeTextExA (g_ObjStrPool, ParsedPattern->Leaf);
|
|
}
|
|
pObjStrFreeMemory (ParsedPattern->ExactRoot);
|
|
pObjStrFreeMemory (ParsedPattern);
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
ObsDestroyParsedPatternW (
|
|
IN POBSPARSEDPATTERNW ParsedPattern
|
|
)
|
|
{
|
|
if (ParsedPattern) {
|
|
if (ParsedPattern->NodePattern) {
|
|
DestroyParsedPatternW (ParsedPattern->NodePattern);
|
|
}
|
|
if (ParsedPattern->LeafPattern) {
|
|
DestroyParsedPatternW (ParsedPattern->LeafPattern);
|
|
}
|
|
if (ParsedPattern->Leaf) {
|
|
FreeTextExW (g_ObjStrPool, ParsedPattern->Leaf);
|
|
}
|
|
pObjStrFreeMemory (ParsedPattern->ExactRoot);
|
|
pObjStrFreeMemory (ParsedPattern);
|
|
}
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
ObsParsedPatternMatch tests the given object against a parsed pattern
|
|
|
|
Arguments:
|
|
|
|
ParsedPattern - Specifies the parsed pattern structure
|
|
EncodedObject - Specifies the object string to test against the pattern
|
|
|
|
Return Value:
|
|
|
|
TRUE if the string matches the pattern
|
|
|
|
--*/
|
|
|
|
BOOL
|
|
ObsParsedPatternMatchA (
|
|
IN POBSPARSEDPATTERNA ParsedPattern,
|
|
IN PCSTR EncodedObject
|
|
)
|
|
{
|
|
PSTR decodedNode;
|
|
PSTR decodedLeaf;
|
|
BOOL b;
|
|
|
|
if (!ObsSplitObjectStringExA (EncodedObject, &decodedNode, &decodedLeaf, NULL, FALSE)) {
|
|
return FALSE;
|
|
}
|
|
|
|
b = ObsParsedPatternMatchExA (ParsedPattern, decodedNode, decodedLeaf);
|
|
|
|
pObjStrFreeMemory (decodedNode);
|
|
pObjStrFreeMemory (decodedLeaf);
|
|
|
|
return b;
|
|
}
|
|
|
|
BOOL
|
|
ObsParsedPatternMatchW (
|
|
IN POBSPARSEDPATTERNW ParsedPattern,
|
|
IN PCWSTR EncodedObject
|
|
)
|
|
{
|
|
PWSTR decodedNode;
|
|
PWSTR decodedLeaf;
|
|
BOOL b;
|
|
|
|
if (!ObsSplitObjectStringExW (EncodedObject, &decodedNode, &decodedLeaf, NULL, FALSE)) {
|
|
return FALSE;
|
|
}
|
|
|
|
b = ObsParsedPatternMatchExW (ParsedPattern, decodedNode, decodedLeaf);
|
|
|
|
pObjStrFreeMemory (decodedNode);
|
|
pObjStrFreeMemory (decodedLeaf);
|
|
|
|
return b;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
ObsParsedPatternMatchEx tests the given object, given by its components,
|
|
against a parsed pattern
|
|
|
|
Arguments:
|
|
|
|
ParsedPattern - Specifies the parsed pattern structure
|
|
Node - Specifies the node part of the object string to test against the pattern
|
|
Leaf - Specifies the leaf part of the object string to test against the pattern
|
|
|
|
Return Value:
|
|
|
|
TRUE if the string components match the pattern
|
|
|
|
--*/
|
|
|
|
BOOL
|
|
ObsParsedPatternMatchExA (
|
|
IN POBSPARSEDPATTERNA ParsedPattern,
|
|
IN PCSTR Node,
|
|
IN PCSTR Leaf OPTIONAL
|
|
)
|
|
{
|
|
MYASSERT (Node && ParsedPattern->NodePattern);
|
|
if (!(Node && ParsedPattern->NodePattern)) {
|
|
return FALSE;
|
|
}
|
|
|
|
if ((ParsedPattern->Flags & OBSPF_NOLEAF) && Leaf ||
|
|
!(ParsedPattern->Flags & OBSPF_NOLEAF) && !Leaf
|
|
) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (!TestParsedPatternA (ParsedPattern->NodePattern, Node)) {
|
|
return FALSE;
|
|
}
|
|
|
|
return !Leaf || TestParsedPatternA (ParsedPattern->LeafPattern, Leaf);
|
|
}
|
|
|
|
BOOL
|
|
ObsParsedPatternMatchExW (
|
|
IN POBSPARSEDPATTERNW ParsedPattern,
|
|
IN PCWSTR Node, OPTIONAL
|
|
IN PCWSTR Leaf OPTIONAL
|
|
)
|
|
{
|
|
MYASSERT (Node && ParsedPattern->NodePattern);
|
|
if (!(Node && ParsedPattern->NodePattern)) {
|
|
return FALSE;
|
|
}
|
|
|
|
if ((ParsedPattern->Flags & OBSPF_NOLEAF) && Leaf ||
|
|
!(ParsedPattern->Flags & OBSPF_NOLEAF) && !Leaf
|
|
) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (!TestParsedPatternW (ParsedPattern->NodePattern, Node)) {
|
|
return FALSE;
|
|
}
|
|
|
|
return !Leaf || TestParsedPatternW (ParsedPattern->LeafPattern, Leaf);
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
ObsPatternMatch tests an object string against a pattern object string
|
|
|
|
Arguments:
|
|
|
|
ParsedPattern - Specifies the parsed pattern structure
|
|
Node - Specifies the node part of the object string to test against the pattern
|
|
Leaf - Specifies the leaf part of the object string to test against the pattern
|
|
|
|
Return Value:
|
|
|
|
TRUE if the string components match the pattern
|
|
|
|
--*/
|
|
|
|
BOOL
|
|
ObsPatternMatchA (
|
|
IN PCSTR ObjectPattern,
|
|
IN PCSTR ObjectStr
|
|
)
|
|
{
|
|
PSTR opNode;
|
|
PSTR opLeaf;
|
|
PSTR osNode;
|
|
PSTR osLeaf;
|
|
BOOL b = FALSE;
|
|
|
|
if (ObsSplitObjectStringExA (ObjectPattern, &opNode, &opLeaf, NULL, FALSE)) {
|
|
if (ObsSplitObjectStringExA (ObjectStr, &osNode, &osLeaf, NULL, TRUE)) {
|
|
|
|
if (opNode) {
|
|
if (osNode) {
|
|
b = IsPatternMatchExABA (opNode, osNode, GetEndOfStringA (osNode));
|
|
} else {
|
|
b = FALSE;
|
|
}
|
|
} else {
|
|
if (osNode) {
|
|
b = FALSE;
|
|
} else {
|
|
b = TRUE;
|
|
}
|
|
}
|
|
|
|
if (b) {
|
|
if (opLeaf) {
|
|
if (osLeaf) {
|
|
b = IsPatternMatchExABA (opLeaf, osLeaf, GetEndOfStringA (osLeaf));
|
|
} else {
|
|
b = TRUE;
|
|
}
|
|
} else {
|
|
if (osLeaf) {
|
|
b = FALSE;
|
|
} else {
|
|
b = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
pObjStrFreeMemory (osNode);
|
|
pObjStrFreeMemory (osLeaf);
|
|
}
|
|
ELSE_DEBUGMSGA ((DBG_OBJSTR, "ObsPatternMatchA: bad ObjectStr: %s", ObjectStr));
|
|
|
|
pObjStrFreeMemory (opNode);
|
|
pObjStrFreeMemory (opLeaf);
|
|
}
|
|
ELSE_DEBUGMSGA ((DBG_OBJSTR, "ObsPatternMatchA: bad ObjectPattern: %s", ObjectPattern));
|
|
|
|
return b;
|
|
}
|
|
|
|
BOOL
|
|
ObsPatternMatchW (
|
|
IN PCWSTR ObjectPattern,
|
|
IN PCWSTR ObjectStr
|
|
)
|
|
{
|
|
PWSTR opNode;
|
|
PWSTR opLeaf;
|
|
PWSTR osNode;
|
|
PWSTR osLeaf;
|
|
BOOL b = FALSE;
|
|
|
|
if (ObsSplitObjectStringExW (ObjectPattern, &opNode, &opLeaf, NULL, FALSE)) {
|
|
if (ObsSplitObjectStringExW (ObjectStr, &osNode, &osLeaf, NULL, FALSE)) {
|
|
|
|
if (opNode) {
|
|
if (osNode) {
|
|
b = IsPatternMatchExABW (opNode, osNode, GetEndOfStringW (osNode));
|
|
} else {
|
|
b = FALSE;
|
|
}
|
|
} else {
|
|
if (osNode) {
|
|
b = FALSE;
|
|
} else {
|
|
b = TRUE;
|
|
}
|
|
}
|
|
|
|
if (b) {
|
|
if (opLeaf) {
|
|
if (osLeaf) {
|
|
b = IsPatternMatchExABW (opLeaf, osLeaf, GetEndOfStringW (osLeaf));
|
|
} else {
|
|
b = FALSE;
|
|
}
|
|
} else {
|
|
if (osLeaf) {
|
|
b = FALSE;
|
|
} else {
|
|
b = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
pObjStrFreeMemory (osNode);
|
|
pObjStrFreeMemory (osLeaf);
|
|
}
|
|
ELSE_DEBUGMSGW ((DBG_OBJSTR, "ObsPatternMatchW: bad ObjectStr: %s", ObjectStr));
|
|
|
|
pObjStrFreeMemory (opNode);
|
|
pObjStrFreeMemory (opLeaf);
|
|
}
|
|
ELSE_DEBUGMSGW ((DBG_OBJSTR, "ObsPatternMatchW: bad ObjectPattern: %s", ObjectPattern));
|
|
|
|
return b;
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
ObsIsPatternContained compares two patterns to see if one of them is
|
|
included in the other. Both patterns may contain any of the following
|
|
expressions:
|
|
|
|
Arguments:
|
|
|
|
Container - Specifies the container pattern
|
|
Contained - Specifies the contained pattern
|
|
|
|
Return Value:
|
|
|
|
TRUE if Contained is contained in Container
|
|
|
|
--*/
|
|
|
|
BOOL
|
|
ObsIsPatternContainedA (
|
|
IN PCSTR Container,
|
|
IN PCSTR Contained
|
|
)
|
|
{
|
|
PSTR opNode;
|
|
PSTR opLeaf;
|
|
PSTR osNode;
|
|
PSTR osLeaf;
|
|
BOOL b = FALSE;
|
|
|
|
if (ObsSplitObjectStringExA (Container, &opNode, &opLeaf, NULL, FALSE)) {
|
|
|
|
if (ObsSplitObjectStringExA (Contained, &osNode, &osLeaf, NULL, FALSE)) {
|
|
|
|
if (opNode) {
|
|
if (osNode) {
|
|
b = IsPatternContainedExA (opNode, osNode);
|
|
} else {
|
|
b = FALSE;
|
|
}
|
|
} else {
|
|
if (osNode) {
|
|
b = FALSE;
|
|
} else {
|
|
b = TRUE;
|
|
}
|
|
}
|
|
|
|
if (b) {
|
|
if (opLeaf) {
|
|
if (osLeaf) {
|
|
b = IsPatternContainedExA (opLeaf, osLeaf);
|
|
} else {
|
|
b = TRUE;
|
|
}
|
|
} else {
|
|
if (osLeaf) {
|
|
b = FALSE;
|
|
} else {
|
|
b = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
pObjStrFreeMemory (osNode);
|
|
pObjStrFreeMemory (osLeaf);
|
|
}
|
|
ELSE_DEBUGMSGA ((DBG_OBJSTR, "ObsIsPatternContainedA: bad Contained string: %s", Contained));
|
|
|
|
pObjStrFreeMemory (opNode);
|
|
pObjStrFreeMemory (opLeaf);
|
|
}
|
|
ELSE_DEBUGMSGA ((DBG_OBJSTR, "ObsIsPatternContainedA: bad Container string: %s", Container));
|
|
|
|
return b;
|
|
}
|
|
|
|
BOOL
|
|
ObsIsPatternContainedW (
|
|
IN PCWSTR Container,
|
|
IN PCWSTR Contained
|
|
)
|
|
{
|
|
PWSTR opNode;
|
|
PWSTR opLeaf;
|
|
PWSTR osNode;
|
|
PWSTR osLeaf;
|
|
BOOL b = FALSE;
|
|
|
|
if (ObsSplitObjectStringExW (Container, &opNode, &opLeaf, NULL, FALSE)) {
|
|
|
|
if (ObsSplitObjectStringExW (Contained, &osNode, &osLeaf, NULL, FALSE)) {
|
|
|
|
if (opNode) {
|
|
if (osNode) {
|
|
b = IsPatternContainedExW (opNode, osNode);
|
|
} else {
|
|
b = FALSE;
|
|
}
|
|
} else {
|
|
if (osNode) {
|
|
b = FALSE;
|
|
} else {
|
|
b = TRUE;
|
|
}
|
|
}
|
|
|
|
if (b) {
|
|
if (opLeaf) {
|
|
if (osLeaf) {
|
|
b = IsPatternContainedExW (opLeaf, osLeaf);
|
|
} else {
|
|
b = TRUE;
|
|
}
|
|
} else {
|
|
if (osLeaf) {
|
|
b = FALSE;
|
|
} else {
|
|
b = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
pObjStrFreeMemory (osNode);
|
|
pObjStrFreeMemory (osLeaf);
|
|
}
|
|
ELSE_DEBUGMSGW ((DBG_OBJSTR, "ObsIsPatternContainedW: bad Contained string: %s", Contained));
|
|
|
|
pObjStrFreeMemory (opNode);
|
|
pObjStrFreeMemory (opLeaf);
|
|
}
|
|
ELSE_DEBUGMSGW ((DBG_OBJSTR, "ObsIsPatternContainedW: bad Container string: %s", Container));
|
|
|
|
return b;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
ObsGetPatternLevels gets the minimum and maximum levels of a string that would
|
|
match the given pattern.
|
|
|
|
Arguments:
|
|
|
|
ObjectPattern - Specifies the pattern
|
|
MinLevel - Receives the minimum possible level; the root has level 1
|
|
MaxLevel - Receives the maximum possible level; the root has level 1
|
|
|
|
Return Value:
|
|
|
|
TRUE if the pattern was correct and computing was done; FALSE otherwise
|
|
|
|
--*/
|
|
|
|
BOOL
|
|
ObsGetPatternLevelsA (
|
|
IN PCSTR ObjectPattern,
|
|
OUT PDWORD MinLevel, OPTIONAL
|
|
OUT PDWORD MaxLevel OPTIONAL
|
|
)
|
|
{
|
|
PSTR decodedNode;
|
|
PSTR decodedLeaf;
|
|
BOOL b;
|
|
|
|
if (!ObsSplitObjectStringExA (ObjectPattern, &decodedNode, &decodedLeaf, NULL, FALSE)) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (decodedNode) {
|
|
b = GetNodePatternMinMaxLevelsA (decodedNode, decodedNode, MinLevel, MaxLevel);
|
|
} else {
|
|
b = FALSE;
|
|
}
|
|
|
|
pObjStrFreeMemory (decodedNode);
|
|
pObjStrFreeMemory (decodedLeaf);
|
|
|
|
return b;
|
|
}
|
|
|
|
BOOL
|
|
ObsGetPatternLevelsW (
|
|
IN PCWSTR ObjectPattern,
|
|
OUT PDWORD MinLevel,
|
|
OUT PDWORD MaxLevel
|
|
)
|
|
{
|
|
PWSTR decodedNode;
|
|
PWSTR decodedLeaf;
|
|
BOOL b;
|
|
|
|
if (!ObsSplitObjectStringExW (ObjectPattern, &decodedNode, &decodedLeaf, NULL, FALSE)) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (decodedNode) {
|
|
b = GetNodePatternMinMaxLevelsW (decodedNode, decodedNode, MinLevel, MaxLevel);
|
|
} else {
|
|
b = FALSE;
|
|
}
|
|
|
|
pObjStrFreeMemory (decodedNode);
|
|
pObjStrFreeMemory (decodedLeaf);
|
|
|
|
return b;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
ObsPatternIncludesPattern decides if a given pattern includes another pattern,
|
|
meaning that any string that would match the second will match the first.
|
|
|
|
Arguments:
|
|
|
|
IncludingPattern - Specifies the first parsed pattern
|
|
IncludedPattern - Specifies the second parsed pattern
|
|
|
|
Return Value:
|
|
|
|
TRUE if the first pattern includes the second
|
|
|
|
--*/
|
|
|
|
BOOL
|
|
ObsPatternIncludesPatternA (
|
|
IN POBSPARSEDPATTERNA IncludingPattern,
|
|
IN POBSPARSEDPATTERNA IncludedPattern
|
|
)
|
|
{
|
|
MYASSERT (IncludingPattern->NodePattern && IncludedPattern->NodePattern);
|
|
if (!(IncludingPattern->NodePattern && IncludedPattern->NodePattern)) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (IncludingPattern->MinNodeLevel > IncludedPattern->MinNodeLevel ||
|
|
IncludingPattern->MaxNodeLevel < IncludedPattern->MaxNodeLevel
|
|
) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (!PatternIncludesPatternA (IncludingPattern->NodePattern, IncludedPattern->NodePattern)) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (IncludingPattern->LeafPattern) {
|
|
if (!IncludedPattern->LeafPattern) {
|
|
return FALSE;
|
|
}
|
|
if (!PatternIncludesPatternA (IncludingPattern->LeafPattern, IncludedPattern->LeafPattern)) {
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
if (IncludedPattern->LeafPattern) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
ObsPatternIncludesPatternW (
|
|
IN POBSPARSEDPATTERNW IncludingPattern,
|
|
IN POBSPARSEDPATTERNW IncludedPattern
|
|
)
|
|
{
|
|
MYASSERT (IncludingPattern->NodePattern && IncludedPattern->NodePattern);
|
|
if (!(IncludingPattern->NodePattern && IncludedPattern->NodePattern)) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (IncludingPattern->MinNodeLevel > IncludedPattern->MinNodeLevel ||
|
|
IncludingPattern->MaxNodeLevel < IncludedPattern->MaxNodeLevel
|
|
) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (!PatternIncludesPatternW (IncludingPattern->NodePattern, IncludedPattern->NodePattern)) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (IncludingPattern->LeafPattern) {
|
|
if (!IncludedPattern->LeafPattern) {
|
|
return FALSE;
|
|
}
|
|
if (!PatternIncludesPatternW (IncludingPattern->LeafPattern, IncludedPattern->LeafPattern)) {
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
if (IncludedPattern->LeafPattern) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|