[PATCH 5/5] kernel32: Implement GetPackagePath().

Paul Gofman pgofman at codeweavers.com
Fri Mar 26 04:37:47 CDT 2021


Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
---
 .../api-ms-win-appmodel-runtime-l1-1-1.spec   |  2 +-
 .../ext-ms-win-kernel32-package-l1-1-1.spec   |  2 +-
 dlls/kernel32/kernel32.spec                   |  1 +
 dlls/kernel32/tests/version.c                 | 64 +++++++++++++--
 dlls/kernelbase/kernelbase.spec               |  2 +-
 dlls/kernelbase/version.c                     | 82 +++++++++++++++++++
 include/appmodel.h                            |  1 +
 7 files changed, 146 insertions(+), 8 deletions(-)

diff --git a/dlls/api-ms-win-appmodel-runtime-l1-1-1/api-ms-win-appmodel-runtime-l1-1-1.spec b/dlls/api-ms-win-appmodel-runtime-l1-1-1/api-ms-win-appmodel-runtime-l1-1-1.spec
index 72a0a33baf5..e77ac397b03 100644
--- a/dlls/api-ms-win-appmodel-runtime-l1-1-1/api-ms-win-appmodel-runtime-l1-1-1.spec
+++ b/dlls/api-ms-win-appmodel-runtime-l1-1-1/api-ms-win-appmodel-runtime-l1-1-1.spec
@@ -13,7 +13,7 @@
 @ stdcall GetPackageFullName(long ptr ptr) kernel32.GetPackageFullName
 @ stub GetPackageId
 @ stub GetPackageInfo
-@ stub GetPackagePath
+@ stdcall GetPackagePath(ptr long ptr ptr) kernel32.GetPackagePath
 @ stub GetPackagePathByFullName
 @ stdcall GetPackagesByPackageFamily(wstr ptr ptr ptr ptr) kernel32.GetPackagesByPackageFamily
 @ stub GetStagedPackageOrigin
diff --git a/dlls/ext-ms-win-kernel32-package-l1-1-1/ext-ms-win-kernel32-package-l1-1-1.spec b/dlls/ext-ms-win-kernel32-package-l1-1-1/ext-ms-win-kernel32-package-l1-1-1.spec
index 42566176b56..58bf807b4be 100644
--- a/dlls/ext-ms-win-kernel32-package-l1-1-1/ext-ms-win-kernel32-package-l1-1-1.spec
+++ b/dlls/ext-ms-win-kernel32-package-l1-1-1/ext-ms-win-kernel32-package-l1-1-1.spec
@@ -11,7 +11,7 @@
 @ stdcall GetPackageFullName(long ptr ptr) kernel32.GetPackageFullName
 @ stub GetPackageId
 @ stub GetPackageInfo
-@ stub GetPackagePath
+@ stdcall GetPackagePath(ptr long ptr ptr) kernel32.GetPackagePath
 @ stdcall GetPackagesByPackageFamily(wstr ptr ptr ptr ptr) kernel32.GetPackagesByPackageFamily
 @ stub GetStagedPackageOrigin
 @ stub OpenPackageInfoByFullName
diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec
index 4cfcf6df188..7d5160a51da 100644
--- a/dlls/kernel32/kernel32.spec
+++ b/dlls/kernel32/kernel32.spec
@@ -768,6 +768,7 @@
 @ stdcall -import GetPackagesByPackageFamily(wstr ptr ptr ptr ptr)
 @ stdcall GetPackageFamilyName(long ptr ptr) kernelbase.GetPackageFamilyName
 @ stdcall GetPackageFullName(long ptr ptr) kernelbase.GetPackageFullName
+@ stdcall -import GetPackagePath(ptr long ptr ptr)
 @ stdcall -import GetPhysicallyInstalledSystemMemory(ptr)
 @ stdcall -import GetPriorityClass(long)
 @ stdcall GetPrivateProfileIntA(str str long str)
diff --git a/dlls/kernel32/tests/version.c b/dlls/kernel32/tests/version.c
index ed1ef3e3bf7..1d5dc550d46 100644
--- a/dlls/kernel32/tests/version.c
+++ b/dlls/kernel32/tests/version.c
@@ -23,6 +23,7 @@
 #include "winternl.h"
 #include "appmodel.h"
 
+static LONG (WINAPI * pGetPackagePath)(const PACKAGE_ID *, const UINT32, UINT32 *, WCHAR *);
 static LONG (WINAPI * pGetPackagesByPackageFamily)(const WCHAR *, UINT32 *, WCHAR **, UINT32 *, WCHAR *);
 static BOOL (WINAPI * pGetProductInfo)(DWORD, DWORD, DWORD, DWORD, DWORD *);
 static UINT (WINAPI * pGetSystemFirmwareTable)(DWORD, DWORD, void *, DWORD);
@@ -45,6 +46,7 @@ static void init_function_pointers(void)
 
     hmod = GetModuleHandleA("kernel32.dll");
 
