#include <glib/gmessages.h>
#include "captive/unicode.h"
#include "reactos/unicode.h" /* for ANSI_* */
+#include "captive/macros.h"
+#include <ctype.h>
+
+
+UCHAR **FsRtlLegalAnsiCharacterArray;
+
+
+/**
+ * captive_FsRtlLegalAnsiCharacterArray_init:
+ *
+ * Initialize #FsRtlLegalAnsiCharacterArray character classes
+ * by appropriate #FSRTL_FAT_LEGAL etc. flags.
+ */
+void captive_FsRtlLegalAnsiCharacterArray_init(void)
+{
+static UCHAR *array;
+guint ui;
+const gchar fat_valid[]="!#&(-./@_~";
+
+ /* Use allocation instead of static array to get ElectricFence sanity boundaries.
+ * Use even the negative 0x80 part as someone may access 'FsRtlLegalAnsiCharacterArray'
+ * with 'signed char' (but also with 'unsigned char'). See also memcpy(3) below.
+ */
+ captive_new0n(array,0x80+0x100);
+ array+=0x80;
+
+ for (ui=0;ui<0x100;ui++) {
+UCHAR f=0;
+
+ if (isalnum(ui) || strchr(fat_valid,ui))
+ f|=FSRTL_FAT_LEGAL;
+ if (isalnum(ui) || strchr(fat_valid,ui))
+ f|=FSRTL_HPFS_LEGAL;
+ if (isalnum(ui) || strchr(fat_valid,ui))
+ f|=FSRTL_NTFS_LEGAL;
+ if (ui=='*' || ui=='?')
+ f|=FSRTL_WILD_CHARACTER;
+ if (isalnum(ui))
+ f|=FSRTL_OLE_LEGAL;
+
+ array[(unsigned int)(unsigned char)ui]=f;
+ }
+
+ memcpy(array-0x80,array+0x80,0x80*sizeof(*array));
+
+ FsRtlLegalAnsiCharacterArray=&array;
+}
/**
*
* Returns: %TRUE if @Name contains "*", "?", %ANSI_DOS_STAR, %ANSI_DOS_DOT or %ANSI_DOS_QM.
*/
-BOOLEAN FsRtlDoesNameContainWildCards(IN PUNICODE_STRING Name_nonconst)
+BOOLEAN FsRtlDoesNameContainWildCards(IN PUNICODE_STRING Name)
{
-const UNICODE_STRING *cName=Name_nonconst;
+const UNICODE_STRING *cName=Name;
const WCHAR *wcp;
g_return_val_if_fail(captive_validate_UnicodeString_noterm(cName),FALSE);
return TRUE;
return FALSE;
}
+
+
+/**
+ * FsRtlDissectName:
+ * @Path_noterm: Initialized #UNICODE_STRING to parse.
+ * @FirstName: Returns the first filename from @Path_noterm.
+ * %NULL value is forbidden.
+ * @RemainingName: Returns the part of @Path_noterm behind @FirstName.
+ * %NULL value is forbidden.
+ *
+ * Will parse @Path_noterm as regex (FirstName,RemainingName)=/^\?([^/]*)/?(.*)$/;
+ * @FirstName and @RemainingName must be pointers to allocated #UNICODE_STRING
+ * but their #Buffer will be pointing to inside @Path_noterm buffer afterwards.
+ * Therefore do not free it! The returned strings may not be 0-terminated strings.
+ *
+ * @Path_noterm does not neet to be zero-terminated.
+ */
+VOID FsRtlDissectName(IN UNICODE_STRING Path_noterm,OUT PUNICODE_STRING FirstName,OUT PUNICODE_STRING RemainingName)
+{
+PWSTR Path_end;
+PWSTR delim_FirstName_start ,delim_FirstName_end;
+PWSTR delim_RemainingName_start,delim_RemainingName_end;
+
+ g_return_if_fail(captive_validate_UnicodeString_noterm(&Path_noterm));
+ g_return_if_fail(FirstName!=NULL);
+ g_return_if_fail(RemainingName!=NULL);
+
+ Path_end=Path_noterm.Buffer+Path_noterm.Length/sizeof(*Path_noterm.Buffer);
+
+ delim_FirstName_start=Path_noterm.Buffer;
+ if (delim_FirstName_start<Path_end && *delim_FirstName_start=='\\')
+ delim_FirstName_start++;
+ for (delim_FirstName_end=delim_FirstName_start;
+ delim_FirstName_end<Path_end && *delim_FirstName_end!='\\';
+ delim_FirstName_end++);
+ delim_RemainingName_start=delim_FirstName_end;
+ if (delim_RemainingName_start<Path_end && *delim_RemainingName_start=='\\')
+ delim_RemainingName_start++;
+ delim_RemainingName_end=Path_end;
+
+ g_assert(delim_FirstName_start <=delim_FirstName_end);
+ g_assert(delim_FirstName_end <=delim_RemainingName_start);
+ g_assert(delim_RemainingName_start<=delim_RemainingName_end);
+
+ FirstName->Buffer=delim_FirstName_start;
+ FirstName->Length=(delim_FirstName_end-delim_FirstName_start)*sizeof(*FirstName->Buffer);
+ FirstName->MaximumLength=FirstName->Length;
+ FirstName->Buffer=delim_FirstName_start;
+
+ RemainingName->Buffer=delim_RemainingName_start;
+ RemainingName->Length=(delim_RemainingName_end-delim_RemainingName_start)*sizeof(*RemainingName->Buffer);
+ RemainingName->MaximumLength=RemainingName->Length;
+ RemainingName->Buffer=delim_RemainingName_start;
+}
+
+
+/**
+ * FsRtlAreNamesEqual:
+ * @Name1: First filesystem name (FIXME: pathname or basename?) of type #PUNICODE_STRING.
+ * Invalid string input is forbidden.
+ * @Name2: Second filesystem name (FIXME: pathname or basename?) of type #PUNICODE_STRING.
+ * Invalid string input is forbidden.
+ * @IgnoreCase: Compare @Name1 and @Name2 case-insensitively?
+ * @UpcaseTable:
+ * %NULL value is required if @IgnoreCase==%FALSE.
+ * TODO: NOT IMPLEMENTED YET.
+ *
+ * Compare the given filenames if they match according to the specified criteria.
+ * FIXME: libcaptive implements this function currently as captive_UnicodeString_compare_insensitive()
+ * or captive_UnicodeString_compare(); How are filesystem names specific from regular strings?
+ *
+ * Returns: %TRUE if @Name1 and @Name2 match.
+ */
+BOOLEAN FsRtlAreNamesEqual
+ (IN PUNICODE_STRING Name1,IN PUNICODE_STRING Name2,IN BOOLEAN IgnoreCase,IN PWCHAR UpcaseTable OPTIONAL)
+{
+ g_return_val_if_fail(captive_validate_UnicodeString(Name1),FALSE);
+ g_return_val_if_fail(FsRtlDoesNameContainWildCards(Name1)==FALSE,FALSE);
+ g_return_val_if_fail(captive_validate_UnicodeString(Name2),FALSE);
+ g_return_val_if_fail(FsRtlDoesNameContainWildCards(Name2)==FALSE,FALSE);
+ g_return_val_if_fail(UpcaseTable==NULL,FALSE); /* TODO: NOT IMPLEMENTED YET */
+ /* Do not permit passing of 'UpcaseTable' if it would not make any sense.
+ * Just a sanity check, it should not harm. Such assertion is not mandatory by W32 doc.
+ */
+ g_return_val_if_fail((IgnoreCase==FALSE && UpcaseTable==NULL) || IgnoreCase==TRUE,FALSE);
+
+ if (IgnoreCase)
+ return captive_UnicodeString_compare_insensitive(Name1,Name2);
+ else
+ return captive_UnicodeString_compare (Name1,Name2);
+}