Author: mjansen
Date: Sat Jun 11 21:12:43 2016
New Revision: 71614

URL: http://svn.reactos.org/svn/reactos?rev=71614&view=rev
Log:
[APPHELP] Implement automatic stringtable generation when writing an Sdb 
database. CORE-10367

Added:
    trunk/reactos/dll/appcompat/apphelp/sdbstringtable.c   (with props)
    trunk/reactos/dll/appcompat/apphelp/sdbstringtable.h   (with props)
    trunk/reactos/dll/appcompat/hacking.txt   (with props)
Modified:
    trunk/reactos/dll/appcompat/apphelp/CMakeLists.txt
    trunk/reactos/dll/appcompat/apphelp/apphelp.h
    trunk/reactos/dll/appcompat/apphelp/sdbapi.c
    trunk/reactos/dll/appcompat/apphelp/sdbpapi.h
    trunk/reactos/dll/appcompat/apphelp/sdbtypes.h
    trunk/reactos/dll/appcompat/apphelp/sdbwrite.c

Modified: trunk/reactos/dll/appcompat/apphelp/CMakeLists.txt
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/appcompat/apphelp/CMakeLists.txt?rev=71614&r1=71613&r2=71614&view=diff
==============================================================================
--- trunk/reactos/dll/appcompat/apphelp/CMakeLists.txt  [iso-8859-1] (original)
+++ trunk/reactos/dll/appcompat/apphelp/CMakeLists.txt  [iso-8859-1] Sat Jun 11 
21:12:43 2016
@@ -5,9 +5,10 @@
     apphelp.c
     layer.c
     sdbapi.c
+    sdbfileattr.c
     sdbread.c
+    sdbstringtable.c
     sdbwrite.c
-    sdbfileattr.c
     apphelp.spec
     apphelp.h
     ${CMAKE_CURRENT_BINARY_DIR}/apphelp_stubs.c)

Modified: trunk/reactos/dll/appcompat/apphelp/apphelp.h
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/appcompat/apphelp/apphelp.h?rev=71614&r1=71613&r2=71614&view=diff
==============================================================================
--- trunk/reactos/dll/appcompat/apphelp/apphelp.h       [iso-8859-1] (original)
+++ trunk/reactos/dll/appcompat/apphelp/apphelp.h       [iso-8859-1] Sat Jun 11 
21:12:43 2016
@@ -50,26 +50,11 @@
     };
 } ATTRINFO, *PATTRINFO;
 
-typedef enum _SHIM_LOG_LEVEL {
-    SHIM_ERR = 1,
-    SHIM_WARN = 2,
-    SHIM_INFO = 3,
-}SHIM_LOG_LEVEL;
-
 /* apphelp.c */