+    GET_PROC(GetPackagePath);
     GET_PROC(GetPackagesByPackageFamily);
     GET_PROC(GetProductInfo);
     GET_PROC(GetSystemFirmwareTable);
@@ -943,15 +945,15 @@ static void test_PackageIdFromFullName(void)
 static void test_package_info(void)
 {
     static const WCHAR package_family_msvc140[] = L"Microsoft.VCLibs.140.00_8wekyb3d8bbwe";
-    UINT32 count, length, curr_length, size;
+    UINT32 count, length, curr_length, size, path_length, total_length;
+    WCHAR buffer[2048], path[MAX_PATH];
+    PACKAGE_ID *id, saved_id;
     WCHAR *full_names[32];
     BYTE id_buffer[512];
-    WCHAR buffer[2048];
+    DWORD arch, attrib;
     BOOL arch_found;
     SYSTEM_INFO si;
     unsigned int i;
-    PACKAGE_ID *id;
-    DWORD arch;
     LONG ret;
 
     if (!pGetPackagesByPackageFamily)
@@ -1032,6 +1034,10 @@ static void test_package_info(void)
     ok(count == ARRAY_SIZE(full_names), "Got unexpected count %u.\n", count);
     ok(length == ARRAY_SIZE(buffer), "Got unexpected length %u.\n", length);
 
+    length = 0;
+    ret = pGetPackagePath(NULL, 0, &length, NULL);
+    ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %u.\n", ret);
+
     count = 0;
     length = 0;
     ret = pGetPackagesByPackageFamily(package_family_msvc140, &count, NULL, &length, NULL);
@@ -1050,6 +1056,7 @@ static void test_package_info(void)
     ok(count >= 1, "Got unexpected count %u.\n", count);
     ok(length > 1, "Got unexpected length %u.\n", length);
 
+    total_length = length;
     id = (PACKAGE_ID *)id_buffer;
     curr_length = 0;
     arch_found = FALSE;
@@ -1063,9 +1070,56 @@ static void test_package_info(void)
 
         if (id->processorArchitecture == arch)
             arch_found = TRUE;
+
+        path_length = 0;
+        ret = pGetPackagePath(id, 0, &path_length, NULL);
+        ok(ret == ERROR_INSUFFICIENT_BUFFER, "Got unexpected ret %u.\n", ret);
+        ok(path_length > 1, "Got unexpected path_length %u.\n", path_length);
+
+        length = path_length;
+        ret = pGetPackagePath(id, 0, &length, path);
+        ok(ret == ERROR_SUCCESS, "Got unexpected ret %u.\n", ret);
+        ok(length == path_length, "Got unexpected length %u.\n", length);
+        attrib = GetFileAttributesW(path);
+        ok(attrib != INVALID_FILE_ATTRIBUTES && attrib & FILE_ATTRIBUTE_DIRECTORY,
+                "Got unexpected attrib %#x, GetLastError() %u.\n", attrib, GetLastError());
     }
-    ok(curr_length == length, "Got unexpected length %u.\n", length);
+    ok(curr_length == total_length, "Got unexpected length %u.\n", length);
     ok(arch_found, "Did not find package for current arch.\n");
+
+    size = sizeof(id_buffer);
+    ret = pPackageIdFromFullName(full_names[0], 0, &size, id_buffer);
+    ok(ret == ERROR_SUCCESS, "Got unexpected ret %u.\n", ret);
+    saved_id = *id;
+
+    id->publisherId = NULL;
+    length = ARRAY_SIZE(path);
+    ret = pGetPackagePath(id, 0, &length, path);
+    ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %u.\n", ret);
+
+    *id = saved_id;
+    id->name = NULL;
+    length = ARRAY_SIZE(path);
+    ret = pGetPackagePath(id, 0, &length, path);
+    ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %u.\n", ret);
+
+    *id = saved_id;
+    id->publisher = NULL;
+    length = ARRAY_SIZE(path);
+    ret = pGetPackagePath(id, 0, &length, path);
+    ok(ret == ERROR_SUCCESS, "Got unexpected ret %u.\n", ret);
+
+    *id = saved_id;
+    id->processorArchitecture = ~0u;
+    length = ARRAY_SIZE(path);
+    ret = pGetPackagePath(id, 0, &length, path);
+    ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %u.\n", ret);
+
+    *id = saved_id;
+    id->name[0] = L'X';
+    length = ARRAY_SIZE(path);
+    ret = pGetPackagePath(id, 0, &length, path);
+    ok(ret == ERROR_NOT_FOUND, "Got unexpected ret %u.\n", ret);
 }
 
 START_TEST(version)
diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec
index fc7671781f1..d318313e0f0 100644
--- a/dlls/kernelbase/kernelbase.spec
+++ b/dlls/kernelbase/kernelbase.spec
@@ -601,7 +601,7 @@
 # @ stub GetPackageInfo
 # @ stub GetPackageInstallTime
 # @ stub GetPackageOSMaxVersionTested
