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/CMakeLists.txt?rev=71380&r1=71379&r2=71380&view=diff ============================================================================== --- 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/apphelp.h?rev=71380&r1=71379&r2=71380&view=diff ============================================================================== --- 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/apphelp.spec?rev=71380&r1=71379&r2=71380&view=diff ============================================================================== --- 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/sdbapi.c?rev=71380&r1=71379&r2=71380&view=diff ============================================================================== --- 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/sdbread.c?rev=71380 ============================================================================== --- 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/sdbwrite.c?rev=71380 ============================================================================== --- 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/CMakeLists.txt?rev=71380&r1=71379&r2=71380&view=diff ============================================================================== --- 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=71380 ============================================================================== --- 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.c?rev=71380&r1=71379&r2=71380&view=diff ============================================================================== --- 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 } };