Author: mjansen
Date: Sun May 22 20:27:02 2016
New Revision: 71380
URL:
http://svn.reactos.org/svn/reactos?rev=71380&view=rev
Log:
[APPHELP][APPHELP_APITEST] Implement most of sdbread and sdbwrite, mainly the work of
Mislav Blaževic, with some small additions from me. CORE-10367
Added:
trunk/reactos/dll/appcompat/apphelp/sdbread.c (with props)
trunk/reactos/dll/appcompat/apphelp/sdbwrite.c (with props)
trunk/rostests/apitests/apphelp/db.c (with props)
Modified:
trunk/reactos/dll/appcompat/apphelp/CMakeLists.txt
trunk/reactos/dll/appcompat/apphelp/apphelp.h
trunk/reactos/dll/appcompat/apphelp/apphelp.spec
trunk/reactos/dll/appcompat/apphelp/sdbapi.c
trunk/rostests/apitests/apphelp/CMakeLists.txt
trunk/rostests/apitests/apphelp/testlist.c
Modified: trunk/reactos/dll/appcompat/apphelp/CMakeLists.txt
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/appcompat/apphelp/CMak…
==============================================================================
--- trunk/reactos/dll/appcompat/apphelp/CMakeLists.txt [iso-8859-1] (original)
+++ trunk/reactos/dll/appcompat/apphelp/CMakeLists.txt [iso-8859-1] Sun May 22 20:27:02
2016
@@ -5,6 +5,8 @@
apphelp.c
layer.c
sdbapi.c
+ sdbread.c
+ sdbwrite.c
sdbfileattr.c
apphelp.spec
apphelp.h
Modified: trunk/reactos/dll/appcompat/apphelp/apphelp.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/appcompat/apphelp/apph…
==============================================================================
--- trunk/reactos/dll/appcompat/apphelp/apphelp.h [iso-8859-1] (original)
+++ trunk/reactos/dll/appcompat/apphelp/apphelp.h [iso-8859-1] Sun May 22 20:27:02 2016
@@ -32,6 +32,19 @@
#define TAGREF_NULL (0)
#define TAGREF_ROOT (0)
+typedef struct _DB {
+ HANDLE file;
+ DWORD size;
+ PBYTE data;
+ TAGID stringtable;
+ DWORD write_iter;
+ GUID database_id;
+} DB, *PDB;
+
+/* Flags for SdbInitDatabase */
+#define HID_DOS_PATHS 0x1
+#define HID_DATABASE_FULLPATH 0x2
+#define HID_NO_DATABASE 0x4
#define HID_DATABASE_TYPE_MASK 0xF00F0000
#define SDB_DATABASE_MAIN_MSI 0x80020000
#define SDB_DATABASE_MAIN_SHIM 0x80030000
@@ -47,6 +60,11 @@
};
} ATTRINFO, *PATTRINFO;
+typedef enum _PATH_TYPE {
+ DOS_PATH,
+ NT_PATH
+} PATH_TYPE;
+
typedef enum _SHIM_LOG_LEVEL {
SHIM_ERR = 1,
SHIM_WARN = 2,
@@ -99,6 +117,18 @@
void WINAPI SdbpCloseMemMappedFile(PMEMMAPPED mapping);
DWORD SdbpStrlen(LPCWSTR string);
PWSTR SdbpStrDup(LPCWSTR string);
+BOOL WINAPI SdbpCheckTagType(TAG tag, WORD type);
+BOOL WINAPI SdbpCheckTagIDType(PDB db, TAGID tagid, WORD type);
+PDB WINAPI SdbpCreate(void);
+PDB WINAPI SdbOpenDatabase(LPCWSTR path, PATH_TYPE type);
+void WINAPI SdbCloseDatabase(PDB);
+BOOL WINAPI SdbIsNullGUID(CONST GUID *Guid);
+
+/* sdbread.c */
+BOOL WINAPI SdbpReadData(PDB db, PVOID dest, DWORD offset, DWORD num);
+TAG WINAPI SdbGetTagFromTagID(PDB db, TAGID tagid);
+TAGID WINAPI SdbFindFirstTag(PDB db, TAGID parent, TAG tag);
+BOOL WINAPI SdbGetDatabaseID(PDB db, GUID* Guid);
/* layer.c */
Modified: trunk/reactos/dll/appcompat/apphelp/apphelp.spec
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/appcompat/apphelp/apph…
==============================================================================
--- trunk/reactos/dll/appcompat/apphelp/apphelp.spec [iso-8859-1] (original)
+++ trunk/reactos/dll/appcompat/apphelp/apphelp.spec [iso-8859-1] Sun May 22 20:27:02
2016
@@ -20,32 +20,32 @@
@ stub SdbAddLayerTagRefToQuery
@ stub SdbApphelpNotify
@ stub SdbApphelpNotifyExSdbApphelpNotifyEx
-@ stub SdbBeginWriteListTag
+@ stdcall SdbBeginWriteListTag(ptr long)
@ stub SdbBuildCompatEnvVariables
@ stub SdbCloseApphelpInformation
-@ stub SdbCloseDatabase
-@ stub SdbCloseDatabaseWrite
+@ stdcall SdbCloseDatabase(ptr)
+@ stdcall SdbCloseDatabaseWrite(ptr)
@ stub SdbCloseLocalDatabase
@ stub SdbCommitIndexes
-@ stub SdbCreateDatabase
+@ stdcall SdbCreateDatabase(wstr long)
@ stub SdbCreateHelpCenterURL
@ stub SdbCreateMsiTransformFile
@ stub SdbDeclareIndex
@ stub SdbDumpSearchPathPartCaches
@ stub SdbEnumMsiTransforms
-@ stub SdbEndWriteListTag
+@ stdcall SdbEndWriteListTag(ptr long)
@ stub SdbEscapeApphelpURL
@ stub SdbFindFirstDWORDIndexedTag
@ stub SdbFindFirstMsiPackage
@ stub SdbFindFirstMsiPackage_Str
@ stub SdbFindFirstNamedTag
@ stub SdbFindFirstStringIndexedTag
-@ stub SdbFindFirstTag
+@ stdcall SdbFindFirstTag(ptr long long)
@ stub SdbFindFirstTagRef
@ stub SdbFindNextDWORDIndexedTag
@ stub SdbFindNextMsiPackage
@ stub SdbFindNextStringIndexedTag
-@ stub SdbFindNextTag
+@ stdcall SdbFindNextTag(ptr long long)
@ stub SdbFindNextTagRef
@ stub SdbFreeDatabaseInformation
@ stdcall SdbFreeFileAttributes(ptr)
@@ -53,8 +53,8 @@
@ stub SdbFreeFlagInfo
@ stub SdbGetAppCompatDataSize
@ stub SdbGetAppPatchDir
-@ stub SdbGetBinaryTagData
-@ stub SdbGetDatabaseID
+@ stdcall SdbGetBinaryTagData(ptr long)
+@ stdcall SdbGetDatabaseID(ptr ptr)
@ stub SdbGetDatabaseInformation
@ stub SdbGetDatabaseInformationByName
@ stub SdbGetDatabaseMatch
@@ -65,7 +65,7 @@
@ stub SdbGetFileImageType
@ stub SdbGetFileImageTypeEx
@ stub SdbGetFileInfo
-@ stub SdbGetFirstChild
+@ stdcall SdbGetFirstChild(ptr long)
@ stub SdbGetIndex
@ stub SdbGetItemFromItemRef
@ stub SdbGetLayerName
@@ -74,15 +74,15 @@
@ stub SdbGetMatchingExe
@ stub SdbGetMsiPackageInformation
@ stub SdbGetNamedLayer
-@ stub SdbGetNextChild
+@ stdcall SdbGetNextChild(ptr long long)
@ stub SdbGetNthUserSdb
@ stdcall SdbGetPermLayerKeys(wstr wstr ptr long)
@ stub SdbGetShowDebugInfoOption
@ stub SdbGetShowDebugInfoOptionValue
@ stdcall SdbGetStandardDatabaseGUID(long ptr)
-@ stub SdbGetStringTagPtr
-@ stub SdbGetTagDataSize
-@ stub SdbGetTagFromTagID
+@ stdcall SdbGetStringTagPtr(ptr long)
+@ stdcall SdbGetTagDataSize(ptr long)
+@ stdcall SdbGetTagFromTagID(ptr long)
@ stub SdbGrabMatchingInfo
@ stub SdbGrabMatchingInfoEx
@ stdcall SdbGUIDFromString(wstr ptr)
@@ -100,7 +100,7 @@
@ stub SdbOpenApphelpInformation
@ stub SdbOpenApphelpInformationByID
@ stub SdbOpenApphelpResourceFile
-@ stub SdbOpenDatabase
+@ stdcall SdbOpenDatabase(wstr long)
@ stub SdbOpenDbFromGuid
@ stub SdbOpenLocalDatabase
@ stub SdbPackAppCompatData
@@ -115,18 +115,18 @@
@ stub SdbQueryReinstallUpgrade
@ stub SdbReadApphelpData
@ stub SdbReadApphelpDetailsData
-@ stub SdbReadBinaryTag
+@ stdcall SdbReadBinaryTag(ptr long ptr long)
@ stub SdbReadBYTETag
-@ stub SdbReadDWORDTag
+@ stdcall SdbReadDWORDTag(ptr long long)
@ stub SdbReadDWORDTagRef
@ stub SdbReadEntryInformation
@ stub SdbReadMsiTransformInfo
@ stub SdbReadPatchBits
-@ stub SdbReadQWORDTag
+@ stdcall SdbReadQWORDTag(ptr long int64)
@ stub SdbReadQWORDTagRef
-@ stub SdbReadStringTag
+@ stdcall SdbReadStringTag(ptr long wstr long)
@ stub SdbReadStringTagRef
-@ stub SdbReadWORDTag
+@ stdcall SdbReadWORDTag(ptr long long)
@ stub SdbReadWORDTagRef
@ stub SdbRegisterDatabase
@ stub SdbReleaseDatabase
@@ -147,16 +147,16 @@
@ stub SdbTagRefToTagID
@ stdcall SdbTagToString(long)
@ stub SdbUnregisterDatabase
-@ stub SdbWriteBinaryTag
-@ stub SdbWriteBinaryTagFromFile
+@ stdcall SdbWriteBinaryTag(ptr long ptr long)
+@ stdcall SdbWriteBinaryTagFromFile(ptr long wstr)
@ stub SdbWriteBYTETag
-@ stub SdbWriteDWORDTag
-@ stub SdbWriteNULLTag
-@ stub SdbWriteQWORDTag
-@ stub SdbWriteStringRefTag
-@ stub SdbWriteStringTag
+@ stdcall SdbWriteDWORDTag(ptr long long)
+@ stdcall SdbWriteNULLTag(ptr long)
+@ stdcall SdbWriteQWORDTag(ptr long int64)
+@ stdcall SdbWriteStringRefTag(ptr long long)
+@ stdcall SdbWriteStringTag(ptr long wstr)
@ stub SdbWriteStringTagDirect
-@ stub SdbWriteWORDTag
+@ stdcall SdbWriteWORDTag(ptr long long)
@ stub SE_DllLoaded
@ stub SE_DllUnloaded
@ stub SE_GetHookAPIs
Modified: trunk/reactos/dll/appcompat/apphelp/sdbapi.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/appcompat/apphelp/sdba…
==============================================================================
--- trunk/reactos/dll/appcompat/apphelp/sdbapi.c [iso-8859-1] (original)
+++ trunk/reactos/dll/appcompat/apphelp/sdbapi.c [iso-8859-1] Sun May 22 20:27:02 2016
@@ -1,7 +1,7 @@
/*
* Copyright 2011 André Hentschel
* Copyright 2013 Mislav BlaževiÄ
- * Copyright 2015 Mark Jansen
+ * Copyright 2015,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
@@ -202,6 +202,12 @@
HeapFree(SdbpHeap(), 0, mem);
}
+PDB WINAPI SdbpCreate(void)
+{
+ PDB db = (PDB)SdbAlloc(sizeof(DB));
+ /* SdbAlloc zeroes the memory. */
+ return db;
+}
DWORD SdbpStrlen(PCWSTR string)
{
return (lstrlenW(string) + 1) * sizeof(WCHAR);
@@ -290,6 +296,119 @@
NtClose(mapping->section);
NtClose(mapping->file);
RtlZeroMemory(mapping, sizeof(*mapping));
+}
+
+BOOL WINAPI SdbpCheckTagType(TAG tag, WORD type)
+{
+ if ((tag & TAG_TYPE_MASK) != type)
+ return FALSE;
+ return TRUE;
+}
+
+BOOL WINAPI SdbpCheckTagIDType(PDB db, TAGID tagid, WORD type)
+{
+ TAG tag = SdbGetTagFromTagID(db, tagid);
+ if (tag == TAG_NULL)
+ return FALSE;
+ return SdbpCheckTagType(tag, type);
+}
+
+/**
+ * Opens specified shim database file.
+ *
+ * @param [in] path Path to the shim database.
+ * @param [in] type Type of path. Either DOS_PATH or NT_PATH.
+ *
+ * @return Success: Handle to the shim database, NULL otherwise.
+ */
+PDB WINAPI SdbOpenDatabase(LPCWSTR path, PATH_TYPE type)
+{
+ NTSTATUS Status;
+ IO_STATUS_BLOCK io;
+ OBJECT_ATTRIBUTES attr;
+ UNICODE_STRING str;
+ PDB db;
+ BYTE header[12];
+ DWORD dwRead = 0;
+
+ if (type == DOS_PATH)
+ {
+ if (!RtlDosPathNameToNtPathName_U(path, &str, NULL, NULL))
+ return NULL;
+ }
+ else
+ RtlInitUnicodeString(&str, path);
+
+ db = SdbpCreate();
+ if (!db)
+ {
+ SHIM_ERR("Failed to allocate memory for shim database\n");
+ return NULL;
+ }
+
+ 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);
+
+ if (type == DOS_PATH)
+ RtlFreeUnicodeString(&str);
+
+ if (!NT_SUCCESS(Status))
+ {
+ SdbCloseDatabase(db);
+ SHIM_ERR("Failed to open shim database file: 0x%lx\n", Status);
+ return NULL;
+ }
+
+ db->size = GetFileSize(db->file, NULL);
+ db->data = SdbAlloc(db->size);
+ ReadFile(db->file, db->data, db->size, &dwRead, NULL);
+
+ if (!SdbpReadData(db, &header, 0, 12))
+ {
+ SdbCloseDatabase(db);
+ SHIM_ERR("Failed to read shim database header\n");
+ return NULL;
+ }
+
+ if (memcmp(&header[8], "sdbf", 4) != 0)
+ {
+ SdbCloseDatabase(db);
+ SHIM_ERR("Shim database header is invalid\n");
+ return NULL;
+ }
+
+ if (*(DWORD*)&header[0] != (DWORD)2)
+ {
+ SdbCloseDatabase(db);
+ SHIM_ERR("Invalid shim database version\n");
+ return NULL;
+ }
+
+ db->stringtable = SdbFindFirstTag(db, TAGID_ROOT, TAG_STRINGTABLE);
+ if(!SdbGetDatabaseID(db, &db->database_id))
+ {
+ SHIM_INFO("Failed to get the database id\n");
+ }
+ return db;
+}
+
+/**
+ * Closes specified database and frees its memory.
+ *
+ * @param [in] db Handle to the shim database.
+ */
+void WINAPI SdbCloseDatabase(PDB db)
+{
+ if (!db)
+ return;
+
+ if (db->file)
+ NtClose(db->file);
+ SdbFree(db->data);
+ SdbFree(db);
}
/**
@@ -380,6 +499,8 @@
* @param [in] tag The tag which will be converted to a string.
*
* @return Success: Pointer to the string matching specified tag, or
L"InvalidTag" on failure.
+ *
+ * @todo: Convert this into a lookup table, this is wasting alot of space.
*/
LPCWSTR WINAPI SdbTagToString(TAG tag)
{
Added: trunk/reactos/dll/appcompat/apphelp/sdbread.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/appcompat/apphelp/sdbr…
==============================================================================
--- trunk/reactos/dll/appcompat/apphelp/sdbread.c (added)
+++ trunk/reactos/dll/appcompat/apphelp/sdbread.c [iso-8859-1] Sun May 22 20:27:02 2016
@@ -0,0 +1,439 @@
+/*
+ * Copyright 2011 André Hentschel
+ * Copyright 2013 Mislav Blaevic
+ * Copyright 2015,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
+ */
+
+#include "windef.h"
+#include "winbase.h"
+#include "apphelp.h"
+
+#include "wine/unicode.h"
+
+
+DWORD WINAPI SdbGetTagDataSize(PDB db, TAGID tagid);
+
+
+BOOL WINAPI SdbpReadData(PDB db, PVOID dest, DWORD offset, DWORD num)
+{
+ DWORD size = offset + num;
+
+ /* Either overflow or no data to read */
+ if (size <= offset)
+ return FALSE;
+
+ /* Overflow */
+ if (db->size < size)
+ return FALSE;
+
+ memcpy(dest, db->data + offset, num);
+ return TRUE;
+}
+
+static DWORD WINAPI SdbpGetTagSize(PDB db, TAGID tagid)
+{
+ WORD type;
+ DWORD size;
+
+ type = SdbGetTagFromTagID(db, tagid) & TAG_TYPE_MASK;
+ if (type == TAG_NULL)
+ return 0;
+
+ size = SdbGetTagDataSize(db, tagid);
+ if (type <= TAG_TYPE_STRINGREF)
+ return size += sizeof(TAG);
+ else size += (sizeof(TAG) + sizeof(DWORD));
+
+ return size;
+}
+
+static LPWSTR WINAPI SdbpGetString(PDB db, TAGID tagid, PDWORD size)
+{
+ TAG tag;
+ TAGID offset;
+
+ tag = SdbGetTagFromTagID(db, tagid);
+ if (tag == TAG_NULL)
+ return NULL;
+
+ if ((tag & TAG_TYPE_MASK) == TAG_TYPE_STRINGREF)
+ {
+ /* No stringtable; all references are invalid */
+ if (db->stringtable == TAGID_NULL)
+ return NULL;
+
+ /* TAG_TYPE_STRINGREF contains offset of string relative to stringtable */
+ if (!SdbpReadData(db, &tagid, tagid + sizeof(TAG), sizeof(TAGID)))
+ return NULL;
+
+ offset = db->stringtable + tagid + sizeof(TAG) + sizeof(TAGID);
+ }
+ else if ((tag & TAG_TYPE_MASK) == TAG_TYPE_STRING)
+ {
+ offset = tagid + sizeof(TAG) + sizeof(TAGID);
+ }
+ else
+ {
+ SHIM_ERR("Tag 0x%u at tagid %u is neither a string or reference to
string\n", tag, tagid);
+ return NULL;
+ }
+
+ /* Optionally read string size */
+ if (size && !SdbpReadData(db, size, tagid + sizeof(TAG), sizeof(*size)))
+ return FALSE;
+
+ return (LPWSTR)(&db->data[offset]);
+}
+
+/**
+ * Searches shim database for the tag associated with specified tagid.
+ *
+ * @param [in] db Handle to the shim database.
+ * @param [in] tagid The TAGID of the tag.
+ *
+ * @return Success: The tag associated with specified tagid, Failure: TAG_NULL.
+ */
+TAG WINAPI SdbGetTagFromTagID(PDB db, TAGID tagid)
+{
+ TAG data;
+ if (!SdbpReadData(db, &data, tagid, sizeof(data)))
+ return TAG_NULL;
+ return data;
+}
+
+/**
+ * Retrieves size of data at specified tagid.
+ *
+ * @param [in] db Handle to the shim database.
+ * @param [in] tagid Tagid of tag whose size is queried.
+ *
+ * @return Success: Size of data at specified tagid, Failure: 0.
+ */
+DWORD WINAPI SdbGetTagDataSize(PDB db, TAGID tagid)
+{
+ /* sizes of data types with fixed size */
+ static const SIZE_T sizes[6] = {
+ 0, /* NULL */ 1, /* BYTE */
+ 2, /* WORD */ 4, /* DWORD */
+ 8, /* QWORD */ 4 /* STRINGREF */
+ };
+ WORD type;
+ DWORD size;
+
+ type = SdbGetTagFromTagID(db, tagid) & TAG_TYPE_MASK;
+ if (type == TAG_NULL)
+ return 0;
+
+ if (type <= TAG_TYPE_STRINGREF)
+ return sizes[(type >> 12) - 1];
+
+ /* tag with dynamic size (e.g. list): must read size */
+ if (!SdbpReadData(db, &size, tagid + sizeof(TAG), sizeof(size)))
+ return 0;
+
+ return size;
+}
+
+/**
+ * Searches shim database for a child of specified parent tag.
+ *
+ * @param [in] db Handle to the shim database.
+ * @param [in] parent TAGID of parent.
+ *
+ * @return Success: TAGID of child tag, Failure: TAGID_NULL.
+ */
+TAGID WINAPI SdbGetFirstChild(PDB db, TAGID parent)
+{
+ /* if we are at beginning of database */
+ if (parent == TAGID_ROOT)
+ {
+ /* header only database: no tags */
+ if (db->size <= _TAGID_ROOT)
+ return TAGID_NULL;
+ /* return *real* root tagid */
+ else return _TAGID_ROOT;
+ }
+
+ /* only list tag can have children */
+ if ((SdbGetTagFromTagID(db, parent) & TAG_TYPE_MASK) != TAG_TYPE_LIST)
+ return TAGID_NULL;
+
+ /* first child is sizeof(TAG) + sizeof(DWORD) bytes after beginning of list */
+ return parent + sizeof(TAG) + sizeof(DWORD);
+}
+
+/**
+ * Searches shim database for next child of specified parent tag.
+ *
+ * @param [in] db Handle to the shim database.
+ * @param [in] parent TAGID of parent.
+ * @param [in] prev_child TAGID of previous child.
+ *
+ * @return Success: TAGID of next child tag, Failure: TAGID_NULL.
+ */
+TAGID WINAPI SdbGetNextChild(PDB db, TAGID parent, TAGID prev_child)
+{
+ TAGID next_child;
+ DWORD prev_child_size, parent_size;
+
+ prev_child_size = SdbpGetTagSize(db, prev_child);
+ if (prev_child_size == 0)
+ return TAGID_NULL;
+
+ /* Bound check */
+ next_child = prev_child + prev_child_size;
+ if (next_child >= db->size)
+ return TAGID_NULL;
+
+ if (parent == TAGID_ROOT)
+ return next_child;
+
+ parent_size = SdbpGetTagSize(db, parent);
+ if (parent_size == 0)
+ return TAGID_NULL;
+
+ /* Specified parent has no more children */
+ if (next_child >= parent + parent_size)
+ return TAGID_NULL;
+
+ return next_child;
+}
+
+/**
+ * Searches shim database for a tag within specified domain.
+ *
+ * @param [in] db Handle to the shim database.
+ * @param [in] parent TAGID of parent.
+ * @param [in] tag TAG to be located.
+ *
+ * @return Success: TAGID of first matching tag, Failure: TAGID_NULL.
+ */
+TAGID WINAPI SdbFindFirstTag(PDB db, TAGID parent, TAG tag)
+{
+ TAGID iter;
+
+ iter = SdbGetFirstChild(db, parent);
+ while (iter != TAGID_NULL)
+ {
+ if (SdbGetTagFromTagID(db, iter) == tag)
+ return iter;
+ iter = SdbGetNextChild(db, parent, iter);
+ }
+ return TAGID_NULL;
+}
+
+/**
+ * Searches shim database for a next tag which matches prev_child within parent's
domain.
+ *
+ * @param [in] db Handle to the shim database.
+ * @param [in] parent TAGID of parent.
+ * @param [in] prev_child TAGID of previous match.
+ *
+ * @return Success: TAGID of next match, Failure: TAGID_NULL.
+ */
+TAGID WINAPI SdbFindNextTag(PDB db, TAGID parent, TAGID prev_child)
+{
+ TAG tag;
+ TAGID iter;
+
+ tag = SdbGetTagFromTagID(db, prev_child);
+ iter = SdbGetNextChild(db, parent, prev_child);
+
+ while (iter != TAGID_NULL)
+ {
+ if (SdbGetTagFromTagID(db, iter) == tag)
+ return iter;
+ iter = SdbGetNextChild(db, parent, iter);
+ }
+ return TAGID_NULL;
+}
+
+/**
+ * Searches shim database for string associated with specified tagid and copies string
into a
+ * buffer.
+ *
+ * If size parameter is less than number of characters in string, this function shall
fail and
+ * no data shall be copied.
+ *
+ * @param [in] db Handle to the shim database.
+ * @param [in] tagid TAGID of string or stringref associated with the string.
+ * @param [out] buffer Buffer in which string will be copied.
+ * @param [in] size Number of characters to copy.
+ *
+ * @return TRUE if string was successfully copied to the buffer FALSE if string was not
copied
+ * to the buffer.
+ */
+BOOL WINAPI SdbReadStringTag(PDB db, TAGID tagid, LPWSTR buffer, DWORD size)
+{
+ LPWSTR string;
+ DWORD string_size;
+
+ string = SdbpGetString(db, tagid, &string_size);
+ if (!string)
+ return FALSE;
+
+ /* Check if buffer is too small */
+ if (size * sizeof(WCHAR) < string_size)
+ return FALSE;
+
+ memcpy(buffer, string, string_size);
+ return TRUE;
+}
+
+/**
+ * Reads WORD value at specified tagid.
+ *
+ * @param [in] db Handle to the shim database.
+ * @param [in] tagid TAGID of WORD value.
+ * @param [in] ret Default return value in case function fails.
+ *
+ * @return Success: WORD value at specified tagid, or ret on failure.
+ */
+WORD WINAPI SdbReadWORDTag(PDB db, TAGID tagid, WORD ret)
+{
+ if (SdbpCheckTagIDType(db, tagid, TAG_TYPE_WORD))
+ SdbpReadData(db, &ret, tagid + 2, sizeof(WORD));
+ return ret;
+}
+
+/**
+ * Reads DWORD value at specified tagid.
+ *
+ * @param [in] db Handle to the shim database.
+ * @param [in] tagid TAGID of DWORD value.
+ * @param [in] ret Default return value in case function fails.
+ *
+ * @return Success: DWORD value at specified tagid, otherwise ret.
+ */
+DWORD WINAPI SdbReadDWORDTag(PDB db, TAGID tagid, DWORD ret)
+{
+ if (SdbpCheckTagIDType(db, tagid, TAG_TYPE_DWORD))
+ SdbpReadData(db, &ret, tagid + 2, sizeof(DWORD));
+ return ret;
+}
+
+/**
+ * Reads QWORD value at specified tagid.
+ *
+ * @param [in] db Handle to the shim database.
+ * @param [in] tagid TAGID of QWORD value.
+ * @param [in] ret Default return value in case function fails.
+ *
+ * @return Success: QWORD value at specified tagid, otherwise ret.
+ */
+QWORD WINAPI SdbReadQWORDTag(PDB db, TAGID tagid, QWORD ret)
+{
+ if (SdbpCheckTagIDType(db, tagid, TAG_TYPE_QWORD))
+ SdbpReadData(db, &ret, tagid + sizeof(TAG), sizeof(QWORD));
+ return ret;
+}
+
+/**
+ * Reads binary data at specified tagid.
+ *
+ * @param [in] db Handle to the shim database.
+ * @param [in] tagid TAGID of binary data.
+ * @param [out] buffer Buffer in which data will be copied.
+ * @param [in] size Size of the buffer.
+ *
+ * @return TRUE if data was successfully written, or FALSE otherwise.
+ */
+BOOL WINAPI SdbReadBinaryTag(PDB db, TAGID tagid, PBYTE buffer, DWORD size)
+{
+ DWORD data_size = 0;
+
+ if (SdbpCheckTagIDType(db, tagid, TAG_TYPE_BINARY))
+ {
+ SdbpReadData(db, &data_size, tagid + sizeof(TAG), sizeof(data_size));
+ if (size >= data_size)
+ return SdbpReadData(db, buffer, tagid + sizeof(TAG) + sizeof(data_size),
data_size);
+ }
+
+ return FALSE;
+}
+
+/**
+ * Retrieves binary data at specified tagid.
+ *
+ * @param [in] db Handle to the shim database.
+ * @param [in] tagid TAGID of binary data.
+ *
+ * @return Success: Pointer to binary data at specified tagid, or NULL on failure.
+ */
+PVOID WINAPI SdbGetBinaryTagData(PDB db, TAGID tagid)
+{
+ if (!SdbpCheckTagIDType(db, tagid, TAG_TYPE_BINARY))
+ return NULL;
+ return &db->data[tagid + sizeof(TAG) + sizeof(DWORD)];
+}
+
+/**
+ * Searches shim database for string associated with specified tagid.
+ *
+ * @param [in] db Handle to the shim database.
+ * @param [in] tagid TAGID of string or stringref associated with the string.
+ *
+ * @return the LPWSTR associated with specified tagid, or NULL on failure.
+ */
+LPWSTR WINAPI SdbGetStringTagPtr(PDB db, TAGID tagid)
+{
+ return SdbpGetString(db, tagid, NULL);
+}
+
+/**
+ * Reads binary data at specified tagid.
+ *
+ * @param [in] db Handle to the shim database.
+ * @param [out] Guid Database ID.
+ *
+ * @return true if the ID was found FALSE otherwise.
+ */
+BOOL WINAPI SdbGetDatabaseID(PDB db, GUID* Guid)
+{
+ if(SdbIsNullGUID(&db->database_id))
+ {
+ TAGID root = SdbFindFirstTag(db, TAGID_ROOT, TAG_DATABASE);
+ if(root != TAGID_NULL)
+ {
+ TAGID id = SdbFindFirstTag(db, root, TAG_DATABASE_ID);
+ if(id != TAGID_NULL)
+ {
+ if(!SdbReadBinaryTag(db, id, (PBYTE)&db->database_id,
sizeof(db->database_id)))
+ {
+ memset(&db->database_id, 0, sizeof(db->database_id));
+ }
+ }
+ else
+ {
+ /* Should we silence this if we are opening a system db? */
+ SHIM_ERR("Failed to get the database id\n");
+ }
+ }
+ else
+ {
+ /* Should we silence this if we are opening a system db? */
+ SHIM_ERR("Failed to get root tag\n");
+ }
+ }
+ if(!SdbIsNullGUID(&db->database_id))
+ {
+ memcpy(Guid, &db->database_id, sizeof(db->database_id));
+ return TRUE;
+ }
+ return FALSE;
+}
+
Propchange: trunk/reactos/dll/appcompat/apphelp/sdbread.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/reactos/dll/appcompat/apphelp/sdbwrite.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/appcompat/apphelp/sdbw…
==============================================================================
--- trunk/reactos/dll/appcompat/apphelp/sdbwrite.c (added)
+++ trunk/reactos/dll/appcompat/apphelp/sdbwrite.c [iso-8859-1] Sun May 22 20:27:02 2016
@@ -0,0 +1,328 @@
+/*
+ * Copyright 2011 André Hentschel
+ * Copyright 2013 Mislav Blaevic
+ * Copyright 2015,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
+ */
+
+#define WIN32_NO_STATUS
+#include "windows.h"
+#include "ntndk.h"
+#include "apphelp.h"
+
+#include "wine/unicode.h"
+
+
+static void WINAPI SdbpFlush(PDB db)
+{
+ IO_STATUS_BLOCK io;
+ NTSTATUS Status = NtWriteFile(db->file, NULL, NULL, NULL, &io,
+ db->data, db->write_iter, NULL, NULL);
+ if( !NT_SUCCESS(Status))
+ SHIM_WARN("failed with 0x%lx\n", Status);
+}
+
+static void WINAPI SdbpWrite(PDB db, LPCVOID data, DWORD size)
+{
+ if (db->write_iter + size > db->size)
+ {
+ /* Round to powers of two to prevent too many reallocations */
+ while (db->size < db->write_iter + size) db->size <<= 1;
+ db->data = SdbReAlloc(db->data, db->size);
+ }
+
+ memcpy(db->data + db->write_iter, data, size);
+ db->write_iter += size;
+}
+
+/**
+ * Creates new shim database file
+ *
+ * If a file already exists on specified path, that file shall be overwritten.
+ *
+ * @note Use SdbCloseDatabasWrite to close the database opened with this function.
+ *
+ * @param [in] path Path to the new shim database.
+ * @param [in] type Type of path. Either DOS_PATH or NT_PATH.
+ *
+ * @return Success: Handle to the newly created shim database, NULL otherwise.
+ */
+PDB WINAPI SdbCreateDatabase(LPCWSTR path, PATH_TYPE type)
+{
+ static const DWORD version_major = 2, version_minor = 1;
+ static const char* magic = "sdbf";
+ NTSTATUS Status;
+ IO_STATUS_BLOCK io;
+ OBJECT_ATTRIBUTES attr;
+ UNICODE_STRING str;
+ PDB db;
+
+ if (type == DOS_PATH)
+ {
+ if (!RtlDosPathNameToNtPathName_U(path, &str, NULL, NULL))
+ return NULL;
+ }
+ else
+ RtlInitUnicodeString(&str, path);
+
+ db = SdbpCreate();
+ if (!db)
+ {
+ SHIM_ERR("Failed to allocate memory for shim database\n");
+ return NULL;
+ }
+
+ InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, NULL, NULL);
+
+ Status = NtCreateFile(&db->file, FILE_GENERIC_WRITE | SYNCHRONIZE,
+ &attr, &io, NULL, FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ,
+ FILE_SUPERSEDE, FILE_NON_DIRECTORY_FILE |
FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
+
+ if (type == DOS_PATH)
+ RtlFreeUnicodeString(&str);
+
+ if (!NT_SUCCESS(Status))
+ {
+ SdbCloseDatabase(db);
+ SHIM_ERR("Failed to create shim database file: %lx\n", Status);
+ return NULL;
+ }
+
+ db->size = sizeof(DWORD) + sizeof(DWORD) + strlen(magic);
+ db->data = SdbAlloc(db->size);
+
+ SdbpWrite(db, &version_major, sizeof(DWORD));
+ SdbpWrite(db, &version_minor, sizeof(DWORD));
+ SdbpWrite(db, magic, strlen(magic));
+
+ return db;
+}
+
+/**
+ * Closes specified database and writes data to file.
+ *
+ * @param [in] db Handle to the shim database.
+ */
+void WINAPI SdbCloseDatabaseWrite(PDB db)
+{
+ SdbpFlush(db);
+ SdbCloseDatabase(db);
+}
+
+/**
+ * Writes a tag-only (NULL) entry to the specified shim database.
+ *
+ * @param [in] db Handle to the shim database.
+ * @param [in] tag A tag for the entry.
+ *
+ * @return TRUE if it succeeds, FALSE if it fails.
+ */
+BOOL WINAPI SdbWriteNULLTag(PDB db, TAG tag)
+{
+ if (!SdbpCheckTagType(tag, TAG_TYPE_NULL))
+ return FALSE;
+
+ SdbpWrite(db, &tag, sizeof(TAG));
+ return TRUE;
+}
+
+/**
+ * Writes a WORD entry to the specified shim database.
+ *
+ * @param [in] db Handle to the shim database.
+ * @param [in] tag A tag for the entry.
+ * @param [in] data WORD entry which will be written to the database.
+ *
+ * @return TRUE if it succeeds, FALSE if it fails.
+ */
+BOOL WINAPI SdbWriteWORDTag(PDB db, TAG tag, WORD data)
+{
+ if (!SdbpCheckTagType(tag, TAG_TYPE_WORD))
+ return FALSE;
+
+ SdbpWrite(db, &tag, sizeof(TAG));
+ SdbpWrite(db, &data, sizeof(data));
+ return TRUE;
+}
+
+/**
+ * Writes a DWORD entry to the specified shim database.
+ *
+ * @param [in] db Handle to the shim database.
+ * @param [in] tag A tag for the entry.
+ * @param [in] data DWORD entry which will be written to the database.
+ *
+ * @return TRUE if it succeeds, FALSE if it fails.
+ */
+BOOL WINAPI SdbWriteDWORDTag(PDB db, TAG tag, DWORD data)
+{
+ if (!SdbpCheckTagType(tag, TAG_TYPE_DWORD))
+ return FALSE;
+
+ SdbpWrite(db, &tag, sizeof(TAG));
+ SdbpWrite(db, &data, sizeof(data));
+ return TRUE;
+}
+
+/**
+ * Writes a DWORD entry to the specified shim database.
+ *
+ * @param [in] db Handle to the shim database.
+ * @param [in] tag A tag for the entry.
+ * @param [in] data QWORD entry which will be written to the database.
+ *
+ * @return TRUE if it succeeds, FALSE if it fails.
+ */
+BOOL WINAPI SdbWriteQWORDTag(PDB db, TAG tag, QWORD data)
+{
+ if (!SdbpCheckTagType(tag, TAG_TYPE_QWORD))
+ return FALSE;
+
+ SdbpWrite(db, &tag, sizeof(TAG));
+ SdbpWrite(db, &data, sizeof(data));
+ return TRUE;
+}
+
+/**
+ * Writes a wide string entry to the specified shim database.
+ *
+ * @param [in] db Handle to the shim database.
+ * @param [in] tag A tag for the entry.
+ * @param [in] string Wide string entry which will be written to the database.
+ *
+ * @return TRUE if it succeeds, FALSE if it fails.
+ */
+BOOL WINAPI SdbWriteStringTag(PDB db, TAG tag, LPCWSTR string)
+{
+ DWORD size;
+
+ if (!SdbpCheckTagType(tag, TAG_TYPE_STRING))
+ return FALSE;
+
+ size = SdbpStrlen(string);
+ SdbpWrite(db, &tag, sizeof(TAG));
+ SdbpWrite(db, &size, sizeof(size));
+ SdbpWrite(db, string, size);
+ return TRUE;
+}
+
+/**
+ * Writes a stringref tag to specified database
+ * @note Reference (tagid) is not checked for validity.
+ *
+ * @param [in] db Handle to the shim database.
+ * @param [in] tag TAG which will be written.
+ * @param [in] tagid TAGID of the string tag refers to.
+ *
+ * @return TRUE if it succeeds, FALSE if it fails.
+ */
+BOOL WINAPI SdbWriteStringRefTag(PDB db, TAG tag, TAGID tagid)
+{
+ if (!SdbpCheckTagType(tag, TAG_TYPE_STRINGREF))
+ return FALSE;
+
+ SdbpWrite(db, &tag, sizeof(TAG));
+ SdbpWrite(db, &tagid, sizeof(tagid));
+ return TRUE;
+}
+
+/**
+ * Writes data the specified shim database.
+ *
+ * @param [in] db Handle to the shim database.
+ * @param [in] tag A tag for the entry.
+ * @param [in] data Pointer to data.
+ * @param [in] size Number of bytes to write.
+ *
+ * @return TRUE if it succeeds, FALSE if it fails.
+ */
+BOOL WINAPI SdbWriteBinaryTag(PDB db, TAG tag, PBYTE data, DWORD size)
+{
+ if (!SdbpCheckTagType(tag, TAG_TYPE_BINARY))
+ return FALSE;
+
+ SdbpWrite(db, &tag, sizeof(TAG));
+ SdbpWrite(db, &size, sizeof(size));
+ SdbpWrite(db, data, size);
+ return TRUE;
+}
+
+/**
+ * Writes data from a file to the specified shim database.
+ *
+ * @param [in] db Handle to the shim database.
+ * @param [in] tag A tag for the entry.
+ * @param [in] path Path of the input file.
+ *
+ * @return TRUE if it succeeds, FALSE if it fails.
+ */
+BOOL WINAPI SdbWriteBinaryTagFromFile(PDB db, TAG tag, LPCWSTR path)
+{
+ MEMMAPPED mapped;
+
+ if (!SdbpCheckTagType(tag, TAG_TYPE_BINARY))
+ return FALSE;
+
+ if (!SdbpOpenMemMappedFile(path, &mapped))
+ return FALSE;
+
+ SdbWriteBinaryTag(db, tag, mapped.view, mapped.size);
+ SdbpCloseMemMappedFile(&mapped);
+ return TRUE;
+}
+
+/**
+ * Writes a list tag to specified database All subsequent SdbWrite* functions shall write
to
+ * newly created list untill TAGID of that list is passed to SdbEndWriteListTag.
+ *
+ * @param [in] db Handle to the shim database.
+ * @param [in] tag TAG for the list
+ *
+ * RETURNS Success: TAGID of the newly created list, or TAGID_NULL on
failure.
+ *
+ * @return A TAGID.
+ */
+TAGID WINAPI SdbBeginWriteListTag(PDB db, TAG tag)
+{
+ TAGID list_id;
+
+ if (!SdbpCheckTagType(tag, TAG_TYPE_LIST))
+ return TAGID_NULL;
+
+ list_id = db->write_iter;
+ SdbpWrite(db, &tag, sizeof(TAG));
+ db->write_iter += sizeof(DWORD); /* reserve some memory for storing list size */
+ return list_id;
+}
+
+/**
+ * Marks end of the specified list.
+ *
+ * @param [in] db Handle to the shim database.
+ * @param [in] tagid TAGID of the list.
+ *
+ * @return TRUE if it succeeds, FALSE if it fails.
+ */
+BOOL WINAPI SdbEndWriteListTag(PDB db, TAGID tagid)
+{
+ if (!SdbpCheckTagIDType(db, tagid, TAG_TYPE_LIST))
+ return FALSE;
+
+ /* Write size of list to list tag header */
+ *(DWORD*)&db->data[tagid + sizeof(TAG)] = db->write_iter - tagid -
sizeof(TAG);
+ return TRUE;
+}
+
Propchange: trunk/reactos/dll/appcompat/apphelp/sdbwrite.c
------------------------------------------------------------------------------
svn:eol-style = native
Modified: trunk/rostests/apitests/apphelp/CMakeLists.txt
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/apphelp/CMakeLis…
==============================================================================
--- trunk/rostests/apitests/apphelp/CMakeLists.txt [iso-8859-1] (original)
+++ trunk/rostests/apitests/apphelp/CMakeLists.txt [iso-8859-1] Sun May 22 20:27:02 2016
@@ -4,6 +4,7 @@
list(APPEND SOURCE
apphelp.c
data.c
+ db.c
layerapi.c
testlist.c)
Added: trunk/rostests/apitests/apphelp/db.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/apphelp/db.c?rev…
==============================================================================
--- trunk/rostests/apitests/apphelp/db.c (added)
+++ trunk/rostests/apitests/apphelp/db.c [iso-8859-1] Sun May 22 20:27:02 2016
@@ -0,0 +1,283 @@
+/*
+ * Copyright 2012 Detlef Riekenberg
+ * Copyright 2013 Mislav BlaževiÄ
+ * Copyright 2015,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
+ */
+
+
+#include <ntstatus.h>
+#define WIN32_NO_STATUS
+#include <windows.h>
+#include <shlwapi.h>
+#include <winnt.h>
+#ifdef __REACTOS__
+#include <ntndk.h>
+#else
+#include <winternl.h>
+#endif
+
+#include <winerror.h>
+#include <stdio.h>
+#include <initguid.h>
+
+#include "wine/test.h"
+
+typedef WORD TAG;
+typedef DWORD TAGID;
+typedef DWORD TAGREF;
+typedef UINT64 QWORD;
+typedef VOID* PDB;
+typedef INT PATH_TYPE;
+#define DOS_PATH 0
+
+#define TAGID_NULL 0x0
+#define TAGID_ROOT 0x0
+#define _TAGID_ROOT 12
+
+
+#define TAG_TYPE_MASK 0xF000
+
+#define TAG_TYPE_NULL 0x1000
+#define TAG_TYPE_BYTE 0x2000
+#define TAG_TYPE_WORD 0x3000
+#define TAG_TYPE_DWORD 0x4000
+#define TAG_TYPE_QWORD 0x5000
+#define TAG_TYPE_STRINGREF 0x6000
+#define TAG_TYPE_LIST 0x7000
+#define TAG_TYPE_STRING 0x8000
+#define TAG_TYPE_BINARY 0x9000
+#define TAG_NULL 0x0
+#define TAG_SIZE (0x1 | TAG_TYPE_DWORD)
+
+#define TAG_MATCH_MODE (0x1 | TAG_TYPE_WORD)
+
+#define TAG_FLAG_LUA (0x10 | TAG_TYPE_QWORD)
+
+#define TAG_STRINGTABLE (0x801 | TAG_TYPE_LIST)
+
+#define TAG_NAME (0x1 | TAG_TYPE_STRINGREF)
+#define TAG_STRINGTABLE_ITEM (0x801 | TAG_TYPE_STRING)
+
+
+#define TAG_GENERAL (0x2 | TAG_TYPE_NULL)
+
+#define TAG_DATA_BITS (0x5 | TAG_TYPE_BINARY)
+
+
+
+static HMODULE hdll;
+static LPCWSTR (WINAPI *pSdbTagToString)(TAG);
+static PDB (WINAPI *pSdbOpenDatabase)(LPCWSTR, PATH_TYPE);
+static PDB (WINAPI *pSdbCreateDatabase)(LPCWSTR, PATH_TYPE);
+static void (WINAPI *pSdbCloseDatabase)(PDB);
+static void (WINAPI *pSdbCloseDatabaseWrite)(PDB);
+static TAG (WINAPI *pSdbGetTagFromTagID)(PDB, TAGID);
+static BOOL (WINAPI *pSdbWriteNULLTag)(PDB, TAG);
+static BOOL (WINAPI *pSdbWriteWORDTag)(PDB, TAG, WORD);
+static BOOL (WINAPI *pSdbWriteDWORDTag)(PDB, TAG, DWORD);
+static BOOL (WINAPI *pSdbWriteQWORDTag)(PDB, TAG, QWORD);
+static BOOL (WINAPI *pSdbWriteBinaryTagFromFile)(PDB, TAG, LPCWSTR);
+static BOOL (WINAPI *pSdbWriteStringTag)(PDB, TAG, LPCWSTR);
+static BOOL (WINAPI *pSdbWriteStringRefTag)(PDB, TAG, TAGID);
+static TAGID (WINAPI *pSdbBeginWriteListTag)(PDB, TAG);
+static BOOL (WINAPI *pSdbEndWriteListTag)(PDB, TAGID);
+static WORD (WINAPI *pSdbReadWORDTag)(PDB, TAGID, WORD);
+static DWORD (WINAPI *pSdbReadDWORDTag)(PDB, TAGID, DWORD);
+static QWORD (WINAPI *pSdbReadQWORDTag)(PDB, TAGID, QWORD);
+static BOOL (WINAPI *pSdbReadBinaryTag)(PDB, TAGID, PBYTE, DWORD);
+static BOOL (WINAPI *pSdbReadStringTag)(PDB, TAGID, LPWSTR, DWORD);
+static DWORD (WINAPI *pSdbGetTagDataSize)(PDB, TAGID);
+static PVOID (WINAPI *pSdbGetBinaryTagData)(PDB, TAGID);
+static LPWSTR (WINAPI *pSdbGetStringTagPtr)(PDB, TAGID);
+static TAGID (WINAPI *pSdbGetFirstChild)(PDB, TAGID);
+static TAGID (WINAPI *pSdbGetNextChild)(PDB, TAGID, TAGID);
+
+static void Write(HANDLE file, LPCVOID buffer, DWORD size)
+{
+ DWORD dwWritten = 0;
+ WriteFile(file, buffer, size, &dwWritten, NULL);
+}
+
+static void test_Sdb(void)
+{
+ static const WCHAR path[] = {'t','e','m','p',0};
+ static const WCHAR path2[] =
{'t','e','m','p','2',0};
+ static const WCHAR tag_size_string[] =
{'S','I','Z','E',0};
+ static const WCHAR tag_flag_lua_string[] =
{'F','L','A','G','_','L','U','A',0};
+ static const TAG tags[5] = {
+ TAG_SIZE, TAG_FLAG_LUA, TAG_NAME,
+ TAG_STRINGTABLE, TAG_STRINGTABLE_ITEM
+ };
+ WCHAR buffer[6] = {0};
+ PDB pdb;
+ QWORD qword;
+ DWORD dword;
+ WORD word;
+ BOOL ret;
+ HANDLE file; /* temp file created for testing purpose */
+ TAG tag;
+ TAGID tagid, ptagid, stringref = 6;
+ LPCWSTR string;
+ PBYTE binary;
+
+ pdb = pSdbCreateDatabase(path, DOS_PATH);
+ ok (pdb != NULL, "failed to create database\n");
+ if(pdb != NULL)
+ {
+ ret = pSdbWriteDWORDTag(pdb, tags[0], 0xDEADBEEF);
+ ok (ret, "failed to write DWORD tag\n");
+ ret = pSdbWriteQWORDTag(pdb, tags[1], 0xDEADBEEFBABE);
+ ok (ret, "failed to write QWORD tag\n");
+ ret = pSdbWriteStringRefTag(pdb, tags[2], stringref);
+ ok (ret, "failed to write stringref tag\n");
+ tagid = pSdbBeginWriteListTag(pdb, tags[3]);
+ ok (tagid != TAGID_NULL, "unexpected NULL tagid\n");
+ ret = pSdbWriteStringTag(pdb, tags[4], path);
+ ok (ret, "failed to write string tag\n");
+ ret = pSdbWriteNULLTag(pdb, TAG_GENERAL);
+ ok (ret, "failed to write NULL tag\n");
+ ret = pSdbWriteWORDTag(pdb, TAG_MATCH_MODE, 0xACE);
+ ok (ret, "failed to write WORD tag\n");
+ ret = pSdbEndWriteListTag(pdb, tagid);
+ ok (ret, "failed to update list size\n");
+ /* [Err ][SdbCloseDatabase ] Failed to close the file. */
+ pSdbCloseDatabaseWrite(pdb);
+ }
+
+ /* [Err ][SdbGetDatabaseID ] Failed to get root tag */
+ pdb = pSdbOpenDatabase(path, DOS_PATH);
+ ok(pdb != NULL, "unexpected NULL handle\n");
+
+ if(pdb)
+ {
+ tagid = pSdbGetFirstChild(pdb, TAGID_ROOT);
+ ok(tagid == _TAGID_ROOT, "unexpected tagid %u, expected %u\n", tagid,
_TAGID_ROOT);
+
+ tag = pSdbGetTagFromTagID(pdb, tagid);
+ ok(tag == TAG_SIZE, "unexpected tag 0x%x, expected 0x%x\n", tag,
TAG_SIZE);
+
+ string = pSdbTagToString(tag);
+ ok(lstrcmpW(string, tag_size_string) == 0, "unexpected string %s, expected
%s\n",
+ wine_dbgstr_w(string), wine_dbgstr_w(tag_size_string));
+
+ dword = pSdbReadDWORDTag(pdb, tagid, 0);
+ ok(dword == 0xDEADBEEF, "unexpected value %u, expected 0xDEADBEEF\n",
dword);
+
+ tagid = pSdbGetNextChild(pdb, TAGID_ROOT, tagid);
+ ok(tagid == _TAGID_ROOT + sizeof(TAG) + sizeof(DWORD), "unexpected tagid %u,
expected %u\n",
+ tagid, _TAGID_ROOT + sizeof(TAG) + sizeof(DWORD));
+
+ tag = pSdbGetTagFromTagID(pdb, tagid);
+ ok (tag == TAG_FLAG_LUA, "unexpected tag 0x%x, expected 0x%x\n", tag,
TAG_FLAG_LUA);
+
+ string = pSdbTagToString(tag);
+ ok(lstrcmpW(string, tag_flag_lua_string) == 0, "unexpected string %s,
expected %s\n",
+ wine_dbgstr_w(string), wine_dbgstr_w(tag_flag_lua_string));
+
+ qword = pSdbReadQWORDTag(pdb, tagid, 0);
+ ok(qword == 0xDEADBEEFBABE, "unexpected value 0x%I64x, expected
0xDEADBEEFBABE\n", qword);
+
+ tagid = pSdbGetNextChild(pdb, TAGID_ROOT, tagid);
+ string = pSdbGetStringTagPtr(pdb, tagid);
+ ok (string && (lstrcmpW(string, path) == 0), "unexpected string %s,
expected %s\n",
+ wine_dbgstr_w(string), wine_dbgstr_w(path));
+
+ ptagid = pSdbGetNextChild(pdb, TAGID_ROOT, tagid);
+ tagid = pSdbGetFirstChild(pdb, ptagid);
+
+ string = pSdbGetStringTagPtr(pdb, tagid);
+ ok (string && (lstrcmpW(string, path) == 0), "unexpected string %s,
expected %s\n",
+ wine_dbgstr_w(string), wine_dbgstr_w(path));
+
+ ok (pSdbReadStringTag(pdb, tagid, buffer, 6), "failed to write string to
buffer\n");
+ /* [Err ][SdbpReadTagData ] Buffer too small. Avail: 6, Need: 10. */
+ ok (!pSdbReadStringTag(pdb, tagid, buffer, 3), "string was written to
buffer, but failure was expected");
+ ok (pSdbGetTagDataSize(pdb, tagid) == 5 * sizeof(WCHAR), "string has
unexpected size\n");
+
+ tagid = pSdbGetNextChild(pdb, ptagid, tagid);
+ tag = pSdbGetTagFromTagID(pdb, tagid);
+ ok (tag == TAG_GENERAL, "unexpected tag 0x%x, expected 0x%x\n", tag,
TAG_GENERAL);
+ ok (pSdbGetTagDataSize(pdb, tagid) == 0, "null tag with size >
0\n");
+
+ tagid = pSdbGetNextChild(pdb, ptagid, tagid);
+ word = pSdbReadWORDTag(pdb, tagid, 0);
+ ok (word == 0xACE, "unexpected value 0x%x, expected 0x%x\n", word,
0xACE);
+
+ pSdbCloseDatabase(pdb);
+ }
+ DeleteFileW(path);
+
+ file = CreateFileW(path2, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,
NULL);
+ ok (file != INVALID_HANDLE_VALUE, "failed to open file\n");
+ Write(file, &qword, 8);
+ CloseHandle(file);
+
+ pdb = pSdbCreateDatabase(path, DOS_PATH);
+ ok(pdb != NULL, "unexpected NULL handle\n");
+
+ if(pdb)
+ {
+ ret = pSdbWriteBinaryTagFromFile(pdb, TAG_DATA_BITS, path2);
+ ok(ret, "failed to write tag from binary file\n");
+ pSdbCloseDatabaseWrite(pdb); /* [Err ][SdbCloseDatabase ] Failed to close
the file. */
+ DeleteFileW(path2);
+
+ pdb = pSdbOpenDatabase(path, DOS_PATH);
+ ok(pdb != NULL, "unexpected NULL handle\n");
+ binary = pSdbGetBinaryTagData(pdb, _TAGID_ROOT);
+ ok(memcmp(binary, &qword, 8) == 0, "binary data is corrupt\n");
+ ret = pSdbReadBinaryTag(pdb, _TAGID_ROOT, (PBYTE)buffer, 12);
+ ok(ret, "failed to read binary tag\n");
+ ok(memcmp(buffer, &qword, 8) == 0, "binary data is corrupt\n");
+ pSdbCloseDatabase(pdb);
+ }
+ DeleteFileW(path);
+}
+
+START_TEST(db)
+{
+ //SetEnvironmentVariable("SHIM_DEBUG_LEVEL", "4");
+ //SetEnvironmentVariable("DEBUGCHANNEL", "+apphelp");
+ hdll = LoadLibraryA("apphelp.dll");
+ pSdbTagToString = (void *) GetProcAddress(hdll, "SdbTagToString");
+ pSdbOpenDatabase = (void *) GetProcAddress(hdll, "SdbOpenDatabase");
+ pSdbCreateDatabase = (void *) GetProcAddress(hdll, "SdbCreateDatabase");
+ pSdbCloseDatabase = (void *) GetProcAddress(hdll, "SdbCloseDatabase");
+ pSdbCloseDatabaseWrite = (void *) GetProcAddress(hdll,
"SdbCloseDatabaseWrite");
+ pSdbGetTagFromTagID = (void *) GetProcAddress(hdll, "SdbGetTagFromTagID");
+ pSdbWriteNULLTag = (void *) GetProcAddress(hdll, "SdbWriteNULLTag");
+ pSdbWriteWORDTag = (void *) GetProcAddress(hdll, "SdbWriteWORDTag");
+ pSdbWriteDWORDTag = (void *) GetProcAddress(hdll, "SdbWriteDWORDTag");
+ pSdbWriteQWORDTag = (void *) GetProcAddress(hdll, "SdbWriteQWORDTag");
+ pSdbWriteBinaryTagFromFile = (void *) GetProcAddress(hdll,
"SdbWriteBinaryTagFromFile");
+ pSdbWriteStringTag = (void *) GetProcAddress(hdll, "SdbWriteStringTag");
+ pSdbWriteStringRefTag = (void *) GetProcAddress(hdll,
"SdbWriteStringRefTag");
+ pSdbBeginWriteListTag = (void *)GetProcAddress(hdll,
"SdbBeginWriteListTag");
+ pSdbEndWriteListTag = (void *) GetProcAddress(hdll, "SdbEndWriteListTag");
+ pSdbReadWORDTag = (void *) GetProcAddress(hdll, "SdbReadWORDTag");
+ pSdbReadDWORDTag = (void *) GetProcAddress(hdll, "SdbReadDWORDTag");
+ pSdbReadQWORDTag = (void *) GetProcAddress(hdll, "SdbReadQWORDTag");
+ pSdbReadBinaryTag = (void *) GetProcAddress(hdll, "SdbReadBinaryTag");
+ pSdbReadStringTag = (void *) GetProcAddress(hdll, "SdbReadStringTag");
+ pSdbGetTagDataSize = (void *) GetProcAddress(hdll, "SdbGetTagDataSize");
+ pSdbGetBinaryTagData = (void *) GetProcAddress(hdll,
"SdbGetBinaryTagData");
+ pSdbGetStringTagPtr = (void *) GetProcAddress(hdll, "SdbGetStringTagPtr");
+ pSdbGetFirstChild = (void *) GetProcAddress(hdll, "SdbGetFirstChild");
+ pSdbGetNextChild = (void *) GetProcAddress(hdll, "SdbGetNextChild");
+
+ test_Sdb();
+}
Propchange: trunk/rostests/apitests/apphelp/db.c
------------------------------------------------------------------------------
svn:eol-style = native
Modified: trunk/rostests/apitests/apphelp/testlist.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/apphelp/testlist…
==============================================================================
--- trunk/rostests/apitests/apphelp/testlist.c [iso-8859-1] (original)
+++ trunk/rostests/apitests/apphelp/testlist.c [iso-8859-1] Sun May 22 20:27:02 2016
@@ -4,11 +4,13 @@
#include <wine/test.h>
extern void func_apphelp(void);
+extern void func_db(void);
extern void func_layerapi(void);
const struct test winetest_testlist[] =
{
{ "apphelp", func_apphelp },
+ { "db", func_db },
{ "layerapi", func_layerapi },
{ 0, 0 }
};