kernel32: Implement PackageIdFromFullName().
Signed-off-by: Paul Gofman <pgofman@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
773161f84b
commit
b1e2780eac
|
@ -22,6 +22,6 @@
|
|||
@ stub PackageFamilyNameFromFullName
|
||||
@ stub PackageFamilyNameFromId
|
||||
@ stub PackageFullNameFromId
|
||||
@ stub PackageIdFromFullName
|
||||
@ stdcall PackageIdFromFullName(wstr long ptr ptr) kernel32.PackageIdFromFullName
|
||||
@ stub PackageNameAndPublisherIdFromFamilyName
|
||||
@ stub ParseApplicationUserModelId
|
||||
|
|
|
@ -18,4 +18,4 @@
|
|||
@ stub PackageFamilyNameFromFullName
|
||||
@ stub PackageFamilyNameFromId
|
||||
@ stub PackageFullNameFromId
|
||||
@ stub PackageIdFromFullName
|
||||
@ stdcall PackageIdFromFullName(wstr long ptr ptr) kernel32.PackageIdFromFullName
|
||||
|
|
|
@ -1152,6 +1152,7 @@
|
|||
@ stdcall -import PeekConsoleInputW(ptr ptr long ptr)
|
||||
@ stdcall -import PeekNamedPipe(long ptr long ptr ptr ptr)
|
||||
@ stdcall -import PostQueuedCompletionStatus(long long ptr ptr)
|
||||
@ stdcall -import PackageIdFromFullName(wstr long ptr ptr)
|
||||
@ stdcall PowerClearRequest(long long)
|
||||
@ stdcall PowerCreateRequest(ptr)
|
||||
@ stdcall PowerSetRequest(long long)
|
||||
|
|
|
@ -21,9 +21,11 @@
|
|||
#include "wine/test.h"
|
||||
#include "winbase.h"
|
||||
#include "winternl.h"
|
||||
#include "appmodel.h"
|
||||
|
||||
static BOOL (WINAPI * pGetProductInfo)(DWORD, DWORD, DWORD, DWORD, DWORD *);
|
||||
static UINT (WINAPI * pGetSystemFirmwareTable)(DWORD, DWORD, void *, DWORD);
|
||||
static LONG (WINAPI * pPackageIdFromFullName)(const WCHAR *, UINT32, UINT32 *, BYTE *);
|
||||
static NTSTATUS (WINAPI * pNtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS, void *, ULONG, ULONG *);
|
||||
static NTSTATUS (WINAPI * pRtlGetVersion)(RTL_OSVERSIONINFOEXW *);
|
||||
|
||||
|
@ -43,6 +45,7 @@ static void init_function_pointers(void)
|
|||
|
||||
GET_PROC(GetProductInfo);
|
||||
GET_PROC(GetSystemFirmwareTable);
|
||||
GET_PROC(PackageIdFromFullName);
|
||||
|
||||
hmod = GetModuleHandleA("ntdll.dll");
|
||||
|
||||
|
@ -746,6 +749,175 @@ static void test_GetSystemFirmwareTable(void)
|
|||
HeapFree(GetProcessHeap(), 0, smbios_table);
|
||||
}
|
||||
|
||||
static const struct
|
||||
{
|
||||
UINT32 code;
|
||||
const WCHAR *name;
|
||||
BOOL broken;
|
||||
}
|
||||
arch_data[] =
|
||||
{
|
||||
{PROCESSOR_ARCHITECTURE_INTEL, L"X86"},
|
||||
{PROCESSOR_ARCHITECTURE_ARM, L"Arm"},
|
||||
{PROCESSOR_ARCHITECTURE_AMD64, L"X64"},
|
||||
{PROCESSOR_ARCHITECTURE_NEUTRAL, L"Neutral"},
|
||||
{PROCESSOR_ARCHITECTURE_ARM64, L"Arm64", TRUE /* Before Win10. */},
|
||||
{PROCESSOR_ARCHITECTURE_UNKNOWN, L"Unknown", TRUE /* Before Win10 1709. */},
|
||||
};
|
||||
|
||||
static const WCHAR *arch_string_from_code(UINT32 arch)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(arch_data); ++i)
|
||||
if (arch_data[i].code == arch)
|
||||
return arch_data[i].name;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static unsigned int get_package_str_size(const WCHAR *str)
|
||||
{
|
||||
return str ? (lstrlenW(str) + 1) * sizeof(*str) : 0;
|
||||
}
|
||||
|
||||
static unsigned int get_package_id_size(const PACKAGE_ID *id)
|
||||
{
|
||||
return sizeof(*id) + get_package_str_size(id->name)
|
||||
+ get_package_str_size(id->resourceId) + 14 * sizeof(WCHAR);
|
||||
}
|
||||
|
||||
static void packagefullname_from_packageid(WCHAR *buffer, size_t count, const PACKAGE_ID *id)
|
||||
{
|
||||
swprintf(buffer, count, L"%s_%u.%u.%u.%u_%s_%s_%s", id->name, id->version.Major,
|
||||
id->version.Minor, id->version.Build, id->version.Revision,
|
||||
arch_string_from_code(id->processorArchitecture), id->resourceId,
|
||||
id->publisherId);
|
||||
}
|
||||
|
||||
static void test_PackageIdFromFullName(void)
|
||||
{
|
||||
static const PACKAGE_ID test_package_id =
|
||||
{
|
||||
0, PROCESSOR_ARCHITECTURE_INTEL,
|
||||
{{.Major = 1, .Minor = 2, .Build = 3, .Revision = 4}},
|
||||
(WCHAR *)L"TestPackage", NULL,
|
||||
(WCHAR *)L"TestResourceId", (WCHAR *)L"0abcdefghjkme"
|
||||
};
|
||||
UINT32 size, expected_size;
|
||||
PACKAGE_ID test_id;
|
||||
WCHAR fullname[512];
|
||||
BYTE id_buffer[512];
|
||||
unsigned int i;
|
||||
PACKAGE_ID *id;
|
||||
LONG ret;
|
||||
|
||||
if (!pPackageIdFromFullName)
|
||||
{
|
||||
win_skip("PackageIdFromFullName not available.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
packagefullname_from_packageid(fullname, ARRAY_SIZE(fullname), &test_package_id);
|
||||
|
||||
id = (PACKAGE_ID *)id_buffer;
|
||||
|
||||
memset(id_buffer, 0xcc, sizeof(id_buffer));
|
||||
expected_size = get_package_id_size(&test_package_id);
|
||||
size = sizeof(id_buffer);
|
||||
ret = pPackageIdFromFullName(fullname, 0, &size, id_buffer);
|
||||
ok(ret == ERROR_SUCCESS, "Got unexpected ret %u.\n", ret);
|
||||
ok(size == expected_size, "Got unexpected length %u, expected %u.\n", size, expected_size);
|
||||
ok(!lstrcmpW(id->name, test_package_id.name), "Got unexpected name %s.\n", debugstr_w(id->name));
|
||||
ok(!lstrcmpW(id->resourceId, test_package_id.resourceId), "Got unexpected resourceId %s.\n",
|
||||
debugstr_w(id->resourceId));
|
||||
ok(!lstrcmpW(id->publisherId, test_package_id.publisherId), "Got unexpected publisherId %s.\n",
|
||||
debugstr_w(id->publisherId));
|
||||
ok(!id->publisher, "Got unexpected publisher %s.\n", debugstr_w(id->publisher));
|
||||
ok(id->processorArchitecture == PROCESSOR_ARCHITECTURE_INTEL, "Got unexpected processorArchitecture %u.\n",
|
||||
id->processorArchitecture);
|
||||
ok(id->version.Version == 0x0001000200030004, "Got unexpected Version %s.\n",
|
||||
wine_dbgstr_longlong(id->version.Version));
|
||||
ok((BYTE *)id->name == id_buffer + sizeof(*id), "Got unexpected name %p, buffer %p.\n", id->name, id_buffer);
|
||||
ok((BYTE *)id->resourceId == (BYTE *)id->name + (lstrlenW(id->name) + 1) * 2,
|
||||
"Got unexpected resourceId %p, buffer %p.\n", id->resourceId, id_buffer);
|
||||
ok((BYTE *)id->publisherId == (BYTE *)id->resourceId + (lstrlenW(id->resourceId) + 1) * 2,
|
||||
"Got unexpected publisherId %p, buffer %p.\n", id->resourceId, id_buffer);
|
||||
|
||||
ret = pPackageIdFromFullName(fullname, 0, NULL, id_buffer);
|
||||
ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %d.\n", ret);
|
||||
|
||||
size = sizeof(id_buffer);
|
||||
ret = pPackageIdFromFullName(NULL, 0, &size, id_buffer);
|
||||
ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %d.\n", ret);
|
||||
ok(size == sizeof(id_buffer), "Got unexpected size %u.\n", size);
|
||||
|
||||
size = sizeof(id_buffer);
|
||||
ret = pPackageIdFromFullName(fullname, 0, &size, NULL);
|
||||
ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %d.\n", ret);
|
||||
ok(size == sizeof(id_buffer), "Got unexpected size %u.\n", size);
|
||||
|
||||
size = expected_size - 1;
|
||||
ret = pPackageIdFromFullName(fullname, 0, &size, NULL);
|
||||
ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %d.\n", ret);
|
||||
ok(size == expected_size - 1, "Got unexpected size %u.\n", size);
|
||||
|
||||
size = expected_size - 1;
|
||||
ret = pPackageIdFromFullName(fullname, 0, &size, id_buffer);
|
||||
ok(ret == ERROR_INSUFFICIENT_BUFFER, "Got unexpected ret %d.\n", ret);
|
||||
ok(size == expected_size, "Got unexpected size %u.\n", size);
|
||||
|
||||
size = 0;
|
||||
ret = pPackageIdFromFullName(fullname, 0, &size, NULL);
|
||||
ok(ret == ERROR_INSUFFICIENT_BUFFER, "Got unexpected ret %d.\n", ret);
|
||||
ok(size == expected_size, "Got unexpected size %u.\n", size);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(arch_data); ++i)
|
||||
{
|
||||
test_id = test_package_id;
|
||||
test_id.processorArchitecture = arch_data[i].code;
|
||||
packagefullname_from_packageid(fullname, ARRAY_SIZE(fullname), &test_id);
|
||||
size = expected_size;
|
||||
ret = pPackageIdFromFullName(fullname, 0, &size, id_buffer);
|
||||
ok(ret == ERROR_SUCCESS || broken(arch_data[i].broken && ret == ERROR_INVALID_PARAMETER),
|
||||
"Got unexpected ret %u.\n", ret);
|
||||
if (ret != ERROR_SUCCESS)
|
||||
continue;
|
||||
ok(size == expected_size, "Got unexpected length %u, expected %u.\n", size, expected_size);
|
||||
ok(id->processorArchitecture == arch_data[i].code, "Got unexpected processorArchitecture %u, arch %S.\n",
|
||||
id->processorArchitecture, arch_data[i].name);
|
||||
}
|
||||
|
||||
size = sizeof(id_buffer);
|
||||
ret = pPackageIdFromFullName(L"TestPackage_1.2.3.4_X86_TestResourceId_0abcdefghjkme", 0, &size, id_buffer);
|
||||
ok(ret == ERROR_SUCCESS, "Got unexpected ret %u.\n", ret);
|
||||
|
||||
size = sizeof(id_buffer);
|
||||
ret = pPackageIdFromFullName(L"TestPackage_1.2.3.4_X86_TestResourceId_abcdefghjkme", 0, &size, id_buffer);
|
||||
ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %u.\n", ret);
|
||||
|
||||
size = sizeof(id_buffer);
|
||||
ret = pPackageIdFromFullName(L"TestPackage_1.2.3.4_X86_TestResourceId_0abcdefghjkmee", 0, &size, id_buffer);
|
||||
ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %u.\n", ret);
|
||||
|
||||
size = sizeof(id_buffer);
|
||||
ret = pPackageIdFromFullName(L"TestPackage_1.2.3_X86_TestResourceId_0abcdefghjkme", 0, &size, id_buffer);
|
||||
ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %u.\n", ret);
|
||||
|
||||
size = sizeof(id_buffer);
|
||||
ret = pPackageIdFromFullName(L"TestPackage_1.2.3.4_X86_TestResourceId_0abcdefghjkme_", 0, &size, id_buffer);
|
||||
ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %u.\n", ret);
|
||||
|
||||
size = sizeof(id_buffer);
|
||||
ret = pPackageIdFromFullName(L"TestPackage_1.2.3.4_X86__0abcdefghjkme", 0, &size, id_buffer);
|
||||
ok(ret == ERROR_SUCCESS, "Got unexpected ret %u.\n", ret);
|
||||
ok(!lstrcmpW(id->resourceId, L""), "Got unexpected resourceId %s.\n", debugstr_w(id->resourceId));
|
||||
|
||||
size = sizeof(id_buffer);
|
||||
ret = pPackageIdFromFullName(L"TestPackage_1.2.3.4_X86_0abcdefghjkme", 0, &size, id_buffer);
|
||||
ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %u.\n", ret);
|
||||
}
|
||||
|
||||
START_TEST(version)
|
||||
{
|
||||
init_function_pointers();
|
||||
|
@ -754,4 +926,5 @@ START_TEST(version)
|
|||
test_GetVersionEx();
|
||||
test_VerifyVersionInfo();
|
||||
test_GetSystemFirmwareTable();
|
||||
test_PackageIdFromFullName();
|
||||
}
|
||||
|
|
|
@ -1014,7 +1014,7 @@
|
|||
# @ stub PackageFamilyNameFromProductId
|
||||
# @ stub PackageFullNameFromId
|
||||
# @ stub PackageFullNameFromProductId
|
||||
# @ stub PackageIdFromFullName
|
||||
@ stdcall PackageIdFromFullName(wstr long ptr ptr)
|
||||
# @ stub PackageIdFromProductId
|
||||
# @ stub PackageNameAndPublisherIdFromFamilyName
|
||||
# @ stub PackageRelativeApplicationIdFromProductId
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "winnls.h"
|
||||
#include "winternl.h"
|
||||
#include "winerror.h"
|
||||
#include "appmodel.h"
|
||||
|
||||
#include "kernelbase.h"
|
||||
#include "wine/debug.h"
|
||||
|
@ -1565,3 +1566,118 @@ LONG WINAPI /* DECLSPEC_HOTPATCH */ GetPackageFamilyName( HANDLE process, UINT32
|
|||
FIXME( "(%p %p %p): stub\n", process, length, name );
|
||||
return APPMODEL_ERROR_NO_PACKAGE;
|
||||
}
|
||||
|
||||
|
||||
static const struct
|
||||
{
|
||||
UINT32 code;
|
||||
const WCHAR *name;
|
||||
}
|
||||
arch_names[] =
|
||||
{
|
||||
{PROCESSOR_ARCHITECTURE_INTEL, L"x86"},
|
||||
{PROCESSOR_ARCHITECTURE_ARM, L"arm"},
|
||||
{PROCESSOR_ARCHITECTURE_AMD64, L"x64"},
|
||||
{PROCESSOR_ARCHITECTURE_NEUTRAL, L"neutral"},
|
||||
{PROCESSOR_ARCHITECTURE_ARM64, L"arm64"},
|
||||
{PROCESSOR_ARCHITECTURE_UNKNOWN, L"unknown"},
|
||||
};
|
||||
|
||||
static UINT32 processor_arch_from_string(const WCHAR *str, unsigned int len)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(arch_names); ++i)
|
||||
if (lstrlenW(arch_names[i].name) == len && !wcsnicmp(str, arch_names[i].name, len))
|
||||
return arch_names[i].code;
|
||||
return ~0u;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* PackageIdFromFullName (kernelbase.@)
|
||||
*/
|
||||
LONG WINAPI PackageIdFromFullName(const WCHAR *full_name, UINT32 flags, UINT32 *buffer_length, BYTE *buffer)
|
||||
{
|
||||
const WCHAR *name, *version_str, *arch_str, *resource_id, *publisher_id, *s;
|
||||
PACKAGE_ID *id = (PACKAGE_ID *)buffer;
|
||||
UINT32 size, buffer_size, len;
|
||||
|
||||
TRACE("full_name %s, flags %#x, buffer_length %p, buffer %p.\n",
|
||||
debugstr_w(full_name), flags, buffer_length, buffer);
|
||||
|
||||
if (flags)
|
||||
FIXME("Flags %#x are not supported.\n", flags);
|
||||
|
||||
if (!full_name || !buffer_length)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
if (!buffer && *buffer_length)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
name = full_name;
|
||||
if (!(version_str = wcschr(name, L'_')))
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
++version_str;
|
||||
|
||||
if (!(arch_str = wcschr(version_str, L'_')))
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
++arch_str;
|
||||
|
||||
if (!(resource_id = wcschr(arch_str, L'_')))
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
++resource_id;
|
||||
|
||||
if (!(publisher_id = wcschr(resource_id, L'_')))
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
++publisher_id;
|
||||
|
||||
/* Publisher id length should be 13. */
|
||||
size = sizeof(*id) + sizeof(WCHAR) * ((version_str - name) + (publisher_id - resource_id) + 13 + 1);
|
||||
buffer_size = *buffer_length;
|
||||
*buffer_length = size;
|
||||
if (buffer_size < size)
|
||||
return ERROR_INSUFFICIENT_BUFFER;
|
||||
|
||||
memset(id, 0, sizeof(*id));
|
||||
if ((id->processorArchitecture = processor_arch_from_string(arch_str, resource_id - arch_str - 1)) == ~0u)
|
||||
{
|
||||
FIXME("Unrecognized arch %s.\n", debugstr_w(arch_str));
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
buffer += sizeof(*id);
|
||||
|
||||
id->version.u.s.Major = wcstol(version_str, NULL, 10);
|
||||
if (!(s = wcschr(version_str, L'.')))
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
++s;
|
||||
id->version.u.s.Minor = wcstol(s, NULL, 10);
|
||||
if (!(s = wcschr(s, L'.')))
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
++s;
|
||||
id->version.u.s.Build = wcstol(s, NULL, 10);
|
||||
if (!(s = wcschr(s, L'.')))
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
++s;
|
||||
id->version.u.s.Revision = wcstol(s, NULL, 10);
|
||||
|
||||
id->name = (WCHAR *)buffer;
|
||||
len = version_str - name - 1;
|
||||
memcpy(id->name, name, sizeof(*id->name) * len);
|
||||
id->name[len] = 0;
|
||||
buffer += sizeof(*id->name) * (len + 1);
|
||||
|
||||
id->resourceId = (WCHAR *)buffer;
|
||||
len = publisher_id - resource_id - 1;
|
||||
memcpy(id->resourceId, resource_id, sizeof(*id->resourceId) * len);
|
||||
id->resourceId[len] = 0;
|
||||
buffer += sizeof(*id->resourceId) * (len + 1);
|
||||
|
||||
id->publisherId = (WCHAR *)buffer;
|
||||
len = lstrlenW(publisher_id);
|
||||
if (len != 13)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
memcpy(id->publisherId, publisher_id, sizeof(*id->publisherId) * len);
|
||||
id->publisherId[len] = 0;
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -48,10 +48,41 @@ typedef enum AppPolicyWindowingModel
|
|||
AppPolicyWindowingModel_ClassicPhone = 3
|
||||
} AppPolicyWindowingModel;
|
||||
|
||||
typedef struct PACKAGE_VERSION
|
||||
{
|
||||
union
|
||||
{
|
||||
UINT64 Version;
|
||||
struct
|
||||
{
|
||||
USHORT Revision;
|
||||
USHORT Build;
|
||||
USHORT Minor;
|
||||
USHORT Major;
|
||||
}
|
||||
DUMMYSTRUCTNAME;
|
||||
}
|
||||
DUMMYUNIONNAME;
|
||||
}
|
||||
PACKAGE_VERSION;
|
||||
|
||||
typedef struct PACKAGE_ID
|
||||
{
|
||||
UINT32 reserved;
|
||||
UINT32 processorArchitecture;
|
||||
PACKAGE_VERSION version;
|
||||
WCHAR *name;
|
||||
WCHAR *publisher;
|
||||
WCHAR *resourceId;
|
||||
WCHAR *publisherId;
|
||||
}
|
||||
PACKAGE_ID;
|
||||
|
||||
LONG WINAPI AppPolicyGetProcessTerminationMethod(HANDLE token, AppPolicyProcessTerminationMethod *policy);
|
||||
LONG WINAPI AppPolicyGetShowDeveloperDiagnostic(HANDLE token, AppPolicyShowDeveloperDiagnostic *policy);
|
||||
LONG WINAPI AppPolicyGetThreadInitializationType(HANDLE token, AppPolicyThreadInitializationType *policy);
|
||||
LONG WINAPI AppPolicyGetWindowingModel(HANDLE processToken, AppPolicyWindowingModel *policy);
|
||||
LONG WINAPI PackageIdFromFullName(const WCHAR *full_name, UINT32 flags, UINT32 *buffer_length, BYTE *buffer);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue