/*++ 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: --*/ /* +-------+ | 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 root1\node1 root1\node1 root1\node1 */ #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; }