mirror of
https://github.com/reactos/reactos.git
synced 2025-07-30 22:01:43 +00:00
[APPHELP][APPHELP_APITEST] Implement most of sdbread and sdbwrite, mainly the work of Mislav Blaževic, with some small additions from me. CORE-10367
svn path=/trunk/; revision=71380
This commit is contained in:
parent
5a7f64ba98
commit
a6879a9948
9 changed files with 1235 additions and 29 deletions
|
@ -5,6 +5,8 @@ list(APPEND SOURCE
|
|||
apphelp.c
|
||||
layer.c
|
||||
sdbapi.c
|
||||
sdbread.c
|
||||
sdbwrite.c
|
||||
sdbfileattr.c
|
||||
apphelp.spec
|
||||
apphelp.h
|
||||
|
|
|
@ -32,6 +32,19 @@ typedef UINT64 QWORD;
|
|||
#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 @@ typedef struct tagATTRINFO {
|
|||
};
|
||||
} 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 @@ BOOL WINAPI SdbpOpenMemMappedFile(LPCWSTR path, PMEMMAPPED mapping);
|
|||
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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 @@ void SdbpFree(LPVOID mem
|
|||
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);
|
||||
|
@ -292,6 +298,119 @@ void WINAPI SdbpCloseMemMappedFile(PMEMMAPPED mapping)
|
|||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a string to retrieve a GUID.
|
||||
*
|
||||
|
@ -380,6 +499,8 @@ BOOL WINAPI SdbGetStandardDatabaseGUID(DWORD Flags, GUID* Guid)
|
|||
* @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)
|
||||
{
|
||||
|
|
439
reactos/dll/appcompat/apphelp/sdbread.c
Normal file
439
reactos/dll/appcompat/apphelp/sdbread.c
Normal file
|
@ -0,0 +1,439 @@
|
|||
/*
|
||||
* Copyright 2011 André Hentschel
|
||||
* Copyright 2013 Mislav Blaževic
|
||||
* 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;
|
||||
}
|
||||
|
328
reactos/dll/appcompat/apphelp/sdbwrite.c
Normal file
328
reactos/dll/appcompat/apphelp/sdbwrite.c
Normal file
|
@ -0,0 +1,328 @@
|
|||
/*
|
||||
* Copyright 2011 André Hentschel
|
||||
* Copyright 2013 Mislav Blaževic
|
||||
* 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;
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ add_definitions(-D__ROS_LONG64__)
|
|||
list(APPEND SOURCE
|
||||
apphelp.c
|
||||
data.c
|
||||
db.c
|
||||
layerapi.c
|
||||
testlist.c)
|
||||
|
||||
|
|
283
rostests/apitests/apphelp/db.c
Normal file
283
rostests/apitests/apphelp/db.c
Normal file
|
@ -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();
|
||||
}
|
|
@ -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 }
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue