mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 18:15:11 +00:00
[APPHELP][APPHELP_APITEST] Add SdbGetFileAttributes + tests, based on the work of Mislav Blažević CORE-10367
- Implement SdbGetFileAttributes (based on the work of Mislav Blažević) - Add tests for SdbGetFileAttributes svn path=/trunk/; revision=71226
This commit is contained in:
parent
535cdf4620
commit
78280ad21f
8 changed files with 1508 additions and 11 deletions
|
@ -3,8 +3,9 @@ spec2def(apphelp.dll apphelp.spec ADD_IMPORTLIB)
|
|||
|
||||
list(APPEND SOURCE
|
||||
apphelp.c
|
||||
sdbapi.c
|
||||
layer.c
|
||||
sdbapi.c
|
||||
sdbfileattr.c
|
||||
apphelp.spec
|
||||
apphelp.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/apphelp_stubs.c)
|
||||
|
@ -15,6 +16,7 @@ add_library(apphelp SHARED
|
|||
|
||||
set_module_type(apphelp win32dll)
|
||||
target_link_libraries(apphelp wine)
|
||||
#add_delay_importlibs(apphelp version imagehlp user32)
|
||||
add_importlibs(apphelp msvcrt kernel32 ntdll)
|
||||
# When binutils is fixed, we should move imagehlp to delay! CORE-6504
|
||||
add_delay_importlibs(apphelp version)
|
||||
add_importlibs(apphelp msvcrt imagehlp kernel32 ntdll)
|
||||
add_cd_file(TARGET apphelp DESTINATION reactos/system32 FOR all)
|
||||
|
|
|
@ -32,6 +32,16 @@ typedef UINT64 QWORD;
|
|||
#define TAGREF_NULL (0)
|
||||
#define TAGREF_ROOT (0)
|
||||
|
||||
typedef struct tagATTRINFO {
|
||||
TAG type;
|
||||
DWORD flags;
|
||||
union {
|
||||
QWORD qwattr;
|
||||
DWORD dwattr;
|
||||
WCHAR *lpattr;
|
||||
};
|
||||
} ATTRINFO, *PATTRINFO;
|
||||
|
||||
typedef enum _SHIM_LOG_LEVEL {
|
||||
SHIM_ERR = 1,
|
||||
SHIM_WARN = 2,
|
||||
|
@ -72,6 +82,19 @@ void SdbpFree(LPVOID mem);
|
|||
|
||||
#endif
|
||||
|
||||
typedef struct tagMEMMAPPED {
|
||||
HANDLE file;
|
||||
HANDLE section;
|
||||
PBYTE view;
|
||||
SIZE_T size;
|
||||
SIZE_T mapped_size;
|
||||
} MEMMAPPED, *PMEMMAPPED;
|
||||
|
||||
BOOL WINAPI SdbpOpenMemMappedFile(LPCWSTR path, PMEMMAPPED mapping);
|
||||
void WINAPI SdbpCloseMemMappedFile(PMEMMAPPED mapping);
|
||||
DWORD SdbpStrlen(LPCWSTR string);
|
||||
PWSTR SdbpStrDup(LPCWSTR string);
|
||||
|
||||
|
||||
/* layer.c */
|
||||
BOOL WINAPI AllowPermLayer(PCWSTR path);
|
||||
|
@ -79,6 +102,9 @@ BOOL WINAPI SdbGetPermLayerKeys(PCWSTR wszPath, PWSTR pwszLayers, PDWORD pdwByte
|
|||
BOOL WINAPI SetPermLayerState(PCWSTR wszPath, PCWSTR wszLayer, DWORD dwFlags, BOOL bMachine, BOOL bEnable);
|
||||
|
||||
|
||||
#define ATTRIBUTE_AVAILABLE 0x1
|
||||
#define ATTRIBUTE_FAILED 0x2
|
||||
|
||||
#define TAGID_NULL 0x0
|
||||
#define TAGID_ROOT 0x0
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
@ stub SdbFindNextTag
|
||||
@ stub SdbFindNextTagRef
|
||||
@ stub SdbFreeDatabaseInformation
|
||||
@ stub SdbFreeFileAttributes
|
||||
@ stdcall SdbFreeFileAttributes(ptr)
|
||||
@ stub SdbFreeFileInfo
|
||||
@ stub SdbFreeFlagInfo
|
||||
@ stub SdbGetAppCompatDataSize
|
||||
|
@ -61,7 +61,7 @@
|
|||
@ stub SdbGetDatabaseVersion
|
||||
@ stub SdbGetDllPath
|
||||
@ stub SdbGetEntryFlags
|
||||
@ stub SdbGetFileAttributes
|
||||
@ stdcall SdbGetFileAttributes(wstr ptr ptr)
|
||||
@ stub SdbGetFileImageType
|
||||
@ stub SdbGetFileImageTypeEx
|
||||
@ stub SdbGetFileInfo
|
||||
|
|
|
@ -155,11 +155,6 @@ void SdbpHeapDeinit(void)
|
|||
HeapDestroy(g_Heap);
|
||||
}
|
||||
|
||||
DWORD SdbpStrlen(PCWSTR string)
|
||||
{
|
||||
return (lstrlenW(string) + 1) * sizeof(WCHAR);
|
||||
}
|
||||
|
||||
static HANDLE SdbpHeap(void)
|
||||
{
|
||||
return g_Heap;
|
||||
|
@ -203,6 +198,94 @@ void SdbpFree(LPVOID mem
|
|||
HeapFree(SdbpHeap(), 0, mem);
|
||||
}
|
||||
|
||||
DWORD SdbpStrlen(PCWSTR string)
|
||||
{
|
||||
return (lstrlenW(string) + 1) * sizeof(WCHAR);
|
||||
}
|
||||
|
||||
PWSTR SdbpStrDup(LPCWSTR string)
|
||||
{
|
||||
PWSTR ret = SdbpAlloc(SdbpStrlen(string));
|
||||
lstrcpyW(ret, string);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
BOOL WINAPI SdbpOpenMemMappedFile(LPCWSTR path, PMEMMAPPED mapping)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
FILE_STANDARD_INFORMATION FileStandard;
|
||||
UNICODE_STRING FileName;
|
||||
|
||||
RtlZeroMemory(mapping, sizeof(*mapping));
|
||||
|
||||
if(!RtlDosPathNameToNtPathName_U(path, &FileName, NULL, NULL))
|
||||
{
|
||||
RtlFreeUnicodeString(&FileName);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
InitializeObjectAttributes(&ObjectAttributes, &FileName, OBJ_CASE_INSENSITIVE, NULL, NULL);
|
||||
Status = NtOpenFile(&mapping->file, GENERIC_READ | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT);
|
||||
RtlFreeUnicodeString(&FileName);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
SHIM_ERR("Failed to open file %S: 0x%lx\n", path, Status);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Status = NtCreateSection(&mapping->section, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ, 0, 0, PAGE_READONLY, SEC_COMMIT, mapping->file);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Special case */
|
||||
if (Status == STATUS_MAPPED_FILE_SIZE_ZERO)
|
||||
{
|
||||
NtClose(mapping->file);
|
||||
mapping->file = mapping->section = NULL;
|
||||
return TRUE;
|
||||
}
|
||||
SHIM_ERR("Failed to create mapping for file: 0x%lx\n", Status);
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
Status = NtQueryInformationFile(mapping->file, &IoStatusBlock, &FileStandard, sizeof(FileStandard), FileStandardInformation);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
SHIM_ERR("Failed to read file info for file: 0x%lx\n", Status);
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
mapping->mapped_size = mapping->size = FileStandard.EndOfFile.LowPart;
|
||||
Status = NtMapViewOfSection(mapping->section, NtCurrentProcess(), (PVOID*)&mapping->view, 0, 0, 0, &mapping->mapped_size, ViewUnmap, 0, PAGE_READONLY);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
SHIM_ERR("Failed to map view of file: 0x%lx\n", Status);
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
err_out:
|
||||
if (!mapping->view)
|
||||
{
|
||||
if (mapping->section)
|
||||
NtClose(mapping->section);
|
||||
NtClose(mapping->file);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void WINAPI SdbpCloseMemMappedFile(PMEMMAPPED mapping)
|
||||
{
|
||||
NtUnmapViewOfSection(NtCurrentProcess(), mapping->view);
|
||||
NtClose(mapping->section);
|
||||
NtClose(mapping->file);
|
||||
RtlZeroMemory(mapping, sizeof(*mapping));
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts specified tag into a string.
|
||||
*
|
||||
|
|
371
reactos/dll/appcompat/apphelp/sdbfileattr.c
Normal file
371
reactos/dll/appcompat/apphelp/sdbfileattr.c
Normal file
|
@ -0,0 +1,371 @@
|
|||
/*
|
||||
* Copyright 2011 André Hentschel
|
||||
* Copyright 2013 Mislav Blaževic
|
||||
* Copyright 2015 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 "imagehlp.h"
|
||||
#include "winver.h"
|
||||
|
||||
#include "wine/unicode.h"
|
||||
|
||||
#define NUM_ATTRIBUTES 28
|
||||
|
||||
static void WINAPI SdbpSetDWORDAttr(PATTRINFO attr, TAG tag, DWORD value)
|
||||
{
|
||||
attr->type = tag;
|
||||
attr->flags = ATTRIBUTE_AVAILABLE;
|
||||
attr->dwattr = value;
|
||||
}
|
||||
|
||||
static void WINAPI SdbpSetQWORDAttr(PATTRINFO attr, TAG tag, QWORD value)
|
||||
{
|
||||
attr->type = tag;
|
||||
attr->flags = ATTRIBUTE_AVAILABLE;
|
||||
attr->qwattr = value;
|
||||
}
|
||||
|
||||
static void WINAPI SdbpSetStringAttr(PATTRINFO attr, TAG tag, WCHAR *string)
|
||||
{
|
||||
if (!string)
|
||||
{
|
||||
attr->flags = ATTRIBUTE_FAILED;
|
||||
return;
|
||||
}
|
||||
|
||||
attr->type = tag;
|
||||
attr->flags = ATTRIBUTE_AVAILABLE;
|
||||
attr->lpattr = SdbpStrDup(string);
|
||||
}
|
||||
|
||||
static void WINAPI SdbpSetAttrFail(PATTRINFO attr)
|
||||
{
|
||||
attr->flags = ATTRIBUTE_FAILED;
|
||||
}
|
||||
|
||||
static WCHAR* WINAPI SdbpGetStringAttr(LPWSTR translation, LPCWSTR attr, PVOID file_info)
|
||||
{
|
||||
UINT size = 0;
|
||||
PVOID buffer;
|
||||
WCHAR value[128] = {0};
|
||||
|
||||
if (!file_info)
|
||||
return NULL;
|
||||
|
||||
snprintfW(value, 128, translation, attr);
|
||||
if (VerQueryValueW(file_info, value, &buffer, &size) && size != 0)
|
||||
return (WCHAR*)buffer;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void WINAPI SdbpSetStringAttrFromAnsiString(PATTRINFO attr, TAG tag, PBYTE string, BYTE len)
|
||||
{
|
||||
WCHAR* dest;
|
||||
if (!string)
|
||||
{
|
||||
attr->flags = ATTRIBUTE_FAILED;
|
||||
return;
|
||||
}
|
||||
|
||||
attr->type = tag;
|
||||
attr->flags = ATTRIBUTE_AVAILABLE;
|
||||
dest = attr->lpattr = SdbpAlloc((len+1) * sizeof(WCHAR));
|
||||
while (len--)
|
||||
*(dest++) = *(string++);
|
||||
*dest = 0;
|
||||
}
|
||||
|
||||
static void WINAPI SdbpSetStringAttrFromPascalString(PATTRINFO attr, TAG tag, PBYTE string)
|
||||
{
|
||||
if (!string)
|
||||
{
|
||||
attr->flags = ATTRIBUTE_FAILED;
|
||||
return;
|
||||
}
|
||||
|
||||
SdbpSetStringAttrFromAnsiString(attr, tag, string + 1, *string);
|
||||
}
|
||||
|
||||
static void SdbpReadFileVersion(PATTRINFO attr_info, PVOID file_info)
|
||||
{
|
||||
static const WCHAR str_root[] = {'\\',0};
|
||||
|
||||
VS_FIXEDFILEINFO* fixed_info;
|
||||
UINT size;
|
||||
if (file_info && VerQueryValueW(file_info, str_root, (LPVOID*)&fixed_info, &size) && size)
|
||||
{
|
||||
if (fixed_info->dwSignature == VS_FFI_SIGNATURE)
|
||||
{
|
||||
LARGE_INTEGER version;
|
||||
version.HighPart = fixed_info->dwFileVersionMS;
|
||||
version.LowPart = fixed_info->dwFileVersionLS;
|
||||
SdbpSetQWORDAttr(&attr_info[2], TAG_BIN_FILE_VERSION, version.QuadPart);
|
||||
SdbpSetQWORDAttr(&attr_info[21], TAG_UPTO_BIN_FILE_VERSION, version.QuadPart);
|
||||
version.HighPart = fixed_info->dwProductVersionMS;
|
||||
version.LowPart = fixed_info->dwProductVersionLS;
|
||||
SdbpSetQWORDAttr(&attr_info[3], TAG_BIN_PRODUCT_VERSION, version.QuadPart);
|
||||
SdbpSetQWORDAttr(&attr_info[22], TAG_UPTO_BIN_PRODUCT_VERSION, version.QuadPart);
|
||||
|
||||
SdbpSetDWORDAttr(&attr_info[12], TAG_VERDATEHI, fixed_info->dwFileDateMS);
|
||||
SdbpSetDWORDAttr(&attr_info[13], TAG_VERDATELO, fixed_info->dwFileDateLS);
|
||||
SdbpSetDWORDAttr(&attr_info[14], TAG_VERFILEOS, fixed_info->dwFileOS); /* 0x000, 0x4, 0x40004, 0x40000, 0x10004, 0x10001*/
|
||||
SdbpSetDWORDAttr(&attr_info[15], TAG_VERFILETYPE, fixed_info->dwFileType); /* VFT_APP, VFT_DLL, .... */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SdbpSetAttrFail(&attr_info[2]);
|
||||
SdbpSetAttrFail(&attr_info[3]);
|
||||
SdbpSetAttrFail(&attr_info[12]);
|
||||
SdbpSetAttrFail(&attr_info[13]);
|
||||
SdbpSetAttrFail(&attr_info[14]);
|
||||
SdbpSetAttrFail(&attr_info[15]);
|
||||
SdbpSetAttrFail(&attr_info[21]);
|
||||
SdbpSetAttrFail(&attr_info[22]);
|
||||
}
|
||||
|
||||
static DWORD WINAPI SdbpCalculateFileChecksum(PMEMMAPPED mapping)
|
||||
{
|
||||
size_t n, size;
|
||||
PDWORD data;
|
||||
DWORD checks = 0, carry = 0;
|
||||
|
||||
if (mapping->size < 4)
|
||||
return 0;
|
||||
|
||||
if (mapping->size >= 0x1000)
|
||||
{
|
||||
size = 0x1000;
|
||||
if (mapping->size < 0x1200)
|
||||
data = (PDWORD)(mapping->view + mapping->size - size);
|
||||
else
|
||||
data = (PDWORD)mapping->view + (0x200 / 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
data = (PDWORD)mapping->view;
|
||||
size = mapping->size;
|
||||
}
|
||||
|
||||
for (n = 0; n < size / 4; ++n)
|
||||
{
|
||||
checks += *data;
|
||||
carry = (checks & 1) ? 0x80000000 : 0;
|
||||
checks >>= 1;
|
||||
checks |= carry;
|
||||
++data;
|
||||
}
|
||||
return checks;
|
||||
}
|
||||
|
||||
static DWORD WINAPI SdbpGetModuleType(PMEMMAPPED mapping)
|
||||
{
|
||||
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)mapping->view;
|
||||
PIMAGE_OS2_HEADER os2;
|
||||
|
||||
if (mapping->size < 2 || dos->e_magic != IMAGE_DOS_SIGNATURE)
|
||||
return 0;
|
||||
|
||||
if (mapping->size < sizeof(IMAGE_DOS_HEADER) || mapping->size < (dos->e_lfanew+2))
|
||||
return 1;
|
||||
|
||||
os2 = (PIMAGE_OS2_HEADER)((PBYTE)dos + dos->e_lfanew);
|
||||
if (os2->ne_magic == IMAGE_OS2_SIGNATURE || os2->ne_magic == IMAGE_OS2_SIGNATURE_LE)
|
||||
return 2;
|
||||
|
||||
if (mapping->size >= (dos->e_lfanew + 4) && ((PIMAGE_NT_HEADERS)os2)->Signature == IMAGE_NT_SIGNATURE)
|
||||
return 3;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees attribute data allocated by SdbGetFileAttributes.
|
||||
*
|
||||
* @note Unlike Windows, this implementation will not crash if attr_info is NULL.
|
||||
*
|
||||
* @param [in] attr_info Pointer to array of ATTRINFO which will be freed.
|
||||
*
|
||||
* @return TRUE if it succeeds, FALSE if it fails.
|
||||
*/
|
||||
BOOL WINAPI SdbFreeFileAttributes(PATTRINFO attr_info)
|
||||
{
|
||||
WORD i;
|
||||
|
||||
if (!attr_info)
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < NUM_ATTRIBUTES; i++)
|
||||
if ((attr_info[i].type & TAG_TYPE_MASK) == TAG_TYPE_STRINGREF)
|
||||
SdbFree(attr_info[i].lpattr);
|
||||
SdbFree(attr_info);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves attribute data shim database requires to match a file with database entry
|
||||
*
|
||||
* @note You must free the attr_info allocated by this function by calling SdbFreeFileAttributes.
|
||||
*
|
||||
* @param [in] path Path to the file.
|
||||
* @param [out] attr_info_ret Pointer to array of ATTRINFO. Contains attribute data.
|
||||
* @param [out] attr_count Number of attributes in attr_info.
|
||||
*
|
||||
* @return TRUE if it succeeds, FALSE if it fails.
|
||||
*/
|
||||
BOOL WINAPI SdbGetFileAttributes(LPCWSTR path, PATTRINFO *attr_info_ret, LPDWORD attr_count)
|
||||
{
|
||||
static const WCHAR str_tinfo[] = {'\\','V','a','r','F','i','l','e','I','n','f','o','\\','T','r','a','n','s','l','a','t','i','o','n',0};
|
||||
static const WCHAR str_trans[] = {'\\','S','t','r','i','n','g','F','i','l','e','I','n','f','o','\\','%','0','4','x','%','0','4','x','\\','%','%','s',0};
|
||||
static const WCHAR str_CompanyName[] = {'C','o','m','p','a','n','y','N','a','m','e',0};
|
||||
static const WCHAR str_FileDescription[] = {'F','i','l','e','D','e','s','c','r','i','p','t','i','o','n',0};
|
||||
static const WCHAR str_FileVersion[] = {'F','i','l','e','V','e','r','s','i','o','n',0};
|
||||
static const WCHAR str_InternalName[] = {'I','n','t','e','r','n','a','l','N','a','m','e',0};
|
||||
static const WCHAR str_LegalCopyright[] = {'L','e','g','a','l','C','o','p','y','r','i','g','h','t',0};
|
||||
static const WCHAR str_OriginalFilename[] = {'O','r','i','g','i','n','a','l','F','i','l','e','n','a','m','e',0};
|
||||
static const WCHAR str_ProductName[] = {'P','r','o','d','u','c','t','N','a','m','e',0};
|
||||
static const WCHAR str_ProductVersion[] = {'P','r','o','d','u','c','t','V','e','r','s','i','o','n',0};
|
||||
|
||||
PIMAGE_NT_HEADERS headers;
|
||||
MEMMAPPED mapped;
|
||||
PVOID file_info = 0;
|
||||
DWORD headersum, checksum, module_type;
|
||||
WCHAR translation[128] = {0};
|
||||
PATTRINFO attr_info;
|
||||
|
||||
struct LANGANDCODEPAGE {
|
||||
WORD language;
|
||||
WORD code_page;
|
||||
} *lang_page;
|
||||
|
||||
if (!SdbpOpenMemMappedFile(path, &mapped))
|
||||
{
|
||||
SHIM_ERR("Error retrieving FILEINFO structure\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
attr_info = (PATTRINFO)SdbAlloc(NUM_ATTRIBUTES * sizeof(ATTRINFO));
|
||||
|
||||
SdbpSetDWORDAttr(&attr_info[0], TAG_SIZE, mapped.size);
|
||||
if (mapped.size)
|
||||
SdbpSetDWORDAttr(&attr_info[1], TAG_CHECKSUM, SdbpCalculateFileChecksum(&mapped));
|
||||
else
|
||||
SdbpSetAttrFail(&attr_info[1]);
|
||||
module_type = SdbpGetModuleType(&mapped);
|
||||
|
||||
if (module_type)
|
||||
SdbpSetDWORDAttr(&attr_info[16], TAG_MODULE_TYPE, module_type);
|
||||
else
|
||||
SdbpSetAttrFail(&attr_info[16]); /* TAG_MODULE_TYPE */
|
||||
|
||||
headers = CheckSumMappedFile(mapped.view, mapped.size, &headersum, &checksum);
|
||||
if (headers)
|
||||
{
|
||||
DWORD info_size;
|
||||
SIZE_T export_dir_size;
|
||||
PIMAGE_EXPORT_DIRECTORY export_dir;
|
||||
|
||||
info_size = GetFileVersionInfoSizeW(path, NULL);
|
||||
if (info_size != 0)
|
||||
{
|
||||
UINT page_size = 0;
|
||||
file_info = SdbAlloc(info_size);
|
||||
GetFileVersionInfoW(path, 0, info_size, file_info);
|
||||
VerQueryValueW(file_info, str_tinfo, (LPVOID)&lang_page, &page_size);
|
||||
snprintfW(translation, 128, str_trans, lang_page->language, lang_page->code_page);
|
||||
}
|
||||
|
||||
/* Handles 2, 3, 12, 13, 14, 15, 21, 22 */
|
||||
SdbpReadFileVersion(attr_info, file_info);
|
||||
|
||||
SdbpSetStringAttr(&attr_info[4], TAG_PRODUCT_VERSION, SdbpGetStringAttr(translation, str_ProductVersion, file_info));
|
||||
SdbpSetStringAttr(&attr_info[5], TAG_FILE_DESCRIPTION, SdbpGetStringAttr(translation, str_FileDescription, file_info));
|
||||
SdbpSetStringAttr(&attr_info[6], TAG_COMPANY_NAME, SdbpGetStringAttr(translation, str_CompanyName, file_info));
|
||||
SdbpSetStringAttr(&attr_info[7], TAG_PRODUCT_NAME, SdbpGetStringAttr(translation, str_ProductName, file_info));
|
||||
SdbpSetStringAttr(&attr_info[8], TAG_FILE_VERSION, SdbpGetStringAttr(translation, str_FileVersion, file_info));
|
||||
SdbpSetStringAttr(&attr_info[9], TAG_ORIGINAL_FILENAME, SdbpGetStringAttr(translation, str_OriginalFilename, file_info));
|
||||
SdbpSetStringAttr(&attr_info[10], TAG_INTERNAL_NAME, SdbpGetStringAttr(translation, str_InternalName, file_info));
|
||||
SdbpSetStringAttr(&attr_info[11], TAG_LEGAL_COPYRIGHT, SdbpGetStringAttr(translation, str_LegalCopyright, file_info));
|
||||
|
||||
/* http://msdn.microsoft.com/en-us/library/windows/desktop/ms680339(v=vs.85).aspx */
|
||||
|
||||
SdbpSetDWORDAttr(&attr_info[17], TAG_PE_CHECKSUM, headers->OptionalHeader.CheckSum);
|
||||
|
||||
SdbpSetDWORDAttr(&attr_info[18], TAG_LINKER_VERSION, /* mislabeled! */
|
||||
((DWORD)headers->OptionalHeader.MajorImageVersion) << 16 | headers->OptionalHeader.MinorImageVersion);
|
||||
SdbpSetAttrFail(&attr_info[19]); /* TAG_16BIT_DESCRIPTION */
|
||||
SdbpSetAttrFail(&attr_info[20]); /* TAG_16BIT_MODULE_NAME */
|
||||
|
||||
SdbpSetDWORDAttr(&attr_info[23], TAG_LINK_DATE, headers->FileHeader.TimeDateStamp);
|
||||
SdbpSetDWORDAttr(&attr_info[24], TAG_UPTO_LINK_DATE, headers->FileHeader.TimeDateStamp);
|
||||
|
||||
export_dir = (PIMAGE_EXPORT_DIRECTORY)ImageDirectoryEntryToData(mapped.view, FALSE, IMAGE_DIRECTORY_ENTRY_EXPORT, &export_dir_size);
|
||||
if (export_dir)
|
||||
{
|
||||
PIMAGE_SECTION_HEADER section = NULL;
|
||||
PBYTE export_name = ImageRvaToVa(headers, mapped.view, export_dir->Name, §ion);
|
||||
if (export_name)
|
||||
SdbpSetStringAttrFromAnsiString(&attr_info[25], TAG_EXPORT_NAME, export_name, strlen((char*)export_name));
|
||||
else
|
||||
SdbpSetAttrFail(&attr_info[25]); /* TAG_EXPORT_NAME */
|
||||
}
|
||||
else
|
||||
{
|
||||
SdbpSetAttrFail(&attr_info[25]); /* TAG_EXPORT_NAME */
|
||||
}
|
||||
|
||||
if (info_size)
|
||||
SdbpSetDWORDAttr(&attr_info[26], TAG_VER_LANGUAGE, lang_page->language);
|
||||
|
||||
SdbpSetDWORDAttr(&attr_info[27], TAG_EXE_WRAPPER, 0); /* boolean */
|
||||
}
|
||||
else
|
||||
{
|
||||
int n;
|
||||
for (n = 2; n < NUM_ATTRIBUTES; ++n)
|
||||
{
|
||||
if (n != 16 && n != 26)
|
||||
SdbpSetAttrFail(&attr_info[n]);
|
||||
}
|
||||
if (module_type == 2)
|
||||
{
|
||||
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)mapped.view;
|
||||
PBYTE end = mapped.view + mapped.size, ptr;
|
||||
PIMAGE_OS2_HEADER os2 = (PIMAGE_OS2_HEADER)((PBYTE)dos + dos->e_lfanew);
|
||||
if ((PBYTE)(os2 + 1) <= end)
|
||||
{
|
||||
ptr = (PBYTE)dos + os2->ne_nrestab;
|
||||
if (ptr <= end && (ptr + 1 + *ptr) <= end)
|
||||
SdbpSetStringAttrFromPascalString(&attr_info[19], TAG_16BIT_DESCRIPTION, ptr);
|
||||
ptr = (PBYTE)os2 + os2->ne_restab;
|
||||
if (ptr <= end && (ptr + 1 + *ptr) <= end)
|
||||
SdbpSetStringAttrFromPascalString(&attr_info[20], TAG_16BIT_MODULE_NAME, ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*attr_info_ret = attr_info;
|
||||
*attr_count = NUM_ATTRIBUTES; /* As far as I know, this one is always 28 */
|
||||
|
||||
SdbFree(file_info);
|
||||
SdbpCloseMemMappedFile(&mapped);
|
||||
return TRUE;
|
||||
}
|
|
@ -2,8 +2,9 @@
|
|||
add_definitions(-D__ROS_LONG64__)
|
||||
|
||||
list(APPEND SOURCE
|
||||
layerapi.c
|
||||
apphelp.c
|
||||
data.c
|
||||
layerapi.c
|
||||
testlist.c)
|
||||
|
||||
add_executable(apphelp_apitest ${SOURCE})
|
||||
|
|
|
@ -35,6 +35,15 @@
|
|||
|
||||
#include "wine/test.h"
|
||||
|
||||
/* data.c */
|
||||
void test_create_exe_imp(const char* name, int skip_rsrc_exports);
|
||||
void test_create_file_imp(const char* name, const char* contents, size_t len);
|
||||
void test_create_ne_imp(const char* name, int skip_names);
|
||||
|
||||
#define test_create_exe (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : test_create_exe_imp
|
||||
#define test_create_file (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : test_create_file_imp
|
||||
#define test_create_ne (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : test_create_ne_imp
|
||||
|
||||
|
||||
static DWORD g_Version;
|
||||
|
||||
|
@ -48,6 +57,9 @@ static DWORD g_Version;
|
|||
|
||||
|
||||
typedef WORD TAG;
|
||||
typedef DWORD TAGID;
|
||||
typedef DWORD TAGREF;
|
||||
typedef UINT64 QWORD;
|
||||
|
||||
#define TAG_TYPE_MASK 0xF000
|
||||
|
||||
|
@ -60,10 +72,55 @@ typedef WORD TAG;
|
|||
#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_CHECKSUM (0x3 | TAG_TYPE_DWORD)
|
||||
#define TAG_MODULE_TYPE (0x6 | TAG_TYPE_DWORD)
|
||||
#define TAG_VERDATEHI (0x7 | TAG_TYPE_DWORD)
|
||||
#define TAG_VERDATELO (0x8 | TAG_TYPE_DWORD)
|
||||
#define TAG_VERFILEOS (0x9 | TAG_TYPE_DWORD)
|
||||
#define TAG_VERFILETYPE (0xA | TAG_TYPE_DWORD)
|
||||
#define TAG_PE_CHECKSUM (0xB | TAG_TYPE_DWORD)
|
||||
#define TAG_VER_LANGUAGE (0x12 | TAG_TYPE_DWORD)
|
||||
#define TAG_LINKER_VERSION (0x1C | TAG_TYPE_DWORD)
|
||||
#define TAG_LINK_DATE (0x1D | TAG_TYPE_DWORD)
|
||||
#define TAG_UPTO_LINK_DATE (0x1E | TAG_TYPE_DWORD)
|
||||
#define TAG_EXE_WRAPPER (0x31 | TAG_TYPE_DWORD)
|
||||
#define TAG_BIN_FILE_VERSION (0x2 | TAG_TYPE_QWORD)
|
||||
#define TAG_BIN_PRODUCT_VERSION (0x3 | TAG_TYPE_QWORD)
|
||||
#define TAG_UPTO_BIN_PRODUCT_VERSION (0x6 | TAG_TYPE_QWORD)
|
||||
#define TAG_UPTO_BIN_FILE_VERSION (0xD | TAG_TYPE_QWORD)
|
||||
#define TAG_NAME (0x1 | TAG_TYPE_STRINGREF)
|
||||
#define TAG_COMPANY_NAME (0x9 | TAG_TYPE_STRINGREF)
|
||||
#define TAG_PRODUCT_NAME (0x10 | TAG_TYPE_STRINGREF)
|
||||
#define TAG_PRODUCT_VERSION (0x11 | TAG_TYPE_STRINGREF)
|
||||
#define TAG_FILE_DESCRIPTION (0x12 | TAG_TYPE_STRINGREF)
|
||||
#define TAG_FILE_VERSION (0x13 | TAG_TYPE_STRINGREF)
|
||||
#define TAG_ORIGINAL_FILENAME (0x14 | TAG_TYPE_STRINGREF)
|
||||
#define TAG_INTERNAL_NAME (0x15 | TAG_TYPE_STRINGREF)
|
||||
#define TAG_LEGAL_COPYRIGHT (0x16 | TAG_TYPE_STRINGREF)
|
||||
#define TAG_16BIT_DESCRIPTION (0x17 | TAG_TYPE_STRINGREF)
|
||||
#define TAG_16BIT_MODULE_NAME (0x20 | TAG_TYPE_STRINGREF)
|
||||
#define TAG_EXPORT_NAME (0x24 | TAG_TYPE_STRINGREF)
|
||||
|
||||
|
||||
#define ATTRIBUTE_AVAILABLE 0x1
|
||||
#define ATTRIBUTE_FAILED 0x2
|
||||
|
||||
typedef struct tagATTRINFO {
|
||||
TAG type;
|
||||
DWORD flags; /* ATTRIBUTE_AVAILABLE, ATTRIBUTE_FAILED */
|
||||
union {
|
||||
QWORD qwattr;
|
||||
DWORD dwattr;
|
||||
WCHAR *lpattr;
|
||||
};
|
||||
} ATTRINFO, *PATTRINFO;
|
||||
|
||||
static HMODULE hdll;
|
||||
static LPCWSTR (WINAPI *pSdbTagToString)(TAG);
|
||||
static BOOL (WINAPI *pSdbGetFileAttributes)(LPCWSTR, PATTRINFO *, LPDWORD);
|
||||
static BOOL (WINAPI *pSdbFreeFileAttributes)(PATTRINFO);
|
||||
|
||||
static void test_SdbTagToString(void)
|
||||
{
|
||||
|
@ -368,6 +425,386 @@ static void test_SdbTagToStringAllTags(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void expect_tag_skip_imp(PATTRINFO pattr, DWORD num)
|
||||
{
|
||||
PATTRINFO p = &pattr[num];
|
||||
winetest_ok(p->type == TAG_NULL, "expected entry #%d to be TAG_NULL, was %x\n", num, p->type);
|
||||
winetest_ok(p->flags == ATTRIBUTE_FAILED, "expected entry #%d to be failed, was %d\n", num, p->flags);
|
||||
winetest_ok(p->qwattr == 0, "expected entry #%d to be 0, was 0x%I64x\n", num, p->qwattr);
|
||||
}
|
||||
static void expect_tag_empty_imp(PATTRINFO pattr, DWORD num)
|
||||
{
|
||||
PATTRINFO p = &pattr[num];
|
||||
winetest_ok(p->type == TAG_NULL, "expected entry #%d to be TAG_NULL, was %x\n", num, p->type);
|
||||
winetest_ok(p->flags == 0, "expected entry #%d to be 0, was %d\n", num, p->flags);
|
||||
winetest_ok(p->qwattr == 0, "expected entry #%d to be 0, was 0x%I64x\n", num, p->qwattr);
|
||||
}
|
||||
|
||||
static void expect_tag_dword_imp(PATTRINFO pattr, DWORD num, TAG tag, DWORD value)
|
||||
{
|
||||
PATTRINFO p = &pattr[num];
|
||||
winetest_ok(p->type == tag, "expected entry #%d to be %x, was %x\n", num, tag, p->type);
|
||||
winetest_ok(p->flags == ATTRIBUTE_AVAILABLE, "expected entry #%d to be available, was %d\n", num, p->flags);
|
||||
winetest_ok(p->dwattr == value, "expected entry #%d to be 0x%x, was 0x%x\n", num, value, p->dwattr);
|
||||
}
|
||||
|
||||
static void expect_tag_qword_imp(PATTRINFO pattr, DWORD num, TAG tag, QWORD value)
|
||||
{
|
||||
PATTRINFO p = &pattr[num];
|
||||
winetest_ok(p->type == tag, "expected entry #%d to be %x, was %x\n", num, tag, p->type);
|
||||
winetest_ok(p->flags == ATTRIBUTE_AVAILABLE, "expected entry #%d to be available, was %d\n", num, p->flags);
|
||||
winetest_ok(p->qwattr == value, "expected entry #%d to be 0x%I64x, was 0x%I64x\n", num, value, p->qwattr);
|
||||
}
|
||||
|
||||
static void expect_tag_str_imp(PATTRINFO pattr, DWORD num, TAG tag, const WCHAR* value)
|
||||
{
|
||||
PATTRINFO p = &pattr[num];
|
||||
winetest_ok(p->type == tag, "expected entry #%d to be %x, was %x\n", num, tag, p->type);
|
||||
winetest_ok(p->flags == ATTRIBUTE_AVAILABLE, "expected entry #%d to be available, was %d\n", num, p->flags);
|
||||
winetest_ok(p->lpattr && wcscmp(p->lpattr, value) == 0, "expected entry #%d to be %s, was %s\n", num, wine_dbgstr_w(value), wine_dbgstr_w(p->lpattr));
|
||||
}
|
||||
|
||||
#define expect_tag_skip (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : expect_tag_skip_imp
|
||||
#define expect_tag_empty (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : expect_tag_empty_imp
|
||||
#define expect_tag_dword (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : expect_tag_dword_imp
|
||||
#define expect_tag_qword (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : expect_tag_qword_imp
|
||||
#define expect_tag_str (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : expect_tag_str_imp
|
||||
#define expect_tag_skip_range(ptr, from, to) \
|
||||
do { \
|
||||
int n = (from), n_end = (to); \
|
||||
winetest_set_location(__FILE__, __LINE__); \
|
||||
for ( ; n < n_end; ++n) \
|
||||
expect_tag_skip_imp((ptr), n); \
|
||||
} while (0)
|
||||
#define test_crc (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : test_crc_imp
|
||||
#define test_crc2 (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : test_crc2_imp
|
||||
|
||||
void test_onefile(WCHAR* filename)
|
||||
{
|
||||
PATTRINFO pattrinfo;
|
||||
DWORD num;
|
||||
|
||||
if (!pSdbFreeFileAttributes)
|
||||
{
|
||||
hdll = LoadLibraryA("apphelp.dll");
|
||||
pSdbTagToString = (void *)GetProcAddress(hdll, "SdbTagToString");
|
||||
pSdbGetFileAttributes = (void *)GetProcAddress(hdll, "SdbGetFileAttributes");
|
||||
pSdbFreeFileAttributes = (void *)GetProcAddress(hdll, "SdbFreeFileAttributes");
|
||||
}
|
||||
|
||||
if (pSdbGetFileAttributes(filename, &pattrinfo, &num))
|
||||
{
|
||||
if (pattrinfo[16].flags == ATTRIBUTE_AVAILABLE)
|
||||
{
|
||||
if (pattrinfo[16].type != TAG_MODULE_TYPE)//SdbpSetAttrFail(&attr_info[16]); /* TAG_MODULE_TYPE (1: WIN16?) (3: WIN32?) (WIN64?), Win32VersionValue? */)
|
||||
printf("FAIL TAG_MODULE_TYPE (%S)\n", filename);
|
||||
if (pattrinfo[16].dwattr != 3 && pattrinfo[16].dwattr != 2)
|
||||
printf("TAG_MODULE_TYPE(%S): %d\n", filename, pattrinfo[16].dwattr); // C:\Program Files (x86)\Windows Kits\8.1\Lib\win7\stub512.com
|
||||
if (pattrinfo[16].dwattr == 2)
|
||||
{
|
||||
printf("TAG_MODULE_TYPE(%S): %d, %d\n", filename, pattrinfo[16].dwattr, pattrinfo[0].dwattr);
|
||||
}
|
||||
}
|
||||
|
||||
if (pattrinfo[27].flags == ATTRIBUTE_AVAILABLE)
|
||||
{
|
||||
if (pattrinfo[27].type != TAG_EXE_WRAPPER)
|
||||
printf("FAIL TAG_EXE_WRAPPER (%S)\n", filename);
|
||||
if (pattrinfo[27].dwattr != 0)
|
||||
printf("TAG_EXE_WRAPPER(%S): %d\n", filename, pattrinfo[27].dwattr);
|
||||
}
|
||||
|
||||
pSdbFreeFileAttributes(pattrinfo);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_crc_imp(size_t len, DWORD expected)
|
||||
{
|
||||
static const WCHAR path[] = {'t','e','s','t','x','x','.','e','x','e',0};
|
||||
static char crc_test[] = {4, 4, 4, 4, 1, 1, 1, 1, 4, 4, 4, 4, 2, 2, 2, 2};
|
||||
|
||||
PATTRINFO pattrinfo = (PATTRINFO)0xdead;
|
||||
DWORD num = 333;
|
||||
BOOL ret;
|
||||
|
||||
test_create_file_imp("testxx.exe", crc_test, len);
|
||||
ret = pSdbGetFileAttributes(path, &pattrinfo, &num);
|
||||
winetest_ok(ret != FALSE, "expected SdbGetFileAttributes to succeed.\n");
|
||||
winetest_ok(pattrinfo != (PATTRINFO)0xdead, "expected a valid pointer.\n");
|
||||
winetest_ok(num == 28, "expected 28 items, got %d.\n", num);
|
||||
|
||||
if (num == 28 && ret)
|
||||
{
|
||||
expect_tag_dword_imp(pattrinfo, 1, TAG_CHECKSUM, expected);
|
||||
}
|
||||
if (ret)
|
||||
pSdbFreeFileAttributes(pattrinfo);
|
||||
}
|
||||
|
||||
static void test_crc2_imp(size_t len, int fill, DWORD expected)
|
||||
{
|
||||
static const WCHAR path[] = {'t','e','s','t','x','x','.','e','x','e',0};
|
||||
|
||||
PATTRINFO pattrinfo = (PATTRINFO)0xdead;
|
||||
DWORD num = 333;
|
||||
BOOL ret;
|
||||
size_t n;
|
||||
char* crc_test = malloc(len);
|
||||
for (n = 0; n < len; ++n)
|
||||
crc_test[n] = (char)(fill ? fill : n);
|
||||
|
||||
test_create_file_imp("testxx.exe", crc_test, len);
|
||||
free(crc_test);
|
||||
ret = pSdbGetFileAttributes(path, &pattrinfo, &num);
|
||||
winetest_ok(ret != FALSE, "expected SdbGetFileAttributes to succeed.\n");
|
||||
winetest_ok(pattrinfo != (PATTRINFO)0xdead, "expected a valid pointer.\n");
|
||||
winetest_ok(num == 28, "expected 28 items, got %d.\n", num);
|
||||
|
||||
if (num == 28 && ret)
|
||||
{
|
||||
expect_tag_dword_imp(pattrinfo, 0, TAG_SIZE, len);
|
||||
expect_tag_dword_imp(pattrinfo, 1, TAG_CHECKSUM, expected);
|
||||
}
|
||||
if (ret)
|
||||
pSdbFreeFileAttributes(pattrinfo);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void test_ApplicationAttributes(void)
|
||||
{
|
||||
static const WCHAR path[] = {'t','e','s','t','x','x','.','e','x','e',0};
|
||||
static const WCHAR PRODUCT_VERSION[] = {'1','.','0','.','0','.','1',0};
|
||||
static const WCHAR FILE_DESCRIPTION[] = {'F','i','l','e','D','e','s','c','r','i','p','t','i','o','n',0};
|
||||
static const WCHAR COMPANY_NAME[] = {'C','o','m','p','a','n','y','N','a','m','e',0};
|
||||
static const WCHAR PRODUCT_NAME[] = {'P','r','o','d','u','c','t','N','a','m','e',0};
|
||||
static const WCHAR FILE_VERSION[] = {'1','.','0','.','0','.','0',0};
|
||||
static const WCHAR ORIGINAL_FILENAME[] = {'O','r','i','g','i','n','a','l','F','i','l','e','n','a','m','e',0};
|
||||
static const WCHAR INTERNAL_NAME[] = {'I','n','t','e','r','n','a','l','N','a','m','e',0};
|
||||
static const WCHAR LEGAL_COPYRIGHT[] = {'L','e','g','a','l','C','o','p','y','r','i','g','h','t',0};
|
||||
static const WCHAR EXPORT_NAME[] = {'T','e','S','t','2','.','e','x','e',0};
|
||||
static const WCHAR OS2_DESCRIPTION[] = {'M','O','D',' ','D','E','S','C','R','I','P','T','I','O','N',' ','H','E','R','E',0};
|
||||
static const WCHAR OS2_EXPORT_NAME[] = {'T','E','S','T','M','O','D','.','h','X','x',0};
|
||||
static const WCHAR OS2_DESCRIPTION_broken[] = {'Z',0};
|
||||
static const WCHAR OS2_EXPORT_NAME_broken[] = {'E',0};
|
||||
|
||||
PATTRINFO pattrinfo = (PATTRINFO)0xdead;
|
||||
DWORD num = 333;
|
||||
BOOL ret;
|
||||
|
||||
/* ensure the file is not there. */
|
||||
DeleteFileA("testxx.exe");
|
||||
ret = pSdbGetFileAttributes(path, &pattrinfo, &num);
|
||||
ok(ret == FALSE, "expected SdbGetFileAttributes to fail.\n");
|
||||
ok(pattrinfo == (PATTRINFO)0xdead, "expected the pointer not to change.\n");
|
||||
ok(num == 333, "expected the number of items not to change.\n");
|
||||
if (ret)
|
||||
pSdbFreeFileAttributes(pattrinfo);
|
||||
|
||||
/* Test a file with as much features as possible */
|
||||
test_create_exe("testxx.exe", 0);
|
||||
|
||||
ret = pSdbGetFileAttributes(path, &pattrinfo, &num);
|
||||
ok(ret != FALSE, "expected SdbGetFileAttributes to succeed.\n");
|
||||
ok(pattrinfo != (PATTRINFO)0xdead, "expected a valid pointer.\n");
|
||||
ok(num == 28, "expected 28 items, got %d.\n", num);
|
||||
|
||||
if (num == 28 && ret)
|
||||
{
|
||||
expect_tag_dword(pattrinfo, 0, TAG_SIZE, 0x800);
|
||||
expect_tag_dword(pattrinfo, 1, TAG_CHECKSUM, 0x178bd629);
|
||||
expect_tag_qword(pattrinfo, 2, TAG_BIN_FILE_VERSION, 0x1000000000000ull);
|
||||
expect_tag_qword(pattrinfo, 3, TAG_BIN_PRODUCT_VERSION, 0x1000000000001ull);
|
||||
expect_tag_str(pattrinfo, 4, TAG_PRODUCT_VERSION, PRODUCT_VERSION);
|
||||
expect_tag_str(pattrinfo, 5, TAG_FILE_DESCRIPTION, FILE_DESCRIPTION);
|
||||
expect_tag_str(pattrinfo, 6, TAG_COMPANY_NAME, COMPANY_NAME);
|
||||
expect_tag_str(pattrinfo, 7, TAG_PRODUCT_NAME, PRODUCT_NAME);
|
||||
expect_tag_str(pattrinfo, 8, TAG_FILE_VERSION, FILE_VERSION);
|
||||
expect_tag_str(pattrinfo, 9, TAG_ORIGINAL_FILENAME, ORIGINAL_FILENAME);
|
||||
expect_tag_str(pattrinfo, 10, TAG_INTERNAL_NAME, INTERNAL_NAME);
|
||||
expect_tag_str(pattrinfo, 11, TAG_LEGAL_COPYRIGHT, LEGAL_COPYRIGHT);
|
||||
expect_tag_dword(pattrinfo, 12, TAG_VERDATEHI, 0x1d1a019);
|
||||
expect_tag_dword(pattrinfo, 13, TAG_VERDATELO, 0xac754c50);
|
||||
expect_tag_dword(pattrinfo, 14, TAG_VERFILEOS, VOS__WINDOWS32);
|
||||
expect_tag_dword(pattrinfo, 15, TAG_VERFILETYPE, VFT_APP);
|
||||
expect_tag_dword(pattrinfo, 16, TAG_MODULE_TYPE, 0x3); /* Win32 */
|
||||
expect_tag_dword(pattrinfo, 17, TAG_PE_CHECKSUM, 0xBAAD);
|
||||
expect_tag_dword(pattrinfo, 18, TAG_LINKER_VERSION, 0x40002);
|
||||
expect_tag_skip(pattrinfo, 19); /* TAG_16BIT_DESCRIPTION */
|
||||
expect_tag_skip(pattrinfo, 20); /* TAG_16BIT_MODULE_NAME */
|
||||
expect_tag_qword(pattrinfo, 21, TAG_UPTO_BIN_FILE_VERSION, 0x1000000000000ull);
|
||||
expect_tag_qword(pattrinfo, 22, TAG_UPTO_BIN_PRODUCT_VERSION, 0x1000000000001ull);
|
||||
expect_tag_dword(pattrinfo, 23, TAG_LINK_DATE, 0x12345);
|
||||
expect_tag_dword(pattrinfo, 24, TAG_UPTO_LINK_DATE, 0x12345);
|
||||
expect_tag_str(pattrinfo, 25, TAG_EXPORT_NAME, EXPORT_NAME);
|
||||
expect_tag_dword(pattrinfo, 26, TAG_VER_LANGUAGE, 0xffff);
|
||||
expect_tag_dword(pattrinfo, 27, TAG_EXE_WRAPPER, 0x0);
|
||||
}
|
||||
if (ret)
|
||||
pSdbFreeFileAttributes(pattrinfo);
|
||||
|
||||
|
||||
/* Disable resource and exports */
|
||||
test_create_exe("testxx.exe", 1);
|
||||
|
||||
ret = pSdbGetFileAttributes(path, &pattrinfo, &num);
|
||||
ok(ret != FALSE, "expected SdbGetFileAttributes to succeed.\n");
|
||||
ok(pattrinfo != (PATTRINFO)0xdead, "expected a valid pointer.\n");
|
||||
ok(num == 28, "expected 28 items, got %d.\n", num);
|
||||
|
||||
if (num == 28 && ret)
|
||||
{
|
||||
expect_tag_dword(pattrinfo, 0, TAG_SIZE, 0x800);
|
||||
expect_tag_dword(pattrinfo, 1, TAG_CHECKSUM, 0xea7caffd);
|
||||
expect_tag_skip_range(pattrinfo, 2, 16);
|
||||
expect_tag_dword(pattrinfo, 16, TAG_MODULE_TYPE, 0x3); /* Win32 */
|
||||
expect_tag_dword(pattrinfo, 17, TAG_PE_CHECKSUM, 0xBAAD);
|
||||
expect_tag_dword(pattrinfo, 18, TAG_LINKER_VERSION, 0x40002);
|
||||
expect_tag_skip_range(pattrinfo, 19, 23);
|
||||
expect_tag_dword(pattrinfo, 23, TAG_LINK_DATE, 0x12345);
|
||||
expect_tag_dword(pattrinfo, 24, TAG_UPTO_LINK_DATE, 0x12345);
|
||||
expect_tag_skip(pattrinfo, 25); /* TAG_EXPORT_NAME */
|
||||
expect_tag_empty(pattrinfo, 26); /* TAG_VER_LANGUAGE */
|
||||
expect_tag_dword(pattrinfo, 27, TAG_EXE_WRAPPER, 0x0);
|
||||
}
|
||||
if (ret)
|
||||
pSdbFreeFileAttributes(pattrinfo);
|
||||
|
||||
/* A file with just 'MZ' */
|
||||
test_create_file("testxx.exe", "MZ", 2);
|
||||
|
||||
ret = pSdbGetFileAttributes(path, &pattrinfo, &num);
|
||||
ok(ret != FALSE, "expected SdbGetFileAttributes to succeed.\n");
|
||||
ok(pattrinfo != (PATTRINFO)0xdead, "expected a valid pointer.\n");
|
||||
ok(num == 28, "expected 28 items, got %d.\n", num);
|
||||
|
||||
if (num == 28 && ret)
|
||||
{
|
||||
expect_tag_dword(pattrinfo, 0, TAG_SIZE, 0x2);
|
||||
expect_tag_dword(pattrinfo, 1, TAG_CHECKSUM, 0);
|
||||
expect_tag_skip_range(pattrinfo, 2, 16);
|
||||
expect_tag_dword(pattrinfo, 16, TAG_MODULE_TYPE, 0x1);
|
||||
expect_tag_skip_range(pattrinfo, 17, 26);
|
||||
expect_tag_empty(pattrinfo, 26); /* TAG_VER_LANGUAGE */
|
||||
expect_tag_skip(pattrinfo, 27); /* TAG_EXE_WRAPPER */
|
||||
}
|
||||
if (ret)
|
||||
pSdbFreeFileAttributes(pattrinfo);
|
||||
|
||||
/* Empty file */
|
||||
test_create_file("testxx.exe", NULL, 0);
|
||||
|
||||
ret = pSdbGetFileAttributes(path, &pattrinfo, &num);
|
||||
ok(ret != FALSE, "expected SdbGetFileAttributes to succeed.\n");
|
||||
ok(pattrinfo != (PATTRINFO)0xdead, "expected a valid pointer.\n");
|
||||
ok(num == 28, "expected 28 items, got %d.\n", num);
|
||||
|
||||
if (num == 28 && ret)
|
||||
{
|
||||
expect_tag_dword(pattrinfo, 0, TAG_SIZE, 0);
|
||||
expect_tag_skip_range(pattrinfo, 1, 26);
|
||||
expect_tag_empty(pattrinfo, 26); /* TAG_VER_LANGUAGE */
|
||||
expect_tag_skip(pattrinfo, 27); /* TAG_EXE_WRAPPER */
|
||||
}
|
||||
if (ret)
|
||||
pSdbFreeFileAttributes(pattrinfo);
|
||||
|
||||
/* minimal NE executable */
|
||||
test_create_ne("testxx.exe", 0);
|
||||
|
||||
ret = pSdbGetFileAttributes(path, &pattrinfo, &num);
|
||||
ok(ret != FALSE, "expected SdbGetFileAttributes to succeed.\n");
|
||||
ok(pattrinfo != (PATTRINFO)0xdead, "expected a valid pointer.\n");
|
||||
ok(num == 28, "expected 28 items, got %d.\n", num);
|
||||
|
||||
if (num == 28 && ret)
|
||||
{
|
||||
expect_tag_dword(pattrinfo, 0, TAG_SIZE, 0xa8);
|
||||
expect_tag_dword(pattrinfo, 1, TAG_CHECKSUM, 0xf2abe4e9);
|
||||
expect_tag_skip_range(pattrinfo, 2, 16);
|
||||
expect_tag_dword(pattrinfo, 16, TAG_MODULE_TYPE, 0x2);
|
||||
expect_tag_skip(pattrinfo, 17); /* TAG_PE_CHECKSUM */
|
||||
expect_tag_skip(pattrinfo, 18); /* TAG_LINKER_VERSION */
|
||||
expect_tag_str(pattrinfo, 19, TAG_16BIT_DESCRIPTION, OS2_DESCRIPTION);
|
||||
expect_tag_str(pattrinfo, 20, TAG_16BIT_MODULE_NAME, OS2_EXPORT_NAME);
|
||||
expect_tag_skip_range(pattrinfo, 21, 26);
|
||||
expect_tag_empty(pattrinfo, 26); /* TAG_VER_LANGUAGE */
|
||||
expect_tag_skip(pattrinfo, 27); /* TAG_EXE_WRAPPER */
|
||||
}
|
||||
if (ret)
|
||||
pSdbFreeFileAttributes(pattrinfo);
|
||||
|
||||
/* NE executable with description / module name pointers zero, to show they are always used */
|
||||
test_create_ne("testxx.exe", 1);
|
||||
|
||||
ret = pSdbGetFileAttributes(path, &pattrinfo, &num);
|
||||
ok(ret != FALSE, "expected SdbGetFileAttributes to succeed.\n");
|
||||
ok(pattrinfo != (PATTRINFO)0xdead, "expected a valid pointer.\n");
|
||||
ok(num == 28, "expected 28 items, got %d.\n", num);
|
||||
|
||||
if (num == 28 && ret)
|
||||
{
|
||||
expect_tag_dword(pattrinfo, 0, TAG_SIZE, 0xa8);
|
||||
expect_tag_dword(pattrinfo, 1, TAG_CHECKSUM, 0xddcbe4c9);
|
||||
expect_tag_skip_range(pattrinfo, 2, 16);
|
||||
expect_tag_dword(pattrinfo, 16, TAG_MODULE_TYPE, 0x2);
|
||||
expect_tag_skip(pattrinfo, 17); /* TAG_PE_CHECKSUM */
|
||||
expect_tag_skip(pattrinfo, 18); /* TAG_LINKER_VERSION */
|
||||
expect_tag_str(pattrinfo, 19, TAG_16BIT_DESCRIPTION, OS2_DESCRIPTION_broken); /* the 'Z' from 'MZ' */
|
||||
expect_tag_str(pattrinfo, 20, TAG_16BIT_MODULE_NAME, OS2_EXPORT_NAME_broken); /* the 'E' from 'NE' */
|
||||
expect_tag_skip_range(pattrinfo, 21, 26);
|
||||
expect_tag_empty(pattrinfo, 26); /* TAG_VER_LANGUAGE */
|
||||
expect_tag_skip(pattrinfo, 27); /* TAG_EXE_WRAPPER */
|
||||
}
|
||||
if (ret)
|
||||
pSdbFreeFileAttributes(pattrinfo);
|
||||
|
||||
test_crc(1, 0);
|
||||
test_crc(2, 0);
|
||||
test_crc(3, 0);
|
||||
test_crc(4, 0x2020202);
|
||||
test_crc(5, 0x2020202);
|
||||
test_crc(6, 0x2020202);
|
||||
test_crc(7, 0x2020202);
|
||||
test_crc(8, 0x81818181);
|
||||
test_crc(9, 0x81818181);
|
||||
test_crc(10, 0x81818181);
|
||||
test_crc(11, 0x81818181);
|
||||
test_crc(12, 0xc2c2c2c2);
|
||||
test_crc(16, 0x62626262);
|
||||
|
||||
/* This seems to be the cutoff point */
|
||||
test_crc2(0xffc, 4, 0xfbfbfcfc);
|
||||
test_crc2(0xffc, 8, 0x7070717);
|
||||
test_crc2(0xffc, 0xcc, 0xc8eba002);
|
||||
test_crc2(0xffc, 0, 0x4622028d);
|
||||
|
||||
test_crc2(0x1000, 4, 0x80);
|
||||
test_crc2(0x1000, 8, 0x8787878f);
|
||||
test_crc2(0x1000, 0xcc, 0x4adc3667);
|
||||
test_crc2(0x1000, 0, 0xa3108044);
|
||||
|
||||
/* Here is another cutoff point */
|
||||
test_crc2(0x11fc, 4, 0x80);
|
||||
test_crc2(0x11fc, 8, 0x8787878f);
|
||||
test_crc2(0x11fc, 0xcc, 0x4adc3667);
|
||||
test_crc2(0x11fc, 0, 0xf03e0800);
|
||||
|
||||
test_crc2(0x1200, 4, 0x80);
|
||||
test_crc2(0x1200, 8, 0x8787878f);
|
||||
test_crc2(0x1200, 0xcc, 0x4adc3667);
|
||||
test_crc2(0x1200, 0, 0xa3108044);
|
||||
|
||||
/* After that, it stays the same for all sizes */
|
||||
test_crc2(0xf000, 4, 0x80);
|
||||
test_crc2(0xf000, 8, 0x8787878f);
|
||||
test_crc2(0xf000, 0xcc, 0x4adc3667);
|
||||
test_crc2(0xf000, 0, 0xa3108044);
|
||||
|
||||
|
||||
DeleteFileA("testxx.exe");
|
||||
}
|
||||
|
||||
START_TEST(apphelp)
|
||||
{
|
||||
RTL_OSVERSIONINFOEXW rtlinfo;
|
||||
|
@ -383,6 +820,10 @@ START_TEST(apphelp)
|
|||
//SetEnvironmentVariable("DEBUGCHANNEL", "+apphelp");
|
||||
hdll = LoadLibraryA("apphelp.dll");
|
||||
pSdbTagToString = (void *) GetProcAddress(hdll, "SdbTagToString");
|
||||
pSdbGetFileAttributes = (void *) GetProcAddress(hdll, "SdbGetFileAttributes");
|
||||
pSdbFreeFileAttributes = (void *) GetProcAddress(hdll, "SdbFreeFileAttributes");
|
||||
|
||||
test_ApplicationAttributes();
|
||||
test_SdbTagToString();
|
||||
#ifdef __REACTOS__
|
||||
if (g_Version < VERSION_WIN7)
|
||||
|
|
573
rostests/apitests/apphelp/data.c
Normal file
573
rostests/apitests/apphelp/data.c
Normal file
|
@ -0,0 +1,573 @@
|
|||
/*
|
||||
* Copyright 2015 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 <exdisp.h>
|
||||
#include <winbase.h>
|
||||
#include "wine/test.h"
|
||||
|
||||
|
||||
static IMAGE_DOS_HEADER dos_header =
|
||||
{
|
||||
IMAGE_DOS_SIGNATURE, /* e_magic */
|
||||
144, /* e_cblp */
|
||||
3, /* e_cp */
|
||||
0, /* e_crlc */
|
||||
4, /* e_cparhdr */
|
||||
0, /* e_minalloc */
|
||||
65535, /* e_maxalloc */
|
||||
0, /* e_ss */
|
||||
184, /* e_sp */
|
||||
0, /* e_csum */
|
||||
0, /* e_ip */
|
||||
0, /* e_cs */
|
||||
64, /* e_lfarlc */
|
||||
0, /* e_ovno */
|
||||
{ 0 }, /* e_res[4] */
|
||||
0, /* e_oemid */
|
||||
0, /* e_oeminfo */
|
||||
{ 0 }, /* e_res2[10] */
|
||||
0x80 /* e_lfanew */
|
||||
};
|
||||
|
||||
static IMAGE_NT_HEADERS32 nt_header =
|
||||
{
|
||||
IMAGE_NT_SIGNATURE, /* Signature */
|
||||
{
|
||||
IMAGE_FILE_MACHINE_I386, /* Machine */
|
||||
2, /* NumberOfSections */
|
||||
0x12345, /* TimeDateStamp */
|
||||
0, /* PointerToSymbolTable */
|
||||
0, /* NumberOfSymbols */
|
||||
sizeof(IMAGE_OPTIONAL_HEADER), /* SizeOfOptionalHeader */
|
||||
IMAGE_FILE_RELOCS_STRIPPED | IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_LINE_NUMS_STRIPPED | IMAGE_FILE_32BIT_MACHINE /* Characteristics */
|
||||
},
|
||||
{
|
||||
IMAGE_NT_OPTIONAL_HDR_MAGIC, /* Magic */
|
||||
6, /* MajorLinkerVersion */
|
||||
3, /* MinorLinkerVersion */
|
||||
0, /* SizeOfCode */
|
||||
0, /* SizeOfInitializedData */
|
||||
0, /* SizeOfUninitializedData */
|
||||
0x1000, /* AddressOfEntryPoint */
|
||||
0x1000, /* BaseOfCode */
|
||||
#ifndef _WIN64
|
||||
0, /* BaseOfData */
|
||||
#endif
|
||||
0x400000, /* ImageBase */
|
||||
0x1000, /* SectionAlignment */
|
||||
0x200, /* FileAlignment */
|
||||
4, /* MajorOperatingSystemVersion */
|
||||
1, /* MinorOperatingSystemVersion */
|
||||
4, /* MajorImageVersion */
|
||||
2, /* MinorImageVersion */
|
||||
4, /* MajorSubsystemVersion */
|
||||
3, /* MinorSubsystemVersion */
|
||||
0, /* Win32VersionValue */
|
||||
0x3000, /* SizeOfImage */
|
||||
0x200, /* SizeOfHeaders */
|
||||
0xBAAD, /* CheckSum: This checksum is not the correct checksum, intentionally! */
|
||||
IMAGE_SUBSYSTEM_WINDOWS_CUI, /* Subsystem */
|
||||
0, /* DllCharacteristics */
|
||||
0x100000, /* SizeOfStackReserve */
|
||||
0x1000, /* SizeOfStackCommit */
|
||||
0x100000, /* SizeOfHeapReserve */
|
||||
0x1000, /* SizeOfHeapCommit */
|
||||
0, /* LoaderFlags */
|
||||
0x10, /* NumberOfRvaAndSizes */
|
||||
{
|
||||
/* IMAGE_DIRECTORY_ENTRY_EXPORT */
|
||||
{
|
||||
0x2370, /* VirtualAddress */
|
||||
76, /* Size */
|
||||
},
|
||||
{ 0 },
|
||||
/* IMAGE_DIRECTORY_ENTRY_RESOURCE */
|
||||
{
|
||||
0x2000, /* VirtualAddress */
|
||||
868, /* Size */
|
||||
},
|
||||
} /* DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES] */
|
||||
}
|
||||
};
|
||||
|
||||
static IMAGE_SECTION_HEADER section_headers[] =
|
||||
{
|
||||
{
|
||||
{ '.','t','e','x','t',0 }, /* Name */
|
||||
{ 24 }, /* VirtualSize */
|
||||
0x1000, /* VirtualAddress */
|
||||
0x200, /* SizeOfRawData */
|
||||
0x200, /* PointerToRawData */
|
||||
0, /* PointerToRelocations */
|
||||
0, /* PointerToLinenumbers */
|
||||
0, /* NumberOfRelocations */
|
||||
0, /* NumberOfLinenumbers */
|
||||
IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ /* Characteristics */
|
||||
},
|
||||
{
|
||||
{ '.','r','s','r','c',0 }, /* Name */
|
||||
{ 880 }, /* VirtualSize */
|
||||
0x2000, /* VirtualAddress */
|
||||
0x400, /* SizeOfRawData */
|
||||
0x400, /* PointerToRawData */
|
||||
0, /* PointerToRelocations */
|
||||
0, /* PointerToLinenumbers */
|
||||
0, /* NumberOfRelocations */
|
||||
0, /* NumberOfLinenumbers */
|
||||
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ /* Characteristics */
|
||||
}
|
||||
};
|
||||
|
||||
static const unsigned char text_section[] =
|
||||
{
|
||||
0x33, 0xc0, /* xor eax, eax */
|
||||
0xc3 /* ret */
|
||||
};
|
||||
|
||||
|
||||
/* taken from fusionpriv.h */
|
||||
typedef struct
|
||||
{
|
||||
WORD wLength;
|
||||
WORD wValueLength;
|
||||
WORD wType;
|
||||
WCHAR szKey[17];
|
||||
VS_FIXEDFILEINFO Value;
|
||||
} VS_VERSIONINFO;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
WORD wLength;
|
||||
WORD wValueLength;
|
||||
WORD wType;
|
||||
WCHAR szKey[15];
|
||||
} STRINGFILEINFO;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
WORD wLength;
|
||||
WORD wValueLength;
|
||||
WORD wType;
|
||||
WCHAR szKey[9];
|
||||
} STRINGTABLE;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
WORD wLength;
|
||||
WORD wValueLength;
|
||||
WORD wType;
|
||||
} STRINGHDR;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
WORD wLength;
|
||||
WORD wValueLength;
|
||||
WORD wType;
|
||||
WCHAR szKey[13];
|
||||
} VARFILEINFO;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
WORD wLength;
|
||||
WORD wValueLength;
|
||||
WORD wType;
|
||||
WCHAR szKey[13];
|
||||
DWORD Value;
|
||||
} VAR;
|
||||
|
||||
typedef struct rsrc_section_t
|
||||
{
|
||||
IMAGE_RESOURCE_DIRECTORY header;
|
||||
IMAGE_RESOURCE_DIRECTORY_ENTRY file_info_id;
|
||||
IMAGE_RESOURCE_DIRECTORY file_info_header;
|
||||
IMAGE_RESOURCE_DIRECTORY_ENTRY version_info_id;
|
||||
IMAGE_RESOURCE_DIRECTORY version_info_header;
|
||||
IMAGE_RESOURCE_DIRECTORY_ENTRY version_lang_id;
|
||||
IMAGE_RESOURCE_DATA_ENTRY version_data_entry;
|
||||
|
||||
VS_VERSIONINFO version_info;
|
||||
STRINGFILEINFO string_file_info;
|
||||
STRINGTABLE string_table;
|
||||
|
||||
STRINGHDR FileVersion_hdr;
|
||||
WCHAR FileVersion_key[13];
|
||||
WCHAR FileVersion_val[8];
|
||||
|
||||
STRINGHDR ProductVersion_hdr;
|
||||
WCHAR ProductVersion_key[15];
|
||||
WCHAR ProductVersion_val[8];
|
||||
|
||||
STRINGHDR CompanyName_hdr;
|
||||
WCHAR CompanyName_key[13];
|
||||
WCHAR CompanyName_val[12];
|
||||
|
||||
STRINGHDR FileDescription_hdr;
|
||||
WCHAR FileDescription_key[17];
|
||||
WCHAR FileDescription_val[16];
|
||||
|
||||
STRINGHDR InternalName_hdr;
|
||||
WCHAR InternalName_key[13];
|
||||
WCHAR InternalName_val[14];
|
||||
|
||||
STRINGHDR LegalCopyright_hdr;
|
||||
WCHAR LegalCopyright_key[15];
|
||||
WCHAR LegalCopyright_val[16];
|
||||
|
||||
STRINGHDR LegalTrademarks_hdr;
|
||||
WCHAR LegalTrademarks_key[17];
|
||||
WCHAR LegalTrademarks_val[16];
|
||||
|
||||
STRINGHDR OriginalFilename_hdr;
|
||||
WCHAR OriginalFilename_key[17];
|
||||
WCHAR OriginalFilename_val[18];
|
||||
|
||||
STRINGHDR Productname_hdr;
|
||||
WCHAR Productname_key[13];
|
||||
WCHAR Productname_val[12];
|
||||
|
||||
VARFILEINFO file_info;
|
||||
VAR translation;
|
||||
} rsrc_section_t;
|
||||
|
||||
static const rsrc_section_t rsrc_section =
|
||||
{
|
||||
/* header */
|
||||
{
|
||||
0, /* Characteristics */
|
||||
0x55FE8E21, /* TimeDateStamp, 20/09/2015 10:44:49 */
|
||||
0, /* MajorVersion */
|
||||
0, /* MinorVersion */
|
||||
0, /* NumberOfNamedEntries */
|
||||
1, /* NumberOfIdEntries */
|
||||
},
|
||||
/* file_info_id */
|
||||
{
|
||||
{{
|
||||
(DWORD)VS_FILE_INFO, /* NameOffset:31 */
|
||||
0 /* NameIsString:1 */
|
||||
}},
|
||||
{
|
||||
0x80000018 /* OffsetToData */
|
||||
}
|
||||
},
|
||||
/* file_info_header */
|
||||
{
|
||||
0, /* Characteristics */
|
||||
0x55FE8E21, /* TimeDateStamp, 20/09/2015 10:44:49 */
|
||||
0, /* MajorVersion */
|
||||
0, /* MinorVersion */
|
||||
0, /* NumberOfNamedEntries */
|
||||
1, /* NumberOfIdEntries */
|
||||
},
|
||||
/* version_info_id */
|
||||
{
|
||||
{{
|
||||
VS_VERSION_INFO, /* NameOffset:31 */
|
||||
0 /* NameIsString:1 */
|
||||
}},
|
||||
{
|
||||
0x80000030 /* OffsetToData */
|
||||
},
|
||||
},
|
||||
/* version_info_header */
|
||||
{
|
||||
0, /* Characteristics */
|
||||
0x55FE8E21, /* TimeDateStamp, 20/09/2015 10:44:49 */
|
||||
0, /* MajorVersion */
|
||||
0, /* MinorVersion */
|
||||
0, /* NumberOfNamedEntries */
|
||||
1, /* NumberOfIdEntries */
|
||||
},
|
||||
/* version_lang_id */
|
||||
{
|
||||
{{
|
||||
1033, /* NameOffset:31 */
|
||||
0 /* NameIsString:1 */
|
||||
}},
|
||||
{
|
||||
0x48 /* OffsetToDirectory */
|
||||
}
|
||||
},
|
||||
/* version_data_entry */
|
||||
{
|
||||
0x2058, /* OffsetToData */
|
||||
0x30C, /* Size */
|
||||
0, /* CodePage */
|
||||
0, /* Reserved */
|
||||
},
|
||||
|
||||
/* version_info */
|
||||
{
|
||||
0x30C, /* wLength */
|
||||
0x34, /* wValueLength */
|
||||
0, /* wType: Binary */
|
||||
{ 'V','S','_','V','E','R','S','I','O','N','_','I','N','F','O','\0','\0' }, /* szKey[17] */
|
||||
/* Value */
|
||||
{
|
||||
0xFEEF04BD, /* dwSignature */
|
||||
0x10000, /* dwStrucVersion */
|
||||
0x10000, /* dwFileVersionMS */
|
||||
0, /* dwFileVersionLS */
|
||||
0x10000, /* dwProductVersionMS */
|
||||
1, /* dwProductVersionLS */
|
||||
0, /* dwFileFlagsMask */
|
||||
0, /* dwFileFlags */
|
||||
VOS__WINDOWS32, /* dwFileOS */
|
||||
VFT_APP, /* dwFileType */
|
||||
0, /* dwFileSubtype */
|
||||
0x01d1a019, /* dwFileDateMS */
|
||||
0xac754c50 /* dwFileDateLS */
|
||||
},
|
||||
},
|
||||
|
||||
/* string_file_info */
|
||||
{
|
||||
0x26C, /* wLength */
|
||||
0, /* wValueLength */
|
||||
1, /* wType: Text */
|
||||
{ 'S','t','r','i','n','g','F','i','l','e','I','n','f','o','\0' } /* szKey[15] */
|
||||
},
|
||||
/* string_table */
|
||||
{
|
||||
0x248, /* wLength */
|
||||
0, /* wValueLength */
|
||||
1, /* wType: Text */
|
||||
{ 'F','F','F','F','0','0','0','0','\0' } /* szKey[9] */
|
||||
},
|
||||
|
||||
/* FileVersion */
|
||||
{
|
||||
48, /* wLength */
|
||||
8, /* wValueLength */
|
||||
1, /* wType: Text */
|
||||
},
|
||||
{ 'F','i','l','e','V','e','r','s','i','o','n','\0' },
|
||||
{ '1','.','0','.','0','.','0','\0' },
|
||||
|
||||
/* ProductVersion */
|
||||
{
|
||||
52, /* wLength */
|
||||
8, /* wValueLength */
|
||||
1, /* wType: Text */
|
||||
},
|
||||
{ 'P','r','o','d','u','c','t','V','e','r','s','i','o','n','\0' },
|
||||
{ '1','.','0','.','0','.','1','\0' },
|
||||
|
||||
/* CompanyName */
|
||||
{
|
||||
56, /* wLength */
|
||||
12, /* wValueLength */
|
||||
1, /* wType: Text */
|
||||
},
|
||||
{ 'C','o','m','p','a','n','y','N','a','m','e','\0' },
|
||||
{ 'C','o','m','p','a','n','y','N','a','m','e','\0' },
|
||||
|
||||
/* FileDescription */
|
||||
{
|
||||
72, /* wLength */
|
||||
16, /* wValueLength */
|
||||
1, /* wType: Text */
|
||||
},
|
||||
{ 'F','i','l','e','D','e','s','c','r','i','p','t','i','o','n','\0' },
|
||||
{ 'F','i','l','e','D','e','s','c','r','i','p','t','i','o','n','\0' },
|
||||
|
||||
/* InternalName */
|
||||
{
|
||||
58, /* wLength */
|
||||
13, /* wValueLength */
|
||||
1, /* wType: Text */
|
||||
},
|
||||
{ 'I','n','t','e','r','n','a','l','N','a','m','e','\0' },
|
||||
{ 'I','n','t','e','r','n','a','l','N','a','m','e','\0' },
|
||||
|
||||
/* LegalCopyright */
|
||||
{
|
||||
66, /* wLength */
|
||||
15, /* wValueLength */
|
||||
1, /* wType: Text */
|
||||
},
|
||||
{ 'L','e','g','a','l','C','o','p','y','r','i','g','h','t','\0' },
|
||||
{ 'L','e','g','a','l','C','o','p','y','r','i','g','h','t','\0' },
|
||||
|
||||
/* LegalTrademarks */
|
||||
{
|
||||
72, /* wLength */
|
||||
16, /* wValueLength */
|
||||
1, /* wType: Text */
|
||||
},
|
||||
{ 'L','e','g','a','l','T','r','a','d','e','m','a','r','k','s','\0' },
|
||||
{ 'L','e','g','a','l','T','r','a','d','e','m','a','r','k','s','\0' },
|
||||
|
||||
/* OriginalFilename */
|
||||
{
|
||||
74, /* wLength */
|
||||
17, /* wValueLength */
|
||||
1, /* wType: Text */
|
||||
},
|
||||
{ 'O','r','i','g','i','n','a','l','F','i','l','e','n','a','m','e','\0' },
|
||||
{ 'O','r','i','g','i','n','a','l','F','i','l','e','n','a','m','e','\0' },
|
||||
|
||||
/* ProductName */
|
||||
{
|
||||
56, /* wLength */
|
||||
12, /* wValueLength */
|
||||
1, /* wType: Text */
|
||||
},
|
||||
{ 'P','r','o','d','u','c','t','N','a','m','e','\0' },
|
||||
{ 'P','r','o','d','u','c','t','N','a','m','e','\0' },
|
||||
|
||||
|
||||
/* file_info */
|
||||
{
|
||||
0x44, /* wLength */
|
||||
0, /* wValueLength */
|
||||
1, /* wType: Text */
|
||||
{ 'V','a','r','F','i','l','e','I','n','f','o','\0' } /* szKey[13] */
|
||||
},
|
||||
|
||||
/* translation */
|
||||
{
|
||||
0x24, /* wLength */
|
||||
4, /* wValueLength */
|
||||
0, /* wType: Binary */
|
||||
{ 'T','r','a','n','s','l','a','t','i','o','n','\0' }, /* szKey[13] */
|
||||
0xffff /* Value */
|
||||
}
|
||||
};
|
||||
|
||||
typedef struct export_section_t
|
||||
{
|
||||
IMAGE_EXPORT_DIRECTORY desc;
|
||||
char binary_name[10];
|
||||
} export_section_t;
|
||||
|
||||
/* This export section is not complete, but the Name RVA is only taken into account */
|
||||
static export_section_t export_dir =
|
||||
{
|
||||
{
|
||||
0, /* Characteristics */
|
||||
0, /* TimeDateStamp */
|
||||
0, /* MajorVersion */
|
||||
0, /* MinorVersion */
|
||||
0x2398, /* Name (RVA) */
|
||||
1, /* Base */
|
||||
0, /* NumberOfFunctions */
|
||||
0, /* NumberOfNames */
|
||||
0, /* AddressOfFunctions (RVA) */
|
||||
0, /* AddressOfNames (RVA) */
|
||||
0, /* AddressOfNameOrdinals (RVA) */
|
||||
},
|
||||
{ 'T','e','S','t','2','.','e','x','e',0 }, /* binary_name */
|
||||
};
|
||||
|
||||
|
||||
void test_create_exe_imp(const char* name, int skip_rsrc_exports)
|
||||
{
|
||||
HANDLE file;
|
||||
char *buf, *cur;
|
||||
DWORD size = 0x800;
|
||||
buf = malloc(size);
|
||||
|
||||
file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
winetest_ok(file != INVALID_HANDLE_VALUE, "can't create file\n");
|
||||
if(file == INVALID_HANDLE_VALUE)
|
||||
return;
|
||||
|
||||
memset(buf, 0, size);
|
||||
cur = buf;
|
||||
cur = memcpy(buf, &dos_header, sizeof(dos_header));
|
||||
cur += dos_header.e_lfanew;
|
||||
|
||||
memcpy(cur, &nt_header, sizeof(nt_header));
|
||||
if (skip_rsrc_exports)
|
||||
{
|
||||
((IMAGE_NT_HEADERS32*)cur)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress = 0;
|
||||
((IMAGE_NT_HEADERS32*)cur)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = 0;
|
||||
}
|
||||
cur += sizeof(nt_header);
|
||||
memcpy(cur, section_headers, sizeof(section_headers));
|
||||
|
||||
/* write code section: */
|
||||
cur = buf + section_headers[0].PointerToRawData;
|
||||
memcpy(cur, text_section, sizeof(text_section));
|
||||
|
||||
if (!skip_rsrc_exports)
|
||||
{
|
||||
/* write resource section: */
|
||||
cur = buf + section_headers[1].PointerToRawData;
|
||||
memcpy(cur, &rsrc_section, sizeof(rsrc_section));
|
||||
|
||||
/* write minimal export directory: */
|
||||
cur += 0x370;
|
||||
memcpy(cur, &export_dir, sizeof(export_dir));
|
||||
}
|
||||
|
||||
WriteFile(file, buf, size, &size, NULL);
|
||||
free(buf);
|
||||
CloseHandle(file);
|
||||
}
|
||||
|
||||
|
||||
/* Almost everything in this filetype is ignored, only e_lfanew, ne_restab and ne_nrestab are relevant */
|
||||
void test_create_ne_imp(const char* name, int skip_names)
|
||||
{
|
||||
HANDLE file;
|
||||
DWORD size;
|
||||
IMAGE_DOS_HEADER MZ_hdr = { IMAGE_DOS_SIGNATURE, 0 };
|
||||
IMAGE_OS2_HEADER NE_hdr = { IMAGE_OS2_SIGNATURE, 0 };
|
||||
static const BYTE NE_names[] =
|
||||
{
|
||||
/* Show that the length is used, not the nullterm*/
|
||||
11,'T','E','S','T','M','O','D','.','h','X','x','x',0,0,0,
|
||||
20,'M','O','D',' ','D','E','S','C','R','I','P','T','I','O','N',' ','H','E','R','E',0,0,0
|
||||
};
|
||||
|
||||
file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
winetest_ok(file != INVALID_HANDLE_VALUE, "can't create file\n");
|
||||
if(file == INVALID_HANDLE_VALUE)
|
||||
return;
|
||||
|
||||
MZ_hdr.e_lfanew = sizeof(MZ_hdr);
|
||||
if (!skip_names)
|
||||
{
|
||||
NE_hdr.ne_restab = sizeof(NE_hdr); /* First entry (pascal string + ordinal) = module name */
|
||||
NE_hdr.ne_nrestab = sizeof(MZ_hdr) + sizeof(NE_hdr) + 16; /* First entry (pascal string + ordinal) = module description */
|
||||
}
|
||||
|
||||
WriteFile(file, &MZ_hdr, sizeof(MZ_hdr), &size, NULL);
|
||||
WriteFile(file, &NE_hdr, sizeof(NE_hdr), &size, NULL);
|
||||
WriteFile(file, NE_names, sizeof(NE_names), &size, NULL);
|
||||
|
||||
CloseHandle(file);
|
||||
}
|
||||
|
||||
void test_create_file_imp(const char* name, const char* contents, size_t len)
|
||||
{
|
||||
HANDLE file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
winetest_ok(file != INVALID_HANDLE_VALUE, "can't create file\n");
|
||||
if (file != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (contents && len)
|
||||
{
|
||||
DWORD size;
|
||||
WriteFile(file, contents, len, &size, NULL);
|
||||
}
|
||||
CloseHandle(file);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in a new issue