-# @ stub GetPackagePath
+@ stdcall GetPackagePath(ptr long ptr ptr)
 # @ stub GetPackagePathByFullName
 # @ stub GetPackagePathOnVolume
 # @ stub GetPackageProperty
diff --git a/dlls/kernelbase/version.c b/dlls/kernelbase/version.c
index b2a6ceb182e..e762d446953 100644
--- a/dlls/kernelbase/version.c
+++ b/dlls/kernelbase/version.c
@@ -1839,3 +1839,85 @@ LONG WINAPI GetPackagesByPackageFamily(const WCHAR *family_name, UINT32 *count,
 
     return short_buffer ? ERROR_INSUFFICIENT_BUFFER : ERROR_SUCCESS;
 }
+
+
+/***********************************************************************
+ *         GetPackagePath   (kernelbase.@)
+ */
+LONG WINAPI GetPackagePath(const PACKAGE_ID *package_id, const UINT32 reserved, UINT32 *length, WCHAR *path)
+{
+    WCHAR *key_name = NULL, *expanded_path = NULL;
+    UINT32 required_length, have_length;
+    unsigned int offset;
+    HKEY key = NULL;
+    DWORD size;
+    LONG ret;
+
+    TRACE("package_id %p, reserved %u, length %p, path %p.\n", package_id, reserved, length, path);
+
+    if (!length)
+        return ERROR_INVALID_PARAMETER;
+    if (!path && *length)
+        return ERROR_INVALID_PARAMETER;
+
+    required_length = 0;
+    if ((ret = PackageFullNameFromId(package_id, &required_length, NULL)) != ERROR_INSUFFICIENT_BUFFER)
+        return ret;
+
+    offset = lstrlenW(packages_key_name) + 1;
+    if (!(key_name = heap_alloc((offset + required_length) * sizeof(WCHAR))))
+    {
+        ERR("No memory.");
+        return ERROR_OUTOFMEMORY;
+    }
+
+    if ((ret = PackageFullNameFromId(package_id, &required_length, key_name + offset)))
+        goto done;
+
+    memcpy(key_name, packages_key_name, (offset - 1) * sizeof(WCHAR));
+    key_name[offset - 1] = L'\\';
+
+    if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, key_name, 0, KEY_READ, &key))
+    {
+        WARN("Key %s not found.\n", debugstr_w(key_name));
+        ret = ERROR_NOT_FOUND;
+        goto done;
+    }
+    if (RegGetValueW(key, NULL, L"Path", RRF_RT_REG_SZ, NULL, NULL, &size))
+    {
+        WARN("Path value not found in %s.\n", debugstr_w(key_name));
+        ret = ERROR_NOT_FOUND;
+        goto done;
+    }
+    if (!(expanded_path = heap_alloc(size)))
+    {
+        ERR("No memory.");
+        ret = ERROR_OUTOFMEMORY;
+        goto done;
+    }
+    if (RegGetValueW(key, NULL, L"Path", RRF_RT_REG_SZ, NULL, expanded_path, &size))
+    {
+        WARN("Could not get Path value from %s.\n", debugstr_w(key_name));
+        ret = ERROR_NOT_FOUND;
+        goto done;
+    }
+
+    have_length = *length;
+    *length = lstrlenW(expanded_path) + 1;
+    if (have_length >= *length)
+    {
+        memcpy(path, expanded_path, *length * sizeof(*path));
+        ret = ERROR_SUCCESS;
+    }
+    else
+    {
+        ret = ERROR_INSUFFICIENT_BUFFER;
+    }
+
+done:
+    if (key)
+        RegCloseKey(key);
+    heap_free(expanded_path);
+    heap_free(key_name);
+    return ret;
+}
diff --git a/include/appmodel.h b/include/appmodel.h
index be59bc70f5f..c73cb8d26ef 100644
--- a/include/appmodel.h
+++ b/include/appmodel.h
@@ -82,6 +82,7 @@ LONG WINAPI AppPolicyGetProcessTerminationMethod(HANDLE token, AppPolicyProcessT
 LONG WINAPI AppPolicyGetShowDeveloperDiagnostic(HANDLE token, AppPolicyShowDeveloperDiagnostic *policy);
 LONG WINAPI AppPolicyGetThreadInitializationType(HANDLE token, AppPolicyThreadInitializationType *policy);
 LONG WINAPI AppPolicyGetWindowingModel(HANDLE processToken, AppPolicyWindowingModel *policy);
+LONG WINAPI GetPackagePath(const PACKAGE_ID *package_id, const UINT32 reserved, UINT32 *length, WCHAR *path);
 LONG WINAPI GetPackagesByPackageFamily(const WCHAR *family_name, UINT32 *count, WCHAR **full_names,
         UINT32 *buffer_length, WCHAR *buffer);
 LONG WINAPI PackageFullNameFromId(const PACKAGE_ID *package_id, UINT32 *length, WCHAR *full_name);
-- 
2.30.2




More information about the wine-devel mailing list