-BOOL WINAPIV ShimDbgPrint(SHIM_LOG_LEVEL Level, PCSTR FunctionName, PCSTR 
Format, ...);
-extern ULONG g_ShimDebugLevel;
-
-#define SHIM_ERR(fmt, ...)  do { if (g_ShimDebugLevel) ShimDbgPrint(SHIM_ERR, 
__FUNCTION__, fmt, ##__VA_ARGS__ ); } while (0)
-#define SHIM_WARN(fmt, ...)  do { if (g_ShimDebugLevel) 
ShimDbgPrint(SHIM_WARN, __FUNCTION__, fmt, ##__VA_ARGS__ ); } while (0)
-#define SHIM_INFO(fmt, ...)  do { if (g_ShimDebugLevel) 
ShimDbgPrint(SHIM_INFO, __FUNCTION__, fmt, ##__VA_ARGS__ ); } while (0)
-
 
 #include "sdbpapi.h"
 
 PWSTR SdbpStrDup(LPCWSTR string);
-BOOL WINAPI SdbpCheckTagType(TAG tag, WORD type);
-BOOL WINAPI SdbpCheckTagIDType(PDB db, TAGID tagid, WORD type);
 
 PDB WINAPI SdbOpenDatabase(LPCWSTR path, PATH_TYPE type);
 void WINAPI SdbCloseDatabase(PDB);

Modified: trunk/reactos/dll/appcompat/apphelp/sdbapi.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/appcompat/apphelp/sdbapi.c?rev=71614&r1=71613&r2=71614&view=diff
==============================================================================
--- trunk/reactos/dll/appcompat/apphelp/sdbapi.c        [iso-8859-1] (original)
+++ trunk/reactos/dll/appcompat/apphelp/sdbapi.c        [iso-8859-1] Sat Jun 11 
21:12:43 2016
@@ -23,6 +23,7 @@
 #include "ntndk.h"
 #include "strsafe.h"
 #include "apphelp.h"
+#include "sdbstringtable.h"
 
 #include "wine/unicode.h"
 
@@ -228,9 +229,6 @@
 
     InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, NULL, NULL);
 
-    //Status = NtCreateFile(&db->file, FILE_GENERIC_READ | SYNCHRONIZE,
-    //                      &attr, &io, NULL, FILE_ATTRIBUTE_NORMAL, 
FILE_SHARE_READ,
-    //                      FILE_OPEN, FILE_NON_DIRECTORY_FILE | 
FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
     Status = NtCreateFile(&db->file, (write ? FILE_GENERIC_WRITE : 
FILE_GENERIC_READ )| SYNCHRONIZE,
                           &attr, &io, NULL, FILE_ATTRIBUTE_NORMAL, 
FILE_SHARE_READ,
                           write ? FILE_SUPERSEDE : FILE_OPEN, 
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
@@ -454,6 +452,10 @@
 
     if (db->file)
         NtClose(db->file);
+    if (db->string_buffer)
+        SdbCloseDatabase(db->string_buffer);
+    if (db->string_lookup)
+        SdbpTableDestroy(&db->string_lookup);
     SdbFree(db->data);
     SdbFree(db);
 }

Modified: trunk/reactos/dll/appcompat/apphelp/sdbpapi.h
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/appcompat/apphelp/sdbpapi.h?rev=71614&r1=71613&r2=71614&view=diff
==============================================================================
--- trunk/reactos/dll/appcompat/apphelp/sdbpapi.h       [iso-8859-1] (original)
+++ trunk/reactos/dll/appcompat/apphelp/sdbpapi.h       [iso-8859-1] Sat Jun 11 
21:12:43 2016
@@ -68,6 +68,22 @@
 DWORD SdbpStrlen(PCWSTR string);
 DWORD SdbpStrsize(PCWSTR string);
 
+BOOL WINAPI SdbpCheckTagType(TAG tag, WORD type);
+BOOL WINAPI SdbpCheckTagIDType(PDB db, TAGID tagid, WORD type);
+
+
+typedef enum _SHIM_LOG_LEVEL {
+    SHIM_ERR = 1,
+    SHIM_WARN = 2,
+    SHIM_INFO = 3,
+} SHIM_LOG_LEVEL;
+
+BOOL WINAPIV ShimDbgPrint(SHIM_LOG_LEVEL Level, PCSTR FunctionName, PCSTR 
Format, ...);
+extern ULONG g_ShimDebugLevel;
+
+#define SHIM_ERR(fmt, ...)  do { if (g_ShimDebugLevel) ShimDbgPrint(SHIM_ERR, 
__FUNCTION__, fmt, ##__VA_ARGS__ ); } while (0)
+#define SHIM_WARN(fmt, ...)  do { if (g_ShimDebugLevel) 
ShimDbgPrint(SHIM_WARN, __FUNCTION__, fmt, ##__VA_ARGS__ ); } while (0)
+#define SHIM_INFO(fmt, ...)  do { if (g_ShimDebugLevel) 
ShimDbgPrint(SHIM_INFO, __FUNCTION__, fmt, ##__VA_ARGS__ ); } while (0)
 
 #ifdef __cplusplus
 } // extern "C"

Added: trunk/reactos/dll/appcompat/apphelp/sdbstringtable.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/appcompat/apphelp/sdbstringtable.c?rev=71614
==============================================================================
--- trunk/reactos/dll/appcompat/apphelp/sdbstringtable.c        (added)
+++ trunk/reactos/dll/appcompat/apphelp/sdbstringtable.c        [iso-8859-1] 
Sat Jun 11 21:12:43 2016
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2016 Mark Jansen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#if !defined(SDBWRITE_HOSTTOOL)
+#define WIN32_NO_STATUS
+#include "windows.h"
+#include "sdbtypes.h"
+#include "sdbpapi.h"
+#else /* !defined(SDBWRITE_HOSTTOOL) */
+#include <typedefs.h>
+#include "sdbtypes.h"
+#include "sdbpapi.h"
+#endif /* !defined(SDBWRITE_HOSTTOOL) */
+
+#include "sdbstringtable.h"
+
+#define DEFAULT_TABLE_SIZE    0x100
+
+typedef struct SdbHashEntry
+{
+    struct SdbHashEntry* Next;
+    TAGID Tagid;
+    WCHAR Name[1];
+} SdbHashEntry;
+
+struct SdbStringHashTable
+{
+    DWORD Size;
+    struct SdbHashEntry** Entries;
+};
+
+
+static struct SdbStringHashTable* HashCreate(void)
+{
+    struct SdbStringHashTable* tab = SdbAlloc(sizeof(*tab));
+    if (!tab)
+    {
+        SHIM_ERR("Failed to allocate 8 bytes.\r\n");
+        return tab;
+    }
+    tab->Size = DEFAULT_TABLE_SIZE;
+    tab->Entries = SdbAlloc(tab->Size * sizeof(*tab->Entries));
+    return tab;
+}
+
+
+void SdbpTableDestroy(struct SdbStringHashTable** pTable)
+{
+    struct SdbStringHashTable* table = *pTable;
+    struct SdbHashEntry* entry, *next;
+    DWORD n, depth = 0, once = 1;
+
+    *pTable = NULL;
+    for (n = 0; n < table->Size; ++n)
+    {
+        depth = 0;
+        entry = next = table->Entries[n];
+        while (entry)
+        {
+            next = entry->Next;
+            SdbFree(entry);
+            entry = next;
+            depth++;
+        }
+        if (once && depth > 3)
+        {
+            // warn
+            once = 0;
+        }
+    }
+    SdbFree(table->Entries);
+    SdbFree(table);
+}
+
+/* Based on RtlHashUnicodeString */
+static DWORD StringHash(const WCHAR* str)
+{
+    DWORD hash = 0;
+    for (; *str; str++)
+    {
+        hash = ((65599 * hash) + (ULONG)(*str));
+    }
+    return hash;
+}
+
+static struct SdbHashEntry** TableFindPtr(struct SdbStringHashTable* table, 
const WCHAR* str)
+{
+    DWORD hash = StringHash(str);
+    struct SdbHashEntry** entry = &table->Entries[hash % table->Size];
+    while (*entry)
+    {
+        if (!wcscmp((*entry)->Name, str))
+            return entry;
+        entry = &(*entry)->Next;
+    }
+    return entry;
+}
+
+static BOOL HashAddString(struct SdbStringHashTable* table, struct 
SdbHashEntry** position, const WCHAR* str, TAGID tagid)
+{
+    struct SdbHashEntry* entry;
+    SIZE_T size;
+
+    if (!position)
+        position = TableFindPtr(table, str);
+
+    size = offsetof(struct SdbHashEntry, Name[SdbpStrlen(str) + 2]);
+    entry = (*position) = SdbAlloc(size);
+    if (!entry)
+    {
+        SHIM_ERR("Failed to allocate %u bytes.", size);
+        return FALSE;
+    }
+    entry->Tagid = tagid;
+    wcscpy(entry->Name, str);
+    return TRUE;
+}
+
+
+BOOL SdbpAddStringToTable(struct SdbStringHashTable** table, const WCHAR* str, 
TAGID* tagid)
+{
+    struct SdbHashEntry** entry;
+
+    if (!*table)
+    {
+        *table = HashCreate();
+        if (!*table)
+        {
+            SHIM_ERR("Error creating hash table\n");
+            return FALSE;
+        }
+    }
+
+    entry = TableFindPtr(*table, str);
+    if (*entry)
+    {
+        *tagid = (*entry)->Tagid;
+        return FALSE;
+    }
+    return HashAddString(*table, entry, str, *tagid);
+}
+

Propchange: trunk/reactos/dll/appcompat/apphelp/sdbstringtable.c
------------------------------------------------------------------------------
    svn:eol-style = native

Added: trunk/reactos/dll/appcompat/apphelp/sdbstringtable.h
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/appcompat/apphelp/sdbstringtable.h?rev=71614
==============================================================================
--- trunk/reactos/dll/appcompat/apphelp/sdbstringtable.h        (added)
+++ trunk/reactos/dll/appcompat/apphelp/sdbstringtable.h        [iso-8859-1] 
Sat Jun 11 21:12:43 2016
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2016 Mark Jansen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef SDBSTRINGTABLE_H
+#define SDBSTRINGTABLE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * Destroy the hashtable and release all resources.
+ *
+ * @param [in]  table       Pointer to table pointer, will be cleared after use
+ *
+ */
+void SdbpTableDestroy(struct SdbStringHashTable* * table);
+
+/**
+ * Find an entry in the stringtable, or allocate it when an entry could not be 
found.
+ * - When the string specified does not yet exist, a new entry will be added 
to the table,
+ *   and the pTagid specified will be associated with this string.
+ * - When the string specified does already exist,
+ *   the TAGID associated with this string will be returned in pTagid.
+ * 
+ *
+ * @param [in]  table       Pointer to table pointer, will be allocated when 
needed.
+ * @param [in]  str         The string to search for
+ * @param [in,out] pTagid   
+ *                          the data written (in bytes)
+ *
+ * @return  TRUE if the string was added to the table, FALSE if it already 
existed
+ */
+BOOL SdbpAddStringToTable(struct SdbStringHashTable* * table, const WCHAR* 
str, TAGID* pTagid);
+
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // SDBSTRINGTABLE_H

Propchange: trunk/reactos/dll/appcompat/apphelp/sdbstringtable.h
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: trunk/reactos/dll/appcompat/apphelp/sdbtypes.h
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/appcompat/apphelp/sdbtypes.h?rev=71614&r1=71613&r2=71614&view=diff
==============================================================================
--- trunk/reactos/dll/appcompat/apphelp/sdbtypes.h      [iso-8859-1] (original)
+++ trunk/reactos/dll/appcompat/apphelp/sdbtypes.h      [iso-8859-1] Sat Jun 11 
21:12:43 2016
@@ -39,6 +39,8 @@
     TAGID stringtable;
     DWORD write_iter;
     GUID database_id;
+    struct SdbStringHashTable* string_lookup;
+    struct _DB* string_buffer;
 } DB, *PDB;
 
 typedef enum _PATH_TYPE {

Modified: trunk/reactos/dll/appcompat/apphelp/sdbwrite.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/appcompat/apphelp/sdbwrite.c?rev=71614&r1=71613&r2=71614&view=diff
==============================================================================
--- trunk/reactos/dll/appcompat/apphelp/sdbwrite.c      [iso-8859-1] (original)
+++ trunk/reactos/dll/appcompat/apphelp/sdbwrite.c      [iso-8859-1] Sat Jun 11 
21:12:43 2016
@@ -1,6 +1,6 @@
 /*
- * Copyright 2011 André Hentschel
- * Copyright 2013 Mislav Blaževic
+ * Copyright 2011 André Hentschel
+ * Copyright 2013 Mislav Blažević
  * Copyright 2015,2016 Mark Jansen
  *
  * This library is free software; you can redistribute it and/or
@@ -19,27 +19,28 @@
  */
 
 #if !defined(SDBWRITE_HOSTTOOL)
-
 #define WIN32_NO_STATUS
 #include "windows.h"
 #include "ntndk.h"
-#include "apphelp.h"
-#include "wine/unicode.h"
-
 #else
-
 #include <typedefs.h>
 #include <guiddef.h>
+#endif
 
 #include "sdbtypes.h"
 #include "sdbpapi.h"
 #include "sdbtagid.h"
-
-#endif
-
+#include "sdbstringtable.h"
+
+
+/* Local functions */
 BOOL WINAPI SdbWriteStringRefTag(PDB db, TAG tag, TAGID tagid);
+BOOL WINAPI SdbWriteStringTag(PDB db, TAG tag, LPCWSTR string);
 TAGID WINAPI SdbBeginWriteListTag(PDB db, TAG tag);
 BOOL WINAPI SdbEndWriteListTag(PDB db, TAGID tagid);
+
+/* sdbapi.c */
+void WINAPI SdbCloseDatabase(PDB);
 
 
 static void WINAPI SdbpWrite(PDB db, const void* data, DWORD size)
@@ -57,19 +58,35 @@
 
 static BOOL WINAPI SdbpGetOrAddStringRef(PDB db, LPCWSTR string, TAGID* tagid)
 {
-    /* TODO:
-    - Insert or find in stringtable
-    - return TAGID
-    */
-
-    return FALSE;
-}
-
-static void WINAPI SdbpWriteStringtable(PDB db)
-{
-    TAGID table = SdbBeginWriteListTag(db, TAG_STRINGTABLE);
-    /* TODO: Write out all strings*/
-    SdbEndWriteListTag(db, table);
+    PDB buf = db->string_buffer;
+    if (db->string_buffer == NULL)
+    {
+        db->string_buffer = buf = SdbpAlloc(sizeof(DB));
+        if (buf == NULL)
+            return FALSE;
+        buf->size = 128;
+        buf->data = SdbAlloc(buf->size);
+        if (buf->data == NULL)
+            return FALSE;
+    }
+
+   *tagid = buf->write_iter + sizeof(TAG) + sizeof(DWORD);
+   if (SdbpAddStringToTable(&db->string_lookup, string, tagid))
+       return SdbWriteStringTag(buf, TAG_STRINGTABLE_ITEM, string);
+
+    return db->string_lookup != NULL;
+}
+
+static BOOL WINAPI SdbpWriteStringtable(PDB db)
+{
+    TAGID table;
+    PDB buf = db->string_buffer;
+    if (buf == NULL || db->string_lookup == NULL)
+        return FALSE;
+
+    table = SdbBeginWriteListTag(db, TAG_STRINGTABLE);
+    SdbpWrite(db, buf->data, buf->write_iter);
+    return SdbEndWriteListTag(db, table);
 }
 
 /**

Added: trunk/reactos/dll/appcompat/hacking.txt
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/appcompat/hacking.txt?rev=71614
==============================================================================
--- trunk/reactos/dll/appcompat/hacking.txt     (added)
+++ trunk/reactos/dll/appcompat/hacking.txt     [iso-8859-1] Sat Jun 11 
21:12:43 2016
@@ -0,0 +1,23 @@
+
+Set the environment variable 'SHIM_DEBUG_LEVEL' to '4' before loading 
apphelp.dll for debug info related to loading / matching modules.
+The environment variable 'SHIMENG_DEBUG_LEVEL' is related to the hooking code.
+
+
+When there is not enough debug output, force memory allocations to fail:
+
+pSdbCreateDatabase
+    [Err ][SdbpCreateFile      ] Failed to convert DOS path "TEST1.SDB"
+    [Err ][SdbCreateDatabase   ] Failed to create the database.
+    [Err ][SdbpWriteBufferedData] Failed to allocate 65548 bytes.
+
+pSdbWriteStringTag
+    [Err ][SdbpAddStringToTable] Error Gettting temp path 0x8
+    [Err ][SdbpCreateFile      ] Failed to convert DOS path 
"C:\Users\MAE67~1.JAN\AppData\Local\Temp\SDBAB16.tmp"
+    [Err ][SdbpAddStringToTable] Error copying string table temp filename
+    [Err ][HashCreate          ] Failed to allocate 8 bytes.
+    [Err ][SdbpAddStringToTable] Error creating hash table
+    [Err ][HashAddString       ] Failed to allocate 22 bytes.
+
+pSdbCloseDatabaseWrite
+    [Err ][SdbCloseDatabase    ] Failed to close the file.
+    [Err ][SdbpDeleteFile      ] Failed to convert DOS path 
"C:\Users\MAE67~1.JAN\AppData\Local\Temp\SDBAB2D.tmp"

Propchange: trunk/reactos/dll/appcompat/hacking.txt
------------------------------------------------------------------------------
    svn:eol-style = native


Reply via email to