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.
2042 lines
52 KiB
2042 lines
52 KiB
/*++
|
|
|
|
Copyright (c) 2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
parse.c
|
|
|
|
Abstract:
|
|
|
|
Implements parsing of script entries.
|
|
|
|
Author:
|
|
|
|
Jim Schmidt (jimschm) 02-Jun-2000
|
|
|
|
Revision History:
|
|
|
|
<alias> <date> <comments>
|
|
|
|
--*/
|
|
|
|
//
|
|
// Includes
|
|
//
|
|
|
|
#include "pch.h"
|
|
#include "v1p.h"
|
|
|
|
#define DBG_V1 "v1"
|
|
|
|
//
|
|
// Strings
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Constants
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Macros
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Types
|
|
//
|
|
|
|
typedef BOOL (SCRIPTTYPE_ALLOC_FN)(
|
|
IN OUT PATTRIB_DATA AttribData CALLER_INITIALIZED
|
|
);
|
|
typedef SCRIPTTYPE_ALLOC_FN *PSCRIPTTYPE_ALLOC_FN;
|
|
|
|
typedef BOOL (SCRIPTTYPE_FREE_FN)(
|
|
IN PATTRIB_DATA AttribData ZEROED
|
|
);
|
|
typedef SCRIPTTYPE_FREE_FN *PSCRIPTTYPE_FREE_FN;
|
|
|
|
typedef struct {
|
|
PCTSTR Tag;
|
|
PSCRIPTTYPE_ALLOC_FN AllocFunction;
|
|
PSCRIPTTYPE_FREE_FN FreeFunction;
|
|
} TAG_TO_SCRIPTTYPEFN, *PTAG_TO_SCRIPTTYPEFN;
|
|
|
|
//
|
|
// Globals
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Macro expansion list
|
|
//
|
|
|
|
#define SCRIPT_TYPES \
|
|
DEFMAC(Registry, pAllocRegistryScriptType, pFreeIsmObjectScriptType) \
|
|
DEFMAC(File, pAllocFileScriptType, pFreeIsmObjectScriptType) \
|
|
DEFMAC(Directory, pAllocDirectoryScriptType, pFreeIsmObjectScriptType) \
|
|
DEFMAC(Text, pAllocTextScriptType, pFreeTextScriptType) \
|
|
DEFMAC(System, pAllocSystemScriptType, pFreeSystemScriptType) \
|
|
DEFMAC(INIFile, pAllocIniFileScriptType, pFreeIniFileScriptType) \
|
|
|
|
//
|
|
// Private function prototypes
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Macro expansion definition
|
|
//
|
|
|
|
#define DEFMAC(tag,fnA,fnF) SCRIPTTYPE_ALLOC_FN fnA; SCRIPTTYPE_FREE_FN fnF;
|
|
|
|
SCRIPT_TYPES
|
|
|
|
#undef DEFMAC
|
|
|
|
|
|
#define DEFMAC(tag,fnA,fnF) {TEXT(#tag),fnA,fnF},
|
|
|
|
TAG_TO_SCRIPTTYPEFN g_TagToScriptTypeFn[] = {
|
|
SCRIPT_TYPES
|
|
{NULL, NULL, NULL}
|
|
};
|
|
|
|
#undef DEFMAC
|
|
|
|
//
|
|
// Code
|
|
//
|
|
|
|
MIG_OBJECTSTRINGHANDLE
|
|
MakeRegExBase (
|
|
IN PCTSTR Node,
|
|
IN PCTSTR Leaf
|
|
)
|
|
{
|
|
MIG_OBJECTSTRINGHANDLE objectBase = NULL;
|
|
PTSTR ptr;
|
|
PTSTR nodeCopy = NULL;
|
|
PCTSTR nodeBase = NULL;
|
|
BOOL useLeaf = FALSE;
|
|
|
|
|
|
if (Node) {
|
|
ptr = _tcschr (Node, TEXT('\\'));
|
|
if (!ptr) {
|
|
return NULL;
|
|
}
|
|
|
|
if (StringIPrefix (Node, TEXT("HKR\\"))) {
|
|
nodeCopy = JoinText (TEXT("HKCU"), ptr);
|
|
} else {
|
|
nodeCopy = DuplicateText (Node);
|
|
}
|
|
|
|
if (nodeCopy) {
|
|
nodeBase = GetPatternBase (nodeCopy);
|
|
|
|
if (nodeBase) {
|
|
if (Leaf && !_tcschr (Leaf, TEXT('*'))) {
|
|
useLeaf = TRUE;
|
|
}
|
|
objectBase = IsmCreateObjectHandle (nodeBase, useLeaf ? Leaf : NULL);
|
|
FreePathString (nodeBase);
|
|
}
|
|
FreeText (nodeCopy);
|
|
}
|
|
}
|
|
|
|
return objectBase;
|
|
}
|
|
|
|
MIG_OBJECTSTRINGHANDLE
|
|
CreatePatternFromNodeLeaf (
|
|
IN PCTSTR Node,
|
|
IN PCTSTR Leaf
|
|
)
|
|
{
|
|
MIG_OBJECTSTRINGHANDLE pattern;
|
|
MIG_SEGMENTS nodeSegment;
|
|
MIG_SEGMENTS leafSegment;
|
|
PTSTR fixedNode = NULL;
|
|
|
|
// let's do some trick for registry objects that start with HKR
|
|
if (Node &&
|
|
(StringIMatch (Node, S_HKR) ||
|
|
StringIMatchTcharCount (Node, TEXT("HKR\\"), 4)
|
|
)
|
|
) {
|
|
fixedNode = JoinText (S_HKCU, Node + 3);
|
|
nodeSegment.Segment = fixedNode;
|
|
} else {
|
|
nodeSegment.Segment = Node;
|
|
}
|
|
|
|
nodeSegment.IsPattern = TRUE;
|
|
leafSegment.Segment = Leaf;
|
|
leafSegment.IsPattern = TRUE;
|
|
|
|
pattern = IsmCreateObjectPattern (&nodeSegment, Node ? 1 : 0, &leafSegment, Leaf ? 1 : 0);
|
|
|
|
FreeText (fixedNode);
|
|
|
|
return pattern;
|
|
}
|
|
|
|
MIG_OBJECTSTRINGHANDLE
|
|
TurnRegStringIntoHandle (
|
|
IN PCTSTR String,
|
|
IN BOOL Pattern,
|
|
OUT PBOOL HadLeaf OPTIONAL
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
TurnRegStringIntoHandle converts the script's reg syntax into a cobra
|
|
object.
|
|
|
|
Arguments:
|
|
|
|
String - Specifies the registry key and value in the script syntax.
|
|
The string must be in the following format:
|
|
|
|
<root>\<key>\* [<value>]
|
|
|
|
Each part is optional.
|
|
|
|
<root> specifies HKCU, HKR, HKLM or HKCC.
|
|
|
|
<key> specifies a subkey (such as Software\Microsoft\Windows)
|
|
|
|
* specifies all subkeys. If <value> is not specified, then all
|
|
values and subvalues are also included.
|
|
|
|
<value> specifies a specific value name
|
|
|
|
|
|
Pattern - Specifies TRUE if the registry string can contain a pattern, or
|
|
FALSE if it cannot.
|
|
|
|
HadLeaf - Receives TRUE if String contains a leaf specification, FALSE
|
|
otherwise
|
|
|
|
Return Value:
|
|
|
|
A handle to a cobra object string, or NULL if parsing failed.
|
|
|
|
--*/
|
|
|
|
{
|
|
PTSTR strCopy;
|
|
PTSTR p;
|
|
PTSTR value = NULL;
|
|
PTSTR valueEnd;
|
|
PTSTR key;
|
|
PTSTR keyEnd;
|
|
BOOL tree = FALSE;
|
|
MIG_SEGMENTS nodeSegment[2];
|
|
UINT nodeCount;
|
|
MIG_SEGMENTS leafSegment;
|
|
UINT leafCount;
|
|
MIG_OBJECTSTRINGHANDLE handle;
|
|
BOOL noSubKeys;
|
|
BOOL noWildcardLeaf;
|
|
PCTSTR fixedKey = NULL;
|
|
|
|
MYASSERT (String);
|
|
if (!String) {
|
|
return NULL;
|
|
}
|
|
|
|
if (Pattern) {
|
|
noSubKeys = FALSE;
|
|
noWildcardLeaf = FALSE;
|
|
} else {
|
|
noSubKeys = TRUE;
|
|
noWildcardLeaf = TRUE;
|
|
}
|
|
|
|
//
|
|
// Inbound syntax is key\* [value]
|
|
//
|
|
|
|
strCopy = DuplicateText (String);
|
|
if (!strCopy) {
|
|
return NULL;
|
|
}
|
|
|
|
key = (PTSTR) SkipSpace (strCopy);
|
|
if (!key) {
|
|
FreeText (strCopy);
|
|
return NULL;
|
|
}
|
|
|
|
if (*key == TEXT('[')) {
|
|
//
|
|
// This is a value-only case
|
|
//
|
|
|
|
value = _tcsinc (key);
|
|
key = NULL;
|
|
|
|
} else {
|
|
//
|
|
// This is a key-value case, or key-only case
|
|
//
|
|
|
|
p = _tcschr (key, TEXT('['));
|
|
|
|
if (p) {
|
|
//
|
|
// Save start of value
|
|
//
|
|
value = _tcsinc (p);
|
|
} else {
|
|
//
|
|
// No value
|
|
//
|
|
p = GetEndOfString (key);
|
|
}
|
|
|
|
keyEnd = p;
|
|
|
|
//
|
|
// Find the true end of the key
|
|
//
|
|
|
|
p = _tcsdec2 (key, p);
|
|
MYASSERT (p); // assert this is not a value-only case
|
|
p = (PTSTR) SkipSpaceR (key, p);
|
|
|
|
if (p) {
|
|
keyEnd = _tcsinc (p);
|
|
}
|
|
|
|
//
|
|
// Test for \* at the end
|
|
//
|
|
|
|
p = _tcsdec2 (key, keyEnd);
|
|
MYASSERT (p);
|
|
|
|
if (p && _tcsnextc (p) == TEXT('*')) {
|
|
p = _tcsdec2 (key, p);
|
|
if (p && _tcsnextc (p) == TEXT('\\')) {
|
|
keyEnd = p;
|
|
tree = (noSubKeys == FALSE);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Trim the key
|
|
//
|
|
|
|
*keyEnd = 0;
|
|
}
|
|
|
|
//
|
|
// Parse the value
|
|
//
|
|
|
|
if (value) {
|
|
value = (PTSTR) SkipSpace (value);
|
|
valueEnd = _tcschr (value, TEXT(']'));
|
|
|
|
if (!valueEnd) {
|
|
LOG ((LOG_ERROR, (PCSTR) MSG_INF_SYNTAX_ERROR, String));
|
|
value = NULL;
|
|
} else {
|
|
//
|
|
// Trim the space at the end of value
|
|
//
|
|
|
|
p = _tcsdec2 (value, valueEnd);
|
|
if (p) {
|
|
p = (PTSTR) SkipSpaceR (value, p);
|
|
if (p) {
|
|
valueEnd = _tcsinc (p);
|
|
}
|
|
}
|
|
|
|
*valueEnd = 0;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Create parsed pattern. Start with the node.
|
|
//
|
|
|
|
nodeSegment[0].Segment = key;
|
|
nodeSegment[0].IsPattern = FALSE;
|
|
|
|
nodeSegment[1].Segment = TEXT("\\*");
|
|
nodeSegment[1].IsPattern = TRUE;
|
|
|
|
if (tree) {
|
|
nodeCount = 2;
|
|
} else {
|
|
nodeCount = 1;
|
|
}
|
|
|
|
//
|
|
// compute the leaf
|
|
//
|
|
|
|
if (value) {
|
|
leafSegment.Segment = value;
|
|
leafSegment.IsPattern = FALSE;
|
|
} else {
|
|
leafSegment.Segment = TEXT("*");
|
|
leafSegment.IsPattern = TRUE;
|
|
}
|
|
|
|
if (noWildcardLeaf && !value) {
|
|
leafCount = 0;
|
|
} else {
|
|
leafCount = 1;
|
|
}
|
|
|
|
if (nodeCount && key &&
|
|
(StringIMatch (key, S_HKR) ||
|
|
StringIMatchTcharCount (key, TEXT("HKR\\"), 4)
|
|
)
|
|
) {
|
|
fixedKey = JoinText (S_HKCU, key + 3);
|
|
nodeSegment[0].Segment = fixedKey;
|
|
}
|
|
|
|
handle = IsmCreateObjectPattern (
|
|
nodeSegment,
|
|
nodeCount,
|
|
leafCount?&leafSegment:NULL,
|
|
leafCount
|
|
);
|
|
|
|
FreeText (strCopy);
|
|
FreeText (fixedKey);
|
|
|
|
if (HadLeaf) {
|
|
*HadLeaf = (value != NULL);
|
|
}
|
|
|
|
return handle;
|
|
}
|
|
|
|
|
|
PTSTR
|
|
pCopyToDest (
|
|
IN PTSTR Destination, OPTIONAL
|
|
IN CHARTYPE Char,
|
|
IN PUINT CharNr
|
|
)
|
|
{
|
|
UINT len = 1;
|
|
|
|
#ifdef UNICODE
|
|
|
|
if (Destination) {
|
|
*Destination++ = Char;
|
|
}
|
|
|
|
(*CharNr) ++;
|
|
return Destination;
|
|
|
|
#else
|
|
|
|
if (IsCharLeadByte ((INT) Char)) {
|
|
len ++;
|
|
}
|
|
|
|
if (Destination) {
|
|
CopyMemory (Destination, &Char, len);
|
|
Destination += len;
|
|
}
|
|
|
|
(*CharNr) += len;
|
|
return Destination;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
// 1->? (if node, no \ or ., if leaf, no .), 2->* (if node, no \ or ., if leaf, no .) 3->* (no \) 4->* (unlimited)
|
|
UINT
|
|
pGetMode (
|
|
IN PCTSTR Source,
|
|
IN BOOL NodePattern,
|
|
IN BOOL PatternAfterWack,
|
|
IN BOOL FirstChar
|
|
)
|
|
{
|
|
UINT ch;
|
|
BOOL end = FALSE;
|
|
UINT mode = 0;
|
|
|
|
ch = _tcsnextc (Source);
|
|
|
|
while (ch) {
|
|
|
|
switch (ch) {
|
|
|
|
case TEXT('?'):
|
|
if (mode < 1) {
|
|
mode = 1;
|
|
}
|
|
break;
|
|
|
|
case TEXT('*'):
|
|
if (NodePattern) {
|
|
if (mode < 3) {
|
|
mode = 3;
|
|
}
|
|
} else {
|
|
if (mode < 4) {
|
|
mode = 4;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case TEXT('\\'):
|
|
if (NodePattern) {
|
|
if (mode < 2) {
|
|
mode = 2;
|
|
}
|
|
}
|
|
end = TRUE;
|
|
break;
|
|
|
|
case TEXT('.'):
|
|
if (mode < 2) {
|
|
mode = 2;
|
|
}
|
|
end = TRUE;
|
|
break;
|
|
|
|
default:
|
|
end = TRUE;
|
|
}
|
|
|
|
if (end) {
|
|
break;
|
|
}
|
|
|
|
Source = _tcsinc (Source);
|
|
ch = _tcsnextc (Source);
|
|
}
|
|
|
|
if (!ch) {
|
|
if ((PatternAfterWack || NodePattern) && (mode == 3)) {
|
|
mode = 4;
|
|
}
|
|
|
|
if (mode < 2) {
|
|
mode = 2;
|
|
}
|
|
}
|
|
|
|
if (FirstChar && (mode == 3)) {
|
|
mode = 4;
|
|
}
|
|
|
|
return mode;
|
|
}
|
|
|
|
|
|
BOOL
|
|
pCopyPatternEx (
|
|
IN UINT Mode,
|
|
IN PCTSTR *Source,
|
|
IN PTSTR *Destination,
|
|
IN PUINT CharNr,
|
|
IN BOOL NodePattern
|
|
)
|
|
{
|
|
CHARTYPE ch;
|
|
BOOL end = FALSE;
|
|
INT numChars = 0;
|
|
UINT chars;
|
|
TCHAR buffer [MAX_PATH] = TEXT("");
|
|
|
|
ch = (CHARTYPE) _tcsnextc (*Source);
|
|
|
|
while (ch) {
|
|
|
|
switch (ch) {
|
|
|
|
case TEXT('*'):
|
|
if (Mode == 1) {
|
|
end = TRUE;
|
|
break;
|
|
}
|
|
|
|
numChars = -1;
|
|
break;
|
|
|
|
case TEXT('?'):
|
|
if (numChars >= 0) {
|
|
numChars ++;
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
end = TRUE;
|
|
break;
|
|
}
|
|
|
|
if (end) {
|
|
break;
|
|
}
|
|
|
|
*Source = _tcsinc (*Source);
|
|
ch = (CHARTYPE) _tcsnextc (*Source);
|
|
}
|
|
|
|
// 1->? (if node, no \ or ., if leaf, no .), 2->* (if node, no \ or ., if leaf, no .) 3->* (no \) 4->* (unlimited)
|
|
switch (Mode) {
|
|
|
|
case 1:
|
|
if (NodePattern) {
|
|
if (numChars > 0) {
|
|
wsprintf (buffer, TEXT("?[%d:!(\\,.)]"), numChars);
|
|
} else {
|
|
wsprintf (buffer, TEXT("?[!(\\,.)]"));
|
|
}
|
|
} else {
|
|
if (numChars > 0) {
|
|
wsprintf (buffer, TEXT("?[%d:!(.)]"), numChars);
|
|
} else {
|
|
wsprintf (buffer, TEXT("?[!(.)]"));
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 2:
|
|
if (NodePattern) {
|
|
if (numChars > 0) {
|
|
wsprintf (buffer, TEXT("*[%d:!(\\,.)]"), numChars);
|
|
} else {
|
|
wsprintf (buffer, TEXT("*[!(\\,.)]"));
|
|
}
|
|
} else {
|
|
if (numChars > 0) {
|
|
wsprintf (buffer, TEXT("*[%d:!(.)]"), numChars);
|
|
} else {
|
|
wsprintf (buffer, TEXT("*[!(.)]"));
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 3:
|
|
if (numChars > 0) {
|
|
wsprintf (buffer, TEXT("*[%d:!(\\)]"), numChars);
|
|
} else {
|
|
wsprintf (buffer, TEXT("*[!(\\)]"));
|
|
}
|
|
break;
|
|
|
|
case 4:
|
|
if (numChars > 0) {
|
|
wsprintf (buffer, TEXT("*[%d:]"), numChars);
|
|
} else {
|
|
wsprintf (buffer, TEXT("*[]"));
|
|
}
|
|
break;
|
|
|
|
default:
|
|
MYASSERT (FALSE);
|
|
}
|
|
|
|
chars = TcharCount (buffer);
|
|
if (CharNr) {
|
|
*CharNr += chars;
|
|
}
|
|
|
|
if (Destination && *Destination) {
|
|
StringCopy (*Destination, buffer);
|
|
*Destination += chars;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
pCopyPattern (
|
|
IN PCTSTR *Source,
|
|
IN PTSTR *Destination,
|
|
IN PUINT CharNr,
|
|
IN BOOL NodePattern,
|
|
IN BOOL PatternAfterWack,
|
|
IN BOOL FirstChar
|
|
)
|
|
{
|
|
// 1->? (if node, no \ or ., if leaf, no .), 2->* (if node, no \ or ., if leaf, no .) 3->* (no \) 4->* (unlimited)
|
|
UINT mode = 0;
|
|
PTSTR result = NULL;
|
|
|
|
mode = pGetMode (*Source, NodePattern, PatternAfterWack, FirstChar);
|
|
|
|
return pCopyPatternEx (mode, Source, Destination, CharNr, NodePattern);
|
|
}
|
|
|
|
|
|
BOOL
|
|
pFixPattern (
|
|
IN PCTSTR Source,
|
|
OUT PTSTR Destination, OPTIONAL
|
|
OUT PUINT DestinationChars, OPTIONAL
|
|
IN BOOL PatternsNotAllowed,
|
|
IN BOOL TruncateAtPattern,
|
|
IN BOOL NodePattern
|
|
)
|
|
{
|
|
UINT chars = 1;
|
|
UINT lastChars = 0;
|
|
PTSTR lastWack = NULL;
|
|
BOOL end = FALSE;
|
|
BOOL result = TRUE;
|
|
BOOL patternAfterWack = FALSE;
|
|
BOOL firstChar = TRUE;
|
|
CHARTYPE ch;
|
|
|
|
if (Destination) {
|
|
*Destination = 0;
|
|
}
|
|
|
|
ch = (CHARTYPE) _tcsnextc (Source);
|
|
while (ch) {
|
|
|
|
switch (ch) {
|
|
case TEXT('*'):
|
|
case TEXT('?'):
|
|
if (TruncateAtPattern) {
|
|
if (lastWack) {
|
|
*lastWack = 0;
|
|
chars = lastChars;
|
|
}
|
|
end = TRUE;
|
|
} else if (PatternsNotAllowed) {
|
|
result = FALSE;
|
|
Destination = pCopyToDest (Destination, TEXT('^'), &chars);
|
|
Destination = pCopyToDest (Destination, ch, &chars);
|
|
Source = _tcsinc (Source);
|
|
} else {
|
|
if (lastWack && (_tcsinc (lastWack) == Destination)) {
|
|
patternAfterWack = TRUE;
|
|
} else {
|
|
patternAfterWack = FALSE;
|
|
}
|
|
pCopyPattern (&Source, Destination?&Destination:NULL, &chars, NodePattern, patternAfterWack, firstChar);
|
|
}
|
|
break;
|
|
|
|
case TEXT('\020'):
|
|
case TEXT('<'):
|
|
case TEXT('>'):
|
|
case TEXT(','):
|
|
case TEXT('^'):
|
|
Destination = pCopyToDest (Destination, TEXT('^'), &chars);
|
|
Destination = pCopyToDest (Destination, ch, &chars);
|
|
Source = _tcsinc (Source);
|
|
break;
|
|
|
|
case TEXT('\\'):
|
|
if (NodePattern) {
|
|
lastWack = Destination;
|
|
lastChars = chars;
|
|
}
|
|
|
|
Destination = pCopyToDest (Destination, ch, &chars);
|
|
Source = _tcsinc (Source);
|
|
break;
|
|
|
|
case TEXT('.'):
|
|
if (!NodePattern) {
|
|
lastWack = Destination;
|
|
lastChars = chars;
|
|
}
|
|
|
|
Destination = pCopyToDest (Destination, ch, &chars);
|
|
Source = _tcsinc (Source);
|
|
break;
|
|
|
|
default:
|
|
Destination = pCopyToDest (Destination, ch, &chars);
|
|
Source = _tcsinc (Source);
|
|
break;
|
|
}
|
|
|
|
firstChar = FALSE;
|
|
|
|
if (end) {
|
|
break;
|
|
}
|
|
|
|
ch = (CHARTYPE) _tcsnextc (Source);
|
|
}
|
|
|
|
if (Destination) {
|
|
*Destination = 0;
|
|
}
|
|
|
|
if (DestinationChars) {
|
|
*DestinationChars = chars;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
MIG_OBJECTSTRINGHANDLE
|
|
TurnFileStringIntoHandle (
|
|
IN PCTSTR String,
|
|
IN DWORD Flags
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
TurnFileStringIntoHandle converts a file specification from the script
|
|
syntax into a cobra object.
|
|
|
|
Arguments:
|
|
|
|
String - Specifies the file string in the script syntax.
|
|
The string must be in the following format:
|
|
|
|
<directory>\<file>
|
|
|
|
Both parts are optional. The Flags member indicates how String
|
|
is parsed.
|
|
|
|
Flags - Specifies zero or more of the following flags:
|
|
|
|
PFF_NO_PATTERNS_ALLOWED - String cannot contain any wildcard
|
|
characters.
|
|
|
|
PFF_COMPUTE_BASE - Returns the directory portion of the string,
|
|
and truncates the directory at the first
|
|
wildcard if necessary. Truncation is done
|
|
at the backslashes only.
|
|
|
|
PFF_NO_SUBDIR_PATTERN - Do not include a trailing \*, even if
|
|
it was specified in String.
|
|
|
|
PFF_NO_LEAF_PATTERN - Do not include a * for the leaf when
|
|
String does not contain a file name.
|
|
If a file name is specified, include it.
|
|
|
|
PFF_PATTERN_IS_DIR - String does not specify a file name. It
|
|
is a directory only. The leaf portion of
|
|
the object string will be a *.
|
|
|
|
PFF_NO_LEAF_AT_ALL - Will return an object string that has a
|
|
node only, and no leaf specified at all.
|
|
|
|
|
|
Return Value:
|
|
|
|
A cobra object handle, or NULL if conversion failed.
|
|
|
|
--*/
|
|
|
|
{
|
|
PTSTR p;
|
|
PTSTR fileCopy = NULL;
|
|
MIG_SEGMENTS nodeSegment[2];
|
|
MIG_SEGMENTS leafSegment;
|
|
MIG_OBJECTSTRINGHANDLE result = NULL;
|
|
BOOL tree = FALSE;
|
|
PTSTR file = NULL;
|
|
UINT nodeCount;
|
|
UINT leafCount;
|
|
UINT charsInPattern;
|
|
BOOL noPatternsAllowed;
|
|
BOOL computeBaseNode;
|
|
BOOL noSubDirPattern;
|
|
BOOL noLeafPattern;
|
|
BOOL forceLeafToStar;
|
|
PCTSTR node;
|
|
PCTSTR leaf = NULL;
|
|
PTSTR fixedNode = NULL;
|
|
PTSTR fixedLeaf = NULL;
|
|
PTSTR tempCopy;
|
|
BOOL patternError = FALSE;
|
|
|
|
noPatternsAllowed = (Flags & PFF_NO_PATTERNS_ALLOWED) == PFF_NO_PATTERNS_ALLOWED;
|
|
computeBaseNode = (Flags & PFF_COMPUTE_BASE) == PFF_COMPUTE_BASE;
|
|
noSubDirPattern = (Flags & PFF_NO_SUBDIR_PATTERN) == PFF_NO_SUBDIR_PATTERN;
|
|
noLeafPattern = (Flags & PFF_NO_LEAF_PATTERN) == PFF_NO_LEAF_PATTERN;
|
|
forceLeafToStar = (Flags & PFF_PATTERN_IS_DIR) == PFF_PATTERN_IS_DIR;
|
|
|
|
//
|
|
// Divide pattern into node and leaf
|
|
//
|
|
|
|
tempCopy = DuplicateText (SkipSpace (String));
|
|
p = (PTSTR) SkipSpaceR (tempCopy, NULL);
|
|
if (p) {
|
|
p = _tcsinc (p);
|
|
*p = 0;
|
|
}
|
|
|
|
node = tempCopy;
|
|
|
|
if (!forceLeafToStar) {
|
|
p = (PTSTR) FindLastWack (tempCopy);
|
|
|
|
if (p) {
|
|
|
|
leaf = SkipSpace (p + 1);
|
|
*p = 0;
|
|
|
|
p = (PTSTR) SkipSpaceR (tempCopy, NULL);
|
|
if (p) {
|
|
p = _tcsinc (p);
|
|
*p = 0;
|
|
}
|
|
|
|
} else {
|
|
if (!_tcschr (tempCopy, TEXT(':'))) {
|
|
node = NULL;
|
|
leaf = tempCopy;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Convert all ? wildcard chars to be compatibile with NT's file system
|
|
// Escape all [ characters that follow wildcards
|
|
//
|
|
|
|
if (node) {
|
|
|
|
p = (PTSTR) GetEndOfString (node);
|
|
p = _tcsdec2 (node, p);
|
|
|
|
if (p) {
|
|
if (_tcsnextc (p) == TEXT('*')) {
|
|
tree = TRUE;
|
|
|
|
p = _tcsdec2 (node, p);
|
|
if (p && _tcsnextc (p) == TEXT('\\')) {
|
|
*p = 0;
|
|
} else {
|
|
tree = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!pFixPattern (
|
|
node,
|
|
NULL,
|
|
&charsInPattern,
|
|
noPatternsAllowed,
|
|
computeBaseNode,
|
|
TRUE
|
|
)) {
|
|
patternError = TRUE;
|
|
}
|
|
|
|
if (charsInPattern) {
|
|
fixedNode = AllocText (charsInPattern + 1);
|
|
|
|
pFixPattern (
|
|
node,
|
|
fixedNode,
|
|
NULL,
|
|
noPatternsAllowed,
|
|
computeBaseNode,
|
|
TRUE
|
|
);
|
|
}
|
|
}
|
|
|
|
if (leaf && !computeBaseNode) {
|
|
|
|
if (!pFixPattern (
|
|
leaf,
|
|
NULL,
|
|
&charsInPattern,
|
|
noPatternsAllowed,
|
|
FALSE,
|
|
FALSE
|
|
)) {
|
|
patternError = TRUE;
|
|
}
|
|
|
|
if (charsInPattern) {
|
|
fixedLeaf = AllocText (charsInPattern + 1);
|
|
|
|
pFixPattern (
|
|
leaf,
|
|
fixedLeaf,
|
|
NULL,
|
|
noPatternsAllowed,
|
|
FALSE,
|
|
FALSE
|
|
);
|
|
}
|
|
}
|
|
|
|
FreeText (tempCopy);
|
|
INVALID_POINTER (tempCopy);
|
|
|
|
//
|
|
// Create the pattern string. Start by preparing the node segments.
|
|
//
|
|
|
|
nodeSegment[0].Segment = fixedNode;
|
|
nodeSegment[0].IsPattern = TRUE; // normally FALSE, but because the pattern charset is
|
|
// exclusive of the valid filename charset, we allow
|
|
// patterns to be in the node
|
|
|
|
nodeSegment[1].Segment = TEXT("\\*");
|
|
nodeSegment[1].IsPattern = TRUE;
|
|
|
|
if (!fixedNode) {
|
|
nodeCount = 0;
|
|
} else if (!tree || noSubDirPattern || noPatternsAllowed) {
|
|
nodeCount = 1; // just the node, not its subnodes
|
|
} else {
|
|
nodeCount = 2; // the node and its subnodes
|
|
}
|
|
|
|
//
|
|
// Prepare the leaf segments. We want all leaves, a specific leaf, or
|
|
// no leaf at all.
|
|
//
|
|
|
|
leafSegment.Segment = fixedLeaf;
|
|
leafSegment.IsPattern = TRUE;
|
|
leafCount = 1;
|
|
|
|
MYASSERT (!forceLeafToStar || !fixedLeaf);
|
|
|
|
if (!fixedLeaf) {
|
|
if (noLeafPattern || noPatternsAllowed) {
|
|
leafCount = 0;
|
|
} else {
|
|
leafSegment.Segment = TEXT("*");
|
|
}
|
|
}
|
|
|
|
if (nodeCount || leafCount) {
|
|
|
|
if ((fixedNode && *fixedNode) || (fixedLeaf && *fixedLeaf)) {
|
|
result = IsmCreateObjectPattern (
|
|
nodeCount ? nodeSegment : NULL,
|
|
nodeCount,
|
|
leafCount ? &leafSegment : NULL,
|
|
leafCount
|
|
);
|
|
}
|
|
}
|
|
|
|
FreeText (fixedNode);
|
|
FreeText (fixedLeaf);
|
|
|
|
return result;
|
|
}
|
|
|
|
MIG_OBJECTSTRINGHANDLE
|
|
TurnIniSpecIntoHandle (
|
|
IN PCTSTR IniFile,
|
|
IN PCTSTR Section,
|
|
IN PCTSTR Key,
|
|
IN BOOL NodePatternsAllowed,
|
|
IN BOOL LeafPatternsAllowed
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
TurnIniSpecIntoHandle converts a ini file specification from the script
|
|
syntax into a cobra object.
|
|
|
|
Arguments:
|
|
|
|
IniFile- Specifies the ini file in the script syntax.
|
|
The string must be a full INI file specification
|
|
|
|
Section- Specifies the full section or the section pattern
|
|
|
|
Key - Specifies the full key or the key pattern
|
|
|
|
PatternsAllowed - if not, the function will compute the base object
|
|
|
|
Return Value:
|
|
|
|
A cobra object handle, or NULL if conversion failed.
|
|
|
|
--*/
|
|
|
|
{
|
|
UINT charsInPattern = 0;
|
|
PTSTR iniNode = NULL;
|
|
PTSTR iniLeaf = NULL;
|
|
PTSTR fixedIniNode = NULL;
|
|
PTSTR fixedIniLeaf = NULL;
|
|
PTSTR fixedSect = NULL;
|
|
PTSTR fixedKey = NULL;
|
|
PCTSTR sectKey = NULL;
|
|
PCTSTR leaf = NULL;
|
|
MIG_SEGMENTS nodePat[1];
|
|
MIG_SEGMENTS leafPat[1];
|
|
UINT nrSegNode = 0;
|
|
UINT nrSegLeaf = 0;
|
|
MIG_OBJECTSTRINGHANDLE result = NULL;
|
|
|
|
if (IniFile) {
|
|
iniNode = DuplicatePathString (IniFile, 0);
|
|
if (!iniNode) {
|
|
// out of memory?
|
|
return NULL;
|
|
}
|
|
|
|
iniLeaf = _tcsrchr (iniNode, TEXT('\\'));
|
|
if (iniLeaf) {
|
|
*iniLeaf = 0;
|
|
iniLeaf ++;
|
|
} else {
|
|
// this was only a leaf specification
|
|
iniLeaf = iniNode;
|
|
iniNode = NULL;
|
|
}
|
|
}
|
|
|
|
if (iniNode) {
|
|
// let's fix the iniNode.
|
|
if (!pFixPattern (
|
|
iniNode,
|
|
NULL,
|
|
&charsInPattern,
|
|
!NodePatternsAllowed,
|
|
!NodePatternsAllowed,
|
|
TRUE
|
|
)) {
|
|
// something is wrong with this INI node specification.
|
|
// The rule is likely invalid
|
|
return NULL;
|
|
}
|
|
|
|
fixedIniNode = AllocText (charsInPattern + 1);
|
|
if (!fixedIniNode) {
|
|
return NULL;
|
|
}
|
|
|
|
if (!pFixPattern (
|
|
iniNode,
|
|
fixedIniNode,
|
|
NULL,
|
|
!NodePatternsAllowed,
|
|
!NodePatternsAllowed,
|
|
TRUE
|
|
)) {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
if (iniLeaf) {
|
|
// let's fix the iniLeaf.
|
|
if (!pFixPattern (
|
|
iniLeaf,
|
|
NULL,
|
|
&charsInPattern,
|
|
!LeafPatternsAllowed,
|
|
!LeafPatternsAllowed,
|
|
FALSE
|
|
)) {
|
|
// something is wrong with this INI dir specification.
|
|
// The rule is likely invalid
|
|
return NULL;
|
|
}
|
|
|
|
fixedIniLeaf = AllocText (charsInPattern + 1);
|
|
if (!fixedIniLeaf) {
|
|
return NULL;
|
|
}
|
|
|
|
if (!pFixPattern (
|
|
iniLeaf,
|
|
fixedIniLeaf,
|
|
NULL,
|
|
!LeafPatternsAllowed,
|
|
!LeafPatternsAllowed,
|
|
FALSE
|
|
)) {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
// now let's fix the section specification. If it contains any pattern and patterns
|
|
// are not allowed we will leave it NULL
|
|
if (Section) {
|
|
if (pFixPattern (
|
|
Section,
|
|
NULL,
|
|
&charsInPattern,
|
|
!LeafPatternsAllowed,
|
|
FALSE,
|
|
FALSE
|
|
)) {
|
|
fixedSect = AllocText (charsInPattern + 1);
|
|
if (fixedSect) {
|
|
pFixPattern (
|
|
Section,
|
|
fixedSect,
|
|
NULL,
|
|
!LeafPatternsAllowed,
|
|
FALSE,
|
|
FALSE
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
// now let's fix the key specification. If it contains any pattern and patterns
|
|
// are not allowed we will leave it NULL
|
|
if (Key) {
|
|
if (pFixPattern (
|
|
Key,
|
|
NULL,
|
|
&charsInPattern,
|
|
!LeafPatternsAllowed,
|
|
FALSE,
|
|
FALSE
|
|
)) {
|
|
fixedKey = AllocText (charsInPattern + 1);
|
|
if (fixedKey) {
|
|
pFixPattern (
|
|
Key,
|
|
fixedKey,
|
|
NULL,
|
|
!LeafPatternsAllowed,
|
|
FALSE,
|
|
FALSE
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
// finally let's build the object name
|
|
sectKey = JoinTextEx (NULL, fixedSect?fixedSect:TEXT(""), (fixedSect && fixedKey)?fixedKey:TEXT(""), TEXT("="), 0, NULL);
|
|
if (!sectKey) {
|
|
// something went wrong, let's get out of here
|
|
FreeText (fixedIniLeaf);
|
|
FreeText (fixedIniNode);
|
|
if (fixedSect) {
|
|
FreeText (fixedSect);
|
|
fixedSect = NULL;
|
|
}
|
|
if (fixedKey) {
|
|
FreeText (fixedKey);
|
|
fixedKey = NULL;
|
|
}
|
|
return NULL;
|
|
}
|
|
if (!LeafPatternsAllowed) {
|
|
if (iniLeaf && fixedIniLeaf && StringIMatch (fixedIniLeaf, iniLeaf)) {
|
|
leaf = JoinTextEx (NULL, fixedIniLeaf, sectKey, TEXT("\\"), 0, NULL);
|
|
} else {
|
|
leaf = JoinTextEx (NULL, TEXT(""), sectKey, TEXT("\\"), 0, NULL);
|
|
}
|
|
} else {
|
|
if (fixedIniLeaf) {
|
|
leaf = JoinTextEx (NULL, fixedIniLeaf, sectKey, TEXT("\\"), 0, NULL);
|
|
} else {
|
|
leaf = JoinTextEx (NULL, TEXT(""), sectKey, TEXT("\\"), 0, NULL);
|
|
}
|
|
}
|
|
if (!leaf) {
|
|
// something went wrong, let's get out of here
|
|
FreeText (fixedIniLeaf);
|
|
FreeText (fixedIniNode);
|
|
FreeText (sectKey);
|
|
if (fixedSect) {
|
|
FreeText (fixedSect);
|
|
fixedSect = NULL;
|
|
}
|
|
if (fixedKey) {
|
|
FreeText (fixedKey);
|
|
fixedKey = NULL;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
nodePat [0].Segment = fixedIniNode?fixedIniNode:TEXT("");
|
|
nodePat [0].IsPattern = TRUE;
|
|
nrSegNode ++;
|
|
leafPat [0].Segment = leaf;
|
|
leafPat [0].IsPattern = TRUE;
|
|
nrSegLeaf ++;
|
|
result = IsmCreateObjectPattern (nodePat, nrSegNode, leafPat, nrSegLeaf);
|
|
|
|
if (fixedIniLeaf) {
|
|
FreeText (fixedIniLeaf);
|
|
fixedIniLeaf = NULL;
|
|
}
|
|
if (fixedIniNode) {
|
|
FreeText (fixedIniNode);
|
|
fixedIniNode = NULL;
|
|
}
|
|
FreeText (sectKey);
|
|
FreeText (leaf);
|
|
if (fixedSect) {
|
|
FreeText (fixedSect);
|
|
fixedSect = NULL;
|
|
}
|
|
if (fixedKey) {
|
|
FreeText (fixedKey);
|
|
fixedKey = NULL;
|
|
}
|
|
|
|
if (iniNode) {
|
|
FreePathString (iniNode);
|
|
iniNode = NULL;
|
|
} else {
|
|
if (iniLeaf) {
|
|
FreePathString (iniLeaf);
|
|
iniLeaf = NULL;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
MIG_OBJECTSTRINGHANDLE
|
|
TurnCertSpecIntoHandle (
|
|
IN PCTSTR CertStore,
|
|
IN PCTSTR CertName,
|
|
IN BOOL PatternsAllowed
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
TurnIniSpecIntoHandle converts a ini file specification from the script
|
|
syntax into a cobra object.
|
|
|
|
Arguments:
|
|
|
|
IniFile- Specifies the ini file in the script syntax.
|
|
The string must be a full INI file specification
|
|
|
|
Section- Specifies the full section or the section pattern
|
|
|
|
Key - Specifies the full key or the key pattern
|
|
|
|
PatternsAllowed - if not, the function will compute the base object
|
|
|
|
Return Value:
|
|
|
|
A cobra object handle, or NULL if conversion failed.
|
|
|
|
--*/
|
|
|
|
{
|
|
UINT charsInPattern = 0;
|
|
PTSTR fixedStore = NULL;
|
|
PTSTR fixedName = NULL;
|
|
PCTSTR leaf = NULL;
|
|
MIG_OBJECTSTRINGHANDLE result = NULL;
|
|
|
|
// let's fix the certificate store. We know that no patterns are allowed here,
|
|
// so we will just return NULL if we detect some pattern
|
|
if (!pFixPattern (
|
|
CertStore,
|
|
NULL,
|
|
&charsInPattern,
|
|
TRUE,
|
|
TRUE,
|
|
TRUE
|
|
)) {
|
|
// something is wrong with this store specification.
|
|
// The rule is likely invalid
|
|
return NULL;
|
|
}
|
|
|
|
if (charsInPattern != (TcharCount (CertStore) + 1)) {
|
|
// something is wrong with this store specification.
|
|
// The rule is likely invalid
|
|
return NULL;
|
|
}
|
|
|
|
fixedStore = AllocText (charsInPattern + 1);
|
|
|
|
pFixPattern (
|
|
CertStore,
|
|
fixedStore,
|
|
NULL,
|
|
TRUE,
|
|
TRUE,
|
|
TRUE
|
|
);
|
|
|
|
if (!StringIMatch (CertStore, fixedStore)) {
|
|
// something is wrong with this store specification.
|
|
// The rule is likely invalid
|
|
return NULL;
|
|
}
|
|
|
|
FreeText (fixedStore);
|
|
|
|
// now let's fix the certificate specification. If it contains any pattern and patterns
|
|
// are not allowed we will leave it NULL
|
|
if (CertName) {
|
|
if (pFixPattern (
|
|
CertName,
|
|
NULL,
|
|
&charsInPattern,
|
|
!PatternsAllowed,
|
|
FALSE,
|
|
FALSE
|
|
)) {
|
|
fixedName = AllocText (charsInPattern + 1);
|
|
if (fixedName) {
|
|
pFixPattern (
|
|
CertName,
|
|
fixedName,
|
|
NULL,
|
|
!PatternsAllowed,
|
|
FALSE,
|
|
FALSE
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
result = IsmCreateSimpleObjectPattern (CertStore, FALSE, fixedName?fixedName:TEXT(""), TRUE);
|
|
if (fixedName) {
|
|
FreeText (fixedName);
|
|
fixedName = NULL;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
BOOL
|
|
pAllocRegistryScriptType (
|
|
IN OUT PATTRIB_DATA AttribData
|
|
)
|
|
{
|
|
TCHAR expandBuffer[4096];
|
|
MIG_CONTENT objectContent;
|
|
DWORD type;
|
|
DWORD size;
|
|
MULTISZ_ENUM multiSzEnum;
|
|
PTSTR ptr;
|
|
|
|
if (!AttribData) {
|
|
SetLastError (ERROR_INVALID_DATA);
|
|
return FALSE;
|
|
}
|
|
|
|
// verify that we have some registry
|
|
if (!AttribData->ScriptSpecifiedObject) {
|
|
SetLastError (ERROR_INVALID_DATA);
|
|
return FALSE;
|
|
}
|
|
|
|
// try to create encoded string
|
|
AttribData->ObjectTypeId = g_RegType;
|
|
AttribData->ObjectName = TurnRegStringIntoHandle (
|
|
AttribData->ScriptSpecifiedObject,
|
|
FALSE,
|
|
NULL
|
|
);
|
|
|
|
if (!AttribData->ObjectName) {
|
|
if (GetLastError() == ERROR_SUCCESS) {
|
|
SetLastError (ERROR_INVALID_DATA);
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
// try to acqure the object
|
|
if (IsmAcquireObject (
|
|
AttribData->ObjectTypeId,
|
|
AttribData->ObjectName,
|
|
&objectContent
|
|
)) {
|
|
|
|
AttribData->ObjectContent = IsmGetMemory (sizeof (MIG_CONTENT));
|
|
CopyMemory (AttribData->ObjectContent, &objectContent, sizeof (MIG_CONTENT));
|
|
|
|
// finally, we want to prepare the return string
|
|
if (!AttribData->ObjectContent->ContentInFile &&
|
|
(AttribData->ObjectContent->Details.DetailsSize == sizeof (DWORD)) &&
|
|
AttribData->ObjectContent->MemoryContent.ContentBytes
|
|
) {
|
|
|
|
type = *((PDWORD) AttribData->ObjectContent->Details.DetailsData);
|
|
|
|
switch (type) {
|
|
case REG_SZ:
|
|
size = SizeOfString ((PCTSTR) AttribData->ObjectContent->MemoryContent.ContentBytes);
|
|
AttribData->ReturnString = (PCTSTR) IsmGetMemory (size);
|
|
StringCopy (
|
|
(PTSTR) AttribData->ReturnString,
|
|
(PCTSTR) AttribData->ObjectContent->MemoryContent.ContentBytes
|
|
);
|
|
break;
|
|
case REG_EXPAND_SZ:
|
|
// we need to expand the content. This will be the return string
|
|
AttribData->ReturnString = IsmExpandEnvironmentString (
|
|
AttribData->Platform,
|
|
S_SYSENVVAR_GROUP,
|
|
(PCTSTR) AttribData->ObjectContent->MemoryContent.ContentBytes,
|
|
NULL
|
|
);
|
|
if (!AttribData->ReturnString) {
|
|
AttribData->ReturnString = IsmDuplicateString ((PCTSTR) AttribData->ObjectContent->MemoryContent.ContentBytes);
|
|
}
|
|
break;
|
|
case REG_MULTI_SZ:
|
|
size = SizeOfMultiSz ((PCTSTR) AttribData->ObjectContent->MemoryContent.ContentBytes);
|
|
AttribData->ReturnString = (PCTSTR) IsmGetMemory (size);
|
|
((PTSTR)AttribData->ReturnString) [0] = 0;
|
|
if (EnumFirstMultiSz (&multiSzEnum, (PCTSTR) AttribData->ObjectContent->MemoryContent.ContentBytes)) {
|
|
do {
|
|
StringCat (
|
|
(PTSTR)AttribData->ReturnString,
|
|
multiSzEnum.CurrentString
|
|
);
|
|
StringCat (
|
|
(PTSTR)AttribData->ReturnString,
|
|
TEXT(";")
|
|
);
|
|
} while (EnumNextMultiSz (&multiSzEnum));
|
|
}
|
|
break;
|
|
case REG_DWORD:
|
|
case REG_DWORD_BIG_ENDIAN:
|
|
AttribData->ReturnString = (PCTSTR) IsmGetMemory ((sizeof (DWORD) * 2 + 3) * sizeof (TCHAR));
|
|
wsprintf (
|
|
(PTSTR) AttribData->ReturnString,
|
|
TEXT("0x%08X"),
|
|
*((PDWORD) AttribData->ObjectContent->MemoryContent.ContentBytes)
|
|
);
|
|
break;
|
|
default:
|
|
AttribData->ReturnString = (PCTSTR) IsmGetMemory ((AttribData->ObjectContent->
|
|
MemoryContent.ContentSize * 3 *
|
|
sizeof (TCHAR)) + sizeof (TCHAR)
|
|
);
|
|
ptr = (PTSTR) AttribData->ReturnString;
|
|
*ptr = 0;
|
|
size = 0;
|
|
while (size < AttribData->ObjectContent->MemoryContent.ContentSize) {
|
|
wsprintf (ptr, TEXT("%02X"), *(AttribData->ObjectContent->MemoryContent.ContentBytes + size));
|
|
size ++;
|
|
ptr = GetEndOfString (ptr);
|
|
if (size < AttribData->ObjectContent->MemoryContent.ContentSize) {
|
|
StringCopy (ptr, TEXT(","));
|
|
ptr = GetEndOfString (ptr);
|
|
}
|
|
}
|
|
}
|
|
} else if (IsmIsObjectHandleNodeOnly (AttribData->ObjectName)) {
|
|
//
|
|
// Node only case
|
|
//
|
|
|
|
AttribData->ReturnString = (PCTSTR) IsmGetMemory (sizeof (TCHAR));
|
|
ptr = (PTSTR) AttribData->ReturnString;
|
|
*ptr = 0;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
pAllocFileScriptType (
|
|
IN OUT PATTRIB_DATA AttribData
|
|
)
|
|
{
|
|
MIG_OBJECTSTRINGHANDLE objectName;
|
|
MIG_OBJECTSTRINGHANDLE objectNameLong;
|
|
PCTSTR nativeNameLong;
|
|
MIG_CONTENT objectContent;
|
|
PCTSTR sanitizedPath = NULL;
|
|
PCTSTR longFileName = NULL;
|
|
|
|
if (!AttribData) {
|
|
SetLastError (ERROR_INVALID_DATA);
|
|
return FALSE;
|
|
}
|
|
|
|
// verify that we have some registry
|
|
if (!AttribData->ScriptSpecifiedObject) {
|
|
SetLastError (ERROR_INVALID_DATA);
|
|
return FALSE;
|
|
}
|
|
|
|
sanitizedPath = SanitizePath (AttribData->ScriptSpecifiedObject);
|
|
if (!sanitizedPath) {
|
|
if (GetLastError() == ERROR_SUCCESS) {
|
|
SetLastError (ERROR_INVALID_DATA);
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
longFileName = sanitizedPath;
|
|
|
|
// let's get the long file name for this. We need to call
|
|
// ISM for this because we might be on the wrong platform
|
|
objectName = TurnFileStringIntoHandle (
|
|
longFileName,
|
|
PFF_NO_LEAF_PATTERN
|
|
);
|
|
if (objectName) {
|
|
objectNameLong = IsmGetLongName (MIG_FILE_TYPE|AttribData->Platform, objectName);
|
|
if (objectNameLong) {
|
|
nativeNameLong = IsmGetNativeObjectName (MIG_FILE_TYPE|AttribData->Platform, objectNameLong);
|
|
if (nativeNameLong) {
|
|
longFileName = DuplicatePathString (nativeNameLong, 0);
|
|
IsmReleaseMemory (nativeNameLong);
|
|
}
|
|
IsmDestroyObjectHandle (objectNameLong);
|
|
}
|
|
IsmDestroyObjectHandle (objectName);
|
|
}
|
|
|
|
// try to create encoded string
|
|
AttribData->ObjectTypeId = g_FileType;
|
|
AttribData->ObjectName = TurnFileStringIntoHandle (
|
|
longFileName,
|
|
PFF_NO_LEAF_PATTERN
|
|
);
|
|
|
|
if (!AttribData->ObjectName) {
|
|
if (longFileName != sanitizedPath) {
|
|
FreePathString (longFileName);
|
|
longFileName = NULL;
|
|
}
|
|
FreePathString (sanitizedPath);
|
|
if (GetLastError() == ERROR_SUCCESS) {
|
|
SetLastError (ERROR_INVALID_DATA);
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
// try to acqure the object
|
|
if (IsmAcquireObject (
|
|
AttribData->ObjectTypeId,
|
|
AttribData->ObjectName,
|
|
&objectContent
|
|
)) {
|
|
|
|
AttribData->ObjectContent = IsmGetMemory (sizeof (MIG_CONTENT));
|
|
CopyMemory (AttribData->ObjectContent, &objectContent, sizeof (MIG_CONTENT));
|
|
|
|
AttribData->ReturnString = IsmGetMemory (SizeOfString (longFileName));
|
|
StringCopy ((PTSTR) AttribData->ReturnString, longFileName);
|
|
}
|
|
|
|
if (longFileName != sanitizedPath) {
|
|
FreePathString (longFileName);
|
|
longFileName = NULL;
|
|
}
|
|
FreePathString (sanitizedPath);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
pAllocDirectoryScriptType (
|
|
IN OUT PATTRIB_DATA AttribData
|
|
)
|
|
{
|
|
MIG_OBJECTSTRINGHANDLE objectName;
|
|
MIG_OBJECTSTRINGHANDLE objectNameLong;
|
|
PCTSTR nativeNameLong;
|
|
MIG_CONTENT objectContent;
|
|
PCTSTR sanitizedPath;
|
|
PCTSTR longFileName = NULL;
|
|
|
|
if (!AttribData) {
|
|
SetLastError (ERROR_INVALID_DATA);
|
|
return FALSE;
|
|
}
|
|
|
|
// verify that we have some registry
|
|
if (!AttribData->ScriptSpecifiedObject) {
|
|
SetLastError (ERROR_INVALID_DATA);
|
|
return FALSE;
|
|
}
|
|
|
|
sanitizedPath = SanitizePath (AttribData->ScriptSpecifiedObject);
|
|
|
|
if (!sanitizedPath) {
|
|
SetLastError (ERROR_INVALID_DATA);
|
|
return FALSE;
|
|
}
|
|
|
|
longFileName = sanitizedPath;
|
|
|
|
// let's get the long file name for this. We need to call
|
|
// ISM for this because we might be on the wrong platform
|
|
objectName = TurnFileStringIntoHandle (
|
|
sanitizedPath,
|
|
PFF_PATTERN_IS_DIR | PFF_NO_LEAF_AT_ALL
|
|
);
|
|
if (objectName) {
|
|
objectNameLong = IsmGetLongName (MIG_FILE_TYPE|AttribData->Platform, objectName);
|
|
if (objectNameLong) {
|
|
nativeNameLong = IsmGetNativeObjectName (MIG_FILE_TYPE|AttribData->Platform, objectNameLong);
|
|
if (nativeNameLong) {
|
|
longFileName = DuplicatePathString (nativeNameLong, 0);
|
|
IsmReleaseMemory (nativeNameLong);
|
|
}
|
|
IsmDestroyObjectHandle (objectNameLong);
|
|
}
|
|
IsmDestroyObjectHandle (objectName);
|
|
}
|
|
|
|
// try to create encoded string
|
|
AttribData->ObjectTypeId = g_FileType;
|
|
AttribData->ObjectName = TurnFileStringIntoHandle (
|
|
sanitizedPath,
|
|
PFF_PATTERN_IS_DIR | PFF_NO_LEAF_AT_ALL
|
|
);
|
|
|
|
if (!AttribData->ObjectName) {
|
|
if (longFileName != sanitizedPath) {
|
|
FreePathString (longFileName);
|
|
longFileName = NULL;
|
|
}
|
|
FreePathString (sanitizedPath);
|
|
if (GetLastError() == ERROR_SUCCESS) {
|
|
SetLastError (ERROR_INVALID_DATA);
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
// try to acqure the object
|
|
if (IsmAcquireObject (
|
|
AttribData->ObjectTypeId,
|
|
AttribData->ObjectName,
|
|
&objectContent
|
|
)) {
|
|
|
|
AttribData->ObjectContent = IsmGetMemory (sizeof (MIG_CONTENT));
|
|
CopyMemory (AttribData->ObjectContent, &objectContent, sizeof (MIG_CONTENT));
|
|
|
|
AttribData->ReturnString = IsmGetMemory (SizeOfString (longFileName));
|
|
StringCopy ((PTSTR) AttribData->ReturnString, longFileName);
|
|
}
|
|
|
|
if (longFileName != sanitizedPath) {
|
|
FreePathString (longFileName);
|
|
longFileName = NULL;
|
|
}
|
|
FreePathString (sanitizedPath);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
pFreeIsmObjectScriptType (
|
|
IN OUT PATTRIB_DATA AttribData
|
|
)
|
|
{
|
|
if (AttribData->ReturnString) {
|
|
IsmReleaseMemory (AttribData->ReturnString);
|
|
AttribData->ReturnString = NULL;
|
|
}
|
|
AttribData->ObjectTypeId = 0;
|
|
if (AttribData->ObjectName) {
|
|
IsmDestroyObjectHandle (AttribData->ObjectName);
|
|
AttribData->ObjectName = NULL;
|
|
}
|
|
if (AttribData->ObjectContent) {
|
|
IsmReleaseObject (AttribData->ObjectContent);
|
|
IsmReleaseMemory (AttribData->ObjectContent);
|
|
AttribData->ObjectContent = NULL;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
pAllocTextScriptType (
|
|
IN OUT PATTRIB_DATA AttribData
|
|
)
|
|
{
|
|
if (!AttribData) {
|
|
SetLastError (ERROR_INVALID_DATA);
|
|
return FALSE;
|
|
}
|
|
|
|
// verify that we have some registry
|
|
if (!AttribData->ScriptSpecifiedObject) {
|
|
SetLastError (ERROR_INVALID_DATA);
|
|
return FALSE;
|
|
}
|
|
|
|
AttribData->ReturnString = IsmGetMemory (SizeOfString (AttribData->ScriptSpecifiedObject));
|
|
StringCopy ((PTSTR) AttribData->ReturnString, AttribData->ScriptSpecifiedObject);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
pFreeTextScriptType (
|
|
IN OUT PATTRIB_DATA AttribData
|
|
)
|
|
{
|
|
if (AttribData->ReturnString) {
|
|
IsmReleaseMemory (AttribData->ReturnString);
|
|
AttribData->ReturnString = NULL;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
pAllocSystemScriptType (
|
|
IN OUT PATTRIB_DATA AttribData
|
|
)
|
|
{
|
|
PTSTR specificSection = NULL;
|
|
MIG_OSVERSIONINFO versionInfo;
|
|
UINT tchars;
|
|
BOOL detected = FALSE;
|
|
|
|
if (!AttribData) {
|
|
SetLastError (ERROR_INVALID_DATA);
|
|
return FALSE;
|
|
}
|
|
|
|
// verify that we have some registry
|
|
if (!AttribData->ScriptSpecifiedObject) {
|
|
SetLastError (ERROR_INVALID_DATA);
|
|
return FALSE;
|
|
}
|
|
|
|
if (!IsmGetOsVersionInfo (PLATFORM_SOURCE, &versionInfo)) {
|
|
return FALSE;
|
|
}
|
|
|
|
tchars = 1;
|
|
if (versionInfo.OsTypeName) {
|
|
tchars += TcharCount (versionInfo.OsTypeName) + 1;
|
|
}
|
|
if (versionInfo.OsMajorVersionName) {
|
|
tchars += TcharCount (versionInfo.OsMajorVersionName) + 1;
|
|
}
|
|
if (versionInfo.OsMinorVersionName) {
|
|
tchars += TcharCount (versionInfo.OsMinorVersionName);
|
|
}
|
|
|
|
specificSection = AllocText (tchars);
|
|
if (!specificSection) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (!detected && versionInfo.OsTypeName) {
|
|
|
|
wsprintf (
|
|
specificSection,
|
|
TEXT("%s"),
|
|
versionInfo.OsTypeName
|
|
);
|
|
if (StringIMatch (AttribData->ScriptSpecifiedObject, specificSection)) {
|
|
detected = TRUE;
|
|
}
|
|
|
|
if (!detected && versionInfo.OsMajorVersionName) {
|
|
|
|
wsprintf (
|
|
specificSection,
|
|
TEXT("%s.%s"),
|
|
versionInfo.OsTypeName,
|
|
versionInfo.OsMajorVersionName
|
|
);
|
|
if (StringIMatch (AttribData->ScriptSpecifiedObject, specificSection)) {
|
|
detected = TRUE;
|
|
}
|
|
|
|
if (!detected && versionInfo.OsMinorVersionName) {
|
|
wsprintf (
|
|
specificSection,
|
|
TEXT("%s.%s.%s"),
|
|
versionInfo.OsTypeName,
|
|
versionInfo.OsMajorVersionName,
|
|
versionInfo.OsMinorVersionName
|
|
);
|
|
if (StringIMatch (AttribData->ScriptSpecifiedObject, specificSection)) {
|
|
detected = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (detected) {
|
|
AttribData->ReturnString = IsmGetMemory (SizeOfString (AttribData->ScriptSpecifiedObject));
|
|
StringCopy ((PTSTR) AttribData->ReturnString, AttribData->ScriptSpecifiedObject);
|
|
}
|
|
|
|
FreeText (specificSection);
|
|
specificSection = NULL;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
pFreeSystemScriptType (
|
|
IN OUT PATTRIB_DATA AttribData
|
|
)
|
|
{
|
|
if (AttribData->ReturnString) {
|
|
IsmReleaseMemory (AttribData->ReturnString);
|
|
AttribData->ReturnString = NULL;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
pAllocIniFileScriptType (
|
|
IN OUT PATTRIB_DATA AttribData
|
|
)
|
|
{
|
|
PTSTR fileName = NULL;
|
|
PTSTR sectName = NULL;
|
|
PTSTR keyName = NULL;
|
|
PTSTR charPtr = NULL;
|
|
PTSTR result = NULL;
|
|
DWORD allocatedChars;
|
|
DWORD chars;
|
|
|
|
if (!AttribData) {
|
|
SetLastError (ERROR_INVALID_DATA);
|
|
return FALSE;
|
|
}
|
|
|
|
// verify that we have something specified
|
|
if (!AttribData->ScriptSpecifiedObject) {
|
|
SetLastError (ERROR_INVALID_DATA);
|
|
return FALSE;
|
|
}
|
|
|
|
// Now, let's extract the INI file name, section and key
|
|
fileName = DuplicatePathString (AttribData->ScriptSpecifiedObject, 0);
|
|
if (!fileName) {
|
|
return FALSE;
|
|
}
|
|
|
|
charPtr = _tcschr (fileName, TEXT('/'));
|
|
if (charPtr) {
|
|
sectName = _tcsinc (charPtr);
|
|
*charPtr = 0;
|
|
if (sectName) {
|
|
charPtr = _tcschr (sectName, TEXT('/'));
|
|
if (charPtr) {
|
|
keyName = _tcsinc (charPtr);
|
|
*charPtr = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
result = NULL;
|
|
allocatedChars = 256;
|
|
do {
|
|
if (result) {
|
|
FreePathString (result);
|
|
}
|
|
allocatedChars *= 2;
|
|
result = AllocPathString (allocatedChars);
|
|
if (!result) {
|
|
return FALSE;
|
|
}
|
|
chars = GetPrivateProfileString (
|
|
sectName,
|
|
keyName,
|
|
TEXT(""),
|
|
result,
|
|
allocatedChars,
|
|
fileName
|
|
);
|
|
} while (chars >= allocatedChars - 1);
|
|
|
|
if (chars) {
|
|
AttribData->ReturnString = IsmGetMemory (SizeOfString (result));
|
|
StringCopy ((PTSTR) AttribData->ReturnString, result);
|
|
FreePathString (result);
|
|
result = NULL;
|
|
return TRUE;
|
|
}
|
|
FreePathString (result);
|
|
result = NULL;
|
|
FreePathString (fileName);
|
|
fileName = NULL;
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL
|
|
pFreeIniFileScriptType (
|
|
IN OUT PATTRIB_DATA AttribData
|
|
)
|
|
{
|
|
if (AttribData->ReturnString) {
|
|
IsmReleaseMemory (AttribData->ReturnString);
|
|
AttribData->ReturnString = NULL;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
AllocScriptType (
|
|
IN OUT PATTRIB_DATA AttribData CALLER_INITIALIZED
|
|
)
|
|
{
|
|
PTAG_TO_SCRIPTTYPEFN scriptFn = g_TagToScriptTypeFn;
|
|
|
|
while (scriptFn->Tag) {
|
|
if (StringIMatch (scriptFn->Tag, AttribData->ScriptSpecifiedType)) {
|
|
break;
|
|
}
|
|
scriptFn ++;
|
|
}
|
|
if (scriptFn->Tag) {
|
|
return (scriptFn->AllocFunction (AttribData));
|
|
} else {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
BOOL
|
|
FreeScriptType (
|
|
IN PATTRIB_DATA AttribData ZEROED
|
|
)
|
|
{
|
|
PTAG_TO_SCRIPTTYPEFN scriptFn = g_TagToScriptTypeFn;
|
|
|
|
while (scriptFn->Tag) {
|
|
if (StringIMatch (scriptFn->Tag, AttribData->ScriptSpecifiedType)) {
|
|
break;
|
|
}
|
|
scriptFn ++;
|
|
}
|
|
if (scriptFn->Tag) {
|
|
return (scriptFn->FreeFunction (AttribData));
|
|
} else {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|