Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195/* * PROJECT: ReactOS Setup Library * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) * PURPOSE: NT Version Resource Management API * COPYRIGHT: Copyright 2017-2018 Hermes Belusca-Maito * * NOTE 1: Adapted from Wine-synced dll/win32/version DLL. * NOTE 2: We only deal with 32-bit PE executables. */
/* INCLUDES *****************************************************************/
#include "precomp.h"#include <ndk/ldrtypes.h>#include <ndk/ldrfuncs.h>
#include "ntverrsrc.h"
#define NDEBUG#include <debug.h>
/* FUNCTIONS ****************************************************************/
#define MAKEINTRESOURCE(i) ((ULONG_PTR)(USHORT)(i))#define RT_VERSION MAKEINTRESOURCE(16) // See psdk/winuser.h#define VS_VERSION_INFO 1 // See psdk/verrsrc.h#define VS_FILE_INFO RT_VERSION
NTSTATUSNtGetVersionResource( IN PVOID BaseAddress, OUT PVOID* Resource, OUT PULONG ResourceSize OPTIONAL){ NTSTATUS Status; LDR_RESOURCE_INFO ResourceInfo; PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry; PVOID Data = NULL; ULONG Size = 0;
/* Try to find the resource (language-neutral) */ ResourceInfo.Type = RT_VERSION; ResourceInfo.Name = VS_VERSION_INFO; ResourceInfo.Language = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
Status = LdrFindResource_U(BaseAddress, &ResourceInfo, RESOURCE_DATA_LEVEL, &ResourceDataEntry); if (!NT_SUCCESS(Status)) { DPRINT1("NtGetVersionResource: Version resource not found, Status 0x%08lx\n", Status); return Status; }
/* Access the resource */ Status = LdrAccessResource(BaseAddress, ResourceDataEntry, &Data, &Size); if (!NT_SUCCESS(Status)) { DPRINT1("NtGetVersionResource: Cannot access Version resource, Status 0x%08lx\n", Status); return Status; }
*Resource = Data; if (ResourceSize) *ResourceSize = Size;
return STATUS_SUCCESS;}
/* NOTE: the xxx_STRUCT16 version differs by storing strings in ANSI, not in UNICODE */typedef struct _VS_VERSION_INFO_STRUCT32{ WORD wLength; WORD wValueLength; WORD wType; /* 1:Text, 0:Binary */ WCHAR szKey[1];#if 0 /* variable length structure */ /* DWORD aligned */ BYTE Value[]; /* DWORD aligned */ VS_VERSION_INFO_STRUCT32 Children[];#endif} VS_VERSION_INFO_STRUCT32, *PVS_VERSION_INFO_STRUCT32;typedef const VS_VERSION_INFO_STRUCT32 *PCVS_VERSION_INFO_STRUCT32;
#define DWORD_ALIGN( base, ptr ) \ ( (ULONG_PTR)(base) + ((((ULONG_PTR)(ptr) - (ULONG_PTR)(base)) + 3) & ~3) )
#define VersionInfo32_Value( ver ) \ DWORD_ALIGN( (ver), (ver)->szKey + wcslen((ver)->szKey) + 1 )
#define VersionInfo32_Children( ver ) \ (PCVS_VERSION_INFO_STRUCT32)( VersionInfo32_Value( ver ) + \ ( ( (ver)->wValueLength * \ ((ver)->wType? 2 : 1) + 3 ) & ~3 ) )
#define VersionInfo32_Next( ver ) \ (PVS_VERSION_INFO_STRUCT32)( (ULONG_PTR)ver + (((ver)->wLength + 3) & ~3) )
static PCVS_VERSION_INFO_STRUCT32VersionInfo32_FindChild( IN PCVS_VERSION_INFO_STRUCT32 info, IN PCWSTR szKey, IN UINT cchKey){ PCVS_VERSION_INFO_STRUCT32 child = VersionInfo32_Children(info);
while ((ULONG_PTR)child < (ULONG_PTR)info + info->wLength) { if (!_wcsnicmp(child->szKey, szKey, cchKey) && !child->szKey[cchKey]) return child;
if (child->wLength == 0) return NULL; child = VersionInfo32_Next(child); }
return NULL;}
static NTSTATUSVersionInfo32_QueryValue( IN PCVS_VERSION_INFO_STRUCT32 info, IN PCWSTR lpSubBlock, OUT PVOID* lplpBuffer, OUT PUINT puLen OPTIONAL, OUT BOOL* pbText OPTIONAL){ PCWSTR lpNextSlash;
DPRINT("lpSubBlock : (%S)\n", lpSubBlock);
while (*lpSubBlock) { /* Find next path component */ for (lpNextSlash = lpSubBlock; *lpNextSlash; lpNextSlash++) { if (*lpNextSlash == '\\') break; }
/* Skip empty components */ if (lpNextSlash == lpSubBlock) { lpSubBlock++; continue; }
/* We have a non-empty component: search info for key */ info = VersionInfo32_FindChild(info, lpSubBlock, lpNextSlash - lpSubBlock); if (!info) { if (puLen) *puLen = 0; return STATUS_RESOURCE_TYPE_NOT_FOUND; }
/* Skip path component */ lpSubBlock = lpNextSlash; }
/* Return value */ *lplpBuffer = (PVOID)VersionInfo32_Value(info); if (puLen) *puLen = info->wValueLength; if (pbText) *pbText = info->wType;
return STATUS_SUCCESS;}
NTSTATUSNtVerQueryValue( IN const VOID* pBlock, IN PCWSTR lpSubBlock, OUT PVOID* lplpBuffer, OUT PUINT puLen){ PCVS_VERSION_INFO_STRUCT32 info = pBlock;
DPRINT("%s (%p, %S, %p, %p)\n", __FUNCTION__, pBlock, lpSubBlock, lplpBuffer, puLen);
if (!pBlock) return FALSE;
if (!lpSubBlock || !*lpSubBlock) lpSubBlock = L"\\";
return VersionInfo32_QueryValue(info, lpSubBlock, lplpBuffer, puLen, NULL);}
/* EOF */